Skip to content

Commit

Permalink
add target_table_info in list_joinable's response
Browse files Browse the repository at this point in the history
  • Loading branch information
Anish9901 committed Jul 30, 2024
1 parent cdb87c4 commit 2e4aed8
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 94 deletions.
30 changes: 25 additions & 5 deletions db/sql/10_msar_joinable_tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ whether to travel from referrer to referant (when False) or from referant to ref

DROP TYPE IF EXISTS msar.joinable_tables CASCADE;
CREATE TYPE msar.joinable_tables AS (
base integer, -- The OID of the table from which the paths start
target integer, -- The OID of the table where the paths end
base bigint, -- The OID of the table from which the paths start
target bigint, -- The OID of the table where the paths end
join_path jsonb, -- A JSONB array of arrays of arrays
fkey_path jsonb,
depth integer,
Expand Down Expand Up @@ -131,8 +131,28 @@ SELECT * FROM output_cte;
$$ LANGUAGE sql;


DROP FUNCTION IF EXISTS msar.get_joinable_tables(integer, oid);
CREATE OR REPLACE FUNCTION
msar.get_joinable_tables(max_depth integer, table_id oid) RETURNS
SETOF msar.joinable_tables AS $$
SELECT * FROM msar.get_joinable_tables(max_depth) WHERE base=table_id
$$ LANGUAGE sql;
jsonb AS $$
WITH jt_cte AS (
SELECT * FROM msar.get_joinable_tables(max_depth) WHERE base=table_id
), target_cte AS (
SELECT jsonb_build_object(
pga.attrelid::text, msar.get_relation_name(pga.attrelid),
'columns', jsonb_agg(
jsonb_build_object(
pga.attnum::text, jsonb_build_object(
'name', pga.attname, 'type', CASE WHEN attndims>0 THEN '_array' ELSE atttypid::regtype::text END
)
)
)
) as tt
FROM pg_catalog.pg_attribute AS pga, jt_cte
WHERE pga.attrelid=jt_cte.target AND pga.attnum > 0 and NOT pga.attisdropped GROUP BY pga.attrelid
)
SELECT jsonb_build_object(
'joinable_tables', jsonb_agg(to_jsonb(jt_cte.*)),
'target_table_info', jsonb_agg(target_cte.tt)
) FROM target_cte, jt_cte
$$ LANGUAGE sql RETURNS NULL ON NULL INPUT;
4 changes: 2 additions & 2 deletions db/tables/operations/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
)
from sqlalchemy.dialects.postgresql import JSONB

from db.connection import exec_msar_func, select_from_msar_func
from db.connection import exec_msar_func
from db.utils import execute_statement, get_pg_catalog_table

BASE = 'base'
Expand Down Expand Up @@ -60,7 +60,7 @@ def get_table_info(schema, conn):


def list_joinable_tables(table_oid, conn, max_depth):
return select_from_msar_func(conn, 'get_joinable_tables', max_depth, table_oid)
return exec_msar_func(conn, 'get_joinable_tables', max_depth, table_oid).fetchone()[0]


def reflect_table(name, schema, engine, metadata, connection_to_use=None, keep_existing=False):
Expand Down
1 change: 1 addition & 0 deletions docs/docs/api/rpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ To use an RPC function:
- list_joinable
- TableInfo
- SettableTableInfo
- JoinableTableRecord
- JoinableTableInfo

## Table Metadata
Expand Down
29 changes: 24 additions & 5 deletions mathesar/rpc/tables/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ class SettableTableInfo(TypedDict):
columns: Optional[list[SettableColumnInfo]]


