From c418a9c9ca251c178ea66047b1385f7d45d21f9f Mon Sep 17 00:00:00 2001 From: Khushboo Vashi Date: Tue, 28 Jan 2020 14:53:17 +0530 Subject: [PATCH] Fixed following schema diff issues: 1) Version mismatch should be displayed if you select EPAS 11 as the source and EPAS 12 as the target. 2) We should handle schema diff if the user stops the server after compare. 3) The data type is not visible for column headers in the query tool/view data. 4) Difference SQL is shown, though source & target SQL are same. 5) Error is shown when the 'target only' table is selected & clicked on Generate Script. 6) Difference SQL generated on deleting primary constraints from source throwing error on running from query tool. 7) Copy button for Difference SQL does not work. 8) Incorrect SQL is generated when check constraint from the source table is dropped. 9) Difference SQL is NOT shown when 'Unique Constraint' is dropped from the source table. 10) In case of difference, no message displayed related to copied successfully or not. 11) create or replace trigger should be on the next line. 12) Comparison Result of exactly identical tables having foreign key constraints is shown as different. 13) The wrong SQL displayed in the difference tab for view and materialized view for the select statements. 14) Wrong SQL displayed for the procedure in the difference section. 15) If the user already opens the compare section of Schema diff tool and Disconnects the server then '<' not supported between instances of 'NoneType' and 'int' message displayed. 16) When 'check constraint' is added on the source table which has already unique constraint & identical target table is created, all SQL panels remain empty. 17) Difference SQL is NOT shown when after adding 'Foreign Key' constraint to existing source table. 18) Incorrect SQL is generated when the existing index on the source table is modified. 19) Wrong SQL displayed for function in difference section. 20) Additional space is added before & after in difference SQL generated on the addition of an index to the source table. 21) Difference SQL is NOT shown when tables have different permission/grants. 22) Incorrect SQL is shown when the source had inherited table & target has a normal table. 23) Exactly identical child(inherited) tables show difference SQL. 24) Comparison is NOT working when the custom vacuum is enabled & one of the parameter modified & again custom vacuum is disabled. --- .../functions/pg/sql/11_plus/update.sql | 2 +- .../functions/pg/sql/12_plus/update.sql | 2 +- .../functions/pg/sql/9.2_plus/update.sql | 2 +- .../functions/pg/sql/9.5_plus/update.sql | 2 +- .../functions/pg/sql/9.6_plus/update.sql | 2 +- .../functions/pg/sql/default/update.sql | 2 +- .../functions/ppas/sql/12_plus/update.sql | 2 +- .../functions/ppas/sql/9.2_plus/update.sql | 2 +- .../functions/ppas/sql/9.5_plus/update.sql | 2 +- .../functions/ppas/sql/9.6_plus/update.sql | 2 +- .../functions/ppas/sql/default/update.sql | 2 +- .../procedures/pg/sql/11_plus/update.sql | 2 +- .../procedures/ppas/sql/11_plus/update.sql | 2 +- .../databases/schemas/packages/__init__.py | 1 - .../databases/schemas/tables/__init__.py | 19 +++- .../constraints/check_constraint/utils.py | 1 + .../constraints/index_constraint/utils.py | 22 +++-- .../schemas/tables/indexes/__init__.py | 54 ++++++++---- .../schemas/tables/schema_diff_utils.py | 36 ++++---- .../templates/columns/sql/10_plus/update.sql | 2 +- .../templates/indexes/sql/default/update.sql | 2 +- .../servers/databases/schemas/tables/utils.py | 22 +++-- web/pgadmin/tools/schema_diff/__init__.py | 19 ++-- .../tools/schema_diff/directory_compare.py | 86 ++++++++++--------- .../schema_diff/static/css/schema_diff.css | 2 +- .../static/js/schema_diff.backform.js | 20 ++--- .../schema_diff/static/js/schema_diff.js | 4 +- .../schema_diff/static/js/schema_diff_ui.js | 10 ++- 28 files changed, 199 insertions(+), 127 deletions(-) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/11_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/11_plus/update.sql index e828cc568..2d74a444c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/11_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/11_plus/update.sql @@ -38,7 +38,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/12_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/12_plus/update.sql index d5738abfc..c98907c0e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/12_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/12_plus/update.sql @@ -40,7 +40,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.2_plus/update.sql index 4b1c14baf..aa8e05076 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.2_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.2_plus/update.sql @@ -35,7 +35,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.5_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.5_plus/update.sql index f0c82e080..5c95464cd 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.5_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.5_plus/update.sql @@ -36,7 +36,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.6_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.6_plus/update.sql index e828cc568..2d74a444c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.6_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/9.6_plus/update.sql @@ -38,7 +38,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/default/update.sql index 04c3a054f..b6e9d304b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/default/update.sql @@ -34,7 +34,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/12_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/12_plus/update.sql index d5738abfc..c98907c0e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/12_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/12_plus/update.sql @@ -40,7 +40,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.2_plus/update.sql index 65d6aa144..1b54540f3 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.2_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.2_plus/update.sql @@ -35,7 +35,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.5_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.5_plus/update.sql index f0c82e080..5c95464cd 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.5_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.5_plus/update.sql @@ -36,7 +36,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.6_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.6_plus/update.sql index e828cc568..2d74a444c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.6_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/9.6_plus/update.sql @@ -38,7 +38,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/default/update.sql index 00c2b80de..c9a4fb071 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/default/update.sql @@ -34,7 +34,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/11_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/11_plus/update.sql index d019d046d..5d5968695 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/11_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/11_plus/update.sql @@ -28,7 +28,7 @@ CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}({% if SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/11_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/11_plus/update.sql index 1b411d86c..bb1b705e8 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/11_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/11_plus/update.sql @@ -37,7 +37,7 @@ CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}({% if {% endif %} {% endif %} -AS {% if 'probin' in data or 'prosrc_c' in data %} +AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %} {% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} $BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %} {{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/__init__.py index a494e874c..2e4b28ddd 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/__init__.py @@ -837,5 +837,4 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare): return sql -SchemaDiffRegistry(blueprint.node_type, PackageView) PackageView.register_node_view(blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py index 1f935050e..5a363db3b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py @@ -1607,10 +1607,21 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings, data={'total_rows': count} ) - def get_delete_sql(self, res): - self.cmd = 'delete' - sql = super(TableView, self).get_delete_sql(res) - self.cmd = None + @BaseTableView.check_precondition + def get_drop_sql(self, sid, did, scid, tid): + SQL = render_template("/".join( + [self.table_template_path, 'properties.sql']), + did=did, scid=scid, tid=tid, + datlastsysoid=self.datlastsysoid + ) + status, res = self.conn.execute_dict(SQL) + sql = '' + + if status: + self.cmd = 'delete' + sql = super(TableView, self).get_delete_sql(res) + self.cmd = None + return sql @BaseTableView.check_precondition diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/utils.py index c1f274a14..77a163f97 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/utils.py @@ -101,6 +101,7 @@ def get_check_constraint_sql(conn, tid, data, template_path=None): if 'deleted' in constraint: for c in constraint['deleted']: c['schema'] = data['schema'] + c['nspname'] = data['schema'] c['table'] = data['name'] # Sql for drop diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/utils.py index d90771c05..1aec295a6 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/utils.py @@ -137,14 +137,22 @@ def get_index_constraint_sql(conn, did, tid, data, template_path=None): # If constraint(s) is/are deleted if 'deleted' in constraint: for c in constraint['deleted']: - c['schema'] = data['schema'] - c['table'] = data['name'] + del_cols = [] + if 'columns_to_be_dropped' in data: + del_cols = list(map(lambda x, y: x['column'] in y, + c['columns'], + data['columns_to_be_dropped']) + ) - # Sql for drop - sql.append(render_template("/".join([template_path, - 'delete.sql']), - data=c, - conn=conn).strip('\n')) + if len(del_cols) == 0: + c['schema'] = data['schema'] + c['table'] = data['name'] + + # Sql for drop + sql.append(render_template("/".join([template_path, + 'delete.sql']), + data=c, + conn=conn).strip('\n')) if 'changed' in constraint: for c in constraint['changed']: c['schema'] = data['schema'] diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py index 2a6743d73..81e539025 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py @@ -834,23 +834,35 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): schema = '' if data: schema = self.schema + + data['schema'] = self.schema + data['nspname'] = self.schema + data['table'] = self.table + + sql, name = index_utils.get_sql( + self.conn, data, did, tid, idx, self.datlastsysoid, + mode='create') + + sql = sql.strip('\n').strip(' ') + elif diff_schema: schema = diff_schema - sql = index_utils.get_reverse_engineered_sql( - self.conn, schema, - self.table, did, tid, idx, - self.datlastsysoid, - template_path=None, with_header=False) + sql = index_utils.get_reverse_engineered_sql( + self.conn, schema, + self.table, did, tid, idx, + self.datlastsysoid, + template_path=None, with_header=False) drop_sql = '' if drop_req: - drop_sql = '\n' + render_template( - "/".join([self.template_path, 'delete.sql']), - data=data, conn=self.conn - ) + drop_sql = '\n' + self.delete(gid=1, sid=sid, did=did, + scid=scid, tid=tid, + idx=idx, only_sql=True) - return drop_sql + '\n\n' + sql + if drop_sql != '': + sql = drop_sql + '\n\n' + sql + return sql @check_precondition def dependents(self, gid, sid, did, scid, tid, idx): @@ -1077,14 +1089,24 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): for key in required_create_keys: if key in diff_dict: - create_req = True + if key == 'columns' and (( + 'added' in diff_dict[key] and + len(diff_dict[key]['added']) > 0 + ) or ('changed' in diff_dict[key] and + len(diff_dict[key]['changed']) > 0) or ( + 'deleted' in diff_dict[key] and + len(diff_dict[key]['deleted']) > 0) + ): + create_req = True + elif key != 'columns': + create_req = True if create_req: - diff = self.get_sql_from_index_diff(sid=src_sid, - did=src_did, - scid=src_scid, - tid=src_tid, - idx=src_oid, + diff = self.get_sql_from_index_diff(sid=tar_sid, + did=tar_did, + scid=tar_scid, + tid=tar_tid, + idx=tar_oid, diff_schema=target_schema, drop_req=True) else: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/schema_diff_utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/schema_diff_utils.py index 5fcfee3a0..7c3f5e89e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/schema_diff_utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/schema_diff_utils.py @@ -32,6 +32,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): 'columns', 'edit_types', 'primary_key', + 'unique_constraint', 'exclude_constraint', 'check_constraint', 'foreign_key', @@ -188,15 +189,9 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): scid=tar_scid, tid=tar_oid, json_resp=False) - SQL = render_template( - "/".join([self.table_template_path, 'properties.sql']), - did=tar_did, scid=tar_scid, tid=tar_oid, - datlastsysoid=self.datlastsysoid - ) - status, res = self.conn.execute_dict(SQL) - if status: - diff = self.get_delete_sql(res) + diff = self.get_drop_sql(sid=tar_sid, did=tar_did, + scid=tar_scid, tid=tar_oid) elif comp_status == SchemaDiffModel.COMPARISON_STATUS['different']: source = self.fetch_tables( @@ -230,10 +225,10 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): diff_dict.update(col_diff) # Constraint comparison - pk_diff = self.constraint_ddl_comp(source, target) + pk_diff = self.constraint_ddl_comp(source, target, diff_dict) diff_dict.update(pk_diff) - diff_dict['relacl'] = self.parce_acl(source, target) + diff_dict.update(self.parce_acl(source, target)) if not generate_script: source = self.get_sql_from_table_diff(sid=src_sid, @@ -308,7 +303,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): ) if child_diff: - diff += child_diff + diff += '\n' + child_diff elif result: # For partition module identical = False @@ -348,7 +343,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): comp_status=res['status'] ) - if ddl_compare: + if child_diff: diff += child_diff else: diff = self.get_sql_from_table_diff( @@ -418,7 +413,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): return different @staticmethod - def constraint_ddl_comp(source_table, target_table): + def constraint_ddl_comp(source_table, target_table, diff_dict): """ Table Constraint DDL comparison :param source: Source Table @@ -427,19 +422,26 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): """ different = {} non_editable_keys = {} + columns_to_be_dropped = [] non_editable_keys = {'primary_key': ['col_count', 'condeferrable', 'condeffered', 'columns'], + 'unique_constraint': ['col_count', + 'condeferrable', + 'condeffered', + 'columns'], 'check_constraint': ['consrc'], 'exclude_constraint': ['amname', 'indconstraint', - 'columns'] + 'columns'], + 'foreign_key': [] } - for constraint in ['primary_key', 'check_constraint', - 'exclude_constraint']: + for constraint in ['primary_key', 'unique_constraint', + 'check_constraint', + 'exclude_constraint', 'foreign_key']: source_cols = source_table[constraint] if \ constraint in source_table else [] target_cols = copy.deepcopy(target_table[constraint]) if\ @@ -472,7 +474,7 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): tmp_updated = None break if tmp_updated: - tmp_updated['oid'] = tmp_tar['oid'] + tmp_updated['oid'] = tmp['oid'] updated.append(tmp_updated) target_cols.remove(tmp) elif tmp_tar and tmp_src == tmp_tar: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/10_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/10_plus/update.sql index 4e8b982fd..997f3c36e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/10_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/10_plus/update.sql @@ -91,7 +91,7 @@ PLAIN{% elif data.attstorage == 'm'%}MAIN{% elif data.attstorage == 'e'%} EXTERNAL{% elif data.attstorage == 'x'%}EXTENDED{% endif %}; {% endif %} -{% if data.description is defined %} +{% if data.description is defined and data.description != None %} {% if data.name %} COMMENT ON COLUMN {{conn|qtIdent(data.schema, data.table, data.name)}} {% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/update.sql index 85a6519c1..2e401d9dc 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/update.sql @@ -9,7 +9,7 @@ ALTER INDEX {{conn|qtIdent(data.schema, o_data.name)}} ALTER INDEX {{conn|qtIdent(data.schema, data.name)}} SET (FILLFACTOR={{data.fillfactor}}); -{% elif data.fillfactor == '' and o_data.fillfactor|default('', 'true') != data.fillfactor %} +{% elif (data.fillfactor == '' or data.fillfactor == None) and o_data.fillfactor|default('', 'true') != data.fillfactor %} ALTER INDEX {{conn|qtIdent(data.schema, data.name)}} RESET (FILLFACTOR); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py index 9d841e5ca..4a91ab101 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py @@ -883,7 +883,8 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): old_col_data['cltype']) # Sql for alter column - if 'inheritedfrom' not in c: + if 'inheritedfrom' not in c and\ + 'inheritedfromtable' not in c: column_sql += render_template("/".join( [self.column_template_path, 'update.sql']), data=c, o_data=old_col_data, conn=self.conn @@ -897,7 +898,8 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): c = column_utils.convert_length_precision_to_string(c) - if 'inheritedfrom' not in c: + if 'inheritedfrom' not in c and\ + 'inheritedfromtable' not in c: column_sql += render_template("/".join( [self.column_template_path, 'create.sql']), data=c, conn=self.conn).strip('\n') + '\n\n' @@ -950,6 +952,11 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): # Combine all the SQL together SQL += '\n' + partitions_sql.strip('\n') + data['columns_to_be_dropped'] = [] + if 'columns' in data and 'deleted' in data['columns']: + data['columns_to_be_dropped'] = list(map( + lambda d: d['name'], data['columns']['deleted'])) + # Check if index constraints are added/changed/deleted index_constraint_sql = \ idxcons_utils.get_index_constraint_sql( @@ -1501,11 +1508,12 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): for data_row in data[vacuum_key]['changed']: for old_data_row in old_data[vacuum_key]: if data_row['name'] == old_data_row['name']: - if data_row['value'] is not None: - set_values.append(data_row) - elif data_row['value'] is None and \ - 'value' in old_data_row: - reset_values.append(data_row) + if 'value' in data_row: + if data_row['value'] is not None: + set_values.append(data_row) + elif data_row['value'] is None and \ + 'value' in old_data_row: + reset_values.append(data_row) if len(set_values) > 0: data[vacuum_key]['set_values'] = set_values diff --git a/web/pgadmin/tools/schema_diff/__init__.py b/web/pgadmin/tools/schema_diff/__init__.py index 1439d9c57..13956a50b 100644 --- a/web/pgadmin/tools/schema_diff/__init__.py +++ b/web/pgadmin/tools/schema_diff/__init__.py @@ -399,8 +399,11 @@ def compare(trans_id, source_sid, source_did, source_scid, if error_msg == gettext('Transaction ID not found in the session.'): return make_json_response(success=0, errormsg=error_msg, status=404) - if not check_version_compatibility(source_sid, target_sid): - return not_implemented(errormsg=gettext("Version mismatch.")) + # Server version compatibility check + status, msg = check_version_compatibility(source_sid, target_sid) + + if not status: + return make_json_response(success=0, errormsg=msg, status=404) comparison_result = [] @@ -584,18 +587,24 @@ def check_version_compatibility(sid, tid): driver = get_driver(PG_DEFAULT_DRIVER) src_server = Server.query.filter_by(id=sid).first() src_manager = driver.connection_manager(src_server.id) + src_conn = src_manager.connection() tar_server = Server.query.filter_by(id=tid).first() tar_manager = driver.connection_manager(tar_server.id) + tar_conn = tar_manager.connection() + + if not (src_conn.connected() or src_conn.connected()): + return False, gettext('Server(s) disconnected.') def get_round_val(x): if x < 10000: return x if x % 100 == 0 else x + 100 - x % 100 else: - return x if x % 10000 == 0 else x + 10000 - x % 10000 + return x + 10000 - x % 10000 if get_round_val(src_manager.version) == \ get_round_val(tar_manager.version): - return True + return True, None - return False + return False, gettext('Source and Target database server must be of ' + 'the same major version.') diff --git a/web/pgadmin/tools/schema_diff/directory_compare.py b/web/pgadmin/tools/schema_diff/directory_compare.py index d99368686..a7543a789 100644 --- a/web/pgadmin/tools/schema_diff/directory_compare.py +++ b/web/pgadmin/tools/schema_diff/directory_compare.py @@ -220,46 +220,54 @@ def directory_diff(source_dict, target_dict, ignore_keys=[], difference={}): ignore_keys, difference) elif type(source_dict[key]) is list: tmp_target = None - for index in range(len(source_dict[key])): - source = copy.deepcopy(source_dict[key][index]) - if type(source) is list: - # TODO - pass - elif type(source) is dict: - if 'name' in source or 'colname' in source: - if type(target_dict[key]) is list and len( - target_dict[key]) > 0: - tmp = None - tmp_target = copy.deepcopy(target_dict[key]) - for item in tmp_target: - if ( - 'name' in item and - item['name'] == source['name'] - ) or ( - 'colname' in item and - item['colname'] == source['colname'] - ): - tmp = copy.deepcopy(item) - if tmp and source != tmp: - updated.append(copy.deepcopy(source)) - tmp_target.remove(tmp) - elif tmp and source == tmp: - tmp_target.remove(tmp) - elif tmp is None: + tmp_list = list(filter( + lambda x: type(x) == list or type(x) == dict, source_dict[key] + )) + + if len(tmp_list) > 0: + for index in range(len(source_dict[key])): + source = copy.deepcopy(source_dict[key][index]) + if type(source) is list: + # TODO + pass + elif type(source) is dict: + if 'name' in source or 'colname' in source: + if type(target_dict[key]) is list and len( + target_dict[key]) > 0: + tmp = None + tmp_target = copy.deepcopy(target_dict[key]) + for item in tmp_target: + if ( + 'name' in item and + item['name'] == source['name'] + ) or ( + 'colname' in item and + item['colname'] == source[ + 'colname'] + ): + tmp = copy.deepcopy(item) + if tmp and source != tmp: + updated.append(copy.deepcopy(source)) + tmp_target.remove(tmp) + elif tmp and source == tmp: + tmp_target.remove(tmp) + elif tmp is None: + added.append(source) + else: added.append(source) - else: - added.append(source) - difference[key] = {} - difference[key]['added'] = added - difference[key]['changed'] = updated - elif target_dict[key] is None or \ - (type(target_dict[key]) is list and - len(target_dict[key]) < index and - source != target_dict[key][index]): - difference[key] = source - elif type(target_dict[key]) is list and\ - len(target_dict[key]) > index: - difference[key] = source + difference[key] = {} + difference[key]['added'] = added + difference[key]['changed'] = updated + elif target_dict[key] is None or \ + (type(target_dict[key]) is list and + len(target_dict[key]) < index and + source != target_dict[key][index]): + difference[key] = source + elif type(target_dict[key]) is list and\ + len(target_dict[key]) > index: + difference[key] = source + else: + target_dict[key] = source_dict[key] if type(source) is dict and tmp_target and key in tmp_target and \ tmp_target[key] and len(tmp_target[key]) > 0: diff --git a/web/pgadmin/tools/schema_diff/static/css/schema_diff.css b/web/pgadmin/tools/schema_diff/static/css/schema_diff.css index 98525bc2f..0d90f8674 100644 --- a/web/pgadmin/tools/schema_diff/static/css/schema_diff.css +++ b/web/pgadmin/tools/schema_diff/static/css/schema_diff.css @@ -50,7 +50,7 @@ padding: 5px 5px !important; } -.slick-header-column.ui-state-default { +#schema-diff-grid .slick-header-column.ui-state-default { height: 32px !important; line-height: 25px !important; } diff --git a/web/pgadmin/tools/schema_diff/static/js/schema_diff.backform.js b/web/pgadmin/tools/schema_diff/static/js/schema_diff.backform.js index 09e360aa8..39f0c2f47 100644 --- a/web/pgadmin/tools/schema_diff/static/js/schema_diff.backform.js +++ b/web/pgadmin/tools/schema_diff/static/js/schema_diff.backform.js @@ -69,6 +69,13 @@ let SchemaDiffSqlControl = copyData() { event.stopPropagation(); clipboard.copyTextToClipboard(this.model.get('diff_ddl')); + this.$el.find('.ddl-copy').text(gettext('Copied!')); + var self = this; + setTimeout(function() { + let $copy = self.$el.find('.ddl-copy'); + if (!$copy.hasClass('d-none')) $copy.addClass('d-none'); + $copy.text(gettext('Copy')); + }, 3000); return false; }, onFocus: function() { @@ -78,14 +85,6 @@ let SchemaDiffSqlControl = if ($copy.hasClass('d-none')) $copy.removeClass('d-none'); }, - onBlur: function() { - let $copy = this.$el.find('.ddl-copy'); - if (!$(event.relatedTarget).hasClass('ddl-copy')) { - if (!$copy.hasClass('d-none')) $copy.addClass('d-none'); - this.$el.find('.pgadmin-controls').first().removeClass('focused'); - } - }, - }); let SchemaDiffSelect2Control = @@ -302,7 +301,8 @@ let SchemaDiffHeaderView = Backform.Form.extend({