1) Add Reverse Engineered and Modified SQL tests for Foreign Keys. Fixes #4616

2) Fix issue where Validated switch option is inverted for the Foreign Key. Fixes #4412
This commit is contained in:
Akshay Joshi
2019-09-11 15:59:13 +05:30
parent b4a754bdc0
commit 6a931588aa
22 changed files with 491 additions and 11 deletions

View File

@@ -796,7 +796,7 @@ define('pgadmin.node.foreign_key', [
return !(_.isUndefined(m.get('oid')) || m.get('convalidated'));
}
// We can't update condeferred of existing foreign key.
return !(m.isNew() || m.get('convalidated'));
return !(m.isNew() || !m.get('convalidated'));
},
},{
id: 'autoindex', label: gettext('Auto FK index?'),

View File

@@ -0,0 +1,13 @@
-- Constraint: FKey1_$%{}[]()&*^!@"'`\/#
-- ALTER TABLE testschema.test_second_table DROP CONSTRAINT "FKey1_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey1_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH FULL
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED;
COMMENT ON CONSTRAINT "FKey1_$%{}[]()&*^!@""'`\/#" ON testschema.test_second_table
IS 'Test Comment Update';

View File

@@ -0,0 +1,8 @@
ALTER TABLE testschema.test_second_table
RENAME CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" TO "FKey1_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema.test_second_table
VALIDATE CONSTRAINT "FKey1_$%{}[]()&*^!@""'`\/#";
COMMENT ON CONSTRAINT "FKey1_$%{}[]()&*^!@""'`\/#" ON testschema.test_second_table
IS 'Test Comment Update';

View File

@@ -0,0 +1,10 @@
-- Constraint: FKey_$%{}[]()&*^!@"'`\/#
-- ALTER TABLE testschema.test_second_table DROP CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE
NOT VALID;

View File

@@ -0,0 +1,6 @@
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE
NOT VALID;

View File

@@ -0,0 +1,10 @@
-- Constraint: FKey_$%{}[]()&*^!@"'`\/#
-- ALTER TABLE testschema.test_second_table DROP CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH SIMPLE
ON UPDATE RESTRICT
ON DELETE RESTRICT
NOT VALID;

View File

@@ -0,0 +1,6 @@
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH SIMPLE
ON UPDATE RESTRICT
ON DELETE RESTRICT
NOT VALID;

View File

@@ -0,0 +1,10 @@
-- Constraint: FKey_$%{}[]()&*^!@"'`\/#
-- ALTER TABLE testschema.test_second_table DROP CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH SIMPLE
ON UPDATE SET DEFAULT
ON DELETE SET DEFAULT
NOT VALID;

View File

@@ -0,0 +1,6 @@
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH SIMPLE
ON UPDATE SET DEFAULT
ON DELETE SET DEFAULT
NOT VALID;

View File

@@ -0,0 +1,10 @@
-- Constraint: FKey_$%{}[]()&*^!@"'`\/#
-- ALTER TABLE testschema.test_second_table DROP CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH SIMPLE
ON UPDATE SET NULL
ON DELETE SET NULL
NOT VALID;

View File

@@ -0,0 +1,6 @@
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH SIMPLE
ON UPDATE SET NULL
ON DELETE SET NULL
NOT VALID;

View File

@@ -0,0 +1,10 @@
-- Constraint: FKey_$%{}[]()&*^!@"'`\/#
-- ALTER TABLE testschema.test_second_table DROP CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
NOT VALID;

View File

@@ -0,0 +1,6 @@
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
NOT VALID;

View File

@@ -0,0 +1,14 @@
-- Constraint: FKey_$%{}[]()&*^!@"'`\/#
-- ALTER TABLE testschema.test_second_table DROP CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH FULL
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED
NOT VALID;
COMMENT ON CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" ON testschema.test_second_table
IS 'Test Comment';

View File

@@ -0,0 +1,13 @@
ALTER TABLE testschema.test_second_table
ADD CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" FOREIGN KEY (so_id)
REFERENCES testschema.test_first_table (id) MATCH FULL
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED
NOT VALID;
COMMENT ON CONSTRAINT "FKey_$%{}[]()&*^!@""'`\/#" ON testschema.test_second_table
IS 'Test Comment';
CREATE INDEX "fki_FKey_$%{}[]()&*^!@""'`\/#"
ON testschema.test_second_table(so_id);

View File

@@ -0,0 +1,293 @@
{
"scenarios": [
{
"type": "create",
"name": "Create First Table for Foreign Key",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"data": {
"name": "test_first_table",
"columns": [{
"name": "id",
"cltype": "integer",
"is_primary_key": true
}, {
"name": "customer_id",
"cltype": "integer"
}],
"is_partitioned": false,
"schema": "testschema",
"spcname": "pg_default",
"primary_key":[{
"columns": [{
"column": "id"
}],
"include": []
}]
},
"store_object_id": true
}, {
"type": "create",
"name": "Create Second Table for Foreign Key",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"data": {
"name": "test_second_table",
"columns": [{
"name": "item_id",
"cltype": "integer",
"is_primary_key": true
}, {
"name": "so_id",
"cltype": "integer",
"is_primary_key": true
}, {
"name": "product_id",
"cltype": "integer"
}, {
"name": "qty",
"cltype": "integer"
}],
"is_partitioned": false,
"schema": "testschema",
"spcname": "pg_default",
"primary_key": [{
"columns": [{
"column": "item_id"
},{
"column": "so_id"
}],
"include": []
}]
},
"store_object_id": true
}, {
"type": "create",
"name": "Create Foreign Key Constraint with all options",
"endpoint": "NODE-foreign_key.obj",
"sql_endpoint": "NODE-foreign_key.sql_id",
"msql_endpoint": "NODE-foreign_key.msql",
"data": {
"name":"FKey_$%{}[]()&*^!@\"'`\\/#",
"comment":"Test Comment",
"condeferrable":true,
"condeferred":true,
"confmatchtype":true,
"convalidated":false,
"columns":[{
"local_column":"so_id",
"references":"<test_first_table>",
"referenced":"id"
}],
"confupdtype":"a",
"confdeltype":"a",
"autoindex":true,
"coveringindex":"fki_FKey_$%{}[]()&*^!@\"'`\\/#"
},
"expected_sql_file": "create_foreign_key_with_all_options.sql",
"expected_msql_file": "create_foreign_key_with_all_options_msql.sql",
"preprocess_data": true
}, {
"type": "alter",
"name": "Alter name, comment and validate option",
"endpoint": "NODE-foreign_key.obj_id",
"sql_endpoint": "NODE-foreign_key.sql_id",
"msql_endpoint": "NODE-foreign_key.msql_id",
"data": {
"name":"FKey1_$%{}[]()&*^!@\"'`\\/#",
"comment":"Test Comment Update",
"convalidated": true
},
"expected_sql_file": "alter_name_comment_validation.sql",
"expected_msql_file": "alter_name_comment_validation_msql.sql"
}, {
"type": "delete",
"name": "Drop Foreign Key",
"endpoint": "NODE-foreign_key.delete_id",
"data": {
"name": "FKey1_$%{}[]()&*^!@\"'`\\/#"
}
}, {
"type": "create",
"name": "Create Foreign Key Constraint with match type simple",
"endpoint": "NODE-foreign_key.obj",
"sql_endpoint": "NODE-foreign_key.sql_id",
"msql_endpoint": "NODE-foreign_key.msql",
"data": {
"name":"FKey_$%{}[]()&*^!@\"'`\\/#",
"condeferrable":false,
"condeferred":false,
"confmatchtype":false,
"convalidated":false,
"columns":[{
"local_column":"so_id",
"references":"<test_first_table>",
"referenced":"id"
}],
"confupdtype":"a",
"confdeltype":"a",
"autoindex":false,
"coveringindex":""
},
"expected_sql_file": "create_foreign_key_simple.sql",
"expected_msql_file": "create_foreign_key_simple_msql.sql",
"preprocess_data": true
}, {
"type": "delete",
"name": "Drop Foreign Key",
"endpoint": "NODE-foreign_key.delete_id",
"data": {
"name": "FKey_$%{}[]()&*^!@\"'`\\/#"
}
}, {
"type": "create",
"name": "Create Foreign Key Constraint with RESTRICT action",
"endpoint": "NODE-foreign_key.obj",
"sql_endpoint": "NODE-foreign_key.sql_id",
"msql_endpoint": "NODE-foreign_key.msql",
"data": {
"name":"FKey_$%{}[]()&*^!@\"'`\\/#",
"condeferrable":false,
"condeferred":false,
"confmatchtype":false,
"convalidated":false,
"columns":[{
"local_column":"so_id",
"references":"<test_first_table>",
"referenced":"id"
}],
"confupdtype":"r",
"confdeltype":"r",
"autoindex":false,
"coveringindex":""
},
"expected_sql_file": "create_foreign_key_restrict.sql",
"expected_msql_file": "create_foreign_key_restrict_msql.sql",
"preprocess_data": true
}, {
"type": "delete",
"name": "Drop Foreign Key",
"endpoint": "NODE-foreign_key.delete_id",
"data": {
"name": "FKey_$%{}[]()&*^!@\"'`\\/#"
}
}, {
"type": "create",
"name": "Create Foreign Key Constraint with CASCADE action",
"endpoint": "NODE-foreign_key.obj",
"sql_endpoint": "NODE-foreign_key.sql_id",
"msql_endpoint": "NODE-foreign_key.msql",
"data": {
"name":"FKey_$%{}[]()&*^!@\"'`\\/#",
"condeferrable":false,
"condeferred":false,
"confmatchtype":false,
"convalidated":false,
"columns":[{
"local_column":"so_id",
"references":"<test_first_table>",
"referenced":"id"
}],
"confupdtype":"c",
"confdeltype":"c",
"autoindex":false,
"coveringindex":""
},
"expected_sql_file": "create_foreign_key_cascade.sql",
"expected_msql_file": "create_foreign_key_cascade_msql.sql",
"preprocess_data": true
}, {
"type": "delete",
"name": "Drop Foreign Key",
"endpoint": "NODE-foreign_key.delete_id",
"data": {
"name": "FKey_$%{}[]()&*^!@\"'`\\/#"
}
}, {
"type": "create",
"name": "Create Foreign Key Constraint with SET NULL action",
"endpoint": "NODE-foreign_key.obj",
"sql_endpoint": "NODE-foreign_key.sql_id",
"msql_endpoint": "NODE-foreign_key.msql",
"data": {
"name":"FKey_$%{}[]()&*^!@\"'`\\/#",
"condeferrable":false,
"condeferred":false,
"confmatchtype":false,
"convalidated":false,
"columns":[{
"local_column":"so_id",
"references":"<test_first_table>",
"referenced":"id"
}],
"confupdtype":"n",
"confdeltype":"n",
"autoindex":false,
"coveringindex":""
},
"expected_sql_file": "create_foreign_key_setnull.sql",
"expected_msql_file": "create_foreign_key_setnull_msql.sql",
"preprocess_data": true
}, {
"type": "delete",
"name": "Drop Foreign Key",
"endpoint": "NODE-foreign_key.delete_id",
"data": {
"name": "FKey_$%{}[]()&*^!@\"'`\\/#"
}
}, {
"type": "create",
"name": "Create Foreign Key Constraint with SET DEFAULT action",
"endpoint": "NODE-foreign_key.obj",
"sql_endpoint": "NODE-foreign_key.sql_id",
"msql_endpoint": "NODE-foreign_key.msql",
"data": {
"name":"FKey_$%{}[]()&*^!@\"'`\\/#",
"condeferrable":false,
"condeferred":false,
"confmatchtype":false,
"convalidated":false,
"columns":[{
"local_column":"so_id",
"references":"<test_first_table>",
"referenced":"id"
}],
"confupdtype":"d",
"confdeltype":"d",
"autoindex":false,
"coveringindex":""
},
"expected_sql_file": "create_foreign_key_setdefault.sql",
"expected_msql_file": "create_foreign_key_setdefault_msql.sql",
"preprocess_data": true
}, {
"type": "delete",
"name": "Drop Foreign Key",
"endpoint": "NODE-foreign_key.delete_id",
"data": {
"name": "FKey_$%{}[]()&*^!@\"'`\\/#"
}
}, {
"type": "delete",
"name": "Drop Foreign Key",
"endpoint": "NODE-foreign_key.delete_id",
"data": {
"name": "FKey_$%{}[]()&*^!@\"'`\\/#"
}
}, {
"type": "delete",
"name": "Drop First Table",
"endpoint": "NODE-table.delete_id",
"data": {
"name": "test_first_table"
}
}, {
"type": "delete",
"name": "Drop Second Table",
"endpoint": "NODE-table.delete_id",
"data": {
"name": "test_second_table"
}
}
]
}

View File

@@ -16,7 +16,7 @@ SELECT ct.oid,
nr.nspname as refnsp,
cr.relname as reftab,
description as comment,
NOT convalidated as convalidated
convalidated
FROM pg_constraint ct
JOIN pg_class cl ON cl.oid=conrelid
JOIN pg_namespace nl ON nl.oid=cl.relnamespace
@@ -28,4 +28,4 @@ conrelid = {{tid}}::oid
{% if cid %}
AND ct.oid = {{cid}}::oid
{% endif %}
ORDER BY conname
ORDER BY conname

View File

@@ -22,11 +22,12 @@ ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
DEFERRABLE{% if data.condeferred %}
INITIALLY DEFERRED{% endif%}
{% endif%}
{% if data.convalidated %}
{% if not data.convalidated %}
NOT VALID{% endif%};
{% if data.comment and data.name %}
COMMENT ON CONSTRAINT {{ conn|qtIdent(data.name) }} ON {{ conn|qtIdent(data.schema, data.table) }}
IS {{ data.comment|qtLiteral }};
{% endif %}
{% endif %}

View File

@@ -1,5 +1,5 @@
SELECT
FALSE as convalidated,
convalidated,
ct.oid,
conname as name,
condeferrable,
@@ -29,4 +29,4 @@ conrelid = {{tid}}::oid
{% if cid %}
AND ct.oid = {{cid}}::oid
{% endif %}
ORDER BY conname
ORDER BY conname

View File

@@ -4,15 +4,17 @@
{% if data.name != o_data.name %}
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
RENAME CONSTRAINT {{ conn|qtIdent(o_data.name) }} TO {{ conn|qtIdent(data.name) }};
{% endif %}
{# ==== To update foreign key validate ==== #}
{% if 'convalidated' in data and o_data.convalidated != data.convalidated and not data.convalidated %}
{% if 'convalidated' in data and o_data.convalidated != data.convalidated and data.convalidated %}
ALTER TABLE {{ conn|qtIdent(data.schema, data.table) }}
VALIDATE CONSTRAINT {{ conn|qtIdent(data.name) }};
{% endif %}
{# ==== To update foreign key comments ==== #}
{% if data.comment is defined and data.comment != o_data.comment %}
COMMENT ON CONSTRAINT {{ conn|qtIdent(data.name) }} ON {{ conn|qtIdent(data.schema, data.table) }}
IS {{ data.comment|qtLiteral }};
{% endif %}
{% endif %}
{% endif %}