class JoinableTableInfo(TypedDict):
class JoinableTableRecord(TypedDict):
"""
Information about a joinable table.
Information about a singular joinable table.
Attributes:
base: The OID of the table from which the paths start
Expand Down Expand Up @@ -102,6 +102,25 @@ def from_dict(cls, joinables):
)


class JoinableTableInfo(TypedDict):
"""
Information about joinable table(s).
Attributes:
joinable_tables: List of reachable joinable table(s) from a base table.
target_table_info: Additional info about target table(s) and its column(s).
"""
joinable_tables: list[JoinableTableRecord]
target_table_info: list

@classmethod
def from_dict(cls, joinable_dict):
return cls(
joinable_tables=[JoinableTableRecord.from_dict(j) for j in joinable_dict["joinable_tables"]],
target_table_info=joinable_dict["target_table_info"]
)


@rpc_method(name="tables.list")
@http_basic_auth_login_required
@handle_rpc_exceptions
Expand Down Expand Up @@ -290,7 +309,7 @@ def list_joinable(
database_id: int,
max_depth: int = 3,
**kwargs
) -> list[JoinableTableInfo]:
) -> JoinableTableInfo:
"""
List details for joinable tables.
Expand All @@ -304,8 +323,8 @@ def list_joinable(
"""
user = kwargs.get(REQUEST_KEY).user
with connect(database_id, user) as conn:
joinables = list_joinable_tables(table_oid, conn, max_depth)
return [JoinableTableInfo.from_dict(joinable) for joinable in joinables]
joinable_dict = list_joinable_tables(table_oid, conn, max_depth)
return JoinableTableInfo.from_dict(joinable_dict)


@rpc_method(name="tables.list_with_metadata")
Expand Down
188 changes: 106 additions & 82 deletions mathesar/tests/rpc/tables/test_t_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,107 +288,131 @@ def mock_connect(_database_id, user):
def mock_list_joinable_tables(_table_oid, conn, max_depth):
if _table_oid != table_oid:
raise AssertionError('incorrect parameters passed')
return [
return {
'joinable_tables': [
{
'base': 2254329,
'depth': 1,
'target': 2254334,
'fkey_path': [[2254406, False]],
'join_path': [[[2254329, 2], [2254334, 1]]],
'multiple_results': False
},
{
'base': 2254329,
'depth': 1,
'target': 2254334,
'fkey_path': [[2254406, False]],
'join_path': [[[2254329, 2], [2254334, 1]]],
'multiple_results': False
},
{
'base': 2254329,
'depth': 1,
'target': 2254350,
'fkey_path': [[2254411, False]],
'join_path': [[[2254329, 3], [2254350, 1]]],
'multiple_results': False
},
{
'base': 2254329,
'depth': 1,
'target': 2254350,
'fkey_path': [[2254411, False]],
'join_path': [[[2254329, 3], [2254350, 1]]],
'multiple_results': False
}],
'target_table_info': [
{
'2254334': 'Items',
'columns': [{'1': {'name': 'id', 'type': 'integer'}},
{'2': {'name': 'Barcode', 'type': 'text'}},
{'3': {'name': 'Acquisition Date', 'type': 'date'}},
{'5': {'name': 'Book', 'type': 'integer'}}]
},
{
'2254350': 'Patrons',
'columns': [{'1': {'name': 'id', 'type': 'integer'}},
{'2': {'name': 'First Name', 'type': 'text'}},
{'3': {'name': 'Last Name', 'type': 'text'}}]
},
{
'2254334': 'Items',
'columns': [{'1': {'name': 'id', 'type': 'integer'}},
{'2': {'name': 'Barcode', 'type': 'text'}},
{'3': {'name': 'Acquisition Date', 'type': 'date'}},
{'5': {'name': 'Book', 'type': 'integer'}}]
},
{
'2254350': 'Patrons',
'columns': [{'1': {'name': 'id', 'type': 'integer'}},
{'2': {'name': 'First Name', 'type': 'text'}},
{'3': {'name': 'Last Name', 'type': 'text'}}]
}]
}
expected_dict = {
'joinable_tables': [
{
'base': 2254329,
'depth': 1,
'target': 2254334,
'join_path': [[[2254329, 2], [2254334, 1]]],
'fkey_path': [[2254406, False]],
'depth': 1,
'join_path': [[[2254329, 2], [2254334, 1]]],
'multiple_results': False
},
{
'base': 2254329,
'target': 2254350,
'join_path': [[[2254329, 3], [2254350, 1]]],
'fkey_path': [[2254411, False]],
'depth': 1,
'target': 2254334,
'fkey_path': [[2254406, False]],
'join_path': [[[2254329, 2], [2254334, 1]]],
'multiple_results': False
},
{
'base': 2254329,
'target': 2254321,
'join_path': [[[2254329, 2], [2254334, 1]], [[2254334, 5], [2254321, 1]]],
'fkey_path': [[2254406, False], [2254399, False]],
'depth': 2,
'depth': 1,
'target': 2254350,
'fkey_path': [[2254411, False]],
'join_path': [[[2254329, 3], [2254350, 1]]],
'multiple_results': False
},
{
'base': 2254329,
'target': 2254358,
'join_path': [
[[2254329, 2], [2254334, 1]],
[[2254334, 5], [2254321, 1]],
[[2254321, 11], [2254358, 1]]
],
'fkey_path': [[2254406, False], [2254399, False], [2254394, False]],
'depth': 3,
'depth': 1,
'target': 2254350,
'fkey_path': [[2254411, False]],
'join_path': [[[2254329, 3], [2254350, 1]]],
'multiple_results': False
}],
'target_table_info': [
{
'2254334': 'Items',
'columns': [{'1': {'name': 'id', 'type': 'integer'}},
{'2': {'name': 'Barcode', 'type': 'text'}},
{'3': {'name': 'Acquisition Date', 'type': 'date'}},
{'5': {'name': 'Book', 'type': 'integer'}}]
},
{
'base': 2254329,
'target': 2254313,
'join_path': [
[[2254329, 2], [2254334, 1]],
[[2254334, 5], [2254321, 1]],
[[2254321, 10], [2254313, 1]]
],
'fkey_path': [[2254406, False], [2254399, False], [2254389, False]],
'depth': 3,
'multiple_results': False
}
]
expected_list = [
{
'base': 2254329,
'target': 2254334,
'join_path': [[[2254329, 2], [2254334, 1]]],
'fkey_path': [[2254406, False]],
'depth': 1,
'multiple_results': False
},
{
'base': 2254329,
'target': 2254350,
'join_path': [[[2254329, 3], [2254350, 1]]],
'fkey_path': [[2254411, False]],
'depth': 1,
'multiple_results': False
},
{
'base': 2254329,
'target': 2254321,
'join_path': [[[2254329, 2], [2254334, 1]], [[2254334, 5], [2254321, 1]]],
'fkey_path': [[2254406, False], [2254399, False]],
'depth': 2,
'multiple_results': False
},
{
'base': 2254329,
'target': 2254358,
'join_path': [
[[2254329, 2], [2254334, 1]],
[[2254334, 5], [2254321, 1]],
[[2254321, 11], [2254358, 1]]
],
'fkey_path': [[2254406, False], [2254399, False], [2254394, False]],
'depth': 3,
'multiple_results': False
},
{
'base': 2254329,
'target': 2254313,
'join_path': [
[[2254329, 2], [2254334, 1]],
[[2254334, 5], [2254321, 1]],
[[2254321, 10], [2254313, 1]]
],
'fkey_path': [[2254406, False], [2254399, False], [2254389, False]],
'depth': 3,
'multiple_results': False
}
]
'2254350': 'Patrons',
'columns': [{'1': {'name': 'id', 'type': 'integer'}},
{'2': {'name': 'First Name', 'type': 'text'}},
{'3': {'name': 'Last Name', 'type': 'text'}}]
},
{
'2254334': 'Items',
'columns': [{'1': {'name': 'id', 'type': 'integer'}},
{'2': {'name': 'Barcode', 'type': 'text'}},
{'3': {'name': 'Acquisition Date', 'type': 'date'}},
{'5': {'name': 'Book', 'type': 'integer'}}]
},
{
'2254350': 'Patrons',
'columns': [{'1': {'name': 'id', 'type': 'integer'}},
{'2': {'name': 'First Name', 'type': 'text'}},
{'3': {'name': 'Last Name', 'type': 'text'}}]
}]
}
monkeypatch.setattr(tables.base, 'connect', mock_connect)
monkeypatch.setattr(tables.base, 'list_joinable_tables', mock_list_joinable_tables)
actual_list = tables.list_joinable(table_oid=2254329, database_id=11, max_depth=3, request=request)
assert expected_list == actual_list
actual_dict = tables.list_joinable(table_oid=2254329, database_id=11, max_depth=1, request=request)
assert expected_dict == actual_dict

0 comments on commit 2e4aed8

Please sign in to comment.