From e1d76b795d40e75352dc0b6f3f7bb12a5dacd683 Mon Sep 17 00:00:00 2001 From: Anish Umale Date: Tue, 3 Sep 2024 00:59:56 +0530 Subject: [PATCH 1/3] wire up column extraction to python --- db/tables/operations/split.py | 19 ++++++++++++++++++- mathesar/rpc/data_modeling.py | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/db/tables/operations/split.py b/db/tables/operations/split.py index c9260eacc0..6ae2b274cb 100644 --- a/db/tables/operations/split.py +++ b/db/tables/operations/split.py @@ -1,4 +1,4 @@ -from db.connection import execute_msar_func_with_engine +from db.connection import execute_msar_func_with_engine, exec_msar_func def extract_columns_from_table( @@ -14,3 +14,20 @@ def extract_columns_from_table( ) extracted_table_oid, new_fkey_attnum = curr.fetchone()[0] return extracted_table_oid, old_table_oid, new_fkey_attnum + + +def split_table( + conn, + old_table_oid, + extracted_column_attnums, + extracted_table_name, + relationship_fk_column_name +): + exec_msar_func( + conn, + 'extract_columns_from_table', + old_table_oid, + extracted_column_attnums, + extracted_table_name, + relationship_fk_column_name + ) diff --git a/mathesar/rpc/data_modeling.py b/mathesar/rpc/data_modeling.py index 30c385b4ff..76f8b3bcfa 100644 --- a/mathesar/rpc/data_modeling.py +++ b/mathesar/rpc/data_modeling.py @@ -7,7 +7,7 @@ from modernrpc.auth.basic import http_basic_auth_login_required from db.links.operations import create as links_create -from db.tables.operations import infer_types +from db.tables.operations import infer_types, split from mathesar.rpc.exceptions.handlers import handle_rpc_exceptions from mathesar.rpc.utils import connect @@ -104,3 +104,35 @@ def suggest_types(*, table_oid: int, database_id: int, **kwargs) -> dict: user = kwargs.get(REQUEST_KEY).user with connect(database_id, user) as conn: return infer_types.infer_table_column_data_types(conn, table_oid) + + +@rpc_method(name="data_modeling.split_table") +@http_basic_auth_login_required +@handle_rpc_exceptions +def split_table( + *, + table_oid: int, + column_attnums: list, + extracted_table_name: str, + relationship_fk_column_name: str, + database_id: int, + **kwargs +) -> None: + """ + Extract columns from a table to create a new table, linked by a foreign key. + + Args: + table_oid: The OID of the table whose columns we'll extract. + column_attnums: A list of the attnums of the columns to extract. + extracted_table_name: The name of the new table to be made from the extracted columns. + relationship_fk_column_name: The name to give the new foreign key column in the remainder table (optional) + """ + user = kwargs.get(REQUEST_KEY).user + with connect(database_id, user) as conn: + split.split_table( + conn, + table_oid, + column_attnums, + extracted_table_name, + relationship_fk_column_name + ) From aa9f9a502557bda6468588d4edb8ec3b84267c81 Mon Sep 17 00:00:00 2001 From: Anish Umale Date: Tue, 3 Sep 2024 01:02:16 +0530 Subject: [PATCH 2/3] add docs and tests for column extraction --- docs/docs/api/rpc.md | 1 + mathesar/tests/rpc/test_data_modeling.py | 48 ++++++++++++++++++++++++ mathesar/tests/rpc/test_endpoints.py | 5 +++ 3 files changed, 54 insertions(+) diff --git a/docs/docs/api/rpc.md b/docs/docs/api/rpc.md index fb6ec1742a..0c63655df4 100644 --- a/docs/docs/api/rpc.md +++ b/docs/docs/api/rpc.md @@ -276,6 +276,7 @@ To use an RPC function: - add_foreign_key_column - add_mapping_table - suggest_types + - split_table - MappingColumn ## Responses diff --git a/mathesar/tests/rpc/test_data_modeling.py b/mathesar/tests/rpc/test_data_modeling.py index 963acf055b..a0099f83ef 100644 --- a/mathesar/tests/rpc/test_data_modeling.py +++ b/mathesar/tests/rpc/test_data_modeling.py @@ -132,3 +132,51 @@ def mock_suggest_types(conn, table_oid): database_id=_database_id, request=request, ) + + +def test_data_modeling_split_table(rf, monkeypatch): + _username = 'alice' + _password = 'pass1234' + _table_oid = 12345 + _database_id = 2 + _column_attnums = [2, 3, 4] + _extracted_table_name = 'extracted_table' + _relationship_fk_column_name = 'fk_col' + request = rf.post('/api/rpc/v0/', data={}) + request.user = User(username=_username, password=_password) + + @contextmanager + def mock_connect(database_id, user): + if database_id == _database_id and user.username == _username: + try: + yield True + finally: + pass + else: + raise AssertionError('incorrect parameters passed') + + def mock_split_table( + conn, + table_oid, + column_attnums, + extracted_table_name, + relationship_fk_column_name + ): + if ( + table_oid != _table_oid + and column_attnums != _column_attnums + and extracted_table_name != _extracted_table_name + and relationship_fk_column_name != _relationship_fk_column_name + ): + raise AssertionError('incorrect parameters passed') + + monkeypatch.setattr(data_modeling, 'connect', mock_connect) + monkeypatch.setattr(data_modeling.split, 'split_table', mock_split_table) + data_modeling.split_table( + table_oid=_table_oid, + column_attnums=_column_attnums, + extracted_table_name=_extracted_table_name, + relationship_fk_column_name=_relationship_fk_column_name, + database_id=_database_id, + request=request + ) diff --git a/mathesar/tests/rpc/test_endpoints.py b/mathesar/tests/rpc/test_endpoints.py index cede022e5c..7dc0e2cfbb 100644 --- a/mathesar/tests/rpc/test_endpoints.py +++ b/mathesar/tests/rpc/test_endpoints.py @@ -128,6 +128,11 @@ "data_modeling.suggest_types", [user_is_authenticated] ), + ( + data_modeling.split_table, + "data_modeling.split_table", + [user_is_authenticated] + ), ( databases.get, From 2a065e342140ac66632085a05090f4484962fdf2 Mon Sep 17 00:00:00 2001 From: Anish Umale Date: Tue, 3 Sep 2024 15:41:59 +0530 Subject: [PATCH 3/3] make fk_column_name optional --- db/tables/operations/split.py | 2 +- mathesar/rpc/data_modeling.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/tables/operations/split.py b/db/tables/operations/split.py index 6ae2b274cb..aa2869073b 100644 --- a/db/tables/operations/split.py +++ b/db/tables/operations/split.py @@ -21,7 +21,7 @@ def split_table( old_table_oid, extracted_column_attnums, extracted_table_name, - relationship_fk_column_name + relationship_fk_column_name=None ): exec_msar_func( conn, diff --git a/mathesar/rpc/data_modeling.py b/mathesar/rpc/data_modeling.py index 76f8b3bcfa..06843e3f27 100644 --- a/mathesar/rpc/data_modeling.py +++ b/mathesar/rpc/data_modeling.py @@ -114,8 +114,8 @@ def split_table( table_oid: int, column_attnums: list, extracted_table_name: str, - relationship_fk_column_name: str, database_id: int, + relationship_fk_column_name: str = None, **kwargs ) -> None: """