diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b680d4b..78cff55 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,7 @@ +**v0.31.4** +### Fixes +1. Include source column names in FOREIGN KEY references. Fix for: https://github.com/xnuinside/simple-ddl-parser/issues/196 + **v0.31.3** ### Improvements #### Snowflake update: diff --git a/simple_ddl_parser/dialects/sql.py b/simple_ddl_parser/dialects/sql.py index a2f97ff..edca04e 100644 --- a/simple_ddl_parser/dialects/sql.py +++ b/simple_ddl_parser/dialects/sql.py @@ -934,10 +934,17 @@ def process_constraints_and_refs(self, data: Dict, p_list: List) -> Dict: def add_ref_information_to_table(self, data, p_list): if len(p_list) > 4 and "constraint" in p_list[3]: + # This is a reference, add the name of the column being referenced + ref_data = p_list[-1]["references"] + ref_col_names = p_list[-2] + if isinstance(ref_col_names, list) and len(ref_col_names) == 1: + ref_col_names = ref_col_names[0] + ref_data["name"] = ref_col_names + data = self.set_constraint( data, "references", - p_list[-1]["references"], + ref_data, p_list[3]["constraint"]["name"], ) elif isinstance(p_list[-2], list): @@ -960,8 +967,6 @@ def set_constraint( target_dict["constraints"] = {} if not target_dict["constraints"].get(_type): target_dict["constraints"][_type] = [] - if "name" in constraint: - del constraint["name"] constraint.update({"constraint_name": constraint_name}) target_dict["constraints"][_type].append(constraint) return target_dict diff --git a/tests/dialects/test_mssql_specific.py b/tests/dialects/test_mssql_specific.py index 332ac84..9f98e94 100644 --- a/tests/dialects/test_mssql_specific.py +++ b/tests/dialects/test_mssql_specific.py @@ -695,6 +695,7 @@ def test_two_unique_constructs(): "columns": ["PersonID"], "constraint_name": "FK_Person_Age_under", "deferrable_initially": None, + "name": "id", "on_delete": None, "on_update": None, "schema": None, @@ -1459,6 +1460,7 @@ def test_alter_unique(): "columns": ["PersonID"], "constraint_name": "FK_Person_Age_under", "deferrable_initially": None, + "name": "id", "on_delete": None, "on_update": None, "schema": None, @@ -1703,6 +1705,7 @@ def test_defaults_in_alter(): "columns": ["PersonID"], "constraint_name": "FK_Person_Age_under", "deferrable_initially": None, + "name": "id", "on_delete": None, "on_update": None, "schema": None, diff --git a/tests/dialects/test_oracle.py b/tests/dialects/test_oracle.py index 04a104d..f38d660 100644 --- a/tests/dialects/test_oracle.py +++ b/tests/dialects/test_oracle.py @@ -487,6 +487,7 @@ def test_partition_by(): "columns": ["order_id"], "constraint_name": "order_items_fk", "deferrable_initially": None, + "name": "order_id", "on_delete": None, "on_update": None, "schema": None, @@ -725,6 +726,7 @@ def test_organization_index(): "columns": [None], "constraint_name": "fk_metacritcombo_parent", "deferrable_initially": None, + "name": "parent_criterion_id", "on_delete": "CASCADE", "on_update": None, "schema": None, @@ -734,6 +736,7 @@ def test_organization_index(): "columns": [None], "constraint_name": "fk_metacritcombo_child", "deferrable_initially": None, + "name": "child_criterion_id", "on_delete": None, "on_update": None, "schema": None, diff --git a/tests/dialects/test_snowflake.py b/tests/dialects/test_snowflake.py index 0cf90e9..626b6d1 100644 --- a/tests/dialects/test_snowflake.py +++ b/tests/dialects/test_snowflake.py @@ -644,7 +644,9 @@ def test_double_single_quotes(): def test_autoincrement_order(): # test for https://github.com/xnuinside/simple-ddl-parser/issues/208 - ddl = """CREATE TABLE table (surrogatekey_SK NUMBER(38,0) NOT NULL autoincrement start 1 increment 1 ORDER COMMENT 'Record Identification Number Ordered')""" + ddl = """CREATE TABLE table ( + surrogatekey_SK NUMBER(38,0) NOT NULL autoincrement start 1 increment 1 + ORDER COMMENT 'Record Identification Number Ordered')""" result = DDLParser(ddl).run(group_by_type=True) expected = { "ddl_properties": [], @@ -667,9 +669,9 @@ def test_autoincrement_order(): "type": "NUMBER", "unique": False, "autoincrement": True, - "start" : '1', - "increment": '1', - "increment_order": True + "start": "1", + "increment": "1", + "increment_order": True, } ], "index": [], @@ -684,10 +686,13 @@ def test_autoincrement_order(): } print(result) assert result == expected - + + def test_autoincrement_noorder(): # test for https://github.com/xnuinside/simple-ddl-parser/issues/208 - ddl = """CREATE TABLE table (surrogatekey_SK NUMBER(38,0) NOT NULL autoincrement start 1 increment 1 NOORDER COMMENT 'Record Identification Number NoOrdered')""" + ddl = """CREATE TABLE table ( + surrogatekey_SK NUMBER(38,0) NOT NULL autoincrement start 1 increment 1 + NOORDER COMMENT 'Record Identification Number NoOrdered')""" result = DDLParser(ddl).run(group_by_type=True) expected = { "ddl_properties": [], @@ -710,9 +715,9 @@ def test_autoincrement_noorder(): "type": "NUMBER", "unique": False, "autoincrement": True, - "start" : '1', - "increment": '1', - "increment_order": False + "start": "1", + "increment": "1", + "increment_order": False, } ], "index": [], @@ -728,26 +733,7 @@ def test_autoincrement_noorder(): print(result) assert result == expected -def test_order_sequence(): - parse_results = DDLParser( - """ - CREATE SEQUENCE dev.incremental_ids_order - START 1 - INCREMENT 1 - ORDER; - """ - ).run() - expected = [ - { - "schema": "dev", - "sequence_name": "incremental_ids", - "increment": 1, - "start": 1, - "order": True, - } - ] - assert expected == parse_results - + def test_order_sequence(): parse_results = DDLParser( """ @@ -769,6 +755,7 @@ def test_order_sequence(): ] assert expected == parse_results + def test_virtual_column_ext_table(): ddl = """ create or replace external table if not exists TABLE_DATA_SRC.EXT_PAYLOAD_MANIFEST_WEB ( @@ -802,8 +789,10 @@ def test_virtual_column_ext_table(): "nullable": True, "default": None, "check": None, - "generated" : {"as" : "SPLIT_PART(SPLIT_PART(METADATA$FILENAME,'/',1),'=',2)" } - } , + "generated": { + "as": "SPLIT_PART(SPLIT_PART(METADATA$FILENAME,'/',1),'=',2)" + }, + }, { "name": "year", "type": "VARCHAR", @@ -813,7 +802,9 @@ def test_virtual_column_ext_table(): "nullable": True, "default": None, "check": None, - "generated" : {"as" : "SPLIT_PART(SPLIT_PART(METADATA$FILENAME,'/',2),'=',2)" } + "generated": { + "as": "SPLIT_PART(SPLIT_PART(METADATA$FILENAME,'/',2),'=',2)" + }, }, { "name": "month", @@ -824,7 +815,9 @@ def test_virtual_column_ext_table(): "nullable": True, "default": None, "check": None, - "generated" : {"as" : "SPLIT_PART(SPLIT_PART(METADATA$FILENAME,'/',3),'=',2)"} + "generated": { + "as": "SPLIT_PART(SPLIT_PART(METADATA$FILENAME,'/',3),'=',2)" + }, }, { "name": "day", @@ -835,7 +828,9 @@ def test_virtual_column_ext_table(): "nullable": True, "default": None, "check": None, - "generated" : {"as" : "SPLIT_PART(SPLIT_PART(METADATA$FILENAME,'/',4),'=',2)"} + "generated": { + "as": "SPLIT_PART(SPLIT_PART(METADATA$FILENAME,'/',4),'=',2)" + }, }, { "name": "path", @@ -846,26 +841,30 @@ def test_virtual_column_ext_table(): "nullable": True, "default": None, "check": None, - "generated" : {"as" : "METADATA$FILENAME" } - } + "generated": {"as": "METADATA$FILENAME"}, + }, ], "index": [], - "partition_by": { "columns" :["type", "year", "month", "day", "path"], "type" : None}, - "partitioned_by" : [], + "partition_by": { + "columns": ["type", "year", "month", "day", "path"], + "type": None, + }, + "partitioned_by": [], "primary_key": [], "primary_key_enforced": None, - "auto_refresh" : False, + "auto_refresh": False, "schema": "TABLE_DATA_SRC", "table_name": "EXT_PAYLOAD_MANIFEST_WEB", "tablespace": None, - "replace" : True, + "replace": True, "if_not_exists": True, - "location" : "@ADL_Azure_Storage_Account_Container_Name/", + "location": "@ADL_Azure_Storage_Account_Container_Name/", } ] assert result_ext_table == expected_ext_table + def test_virtual_column_table(): ddl = """ create or replace table if not exists TABLE_DATA_SRC.EXT_PAYLOAD_MANIFEST_WEB ( @@ -907,23 +906,28 @@ def test_virtual_column_table(): "nullable": True, "default": None, "check": None, - "generated" : {"as" : "id * 10" } - } + "generated": {"as": "id * 10"}, + }, ], "index": [], - "partitioned_by" : [], + "partitioned_by": [], "primary_key": [], "primary_key_enforced": None, - "auto_refresh" : False, + "auto_refresh": False, "schema": "TABLE_DATA_SRC", "table_name": "EXT_PAYLOAD_MANIFEST_WEB", "tablespace": None, - "replace" : True, + "replace": True, "if_not_exists": True, - "location" : "@ADL_Azure_Storage_Account_Container_Name/", - "file_format": ['TYPE=JSON', "NULL_IF=('field')",'DATE_FORMAT=AUTO','TRIM_SPACE=TRUE'], - 'stage_file_format': ['TYPE=JSON','NULL_IF=()'] - } + "location": "@ADL_Azure_Storage_Account_Container_Name/", + "file_format": [ + "TYPE=JSON", + "NULL_IF=('field')", + "DATE_FORMAT=AUTO", + "TRIM_SPACE=TRUE", + ], + "stage_file_format": ["TYPE=JSON", "NULL_IF=()"], + } ] - assert result_ext_table == expected_ext_table \ No newline at end of file + assert result_ext_table == expected_ext_table diff --git a/tests/test_checks.py b/tests/test_checks.py index 30621f9..1398fa3 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -135,6 +135,7 @@ def test_checks_with_in_works(): "columns": [None], "constraint_name": "fk_metacritcombo_parent", "deferrable_initially": None, + "name": "parent_criterion_id", "on_delete": "CASCADE", "on_update": None, "schema": None, @@ -144,6 +145,7 @@ def test_checks_with_in_works(): "columns": [None], "constraint_name": "fk_metacritcombo_child", "deferrable_initially": None, + "name": "child_criterion_id", "on_delete": None, "on_update": None, "schema": None, diff --git a/tests/test_indexes.py b/tests/test_indexes.py index db64e93..04632bc 100644 --- a/tests/test_indexes.py +++ b/tests/test_indexes.py @@ -270,6 +270,7 @@ def test_several_indexes_types(): "columns": ["PersonID"], "constraint_name": "FK_Person_Age_under", "deferrable_initially": None, + "name": "id", "on_delete": None, "on_update": None, "schema": None, @@ -612,6 +613,7 @@ def test_clustered_index(): "columns": ["PersonID"], "constraint_name": "FK_Person_Age_under", "deferrable_initially": None, + "name": "id", "on_delete": None, "on_update": None, "schema": None, @@ -926,6 +928,7 @@ def test_indexes_in_table(): ] assert expected == parse_results + def test_index_as_key(): """ Tests that CREATE TABLE with KEY statements properly create the index @@ -947,54 +950,93 @@ def test_index_as_key(): """ result = DDLParser(ddl).run(group_by_type=True, output_mode="mysql") expected = { - 'tables': [ - {'columns': [ - {'name': '"criteria_id"', 'type': 'int unsigned', 'size': None, - 'references': None, 'unique': False, 'nullable': False, - 'default': None, 'check': None}, - {'name': '"super_category"', 'type': 'tinyint unsigned', - 'size': None, 'references': None, 'unique': False, - 'nullable': False, 'default': None, 'check': None, - 'comment': "'Da category'"}, - {'name': '"currency_id"', 'type': 'int unsigned', 'size': None, - 'references': None, 'unique': False, 'nullable': True, - 'default': "'1'", 'check': None}, - ], - 'primary_key': ['"criteria_id"', '"super_category"'], - 'alter': {}, - 'checks': [], - 'index': [ - { - "clustered": False, - "columns": ['"currency_id"'], - "detailed_columns": [ - {"name": '"currency_id"', "nulls": "LAST", "order": "ASC"} - ], - "index_name": '"currency_ibfk"', - "unique": False, - }, - ], - 'partitioned_by': [], - 'tablespace': None, - 'constraints': {'references': [ - {'table': '"currency"', 'columns': ['"id"'], 'schema': None, - 'on_delete': None, 'on_update': None, - 'deferrable_initially': None, - 'constraint_name': '"currency_ibfk"'}, - {'table': '"criteria"', 'columns': ['"id"'], 'schema': None, - 'on_delete': None, 'on_update': None, - 'deferrable_initially': None, - 'constraint_name': '"criteria_ibfk"'}]}, - 'schema': None, - 'table_name': '"test_with_key"'} + "tables": [ + { + "columns": [ + { + "name": '"criteria_id"', + "type": "int unsigned", + "size": None, + "references": None, + "unique": False, + "nullable": False, + "default": None, + "check": None, + }, + { + "name": '"super_category"', + "type": "tinyint unsigned", + "size": None, + "references": None, + "unique": False, + "nullable": False, + "default": None, + "check": None, + "comment": "'Da category'", + }, + { + "name": '"currency_id"', + "type": "int unsigned", + "size": None, + "references": None, + "unique": False, + "nullable": True, + "default": "'1'", + "check": None, + }, + ], + "primary_key": ['"criteria_id"', '"super_category"'], + "alter": {}, + "checks": [], + "index": [ + { + "clustered": False, + "columns": ['"currency_id"'], + "detailed_columns": [ + {"name": '"currency_id"', "nulls": "LAST", "order": "ASC"} + ], + "index_name": '"currency_ibfk"', + "unique": False, + }, + ], + "partitioned_by": [], + "tablespace": None, + "constraints": { + "references": [ + { + "table": '"currency"', + "columns": ['"id"'], + "schema": None, + "name": '"currency_id"', + "on_delete": None, + "on_update": None, + "deferrable_initially": None, + "constraint_name": '"currency_ibfk"', + }, + { + "table": '"criteria"', + "columns": ['"id"'], + "schema": None, + "name": '"criteria_id"', + "on_delete": None, + "on_update": None, + "deferrable_initially": None, + "constraint_name": '"criteria_ibfk"', + }, + ] + }, + "schema": None, + "table_name": '"test_with_key"', + } + ], + "types": [], + "sequences": [], + "domains": [], + "schemas": [], + "ddl_properties": [], + "comments": [ + "!50503 SET character_set_client = utf8mb4 */;", + "!40101 SET character_set_client = @saved_cs_client */;", ], - 'types': [], - 'sequences': [], - 'domains': [], - 'schemas': [], - 'ddl_properties': [], - 'comments': [ - '!50503 SET character_set_client = utf8mb4 */;', - '!40101 SET character_set_client = @saved_cs_client */;'], } assert result == expected