From 44c0d765415731172b9bfdc8f93c6854d2153b91 Mon Sep 17 00:00:00 2001 From: Akshay Joshi Date: Sun, 15 Mar 2020 14:51:16 +0530 Subject: [PATCH] Improve logic to get the DDL statements as a part of the comparison. Fixes #5221 Fixed 23 issues related to schema diff. --- docs/en_US/release_notes_4_20.rst | 3 +- .../databases/schemas/functions/__init__.py | 23 +- .../functions/gpdb/sql/default/update.sql | 3 +- .../functions/pg/sql/11_plus/update.sql | 5 +- .../functions/pg/sql/12_plus/update.sql | 5 +- .../functions/pg/sql/9.2_plus/update.sql | 5 +- .../functions/pg/sql/9.5_plus/update.sql | 5 +- .../functions/pg/sql/9.6_plus/update.sql | 5 +- .../functions/pg/sql/default/update.sql | 5 +- .../functions/ppas/sql/12_plus/update.sql | 5 +- .../functions/ppas/sql/9.2_plus/update.sql | 5 +- .../functions/ppas/sql/9.5_plus/update.sql | 5 +- .../functions/ppas/sql/9.6_plus/update.sql | 5 +- .../functions/ppas/sql/default/update.sql | 5 +- .../databases/schemas/tables/__init__.py | 51 +- .../tables/compound_triggers/__init__.py | 59 ++- .../tables/constraints/foreign_key/utils.py | 4 +- .../schemas/tables/indexes/__init__.py | 101 ++-- .../schemas/tables/partitions/__init__.py | 159 +++--- .../schemas/tables/rules/__init__.py | 74 ++- .../schemas/tables/schema_diff_utils.py | 496 ++++++------------ .../templates/columns/sql/10_plus/update.sql | 4 +- .../templates/columns/sql/9.2_plus/update.sql | 9 +- .../templates/columns/sql/default/update.sql | 2 +- .../sql/pg/10_plus/partition_diff.sql | 22 + .../sql/pg/11_plus/partition_diff.sql | 24 + .../sql/ppas/10_plus/partition_diff.sql | 22 + .../sql/ppas/11_plus/partition_diff.sql | 24 + .../tables/sql/10_plus/schema_diff.sql | 14 - .../templates/tables/sql/12_plus/update.sql | 2 +- .../templates/tables/sql/default/update.sql | 2 +- .../triggers/sql/pg/default/update.sql | 26 +- .../triggers/sql/ppas/default/update.sql | 27 +- .../schemas/tables/triggers/__init__.py | 60 ++- .../schemas/tables/triggers/utils.py | 35 +- .../servers/databases/schemas/tables/utils.py | 14 +- .../mviews/pg/9.4_plus/sql/update.sql | 4 +- .../mviews/ppas/9.3_plus/sql/update.sql | 11 +- .../views/pg/9.4_plus/sql/update.sql | 2 + .../views/ppas/9.4_plus/sql/update.sql | 2 + .../alter_view_add_some_priv_msql.sql | 4 + .../pg/9.4_plus/alter_view_definition.sql | 5 +- .../9.4_plus/alter_view_definition_msql.sql | 1 - .../alter_view_add_some_priv_msql.sql | 4 + .../ppas/9.4_plus/alter_view_definition.sql | 5 +- .../9.4_plus/alter_view_definition_msql.sql | 1 - web/pgadmin/tools/schema_diff/__init__.py | 62 +-- web/pgadmin/tools/schema_diff/compare.py | 117 +---- .../tools/schema_diff/directory_compare.py | 208 ++++++-- .../static/js/schema_diff.backform.js | 2 + .../schema_diff/static/js/schema_diff_ui.js | 115 ++-- .../tests/test_schema_diff_comp.py | 14 +- 52 files changed, 951 insertions(+), 921 deletions(-) create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/pg/10_plus/partition_diff.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/pg/11_plus/partition_diff.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/ppas/10_plus/partition_diff.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/ppas/11_plus/partition_diff.sql delete mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/10_plus/schema_diff.sql diff --git a/docs/en_US/release_notes_4_20.rst b/docs/en_US/release_notes_4_20.rst index 0d4dcd4bf..be1a58c0d 100644 --- a/docs/en_US/release_notes_4_20.rst +++ b/docs/en_US/release_notes_4_20.rst @@ -19,4 +19,5 @@ Bug fixes | `Issue #4237 `_ - Fix an issue where the user can not change the value of DateTime picker control using keyboard. | `Issue #4942 `_ - Fixed chrome driver download utility issue for Ubuntu. -| `Issue #5143 `_ - Fix an accessibility issue to maximize the panel for all alertify dialog. \ No newline at end of file +| `Issue #5143 `_ - Fix an accessibility issue to maximize the panel for all alertify dialog. +| `Issue #5221 `_ - Improve logic to get the DDL statements as a part of the comparison. \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py index a623351a5..c5864ab23 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py @@ -220,7 +220,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): }) keys_to_ignore = ['oid', 'proowner', 'typnsp', 'xmin', 'prokind', - 'proisagg', 'pronamespace', 'proargdefaults'] + 'proisagg', 'pronamespace', 'proargdefaults', + 'prorettype', 'proallargtypes', 'proacl'] @property def required_args(self): @@ -1125,7 +1126,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): SQL = re.sub('\n{2,}', '\n\n', SQL) return SQL - def _get_sql(self, gid, sid, did, scid, data, fnid=None, is_sql=False): + def _get_sql(self, gid, sid, did, scid, data, fnid=None, is_sql=False, + is_schema_diff=False): """ Generates the SQL statements to create/update the Function. @@ -1239,8 +1241,11 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): for v in data['variables']['added']: chngd_variables[v['name']] = v['value'] - for v in old_data['variables']: - old_data['chngd_variables'][v['name']] = v['value'] + # In case of schema diff we don't want variables from + # old data + if not is_schema_diff: + for v in old_data['variables']: + old_data['chngd_variables'][v['name']] = v['value'] # Prepare final dict of new and old variables for name, val in old_data['chngd_variables'].items(): @@ -1624,7 +1629,15 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): if data: if diff_schema: data['schema'] = diff_schema - status, sql = self._get_sql(gid, sid, did, scid, data, oid) + status, sql = self._get_sql(gid, sid, did, scid, data, oid, False, + True) + # Check if return type is changed then we need to drop the + # function first and then recreate it. + drop_fun_sql = '' + if 'prorettypename' in data: + drop_fun_sql = self.delete(gid=gid, sid=sid, did=did, + scid=scid, fnid=oid, only_sql=True) + sql = drop_fun_sql + '\n' + sql else: if drop_sql: sql = self.delete(gid=gid, sid=sid, did=did, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/gpdb/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/gpdb/sql/default/update.sql index 04c3a054f..6219ffb76 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/gpdb/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/gpdb/sql/default/update.sql @@ -18,7 +18,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} 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 2d74a444c..5e8d357d7 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 @@ -19,7 +19,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -31,7 +32,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if 'proparallel' in data and data.proparallel %}PARALLEL {{ data.proparallel }}{% elif 'proparallel' not in data and o_data.proparallel %}PARALLEL {{ o_data.proparallel }}{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0'%} ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} 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 c98907c0e..6b5772851 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 @@ -19,7 +19,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -31,7 +32,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if 'proparallel' in data and data.proparallel %}PARALLEL {{ data.proparallel }}{% elif 'proparallel' not in data and o_data.proparallel %}PARALLEL {{ o_data.proparallel }}{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %} ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}} {%endif %} 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 aa8e05076..8c18299b4 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 @@ -18,7 +18,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -28,7 +29,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} {% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %} ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} 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 5c95464cd..963a7f3be 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 @@ -19,7 +19,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -29,7 +30,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} {% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %} ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} 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 2d74a444c..1917283f9 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 @@ -19,7 +19,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -31,7 +32,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if 'proparallel' in data and data.proparallel %}PARALLEL {{ data.proparallel }}{% elif 'proparallel' not in data and o_data.proparallel %}PARALLEL {{ o_data.proparallel }}{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %} ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} 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 b6e9d304b..aad4b6612 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 @@ -18,7 +18,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -27,7 +28,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} {% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %} ROWS {{data.prorows}}{% elif o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}}{%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} 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 c98907c0e..6b5772851 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 @@ -19,7 +19,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -31,7 +32,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if 'proparallel' in data and data.proparallel %}PARALLEL {{ data.proparallel }}{% elif 'proparallel' not in data and o_data.proparallel %}PARALLEL {{ o_data.proparallel }}{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %} ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}} {%endif %} 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 1b54540f3..c9c76b82d 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 @@ -18,7 +18,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -28,7 +29,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} {% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %} ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} 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 5c95464cd..963a7f3be 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 @@ -19,7 +19,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -29,7 +30,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} {% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %} ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} 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 2d74a444c..1917283f9 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 @@ -19,7 +19,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -31,7 +32,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if 'proparallel' in data and data.proparallel %}PARALLEL {{ data.proparallel }}{% elif 'proparallel' not in data and o_data.proparallel %}PARALLEL {{ o_data.proparallel }}{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %} ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} 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 c9a4fb071..2564b5d5b 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 @@ -18,7 +18,8 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% endfor %} {% endif -%} ) - RETURNS {{ o_data.prorettypename }} + RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %} + {% if 'lanname' in data %} LANGUAGE {{ data.lanname|qtLiteral }} {% else %} LANGUAGE {{ o_data.lanname|qtLiteral }} @@ -27,7 +28,7 @@ CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if d {% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} {% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} - {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %} ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} ROWS {{o_data.prorows}}{%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} 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 5a363db3b..25797a520 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 @@ -11,8 +11,6 @@ import simplejson as json import re -import copy -import random import pgadmin.browser.server_groups.servers.databases as database from flask import render_template, request, jsonify, url_for, current_app @@ -25,11 +23,6 @@ from pgadmin.utils.ajax import make_json_response, internal_server_error, \ from .utils import BaseTableView from pgadmin.utils.preferences import Preferences from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry -from pgadmin.tools.schema_diff.directory_compare import compare_dictionaries,\ - directory_diff -from pgadmin.tools.schema_diff.model import SchemaDiffModel -from pgadmin.utils.driver import get_driver -from config import PG_DEFAULT_DRIVER from pgadmin.browser.server_groups.servers.databases.schemas.tables.\ constraints.foreign_key import utils as fkey_utils from .schema_diff_utils import SchemaDiffTableCompare @@ -1212,8 +1205,6 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings, json_resp = kwargs['json_resp'] if 'json_resp' in kwargs else True diff_schema = kwargs['diff_schema'] if 'diff_schema' in kwargs else\ None - schema_diff_table = kwargs['schema_diff_table'] if\ - 'schema_diff_table' in kwargs else None if diff_data: return self._fetch_sql(did, scid, tid, diff_data, json_resp) @@ -1239,24 +1230,8 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings, if diff_schema: data['schema'] = diff_schema - if schema_diff_table: - data['orig_name'] = data['name'] - data['name'] = 'schema_diff_temp_{0}'.format( - random.randint(1, 9999999)) - - sql, partition_sql = BaseTableView.get_reverse_engineered_sql( - self, did, scid, tid, main_sql, data, json_resp, - diff_partition_sql=True) - else: - sql, partition_sql = BaseTableView.get_reverse_engineered_sql( - self, did, scid, tid, main_sql, data, json_resp) - - if schema_diff_table: - # If partition tables have different partitions - sql += render_template( - "/".join([self.table_template_path, 'schema_diff.sql']), - conn=self.conn, data=data, partition_sql=partition_sql - ) + sql, partition_sql = BaseTableView.get_reverse_engineered_sql( + self, did, scid, tid, main_sql, data, json_resp) return sql @@ -1625,7 +1600,7 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings, return sql @BaseTableView.check_precondition - def fetch_tables(self, sid, did, scid, tid=None, keys_to_remove=None): + def fetch_tables(self, sid, did, scid, tid=None): """ This function will fetch the list of all the tables and will be used by schema diff. @@ -1634,9 +1609,13 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings, :param did: Database Id :param scid: Schema Id :param tid: Table Id - :param keys_to_remove: Table columns to be removed from the dataset :return: Table dataset """ + sub_modules = ['index', 'rule', 'trigger'] + if self.manager.server_type == 'ppas' and \ + self.manager.version >= 120000: + sub_modules.append('compound_trigger') + if tid: status, data = self._fetch_properties(did, scid, tid) @@ -1647,7 +1626,7 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings, data = super(TableView, self).properties( 0, sid, did, scid, tid, data, False ) - self.remove_keys_for_comparision(data, keys_to_remove) + return data else: @@ -1667,7 +1646,17 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings, 0, sid, did, scid, row['oid'], data, False ) - self.remove_keys_for_comparision(data, keys_to_remove) + # Get sub module data of a specified table for object + # comparison + for module in sub_modules: + module_view = SchemaDiffRegistry.get_node_view(module) + if module_view.blueprint.server_type is None or \ + self.manager.server_type in \ + module_view.blueprint.server_type: + sub_data = module_view.fetch_objects_to_compare( + sid=sid, did=did, scid=scid, tid=row['oid'], + oid=None) + data[module] = sub_data res[row['name']] = data return res diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/__init__.py index d096288ba..b6c724b21 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/__init__.py @@ -29,6 +29,8 @@ from pgadmin.utils import IS_PY2 from pgadmin.utils.compile_template_name import compile_template_path from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare +from pgadmin.tools.schema_diff.directory_compare import directory_diff,\ + parce_acl # If we are in Python3 @@ -938,8 +940,7 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare): return SQL @check_precondition - def fetch_objects_to_compare(self, sid, did, scid, tid, oid=None, - ignore_keys=False): + def fetch_objects_to_compare(self, sid, did, scid, tid, oid=None): """ This function will fetch the list of all the triggers for specified schema id. @@ -969,14 +970,60 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare): for row in triggers['rows']: status, data = self._fetch_properties(tid, row['oid']) if status: - if ignore_keys: - for key in self.keys_to_ignore: - if key in data: - del data[key] res[row['name']] = data return res + def ddl_compare(self, **kwargs): + """ + This function returns the DDL/DML statements based on the + comparison status. + + :param kwargs: + :return: + """ + + src_params = kwargs.get('source_params') + tgt_params = kwargs.get('target_params') + source = kwargs.get('source') + target = kwargs.get('target') + target_schema = kwargs.get('target_schema') + comp_status = kwargs.get('comp_status') + + diff = '' + if comp_status == 'source_only': + diff = self.get_sql_from_diff(gid=src_params['gid'], + sid=src_params['sid'], + did=src_params['did'], + scid=src_params['scid'], + tid=src_params['tid'], + oid=source['oid'], + diff_schema=target_schema) + elif comp_status == 'target_only': + diff = self.get_sql_from_diff(gid=tgt_params['gid'], + sid=tgt_params['sid'], + did=tgt_params['did'], + scid=tgt_params['scid'], + tid=tgt_params['tid'], + oid=target['oid'], + drop_sql=True) + elif comp_status == 'different': + diff_dict = directory_diff( + source, target, + ignore_keys=self.keys_to_ignore, difference={} + ) + diff_dict.update(parce_acl(source, target)) + + diff = self.get_sql_from_diff(gid=tgt_params['gid'], + sid=tgt_params['sid'], + did=tgt_params['did'], + scid=tgt_params['scid'], + tid=tgt_params['tid'], + oid=target['oid'], + data=diff_dict) + + return diff + SchemaDiffRegistry(blueprint.node_type, CompoundTriggerView, 'table') CompoundTriggerView.register_node_view(blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/utils.py index 15b1e2dce..027f39dc1 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/utils.py @@ -82,10 +82,10 @@ def get_foreign_keys(conn, tid, fkid=None, template_path=None): coveringindex = search_coveringindex(conn, tid, cols) fk['coveringindex'] = coveringindex if coveringindex: - fk['autoindex'] = True + fk['autoindex'] = False fk['hasindex'] = True else: - fk['autoindex'] = False + fk['autoindex'] = True fk['hasindex'] = False return True, result['rows'] 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 81e539025..5ec8ec444 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 @@ -26,9 +26,7 @@ from pgadmin.utils.driver import get_driver from config import PG_DEFAULT_DRIVER from pgadmin.utils import IS_PY2 from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry -from pgadmin.tools.schema_diff.directory_compare import compare_dictionaries,\ - directory_diff -from pgadmin.tools.schema_diff.model import SchemaDiffModel +from pgadmin.tools.schema_diff.directory_compare import directory_diff from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare from pgadmin.browser.server_groups.servers.databases.schemas. \ tables.indexes import utils as index_utils @@ -830,11 +828,8 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): def get_sql_from_index_diff(self, sid, did, scid, tid, idx, data=None, diff_schema=None, drop_req=False): - tmp_idx = idx - schema = '' + sql = '' if data: - schema = self.schema - data['schema'] = self.schema data['nspname'] = self.schema data['table'] = self.table @@ -987,8 +982,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): ) @check_precondition - def fetch_objects_to_compare(self, sid, did, scid, tid, oid=None, - ignore_keys=False): + def fetch_objects_to_compare(self, sid, did, scid, tid, oid=None): """ This function will fetch the list of all the indexes for specified schema id. @@ -996,6 +990,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): :param sid: Server Id :param did: Database Id :param scid: Schema Id + :param oid: Index Id :return: """ @@ -1013,10 +1008,6 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): status, data = self._fetch_properties(did, tid, row['oid']) if status: - if ignore_keys: - for key in self.keys_to_ignore: - if key in data: - del data[key] res[row['name']] = data else: status, data = self._fetch_properties(did, tid, @@ -1030,55 +1021,35 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): def ddl_compare(self, **kwargs): """ - This function will compare index properties and - return the difference of SQL + This function returns the DDL/DML statements based on the + comparison status. + + :param kwargs: + :return: """ - src_sid = kwargs.get('source_sid') - src_did = kwargs.get('source_did') - src_scid = kwargs.get('source_scid') - src_tid = kwargs.get('source_tid') - src_oid = kwargs.get('source_oid') - tar_sid = kwargs.get('target_sid') - tar_did = kwargs.get('target_did') - tar_scid = kwargs.get('target_scid') - tar_tid = kwargs.get('target_tid') - tar_oid = kwargs.get('target_oid') + src_params = kwargs.get('source_params') + tgt_params = kwargs.get('target_params') + source = kwargs.get('source') + target = kwargs.get('target') + target_schema = kwargs.get('target_schema') comp_status = kwargs.get('comp_status') - source = '' - target = '' diff = '' - - status, target_schema = self.get_schema(tar_sid, - tar_did, - tar_scid - ) - if not status: - return internal_server_error(errormsg=target_schema) - - if comp_status == SchemaDiffModel.COMPARISON_STATUS['source_only']: - diff = self.get_sql_from_index_diff(sid=src_sid, - did=src_did, scid=src_scid, - tid=src_tid, idx=src_oid, + if comp_status == 'source_only': + diff = self.get_sql_from_index_diff(sid=src_params['sid'], + did=src_params['did'], + scid=src_params['scid'], + tid=src_params['tid'], + idx=source['oid'], diff_schema=target_schema) + elif comp_status == 'target_only': + diff = self.delete(gid=1, sid=tgt_params['sid'], + did=tgt_params['did'], scid=tgt_params['scid'], + tid=tgt_params['tid'], idx=target['oid'], + only_sql=True) - elif comp_status == SchemaDiffModel.COMPARISON_STATUS['target_only']: - diff = self.delete(gid=1, sid=tar_sid, did=tar_did, - scid=tar_scid, tid=tar_tid, - idx=tar_oid, only_sql=True) - - else: - source = self.fetch_objects_to_compare(sid=src_sid, did=src_did, - scid=src_scid, tid=src_tid, - oid=src_oid) - target = self.fetch_objects_to_compare(sid=tar_sid, did=tar_did, - scid=tar_scid, tid=tar_tid, - oid=tar_oid) - - if not (source or target): - return None - + elif comp_status == 'different': diff_dict = directory_diff( source, target, ignore_keys=self.keys_to_ignore, difference={} @@ -1102,19 +1073,19 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): create_req = True if create_req: - diff = self.get_sql_from_index_diff(sid=tar_sid, - did=tar_did, - scid=tar_scid, - tid=tar_tid, - idx=tar_oid, + diff = self.get_sql_from_index_diff(sid=tgt_params['sid'], + did=tgt_params['did'], + scid=tgt_params['scid'], + tid=tgt_params['tid'], + idx=target['oid'], diff_schema=target_schema, drop_req=True) else: - diff = self.get_sql_from_index_diff(sid=tar_sid, - did=tar_did, - scid=tar_scid, - tid=tar_tid, - idx=tar_oid, + diff = self.get_sql_from_index_diff(sid=tgt_params['sid'], + did=tgt_params['did'], + scid=tgt_params['scid'], + tid=tgt_params['tid'], + idx=target['oid'], data=diff_dict) return diff diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py index 03027a4d4..8aaccf13f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py @@ -10,9 +10,10 @@ """ Implements Partitions Node """ import re +import random import simplejson as json import pgadmin.browser.server_groups.servers.databases.schemas as schema -from flask import render_template, request +from flask import render_template, request, current_app from flask_babelex import gettext from pgadmin.browser.server_groups.servers.databases.schemas.utils \ import DataTypeReader, VacuumSettings @@ -21,13 +22,9 @@ from pgadmin.utils.ajax import internal_server_error, \ from pgadmin.browser.server_groups.servers.databases.schemas.tables.utils \ import BaseTableView from pgadmin.browser.collection import CollectionNodeModule -from pgadmin.utils.ajax import make_json_response, precondition_required -from config import PG_DEFAULT_DRIVER +from pgadmin.utils.ajax import make_json_response from pgadmin.browser.utils import PGChildModule from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry -from pgadmin.tools.schema_diff.directory_compare import compare_dictionaries,\ - directory_diff -from pgadmin.tools.schema_diff.model import SchemaDiffModel from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare @@ -464,58 +461,57 @@ class PartitionsView(BaseTableView, DataTypeReader, VacuumSettings, @BaseTableView.check_precondition def get_sql_from_diff(self, **kwargs): """ - This function will create sql on the basis the difference of 2 tables + This function is used to get the DDL/DML statements for + partitions. + + :param kwargs: + :return: """ - data = dict() - res = None - sid = kwargs['sid'] - did = kwargs['did'] - scid = kwargs['scid'] - tid = kwargs['tid'] - ptid = kwargs['ptid'] - diff_data = kwargs['diff_data'] if 'diff_data' in kwargs else None - json_resp = kwargs['json_resp'] if 'json_resp' in kwargs else True - diff_schema = kwargs['diff_schema'] if 'diff_schema' in kwargs else\ - None - if diff_data: - SQL = render_template("/".join([self.partition_template_path, - 'properties.sql']), - did=did, scid=scid, tid=tid, - ptid=ptid, datlastsysoid=self.datlastsysoid) - status, res = self.conn.execute_dict(SQL) - if not status: - return internal_server_error(errormsg=res) + source_data = kwargs['source_data'] if 'source_data' in kwargs \ + else None + target_data = kwargs['target_data'] if 'target_data' in kwargs \ + else None - SQL, name = self.get_sql(did, scid, ptid, diff_data, res) - SQL = re.sub('\n{2,}', '\n\n', SQL) - SQL = SQL.strip('\n') - return SQL - else: - main_sql = [] + # Store the original name and create a temporary name for + # the partitioned(base) table. + target_data['orig_name'] = target_data['name'] + target_data['name'] = 'temp_partitioned_{0}'.format( + random.randint(1, 9999999)) + # For PG/EPAS 11 and above when we copy the data from original + # table to temporary table for schema diff, we will have to create + # a default partition to prevent the data loss. + target_data['default_partition_name'] = \ + target_data['orig_name'] + '_default' - SQL = render_template("/".join([self.partition_template_path, - 'properties.sql']), - did=did, scid=scid, tid=tid, - ptid=ptid, datlastsysoid=self.datlastsysoid) - status, res = self.conn.execute_dict(SQL) - if not status: - return internal_server_error(errormsg=res) + # Copy the partition scheme from source to target. + if 'partition_scheme' in source_data: + target_data['partition_scheme'] = source_data['partition_scheme'] - if len(res['rows']) == 0: - return gone(gettext( - "The specified partitioned table could not be found.")) + partition_data = dict() + partition_data['name'] = target_data['name'] + partition_data['schema'] = target_data['schema'] + partition_data['partition_type'] = source_data['partition_type'] + partition_data['default_partition_header'] = \ + '-- Create a default partition to prevent the data loss.\n' \ + '-- It helps when none of the partitions of a relation\n' \ + '-- matches the inserted data.' - data = res['rows'][0] + # Create temporary name for partitions + for item in source_data['partitions']: + item['temp_partition_name'] = 'partition_{0}'.format( + random.randint(1, 9999999)) - if diff_schema: - data['schema'] = diff_schema - data['parent_schema'] = diff_schema + partition_data['partitions'] = source_data['partitions'] - return BaseTableView.get_reverse_engineered_sql(self, did, - scid, ptid, - main_sql, data, - False) + partition_sql = self.get_partitions_sql(partition_data, + schema_diff=True) + + return render_template( + "/".join([self.partition_template_path, 'partition_diff.sql']), + conn=self.conn, data=target_data, partition_sql=partition_sql, + partition_data=partition_data + ) @BaseTableView.check_precondition def detach(self, gid, sid, did, scid, tid, ptid): @@ -775,58 +771,25 @@ class PartitionsView(BaseTableView, DataTypeReader, VacuumSettings, def ddl_compare(self, **kwargs): """ - This function will compare index properties and - return the difference of SQL + This function returns the DDL/DML statements based on the + comparison status. + + :param kwargs: + :return: """ - src_sid = kwargs.get('source_sid') - src_did = kwargs.get('source_did') - src_scid = kwargs.get('source_scid') - src_tid = kwargs.get('source_tid') - src_oid = kwargs.get('source_oid') - tar_sid = kwargs.get('target_sid') - tar_did = kwargs.get('target_did') - tar_scid = kwargs.get('target_scid') - tar_tid = kwargs.get('target_tid') - tar_oid = kwargs.get('target_oid') - comp_status = kwargs.get('comp_status') + tgt_params = kwargs.get('target_params') + parent_source_data = kwargs.get('parent_source_data') + parent_target_data = kwargs.get('parent_target_data') - source = '' - target = '' - diff = '' + diff = self.get_sql_from_diff(sid=tgt_params['sid'], + did=tgt_params['did'], + scid=tgt_params['scid'], + tid=tgt_params['tid'], + source_data=parent_source_data, + target_data=parent_target_data) - status, target_schema = self.get_schema_for_schema_diff(tar_sid, - tar_did, - tar_scid - ) - if not status: - return internal_server_error(errormsg=target_schema) - - if comp_status == SchemaDiffModel.COMPARISON_STATUS['source_only']: - diff = self.get_sql_from_diff(sid=src_sid, - did=src_did, scid=src_scid, - tid=src_tid, ptid=src_oid, - diff_schema=target_schema) - - elif comp_status == SchemaDiffModel.COMPARISON_STATUS['target_only']: - SQL = render_template("/".join([self.partition_template_path, - 'properties.sql']), - did=did, scid=scid, tid=tid, - ptid=ptid, datlastsysoid=self.datlastsysoid) - status, res = self.conn.execute_dict(SQL) - - 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: - self.cmd = 'delete' - diff = super(PartitionsView, self).get_delete_sql(res) - self.cmd = None - - return diff + return diff + '\n' SchemaDiffRegistry(blueprint.node_type, PartitionsView, 'table') diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py index 67030bb53..9afb26011 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py @@ -28,6 +28,8 @@ from pgadmin.utils.compile_template_name import compile_template_path from pgadmin.utils import IS_PY2 from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare +from pgadmin.tools.schema_diff.directory_compare import directory_diff,\ + parce_acl # If we are in Python3 if not IS_PY2: @@ -520,7 +522,8 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): @check_precondition def get_sql_from_diff(self, gid, sid, did, scid, tid, oid, data=None, - diff_schema=None, drop_sql=False): + source_schema=None, diff_schema=None, + drop_sql=False): if drop_sql: SQL = self.delete(gid=gid, sid=sid, did=did, @@ -541,6 +544,11 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): SQL = '' if data: + if source_schema: + if 'statements' in data: + # Replace the source schema with the target schema + data['statements'] = data['statements'].replace( + source_schema, diff_schema) old_data = res_data SQL = render_template( "/".join([self.template_path, 'update.sql']), @@ -548,6 +556,11 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): ) else: if diff_schema: + if 'statements' in res_data: + # Replace the source schema with the target schema + res_data['statements'] = \ + res_data['statements'].replace( + res_data['schema'], diff_schema) res_data['schema'] = diff_schema SQL = render_template("/".join( @@ -595,8 +608,7 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): ) @check_precondition - def fetch_objects_to_compare(self, sid, did, scid, tid, oid=None, - ignore_keys=False): + def fetch_objects_to_compare(self, sid, did, scid, tid, oid=None): """ This function will fetch the list of all the rules for specified schema id. @@ -628,13 +640,61 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): for row in rules['rows']: status, data = self._fetch_properties(row['oid']) if status: - if ignore_keys: - for key in self.keys_to_ignore: - if key in data: - del data[key] res[row['name']] = data return res + def ddl_compare(self, **kwargs): + """ + This function returns the DDL/DML statements based on the + comparison status. + + :param kwargs: + :return: + """ + + src_params = kwargs.get('source_params') + tgt_params = kwargs.get('target_params') + source = kwargs.get('source') + target = kwargs.get('target') + target_schema = kwargs.get('target_schema') + comp_status = kwargs.get('comp_status') + + diff = '' + if comp_status == 'source_only': + diff = self.get_sql_from_diff(gid=src_params['gid'], + sid=src_params['sid'], + did=src_params['did'], + scid=src_params['scid'], + tid=src_params['tid'], + oid=source['oid'], + diff_schema=target_schema) + elif comp_status == 'target_only': + diff = self.get_sql_from_diff(gid=tgt_params['gid'], + sid=tgt_params['sid'], + did=tgt_params['did'], + scid=tgt_params['scid'], + tid=tgt_params['tid'], + oid=target['oid'], + drop_sql=True) + elif comp_status == 'different': + diff_dict = directory_diff( + source, target, + ignore_keys=self.keys_to_ignore, difference={} + ) + diff_dict.update(parce_acl(source, target)) + + diff = self.get_sql_from_diff(gid=tgt_params['gid'], + sid=tgt_params['sid'], + did=tgt_params['did'], + scid=tgt_params['scid'], + tid=tgt_params['tid'], + oid=target['oid'], + source_schema=source['schema'], + diff_schema=target_schema, + data=diff_dict) + + return diff + SchemaDiffRegistry(blueprint.node_type, RuleView, 'table') RuleView.register_node_view(blueprint) 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 560353dcc..70bcfa782 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 @@ -11,365 +11,96 @@ import copy -from pgadmin.utils.driver import get_driver -from config import PG_DEFAULT_DRIVER from pgadmin.utils.ajax import internal_server_error from pgadmin.tools.schema_diff.directory_compare import compare_dictionaries,\ - directory_diff -from pgadmin.tools.schema_diff.model import SchemaDiffModel + are_dictionaries_identical from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry class SchemaDiffTableCompare(SchemaDiffObjectCompare): + table_keys_to_ignore = ['oid', 'schema', 'edit_types', 'attnum', + 'col_type', 'references', 'reltuples', 'oid-2', + 'rows_cnt', 'seqrelid', 'atttypid', 'elemoid', + 'hastoasttable', 'relhassubclass'] - keys_to_ignore = ['oid', 'schema', 'vacuum_table', - 'vacuum_toast', 'edit_types', 'attnum', 'col_type', - 'references', 'reltuples', 'rows_cnt'] + constraint_keys_to_ignore = ['relname', 'nspname', 'parent_tbl', + 'attrelid', 'adrelid', 'fknsp', 'confrelid', + 'references', 'refnsp', 'remote_schema'] - keys_to_ignore_ddl_comp = ['oid', - 'schema', - 'columns', - 'edit_types', - 'primary_key', - 'unique_constraint', - 'exclude_constraint', - 'check_constraint', - 'foreign_key', - 'reltuples', - 'rows_cnt' - ] + trigger_keys_to_ignore = ['xmin', 'tgrelid', 'tgfoid', 'tfunction', + 'tgqual', 'tgconstraint'] + index_keys_to_ignore = ['relowner', 'indrelid'] - keys_to_remove = { - 'columns': ['relname', 'nspname', 'parent_tbl', 'attrelid', 'adrelid'], - 'primary_key': ['oid'], - 'unique_constraint': ['oid'], - 'check_constraint': ['oid', 'nspname'], - 'foreign_key': ['oid', 'fknsp', 'confrelid'], - 'exclude_constraint': ['oid'], - 'partitions': ['oid'], - } - - keys_to_remove_ddl_comp = { - 'columns': ['relname', 'nspname', 'parent_tbl', 'attrelid', 'adrelid'], - 'check_constraint': ['nspname'], - 'foreign_key': ['fknsp', 'confrelid'] - } + keys_to_ignore = table_keys_to_ignore + constraint_keys_to_ignore \ + + trigger_keys_to_ignore + index_keys_to_ignore def compare(self, **kwargs): """ This function is used to compare all the table objects from two different schemas. - :return: Comparison Dictionary + :param kwargs: + :return: """ - src_sid = kwargs.get('source_sid') - src_did = kwargs.get('source_did') - src_scid = kwargs.get('source_scid') - tar_sid = kwargs.get('target_sid') - tar_did = kwargs.get('target_did') - tar_scid = kwargs.get('target_scid') - sub_modules = ['index', 'rule', 'trigger'] + source_params = {'sid': kwargs.get('source_sid'), + 'did': kwargs.get('source_did'), + 'scid': kwargs.get('source_scid')} + target_params = {'sid': kwargs.get('target_sid'), + 'did': kwargs.get('target_did'), + 'scid': kwargs.get('target_scid')} - source_tables = self.fetch_tables(sid=src_sid, did=src_did, - scid=src_scid) + status, target_schema = self.get_schema(**target_params) + if not status: + return internal_server_error(errormsg=target_schema) - target_tables = self.fetch_tables(sid=tar_sid, did=tar_did, - scid=tar_scid) - - if self.manager.version >= 120000: - sub_modules.append('compound_trigger') + source_tables = self.fetch_tables(**source_params) + target_tables = self.fetch_tables(**target_params) # If both the dict have no items then return None. if not (source_tables or target_tables) or ( len(source_tables) <= 0 and len(target_tables) <= 0): return None - src_server_type, tar_server_type = self.get_server_type(src_sid, - tar_sid) - for module in sub_modules: - - module_view = SchemaDiffRegistry.get_node_view( - module) - - # Get sub module data for source tables - if module_view.blueprint.server_type is None or \ - src_server_type in module_view.blueprint.server_type: - for key, val in source_tables.items(): - source = module_view.fetch_objects_to_compare( - sid=src_sid, - did=src_did, - scid=src_scid, - tid=val['oid'], - oid=None, - ignore_keys=True - ) - source_tables[key][module] = source - - # Get sub module data for target tables - if module_view.blueprint.server_type is None or \ - tar_server_type in module_view.blueprint.server_type: - for key, val in target_tables.items(): - target = module_view.fetch_objects_to_compare( - sid=tar_sid, - did=tar_did, - scid=tar_scid, - tid=val['oid'], - oid=None, - ignore_keys=True - ) - target_tables[key][module] = target - - return compare_dictionaries(source_tables, target_tables, + return compare_dictionaries(self, source_params, target_params, + target_schema, source_tables, + target_tables, self.node_type, self.blueprint.COLLECTION_LABEL, self.keys_to_ignore) - @staticmethod - def get_server_type(src_id, tar_id): - """Get server types of source and target servers.""" - driver = get_driver(PG_DEFAULT_DRIVER) - src_manager = driver.connection_manager(src_id) - tar_manager = driver.connection_manager(tar_id) - - return src_manager.server_type, tar_manager.server_type - def ddl_compare(self, **kwargs): """ This function will compare properties of 2 tables and return the source DDL, target DDL and Difference of them. + + :param kwargs: + :return: """ + source_params = {'sid': kwargs.get('source_sid'), + 'did': kwargs.get('source_did'), + 'scid': kwargs.get('source_scid'), + 'tid': kwargs.get('source_oid'), + 'json_resp': False + } - src_sid = kwargs.get('source_sid') - src_did = kwargs.get('source_did') - src_scid = kwargs.get('source_scid') - src_oid = kwargs.get('source_oid') - tar_sid = kwargs.get('target_sid') - tar_did = kwargs.get('target_did') - tar_scid = kwargs.get('target_scid') - tar_oid = kwargs.get('target_oid') - comp_status = kwargs.get('comp_status') - generate_script = False + target_params = {'sid': kwargs.get('target_sid'), + 'did': kwargs.get('target_did'), + 'scid': kwargs.get('target_scid'), + 'tid': kwargs.get('target_oid'), + 'json_resp': False + } - if 'generate_script' in kwargs and kwargs['generate_script']: - generate_script = True - - source = '' - target = '' - diff = '' - ignore_sub_modules = ['column', 'constraints'] - - src_server_type, tar_server_type = self.get_server_type(src_sid, - tar_sid) - - status, target_schema = self.get_schema(tar_sid, - tar_did, - tar_scid - ) - - if not status: - return internal_server_error(errormsg=target_schema) - - if comp_status == SchemaDiffModel.COMPARISON_STATUS['source_only']: - if not generate_script: - source = self.get_sql_from_table_diff(sid=src_sid, - did=src_did, - scid=src_scid, - tid=src_oid, - json_resp=False) - diff = self.get_sql_from_table_diff(sid=src_sid, did=src_did, - scid=src_scid, tid=src_oid, - diff_schema=target_schema, - json_resp=False) - - elif comp_status == SchemaDiffModel.COMPARISON_STATUS['target_only']: - if not generate_script: - target = self.get_sql_from_table_diff(sid=tar_sid, - did=tar_did, - scid=tar_scid, - tid=tar_oid, - json_resp=False) - - 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( - sid=src_sid, did=src_did, - scid=src_scid, tid=src_oid, - keys_to_remove=self.keys_to_remove_ddl_comp - ) - target = self.fetch_tables( - sid=tar_sid, did=tar_did, - scid=tar_scid, tid=tar_oid, - keys_to_remove=self.keys_to_remove_ddl_comp - ) - - if self.manager.version < 100000: - ignore_sub_modules.append('partition') - - if self.manager.version < 120000: - ignore_sub_modules.append('compound_trigger') - - # In case of error return None - if not (source or target): - return None - - diff_dict = directory_diff( - source, target, ignore_keys=self.keys_to_ignore_ddl_comp, - difference={} - ) - - # Column comparison - col_diff = self.table_col_ddl_comp(source, target) - diff_dict.update(col_diff) - - # Constraint comparison - pk_diff = self.constraint_ddl_comp(source, target, diff_dict) - diff_dict.update(pk_diff) - - diff_dict.update(self.parce_acl(source, target)) - - if not generate_script: - source = self.get_sql_from_table_diff(sid=src_sid, - did=src_did, - scid=src_scid, - tid=src_oid, - json_resp=False) - target = self.get_sql_from_table_diff(sid=tar_sid, - did=tar_did, - scid=tar_scid, - tid=tar_oid, - json_resp=False) - diff = self.get_sql_from_table_diff(sid=tar_sid, did=tar_did, - scid=tar_scid, tid=tar_oid, - diff_data=diff_dict, - json_resp=False) - - for module in self.blueprint.submodules: - if module.NODE_TYPE not in ignore_sub_modules: - module_view = SchemaDiffRegistry.get_node_view( - module.NODE_TYPE) - - if module_view.blueprint.server_type and ( - src_server_type not in - module_view.blueprint.server_type and - tar_server_type not in - module_view.blueprint.server_type - ): - continue - - if module_view.blueprint.server_type and ( - (src_server_type in - module_view.blueprint.server_type and - tar_server_type not in - module_view.blueprint.server_type) or ( - src_server_type not in - module_view.blueprint.server_type and - tar_server_type in - module_view.blueprint.server_type) - ): - continue - - result = module_view.compare( - source_sid=src_sid, source_did=src_did, - source_scid=src_scid, source_tid=src_oid, - target_sid=tar_sid, target_did=tar_did, - target_scid=tar_scid, target_tid=tar_oid - ) - if result and module.NODE_TYPE != 'partition': - child_diff = '' - for res in result: - if res['status'] == \ - SchemaDiffModel.COMPARISON_STATUS[ - 'different']: - source_oid = res['source_oid'] - target_oid = res['target_oid'] - else: - source_oid = res['oid'] - target_oid = res['oid'] - - if res['status'] != \ - SchemaDiffModel.COMPARISON_STATUS[ - 'identical']: - child_diff = module_view.ddl_compare( - source_sid=src_sid, source_did=src_did, - source_scid=src_scid, - source_oid=source_oid, - source_tid=src_oid, target_sid=tar_sid, - target_did=tar_did, target_scid=tar_scid, - target_tid=tar_oid, target_oid=target_oid, - comp_status=res['status'] - - ) - if child_diff: - diff += '\n' + child_diff - elif result: - # For partition module - identical = False - source_only = False - target_only = False - different = False - for res in result: - if res['status'] == \ - SchemaDiffModel.COMPARISON_STATUS[ - 'identical']: - identical = True - elif res['status'] == \ - SchemaDiffModel.COMPARISON_STATUS[ - 'source_only']: - source_only = True - elif res['status'] == \ - SchemaDiffModel.COMPARISON_STATUS[ - 'target_only']: - target_only = True - else: - different = True - - if identical: - pass - elif (source_only or target_only) and not different: - for res in result: - source_oid = res['oid'] - target_oid = res['oid'] - - child_diff = module_view.ddl_compare( - source_sid=src_sid, source_did=src_did, - source_scid=src_scid, - source_oid=source_oid, - source_tid=src_oid, target_sid=tar_sid, - target_did=tar_did, target_scid=tar_scid, - target_tid=tar_oid, target_oid=target_oid, - comp_status=res['status'] - - ) - if child_diff: - diff += child_diff - else: - diff = self.get_sql_from_table_diff( - sid=src_sid, - did=src_did, - scid=src_scid, - tid=src_oid, - diff_schema=target_schema, - json_resp=False, - schema_diff_table=True - ) - else: - source = self.get_sql_from_table_diff(sid=src_sid, did=src_did, - scid=src_scid, tid=src_oid, - json_resp=False) - target = self.get_sql_from_table_diff(sid=tar_sid, did=tar_did, - scid=tar_scid, tid=tar_oid, - json_resp=False) + source = self.get_sql_from_table_diff(**source_params) + target = self.get_sql_from_table_diff(**target_params) return {'source_ddl': source, 'target_ddl': target, - 'diff_ddl': diff + 'diff_ddl': '' } @staticmethod - def table_col_ddl_comp(source, target): + def table_col_comp(source, target): """ Table Column comparison :param source: Source columns @@ -413,17 +144,14 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): return different @staticmethod - def constraint_ddl_comp(source_table, target_table, diff_dict): + def table_constraint_comp(source_table, target_table): """ Table Constraint DDL comparison - :param source: Source Table - :param target: Target Table + :param source_table: Source Table + :param target_table: Target Table :return: Difference of constraints """ different = {} - non_editable_keys = {} - columns_to_be_dropped = [] - non_editable_keys = {'primary_key': ['col_count', 'condeferrable', 'condeffered', @@ -456,14 +184,16 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): if type(target_cols) is list and len( target_cols) > 0: tmp_src = copy.deepcopy(source) - tmp_src.pop('oid') + if 'oid' in tmp_src: + tmp_src.pop('oid') tmp_tar = None tmp = None for item in target_cols: if item['name'] == source['name']: tmp_tar = copy.deepcopy(item) tmp = copy.deepcopy(item) - tmp_tar.pop('oid') + if 'oid' in tmp_tar: + tmp_tar.pop('oid') if tmp_tar and tmp_src != tmp_tar: tmp_updated = copy.deepcopy(source) for key in non_editable_keys[constraint]: @@ -474,7 +204,8 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): tmp_updated = None break if tmp_updated: - tmp_updated['oid'] = tmp['oid'] + if 'oid' in tmp: + tmp_updated['oid'] = tmp['oid'] updated.append(tmp_updated) target_cols.remove(tmp) elif tmp_tar and tmp_src == tmp_tar: @@ -492,18 +223,109 @@ class SchemaDiffTableCompare(SchemaDiffObjectCompare): return different - def remove_keys_for_comparision(self, data, keys=None): + def get_sql_from_submodule_diff(self, source_params, target_params, + target_schema, source, target, diff_dict): """ - This function is used to remove specific keys from data + This function returns the DDL/DML statements of the + submodules of table based on the comparison status. + + :param source_params: + :param target_params: + :param target_schema: + :param source: + :param target: + :param diff_dict: + :return: """ + # Get the difference result for source and target columns + col_diff = self.table_col_comp(source, target) + diff_dict.update(col_diff) - keys_to_remove = keys if keys else self.keys_to_remove + # Get the difference result for source and target constraints + pk_diff = self.table_constraint_comp(source, target) + diff_dict.update(pk_diff) - for p_key, p_val in keys_to_remove.items(): - if p_key in data and data[p_key] is not None \ - and len(data[p_key]) > 0: - for item in data[p_key]: - # Remove keys that should not be the part of comparision. - for key in p_val: - if key in item: - item.pop(key) + # Get the difference DDL/DML statements for table + target_params['diff_data'] = diff_dict + diff = self.get_sql_from_table_diff(**target_params) + + ignore_sub_modules = ['column', 'constraints'] + if self.manager.version < 100000: + ignore_sub_modules.append('partition') + if self.manager.server_type == 'pg' or self.manager.version < 120000: + ignore_sub_modules.append('compound_trigger') + + # Iterate through all the sub modules of the table + for module in self.blueprint.submodules: + if module.NODE_TYPE not in ignore_sub_modules: + module_view = \ + SchemaDiffRegistry.get_node_view(module.NODE_TYPE) + + if module.NODE_TYPE == 'partition' and \ + ('is_partitioned' in source and source['is_partitioned'])\ + and ('is_partitioned' in target and + target['is_partitioned']): + target_ddl = module_view.ddl_compare( + target_params=target_params, + parent_source_data=source, + parent_target_data=target + ) + + diff += '\n' + target_ddl + elif module.NODE_TYPE != 'partition': + dict1 = copy.deepcopy(source[module.NODE_TYPE]) + dict2 = copy.deepcopy(target[module.NODE_TYPE]) + + # Find the duplicate keys in both the dictionaries + dict1_keys = set(dict1.keys()) + dict2_keys = set(dict2.keys()) + intersect_keys = dict1_keys.intersection(dict2_keys) + + # Keys that are available in source and missing in target. + added = dict1_keys - dict2_keys + for item in added: + source_ddl = module_view.ddl_compare( + source_params=source_params, + target_params=target_params, + source=dict1[item], + target=None, + target_schema=target_schema, + comp_status='source_only' + ) + + diff += '\n' + source_ddl + + # Keys that are available in target and missing in source. + removed = dict2_keys - dict1_keys + for item in removed: + target_ddl = module_view.ddl_compare( + source_params=source_params, + target_params=target_params, + source=None, + target=dict2[item], + target_schema=target_schema, + comp_status='target_only' + ) + + diff += '\n' + target_ddl + + # Keys that are available in both source and target. + for key in intersect_keys: + # Recursively Compare the two dictionary + if not are_dictionaries_identical( + dict1[key], dict2[key], self.keys_to_ignore): + + diff_ddl = module_view.ddl_compare( + source_params=source_params, + target_params=target_params, + source=dict1[key], + target=dict2[key], + target_schema=target_schema, + comp_status='different', + parent_source_data=source, + parent_target_data=target + ) + + diff += '\n' + diff_ddl + + return diff 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 997f3c36e..6bf17eb33 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 @@ -9,7 +9,7 @@ ALTER TABLE {{conn|qtIdent(data.schema, data.table)}} {% endif %} {### Alter column type and collation ###} -{% if (data.cltype and data.cltype != o_data.cltype) or (data.attlen is defined and data.attlen != o_data.attlen) or (data.attprecision is defined and data.attprecision != o_data.attprecision) or (data.collspcname and data.collspcname != o_data.collspcname)%} +{% if (data.cltype and data.cltype != o_data.cltype) or (data.attlen is defined and data.attlen != o_data.attlen) or (data.attprecision is defined and data.attprecision != o_data.attprecision) or (data.collspcname and data.collspcname != o_data.collspcname) or data.col_type_conversion is defined %} {% if data.col_type_conversion is defined and data.col_type_conversion == False %} -- WARNING: -- The SQL statement below would normally be used to alter the datatype for the {{o_data.name}} column, however, @@ -101,7 +101,7 @@ COMMENT ON COLUMN {{conn|qtIdent(data.schema, data.table, o_data.name)}} {% endif %} {### Update column variables ###} -{% if 'attoptions' in data and data.attoptions and data.attoptions|length > 0 %} +{% if 'attoptions' in data and data.attoptions != None and data.attoptions|length > 0 %} {% set variables = data.attoptions %} {% if 'deleted' in variables and variables.deleted|length > 0 %} ALTER TABLE {{conn|qtIdent(data.schema, data.table)}} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/9.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/9.2_plus/update.sql index dfb7555c1..1d9f79a19 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/9.2_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/9.2_plus/update.sql @@ -6,17 +6,18 @@ {% if data.name and data.name != o_data.name %} ALTER TABLE {{conn|qtIdent(data.schema, data.table)}} RENAME {{conn|qtIdent(o_data.name)}} TO {{conn|qtIdent(data.name)}}; + {% endif %} +{### Alter column type and collation ###} +{% if (data.cltype and data.cltype != o_data.cltype) or (data.attlen is defined and data.attlen != o_data.attlen) or (data.attprecision is defined and data.attprecision != o_data.attprecision) or (data.collspcname and data.collspcname != o_data.collspcname) or data.col_type_conversion is defined %} {% if data.col_type_conversion is defined and data.col_type_conversion == False %} -- WARNING: -- The SQL statement below would normally be used to alter the datatype for the {{o_data.name}} column, however, -- the current datatype cannot be cast to the target datatype so this conversion cannot be made automatically. {% endif %} -{### Alter column type and collation ###} -{% if (data.cltype and data.cltype != o_data.cltype) or (data.attlen is defined and data.attlen != o_data.attlen) or (data.attprecision is defined and data.attprecision != o_data.attprecision) or (data.collspcname and data.collspcname != o_data.collspcname)%} -ALTER TABLE {{conn|qtIdent(data.schema, data.table)}} - ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} TYPE {{ GET_TYPE.UPDATE_TYPE_SQL(conn, data, o_data) }}{% if data.collspcname and data.collspcname != o_data.collspcname %} +{% if data.col_type_conversion is defined and data.col_type_conversion == False %} -- {% endif %}ALTER TABLE {{conn|qtIdent(data.schema, data.table)}} +{% if data.col_type_conversion is defined and data.col_type_conversion == False %} -- {% endif %} ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} TYPE {{ GET_TYPE.UPDATE_TYPE_SQL(conn, data, o_data) }}{% if data.collspcname and data.collspcname != o_data.collspcname %} COLLATE {{data.collspcname}}{% elif o_data.collspcname %} COLLATE {{o_data.collspcname}}{% endif %}; {% endif %} {### Alter column default value ###} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/update.sql index 3c6ae0a91..5d99eb66d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/update.sql @@ -9,7 +9,7 @@ ALTER TABLE {{conn|qtIdent(data.schema, data.table)}} {% endif %} {### Alter column type and collation ###} -{% if (data.cltype and data.cltype != o_data.cltype) or (data.attlen is defined and data.attlen != o_data.attlen) or (data.attprecision is defined and data.attprecision != o_data.attprecision) or (data.collspcname and data.collspcname != o_data.collspcname)%} +{% if (data.cltype and data.cltype != o_data.cltype) or (data.attlen is defined and data.attlen != o_data.attlen) or (data.attprecision is defined and data.attprecision != o_data.attprecision) or (data.collspcname and data.collspcname != o_data.collspcname) or data.col_type_conversion is defined %} {% if data.col_type_conversion is defined and data.col_type_conversion == False %} -- WARNING: -- The SQL statement below would normally be used to alter the datatype for the XXX column, however, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/pg/10_plus/partition_diff.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/pg/10_plus/partition_diff.sql new file mode 100644 index 000000000..fed36f2b7 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/pg/10_plus/partition_diff.sql @@ -0,0 +1,22 @@ +CREATE TABLE {{conn|qtIdent(data.schema, data.name)}} ( + LIKE {{conn|qtIdent(data.schema, data.orig_name)}} INCLUDING ALL +) PARTITION BY {{ data.partition_scheme }}; +{{partition_sql}} +INSERT INTO {{conn|qtIdent(data.schema, data.name)}}( +{% if data.columns and data.columns|length > 0 %} +{% for c in data.columns %} {{c.name}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %}) +SELECT {% if data.columns and data.columns|length > 0 %}{% for c in data.columns %}{{c.name}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %} + FROM {{conn|qtIdent(data.schema, data.orig_name)}}; + +{% if partition_data.partitions and partition_data.partitions|length > 0 %} +{% for part in partition_data.partitions %} +DROP TABLE IF EXISTS {{conn|qtIdent(data.schema, part.partition_name)}}; + +ALTER TABLE {{conn|qtIdent(data.schema, part.temp_partition_name)}} + RENAME TO {{conn|qtIdent(part.partition_name)}}; + +{% endfor %}{% endif %} +DROP TABLE {{conn|qtIdent(data.schema, data.orig_name)}}; + +ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} + RENAME TO {{data.orig_name}}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/pg/11_plus/partition_diff.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/pg/11_plus/partition_diff.sql new file mode 100644 index 000000000..bfc063c0f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/pg/11_plus/partition_diff.sql @@ -0,0 +1,24 @@ +CREATE TABLE {{conn|qtIdent(data.schema, data.name)}} ( + LIKE {{conn|qtIdent(data.schema, data.orig_name)}} INCLUDING ALL +) PARTITION BY {{ data.partition_scheme }}; +{{partition_sql}}{{partition_data.default_partition_header}} +CREATE TABLE IF NOT EXISTS {{conn|qtIdent(data.schema, data.default_partition_name)}} PARTITION OF {{conn|qtIdent(data.schema, data.name)}} DEFAULT; + +INSERT INTO {{conn|qtIdent(data.schema, data.name)}}( +{% if data.columns and data.columns|length > 0 %} +{% for c in data.columns %} {{c.name}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %}) +SELECT {% if data.columns and data.columns|length > 0 %}{% for c in data.columns %}{{c.name}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %} + FROM {{conn|qtIdent(data.schema, data.orig_name)}}; + +{% if partition_data.partitions and partition_data.partitions|length > 0 %} +{% for part in partition_data.partitions %} +DROP TABLE IF EXISTS {{conn|qtIdent(data.schema, part.partition_name)}}; + +ALTER TABLE {{conn|qtIdent(data.schema, part.temp_partition_name)}} + RENAME TO {{conn|qtIdent(part.partition_name)}}; + +{% endfor %}{% endif %} +DROP TABLE {{conn|qtIdent(data.schema, data.orig_name)}}; + +ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} + RENAME TO {{data.orig_name}}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/ppas/10_plus/partition_diff.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/ppas/10_plus/partition_diff.sql new file mode 100644 index 000000000..fed36f2b7 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/ppas/10_plus/partition_diff.sql @@ -0,0 +1,22 @@ +CREATE TABLE {{conn|qtIdent(data.schema, data.name)}} ( + LIKE {{conn|qtIdent(data.schema, data.orig_name)}} INCLUDING ALL +) PARTITION BY {{ data.partition_scheme }}; +{{partition_sql}} +INSERT INTO {{conn|qtIdent(data.schema, data.name)}}( +{% if data.columns and data.columns|length > 0 %} +{% for c in data.columns %} {{c.name}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %}) +SELECT {% if data.columns and data.columns|length > 0 %}{% for c in data.columns %}{{c.name}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %} + FROM {{conn|qtIdent(data.schema, data.orig_name)}}; + +{% if partition_data.partitions and partition_data.partitions|length > 0 %} +{% for part in partition_data.partitions %} +DROP TABLE IF EXISTS {{conn|qtIdent(data.schema, part.partition_name)}}; + +ALTER TABLE {{conn|qtIdent(data.schema, part.temp_partition_name)}} + RENAME TO {{conn|qtIdent(part.partition_name)}}; + +{% endfor %}{% endif %} +DROP TABLE {{conn|qtIdent(data.schema, data.orig_name)}}; + +ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} + RENAME TO {{data.orig_name}}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/ppas/11_plus/partition_diff.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/ppas/11_plus/partition_diff.sql new file mode 100644 index 000000000..bfc063c0f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/partitions/sql/ppas/11_plus/partition_diff.sql @@ -0,0 +1,24 @@ +CREATE TABLE {{conn|qtIdent(data.schema, data.name)}} ( + LIKE {{conn|qtIdent(data.schema, data.orig_name)}} INCLUDING ALL +) PARTITION BY {{ data.partition_scheme }}; +{{partition_sql}}{{partition_data.default_partition_header}} +CREATE TABLE IF NOT EXISTS {{conn|qtIdent(data.schema, data.default_partition_name)}} PARTITION OF {{conn|qtIdent(data.schema, data.name)}} DEFAULT; + +INSERT INTO {{conn|qtIdent(data.schema, data.name)}}( +{% if data.columns and data.columns|length > 0 %} +{% for c in data.columns %} {{c.name}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %}) +SELECT {% if data.columns and data.columns|length > 0 %}{% for c in data.columns %}{{c.name}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %} + FROM {{conn|qtIdent(data.schema, data.orig_name)}}; + +{% if partition_data.partitions and partition_data.partitions|length > 0 %} +{% for part in partition_data.partitions %} +DROP TABLE IF EXISTS {{conn|qtIdent(data.schema, part.partition_name)}}; + +ALTER TABLE {{conn|qtIdent(data.schema, part.temp_partition_name)}} + RENAME TO {{conn|qtIdent(part.partition_name)}}; + +{% endfor %}{% endif %} +DROP TABLE {{conn|qtIdent(data.schema, data.orig_name)}}; + +ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} + RENAME TO {{data.orig_name}}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/10_plus/schema_diff.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/10_plus/schema_diff.sql deleted file mode 100644 index ebd4ae6e5..000000000 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/10_plus/schema_diff.sql +++ /dev/null @@ -1,14 +0,0 @@ - - -INSERT INTO {{conn|qtIdent(data.schema, data.name)}}( -{% if data.columns and data.columns|length > 0 %} -{% for c in data.columns %}{{c.name}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %}) -SELECT {% if data.columns and data.columns|length > 0 %}{% for c in data.columns %}{{c.name}}{% if not loop.last %},{% endif %}{% endfor %}{% endif %} - FROM {{conn|qtIdent(data.schema, data.orig_name)}}; - -DROP TABLE {{conn|qtIdent(data.schema, data.orig_name)}}; - -{{partition_sql}} - -ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} - RENAME TO {{conn|qtIdent(data.orig_name)}}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/12_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/12_plus/update.sql index 804620898..3ed12302d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/12_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/12_plus/update.sql @@ -56,7 +56,7 @@ ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} {% if data.fillfactor and data.fillfactor != o_data.fillfactor %} ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} SET (FILLFACTOR={{data.fillfactor}}); -{% elif data.fillfactor == '' and data.fillfactor != o_data.fillfactor %} +{% elif (data.fillfactor == '' or data.fillfactor == None) and data.fillfactor != o_data.fillfactor %} ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} RESET (FILLFACTOR); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/update.sql index 5673cff73..36eb180db 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/update.sql @@ -64,7 +64,7 @@ ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} {% if data.fillfactor and data.fillfactor != o_data.fillfactor %} ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} SET (FILLFACTOR={{data.fillfactor}}); -{% elif data.fillfactor == '' and data.fillfactor != o_data.fillfactor %} +{% elif (data.fillfactor == '' or data.fillfactor == None) and data.fillfactor != o_data.fillfactor %} ALTER TABLE {{conn|qtIdent(data.schema, data.name)}} RESET (FILLFACTOR); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/pg/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/pg/default/update.sql index 3b8d64545..359d295bf 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/pg/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/pg/default/update.sql @@ -3,9 +3,13 @@ ALTER TRIGGER {{ conn|qtIdent(o_data.name) }} ON {{ conn|qtIdent(o_data.nspname, RENAME TO {{ conn|qtIdent(data.name) }}; {% endif %} -{% if ((data.prosrc is defined or data.is_row_trigger is defined or data.evnt_insert is defined or data.evnt_delete is defined or data.evnt_update is defined or data.fires is defined) and o_data.lanname == 'edbspl' and (o_data.prosrc != data.prosrc or data.is_row_trigger != o_data.is_row_trigger or data.evnt_insert != o_data.evnt_insert or data.evnt_delete != o_data.evnt_delete or data.evnt_update != o_data.evnt_update or o_data.fires != data.fires)) %} +{% if ((data.prosrc is defined or data.is_row_trigger is defined or data.evnt_insert is defined or data.evnt_delete is defined or data.evnt_update is defined or data.fires is defined or data.is_constraint_trigger is defined) and (o_data.prosrc != data.prosrc or data.is_row_trigger != o_data.is_row_trigger or data.evnt_insert != o_data.evnt_insert or data.evnt_delete != o_data.evnt_delete or data.evnt_update != o_data.evnt_update or o_data.fires != data.fires or data.is_constraint_trigger != o_data.is_constraint_trigger)) %} {% set or_flag = False %} +{% if data.lanname == 'edbspl' or data.tfunction == 'Inline EDB-SPL' %} CREATE OR REPLACE TRIGGER {{ conn|qtIdent(data.name) }} +{% else %} +CREATE{% if data.is_constraint_trigger %} CONSTRAINT{% endif %} TRIGGER {{ conn|qtIdent(data.name) }} +{% endif %} {% if data.fires is defined %}{{data.fires}} {% else %}{{o_data.fires}} {% endif %}{% if data.evnt_insert is not defined %}{% if o_data.evnt_insert %}INSERT{% set or_flag = True %} {% endif %}{% else %}{% if data.evnt_insert %}INSERT{% set or_flag = True %}{% endif %}{% endif %}{% if data.evnt_delete is not defined %}{% if o_data.evnt_delete %} {% if or_flag %} OR {% endif %}DELETE{% set or_flag = True %} @@ -16,23 +20,29 @@ CREATE OR REPLACE TRIGGER {{ conn|qtIdent(data.name) }} {% if or_flag %} OR {% endif %}TRUNCATE{% set or_flag = True %}{%endif %}{% endif %}{% if data.evnt_update is not defined %}{% if o_data.evnt_update %} {% if or_flag %} OR {% endif %}UPDATE {% if o_data.columns|length > 0 %}OF {% for c in o_data.columns %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(c) }}{% endfor %}{% endif %} {% endif %}{% else %}{% if data.evnt_update %} -{% if or_flag %} OR {% endif %}UPDATE {% if o_data.columns|length > 0 %}OF {% for c in o_data.columns %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(c) }}{% endfor %}{% endif %}{% endif %} +{% if or_flag %} OR {% endif %}UPDATE {% if data.columns|length > 0 %}OF {% for c in data.columns %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(c) }}{% endfor %}{% endif %}{% endif %} {% endif %} ON {{ conn|qtIdent(data.schema, data.table) }} -{% if o_data.tgdeferrable %} +{% if data.tgdeferrable %} + DEFERRABLE{% if data.tginitdeferred %} INITIALLY DEFERRED{% endif %} + +{% elif o_data.tgdeferrable %} DEFERRABLE{% if o_data.tginitdeferred %} INITIALLY DEFERRED{% endif %} + {% endif %}{% if data.is_row_trigger is not defined %} FOR EACH{% if o_data.is_row_trigger %} ROW{% else %} STATEMENT{% endif %} {% else %} FOR EACH{% if data.is_row_trigger %} ROW{% else %} STATEMENT{% endif %} {% endif %} -{% if o_data.whenclause %} + +{% if data.whenclause %} + WHEN {{ data.whenclause }} +{% elif o_data.whenclause %} WHEN {{ o_data.whenclause }} {% endif %} - -{% if (data.prosrc is not defined) %} -{{ o_data.prosrc }}; +{% if (data.tfunction is defined) %} + EXECUTE PROCEDURE {{ data.tfunction }}{% if data.tgargs %}({{ data.tgargs }}){% else %}(){% endif%}; {% else %} -{{ data.prosrc }}; + EXECUTE PROCEDURE {{ o_data.tfunction }}{% if o_data.tgargs %}({{ o_data.tgargs }}){% else %}(){% endif%}; {% endif %} {% if data.description is not defined and o_data.description %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/ppas/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/ppas/default/update.sql index 3b8d64545..822dbb836 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/ppas/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/ppas/default/update.sql @@ -3,9 +3,13 @@ ALTER TRIGGER {{ conn|qtIdent(o_data.name) }} ON {{ conn|qtIdent(o_data.nspname, RENAME TO {{ conn|qtIdent(data.name) }}; {% endif %} -{% if ((data.prosrc is defined or data.is_row_trigger is defined or data.evnt_insert is defined or data.evnt_delete is defined or data.evnt_update is defined or data.fires is defined) and o_data.lanname == 'edbspl' and (o_data.prosrc != data.prosrc or data.is_row_trigger != o_data.is_row_trigger or data.evnt_insert != o_data.evnt_insert or data.evnt_delete != o_data.evnt_delete or data.evnt_update != o_data.evnt_update or o_data.fires != data.fires)) %} +{% if ((data.prosrc is defined or data.is_row_trigger is defined or data.evnt_insert is defined or data.evnt_delete is defined or data.evnt_update is defined or data.fires is defined or data.is_constraint_trigger is defined) and (o_data.prosrc != data.prosrc or data.is_row_trigger != o_data.is_row_trigger or data.evnt_insert != o_data.evnt_insert or data.evnt_delete != o_data.evnt_delete or data.evnt_update != o_data.evnt_update or o_data.fires != data.fires or data.is_constraint_trigger != o_data.is_constraint_trigger)) %} {% set or_flag = False %} +{% if data.lanname == 'edbspl' or data.tfunction == 'Inline EDB-SPL' %} CREATE OR REPLACE TRIGGER {{ conn|qtIdent(data.name) }} +{% else %} +CREATE{% if data.is_constraint_trigger %} CONSTRAINT{% endif %} TRIGGER {{ conn|qtIdent(data.name) }} +{% endif %} {% if data.fires is defined %}{{data.fires}} {% else %}{{o_data.fires}} {% endif %}{% if data.evnt_insert is not defined %}{% if o_data.evnt_insert %}INSERT{% set or_flag = True %} {% endif %}{% else %}{% if data.evnt_insert %}INSERT{% set or_flag = True %}{% endif %}{% endif %}{% if data.evnt_delete is not defined %}{% if o_data.evnt_delete %} {% if or_flag %} OR {% endif %}DELETE{% set or_flag = True %} @@ -16,24 +20,39 @@ CREATE OR REPLACE TRIGGER {{ conn|qtIdent(data.name) }} {% if or_flag %} OR {% endif %}TRUNCATE{% set or_flag = True %}{%endif %}{% endif %}{% if data.evnt_update is not defined %}{% if o_data.evnt_update %} {% if or_flag %} OR {% endif %}UPDATE {% if o_data.columns|length > 0 %}OF {% for c in o_data.columns %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(c) }}{% endfor %}{% endif %} {% endif %}{% else %}{% if data.evnt_update %} -{% if or_flag %} OR {% endif %}UPDATE {% if o_data.columns|length > 0 %}OF {% for c in o_data.columns %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(c) }}{% endfor %}{% endif %}{% endif %} +{% if or_flag %} OR {% endif %}UPDATE {% if data.columns|length > 0 %}OF {% for c in data.columns %}{% if loop.index != 1 %}, {% endif %}{{ conn|qtIdent(c) }}{% endfor %}{% endif %}{% endif %} {% endif %} ON {{ conn|qtIdent(data.schema, data.table) }} -{% if o_data.tgdeferrable %} +{% if data.tgdeferrable %} + DEFERRABLE{% if data.tginitdeferred %} INITIALLY DEFERRED{% endif %} + +{% elif o_data.tgdeferrable %} DEFERRABLE{% if o_data.tginitdeferred %} INITIALLY DEFERRED{% endif %} + {% endif %}{% if data.is_row_trigger is not defined %} FOR EACH{% if o_data.is_row_trigger %} ROW{% else %} STATEMENT{% endif %} {% else %} FOR EACH{% if data.is_row_trigger %} ROW{% else %} STATEMENT{% endif %} {% endif %} -{% if o_data.whenclause %} + +{% if data.whenclause %} + WHEN {{ data.whenclause }} +{% elif o_data.whenclause %} WHEN {{ o_data.whenclause }} {% endif %} +{%if data.tfunction == 'Inline EDB-SPL' %} {% if (data.prosrc is not defined) %} {{ o_data.prosrc }}; {% else %} {{ data.prosrc }}; {% endif %} +{% else %} +{% if (data.tfunction is defined) %} + EXECUTE PROCEDURE {{ data.tfunction }}{% if data.tgargs %}({{ data.tgargs }}){% else %}(){% endif%}; +{% else %} + EXECUTE PROCEDURE {{ o_data.tfunction }}{% if o_data.tgargs %}({{ o_data.tgargs }}){% else %}(){% endif%}; +{% endif %} +{% endif %} {% if data.description is not defined and o_data.description %} COMMENT ON TRIGGER {{ conn|qtIdent(data.name) }} ON {{ conn|qtIdent(o_data.nspname, o_data.relname) }} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py index b0f2e627b..dad149e15 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py @@ -29,6 +29,8 @@ from pgadmin.utils.compile_template_name import compile_template_path from pgadmin.utils import IS_PY2 from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare +from pgadmin.tools.schema_diff.directory_compare import directory_diff,\ + parce_acl # If we are in Python3 if not IS_PY2: @@ -794,7 +796,7 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare): SQL, name = trigger_utils.get_sql( self.conn, data, tid, oid, self.datlastsysoid, - self.blueprint.show_system_objects) + self.blueprint.show_system_objects, True) if not isinstance(SQL, (str, unicode)): return SQL @@ -932,8 +934,7 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare): ) @check_precondition - def fetch_objects_to_compare(self, sid, did, scid, tid, oid=None, - ignore_keys=False): + def fetch_objects_to_compare(self, sid, did, scid, tid, oid=None): """ This function will fetch the list of all the triggers for specified schema id. @@ -963,14 +964,59 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare): for row in triggers['rows']: status, data = self._fetch_properties(tid, row['oid']) if status: - if ignore_keys: - for key in self.keys_to_ignore: - if key in data: - del data[key] res[row['name']] = data return res + def ddl_compare(self, **kwargs): + """ + This function returns the DDL/DML statements based on the + comparison status. + + :param kwargs: + :return: + """ + + src_params = kwargs.get('source_params') + tgt_params = kwargs.get('target_params') + source = kwargs.get('source') + target = kwargs.get('target') + target_schema = kwargs.get('target_schema') + comp_status = kwargs.get('comp_status') + + diff = '' + if comp_status == 'source_only': + diff = self.get_sql_from_diff(gid=src_params['gid'], + sid=src_params['sid'], + did=src_params['did'], + scid=src_params['scid'], + tid=src_params['tid'], + oid=source['oid'], + diff_schema=target_schema) + elif comp_status == 'target_only': + diff = self.get_sql_from_diff(gid=tgt_params['gid'], + sid=tgt_params['sid'], + did=tgt_params['did'], + scid=tgt_params['scid'], + tid=tgt_params['tid'], + oid=target['oid'], + drop_sql=True) + elif comp_status == 'different': + diff_dict = directory_diff( + source, target, + ignore_keys=self.keys_to_ignore, difference={} + ) + diff_dict.update(parce_acl(source, target)) + + diff = self.get_sql_from_diff(gid=tgt_params['gid'], + sid=tgt_params['sid'], + did=tgt_params['did'], + scid=tgt_params['scid'], + tid=tgt_params['tid'], + oid=target['oid'], + data=diff_dict) + return diff + SchemaDiffRegistry(blueprint.node_type, TriggerView, 'table') TriggerView.register_node_view(blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/utils.py index 6fddf0f40..4bbe8102c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/utils.py @@ -141,7 +141,7 @@ def get_trigger_function_and_columns(conn, data, tid, @get_template_path def get_sql(conn, data, tid, trid, datlastsysoid, - show_system_objects, template_path=None): + show_system_objects, is_schema_diff=False, template_path=None): """ This function will generate sql from model data. @@ -151,6 +151,7 @@ def get_sql(conn, data, tid, trid, datlastsysoid, :param trid: Trigger ID :param datlastsysoid: :param show_system_objects: Show System Object value True or False + :param is_schema_diff: :param template_path: Optional template path :return: """ @@ -173,6 +174,35 @@ def get_sql(conn, data, tid, trid, datlastsysoid, if 'name' not in data: name = data['name'] = old_data['name'] + drop_sql = '' + if is_schema_diff: + if 'table' not in data: + data['table'] = old_data['relname'] + if 'schema' not in data: + data['schema'] = old_data['nspname'] + + # If any of the below key is present in data then we need to drop + # trigger and re-create it. + key_array = ['prosrc', 'is_row_trigger', 'evnt_insert', + 'evnt_delete', 'evnt_update', 'fires', 'tgdeferrable', + 'whenclause', 'tfunction', 'tgargs', 'columns', + 'is_constraint_trigger', 'tginitdeferred'] + + is_drop_trigger = False + for key in key_array: + if key in data: + is_drop_trigger = True + break + + if is_drop_trigger: + tmp_data = dict() + tmp_data['name'] = data['name'] + tmp_data['nspname'] = old_data['nspname'] + tmp_data['relname'] = old_data['relname'] + drop_sql = render_template("/".join([template_path, + 'delete.sql']), + data=tmp_data, conn=conn) + old_data = get_trigger_function_and_columns( conn, old_data, tid, show_system_objects) @@ -182,6 +212,9 @@ def get_sql(conn, data, tid, trid, datlastsysoid, "/".join([template_path, 'update.sql']), data=data, o_data=old_data, conn=conn ) + + if is_schema_diff: + SQL = drop_sql + '\n' + SQL else: required_args = { 'name': 'Name', 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 4a91ab101..413a95255 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 @@ -588,6 +588,10 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): if not json_resp: display_comments = False res_data = parse_rule_definition(res) + # Update the correct table name for rules + if 'view' in res_data: + res_data['view'] = table + rules_sql += render_template("/".join( [self.rules_template_path, 'create.sql']), data=res_data, display_comments=display_comments) @@ -1298,11 +1302,12 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): status=200 ) - def get_partitions_sql(self, partitions): + def get_partitions_sql(self, partitions, schema_diff=False): """ This function will iterate all the partitions and create SQL. :param partitions: List of partitions + :param schema_diff: If true then create sql accordingly. """ sql = '' @@ -1370,12 +1375,17 @@ class BaseTableView(PGChildNodeView, BasePartitionTable): data=part_data, conn=self.conn ) else: + # For schema diff we create temporary partitions to copy the + # data from original table to temporary table. + if schema_diff: + part_data['name'] = row['temp_partition_name'] + partition_sql = render_template( "/".join([self.partition_template_path, 'create.sql']), data=part_data, conn=self.conn ) - sql += partition_sql + '\n' + sql += partition_sql return sql diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mviews/pg/9.4_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mviews/pg/9.4_plus/sql/update.sql index a728b18c9..922b11887 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mviews/pg/9.4_plus/sql/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mviews/pg/9.4_plus/sql/update.sql @@ -30,9 +30,9 @@ CREATE MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }} {% if data.fillfactor or o_data.fillfactor %} WITH( {% if data.fillfactor %} -FILLFACTOR = {{ data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) or (o_data['vacuum_data'] is defined and o_data['vacuum_data']['changed']|length > 0) %},{% endif %} +FILLFACTOR = {{ data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %} {% elif o_data.fillfactor %} -FILLFACTOR = {{ o_data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) or (o_data['vacuum_data'] is defined and o_data['vacuum_data']['changed']|length > 0) %},{% endif %} +FILLFACTOR = {{ o_data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %} {% endif %} {% if data['vacuum_data']['changed']|length > 0 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mviews/ppas/9.3_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mviews/ppas/9.3_plus/sql/update.sql index 55cdfb03e..922b11887 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mviews/ppas/9.3_plus/sql/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mviews/ppas/9.3_plus/sql/update.sql @@ -30,12 +30,13 @@ CREATE MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }} {% if data.fillfactor or o_data.fillfactor %} WITH( {% if data.fillfactor %} -FILLFACTOR = {{ data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) or (o_data['vacuum_data'] is defined and o_data['vacuum_data']['changed']|length > 0) %},{% endif %} +FILLFACTOR = {{ data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %} {% elif o_data.fillfactor %} -FILLFACTOR = {{ o_data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) or (o_data['vacuum_data'] is defined and o_data['vacuum_data']['changed']|length > 0) %},{% endif %} +FILLFACTOR = {{ o_data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %} {% endif %} + {% if data['vacuum_data']['changed']|length > 0 %} -{% for field in data['vacuum_data']['changed'] %} {{ field.name }} = {{ field.value|lower }}{% if not loop.last %},{% endif %}{{ '\n' }} +{% for field in data['vacuum_data']['changed'] %} {{ field.name }} = {{ field.value|lower }}{% if not loop.last %},{{ '\n' }}{% endif %} {% endfor %} {% endif %} ) @@ -44,7 +45,6 @@ FILLFACTOR = {{ o_data.fillfactor }}{% if (data['vacuum_data'] is defined and da {{ def }} {% if data.with_data is defined %} WITH {{ 'DATA' if data.with_data else 'NO DATA' }}; - {% elif o_data.with_data is defined %} WITH {{ 'DATA' if o_data.with_data else 'NO DATA' }}; @@ -128,8 +128,7 @@ ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }} RESET( {% if('vacuum_table' in data and data['vacuum_table']['changed']|length > 0) %} ALTER MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }} SET( {% for field in data['vacuum_table']['changed'] %} -{% if field.value != None %} {{ field.name }} = {{ field.value|lower }}{% if not loop.last %},{% endif %} -{% endif %} +{% if field.value != None %} {{ field.name }} = {{ field.value|lower }}{% if not loop.last %},{% endif %}{% endif %} {% endfor %} ); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/views/pg/9.4_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/views/pg/9.4_plus/sql/update.sql index 805c658d1..7576600c9 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/views/pg/9.4_plus/sql/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/views/pg/9.4_plus/sql/update.sql @@ -19,7 +19,9 @@ ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }} {% endif %} {% if def and def != o_data.definition.rstrip(';') %} CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }} +{% if ((data.check_option and data.check_option.lower() != 'no') or data.security_barrier) %} WITH ({% if (data.check_option or o_data.check_option) %}check_option={{ data.check_option if data.check_option else o_data.check_option }}{{', ' }}{% endif %}security_barrier={{ data.security_barrier|lower if data.security_barrier is defined else o_data.security_barrier|default('false', 'true')|lower }}) +{% endif %} AS {{ def }}; {% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/views/ppas/9.4_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/views/ppas/9.4_plus/sql/update.sql index 4235f5c90..099a3a2bb 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/views/ppas/9.4_plus/sql/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/views/ppas/9.4_plus/sql/update.sql @@ -19,7 +19,9 @@ ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }} {% endif %} {% if def and def != o_data.definition.rstrip(';') %} CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }} +{% if ((data.check_option and data.check_option.lower() != 'no') or data.security_barrier) %} WITH ({% if (data.check_option or o_data.check_option) %}check_option={{ data.check_option if data.check_option else o_data.check_option }}{{', ' }}{% endif %}security_barrier={{ data.security_barrier|lower if data.security_barrier else o_data.security_barrier|default('false', 'true')|lower }}) +{% endif %} AS {{ def }}; {% else %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_add_some_priv_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_add_some_priv_msql.sql index 285bb2268..dc05c982c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_add_some_priv_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_add_some_priv_msql.sql @@ -1 +1,5 @@ +ALTER VIEW public."testview_$%{}[]()&*^!@""'`\/#" + SET (security_barrier=true); +ALTER VIEW public."testview_$%{}[]()&*^!@""'`\/#" + SET (check_option=cascaded); GRANT SELECT ON TABLE public."testview_$%{}[]()&*^!@""'`\/#" TO PUBLIC; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_definition.sql index 2588f4194..b298f31fa 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_definition.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_definition.sql @@ -3,10 +3,7 @@ -- DROP VIEW public."testview_$%{}[]()&*^!@""'`\/#"; CREATE OR REPLACE VIEW public."testview_$%{}[]()&*^!@""'`\/#" -WITH ( - check_option=cascaded, - security_barrier=true -) AS + AS SELECT test_view_table.col1 FROM test_view_table; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_definition_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_definition_msql.sql index 84f01f995..aa577020e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_definition_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/pg/9.4_plus/alter_view_definition_msql.sql @@ -1,4 +1,3 @@ CREATE OR REPLACE VIEW public."testview_$%{}[]()&*^!@""'`\/#" - WITH (check_option=cascaded, security_barrier=true) AS SELECT * FROM test_view_table; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_add_some_priv_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_add_some_priv_msql.sql index 285bb2268..dc05c982c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_add_some_priv_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_add_some_priv_msql.sql @@ -1 +1,5 @@ +ALTER VIEW public."testview_$%{}[]()&*^!@""'`\/#" + SET (security_barrier=true); +ALTER VIEW public."testview_$%{}[]()&*^!@""'`\/#" + SET (check_option=cascaded); GRANT SELECT ON TABLE public."testview_$%{}[]()&*^!@""'`\/#" TO PUBLIC; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_definition.sql index 62ce17449..6a91976ae 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_definition.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_definition.sql @@ -3,10 +3,7 @@ -- DROP VIEW public."testview_$%{}[]()&*^!@""'`\/#"; CREATE OR REPLACE VIEW public."testview_$%{}[]()&*^!@""'`\/#" -WITH ( - check_option=cascaded, - security_barrier=true -) AS + AS SELECT test_view_table.col1 FROM test_view_table; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_definition_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_definition_msql.sql index 84f01f995..aa577020e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_definition_msql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/tests/ppas/9.4_plus/alter_view_definition_msql.sql @@ -1,4 +1,3 @@ CREATE OR REPLACE VIEW public."testview_$%{}[]()&*^!@""'`\/#" - WITH (check_option=cascaded, security_barrier=true) AS SELECT * FROM test_view_table; diff --git a/web/pgadmin/tools/schema_diff/__init__.py b/web/pgadmin/tools/schema_diff/__init__.py index a8ca5749c..04ff644ce 100644 --- a/web/pgadmin/tools/schema_diff/__init__.py +++ b/web/pgadmin/tools/schema_diff/__init__.py @@ -68,7 +68,6 @@ class SchemaDiffModule(PgAdminModule): 'schema_diff.connect_server', 'schema_diff.connect_database', 'schema_diff.get_server', - 'schema_diff.generate_script', 'schema_diff.close' ] @@ -452,7 +451,7 @@ def compare(trans_id, source_sid, source_did, source_scid, for node_name, node_view in all_registered_nodes.items(): view = SchemaDiffRegistry.get_node_view(node_name) if hasattr(view, 'compare'): - msg = "Comparing " + view.blueprint.COLLECTION_LABEL + " ..." + msg = "Comparing " + view.blueprint.COLLECTION_LABEL diff_model_obj.set_comparison_info(msg, total_percent) # Update the message and total percentage in session object update_session_diff_transaction(trans_id, session_obj, @@ -510,59 +509,6 @@ def poll(trans_id): 'diff_percentage': diff_percentage}) -@blueprint.route( - '/generate_script//', - methods=["POST"], - endpoint="generate_script" -) -def generate_script(trans_id): - """This function will generate the scripts for the selected objects.""" - data = request.form if request.form else json.loads( - request.data, encoding='utf-8' - ) - - status, error_msg, diff_model_obj, session_obj = \ - check_transaction_status(trans_id) - - if error_msg == gettext('Transaction ID not found in the session.'): - return make_json_response(success=0, errormsg=error_msg, status=404) - - source_sid = int(data['source_sid']) - source_did = int(data['source_did']) - source_scid = int(data['source_scid']) - target_sid = int(data['target_sid']) - target_did = int(data['target_did']) - target_scid = int(data['target_scid']) - diff_ddl = '' - - for d in data['sel_rows']: - node_type = d['node_type'] - source_oid = int(d['source_oid']) - target_oid = int(d['target_oid']) - comp_status = d['comp_status'] - - view = SchemaDiffRegistry.get_node_view(node_type) - if view and hasattr(view, 'ddl_compare') and \ - comp_status != SchemaDiffModel.COMPARISON_STATUS['identical']: - sql = view.ddl_compare(source_sid=source_sid, - source_did=source_did, - source_scid=source_scid, - target_sid=target_sid, - target_did=target_did, - target_scid=target_scid, - source_oid=source_oid, - target_oid=target_oid, - comp_status=comp_status, - generate_script=True) - - diff_ddl += sql['diff_ddl'] + '\n\n' - - return ajax_response( - status=200, - response={'diff_ddl': diff_ddl} - ) - - @blueprint.route( '/ddl_compare////' '////' @@ -620,7 +566,11 @@ def check_version_compatibility(sid, tid): tar_server = Server.query.filter_by(id=tid).first() tar_manager = driver.connection_manager(tar_server.id) - tar_conn = tar_manager.connection() + + if src_manager.server_type != tar_manager.server_type: + return False, gettext('Schema diff does not support the comparison ' + 'between Postgres Server and EDB Postgres ' + 'Advanced Server.') if not (src_conn.connected() or src_conn.connected()): return False, gettext('Server(s) disconnected.') diff --git a/web/pgadmin/tools/schema_diff/compare.py b/web/pgadmin/tools/schema_diff/compare.py index 793b204df..40d4382bb 100644 --- a/web/pgadmin/tools/schema_diff/compare.py +++ b/web/pgadmin/tools/schema_diff/compare.py @@ -15,8 +15,7 @@ from flask import render_template from pgadmin.utils.driver import get_driver from config import PG_DEFAULT_DRIVER from pgadmin.utils.ajax import internal_server_error -from pgadmin.tools.schema_diff.directory_compare import compare_dictionaries,\ - directory_diff +from pgadmin.tools.schema_diff.directory_compare import compare_dictionaries from pgadmin.tools.schema_diff.model import SchemaDiffModel @@ -68,10 +67,12 @@ class SchemaDiffObjectCompare: 'scid': kwargs.get('target_scid') } - if 'source_tid' in kwargs: - source_params['tid'] = kwargs['source_tid'] - if 'target_tid' in kwargs: - target_params['tid'] = kwargs['target_tid'] + status, target_schema = self.get_schema(kwargs.get('target_sid'), + kwargs.get('target_did'), + kwargs.get('target_scid') + ) + if not status: + return internal_server_error(errormsg=target_schema) source = self.fetch_objects_to_compare(**source_params) @@ -82,7 +83,8 @@ class SchemaDiffObjectCompare: len(source) <= 0 and len(target) <= 0): return None - return compare_dictionaries(source, target, + return compare_dictionaries(self, source_params, target_params, + target_schema, source, target, self.node_type, self.blueprint.COLLECTION_LABEL, self.keys_to_ignore) @@ -93,13 +95,6 @@ class SchemaDiffObjectCompare: return the difference of SQL """ - source = '' - target = '' - diff = '' - comp_status = kwargs.get('comp_status') - only_diff = False - generate_script = False - source_params = {'gid': 1, 'sid': kwargs.get('source_sid'), 'did': kwargs.get('source_did'), @@ -114,98 +109,10 @@ class SchemaDiffObjectCompare: 'oid': kwargs.get('target_oid') } - if 'source_tid' in kwargs: - source_params['tid'] = kwargs['source_tid'] - only_diff = True - if 'target_tid' in kwargs: - target_params['tid'] = kwargs['target_tid'] - only_diff = True - - if 'generate_script' in kwargs and kwargs['generate_script']: - generate_script = True - - source_params_adv = copy.deepcopy(source_params) - target_params_adv = copy.deepcopy(target_params) - - del source_params_adv['gid'] - del target_params_adv['gid'] - - status, target_schema = self.get_schema(kwargs.get('target_sid'), - kwargs.get('target_did'), - kwargs.get('target_scid') - ) - if not status: - return internal_server_error(errormsg=target_schema) - - if comp_status == SchemaDiffModel.COMPARISON_STATUS['source_only']: - if not generate_script: - source = self.get_sql_from_diff(**source_params) - source_params.update({ - 'diff_schema': target_schema - }) - diff = self.get_sql_from_diff(**source_params) - - elif comp_status == SchemaDiffModel.COMPARISON_STATUS['target_only']: - if not generate_script: - target = self.get_sql_from_diff(**target_params) - target_params.update( - {'drop_sql': True}) - diff = self.get_sql_from_diff(**target_params) - - elif comp_status == SchemaDiffModel.COMPARISON_STATUS['different']: - source = self.fetch_objects_to_compare(**source_params_adv) - target = self.fetch_objects_to_compare(**target_params_adv) - - if not (source or target): - return None - - diff_dict = directory_diff(source, - target, - ignore_keys=self.keys_to_ignore, - difference={} - ) - - diff_dict.update(self.parce_acl(source, target)) - - if not generate_script: - source = self.get_sql_from_diff(**source_params) - target = self.get_sql_from_diff(**target_params) - - target_params.update( - {'data': diff_dict}) - diff = self.get_sql_from_diff(**target_params) - else: - source = self.get_sql_from_diff(**source_params) - target = self.get_sql_from_diff(**target_params) - - if only_diff: - return diff + source = self.get_sql_from_diff(**source_params) + target = self.get_sql_from_diff(**target_params) return {'source_ddl': source, 'target_ddl': target, - 'diff_ddl': diff + 'diff_ddl': '' } - - @staticmethod - def parce_acl(source, target): - key = 'acl' - - if 'datacl' in source: - key = 'datacl' - elif 'relacl' in source: - key = 'relacl' - - tmp_source = source[key] if\ - key in source and source[key] is not None else [] - tmp_target = copy.deepcopy(target[key]) if\ - key in target and target[key] is not None else [] - - diff = {'added': [], 'deleted': []} - for acl in tmp_source: - if acl in tmp_target: - tmp_target.remove(acl) - elif acl not in tmp_target: - diff['added'].append(acl) - diff['deleted'] = tmp_target - - return {key: diff} diff --git a/web/pgadmin/tools/schema_diff/directory_compare.py b/web/pgadmin/tools/schema_diff/directory_compare.py index 82a24f0ca..eb0d7d220 100644 --- a/web/pgadmin/tools/schema_diff/directory_compare.py +++ b/web/pgadmin/tools/schema_diff/directory_compare.py @@ -15,11 +15,17 @@ from pgadmin.tools.schema_diff.model import SchemaDiffModel count = 1 -def compare_dictionaries(source_dict, target_dict, node, node_label, +def compare_dictionaries(view_object, source_params, target_params, + target_schema, source_dict, target_dict, node, + node_label, ignore_keys=None): """ This function will compare the two dictionaries. + :param view_object: View Object + :param source_params: Source Parameters + :param target_params: Target Parameters + :param target_schema: Target Schema Name :param source_dict: First Dictionary :param target_dict: Second Dictionary :param node: node type @@ -36,18 +42,43 @@ def compare_dictionaries(source_dict, target_dict, node, node_label, dict2_keys = set(dict2.keys()) intersect_keys = dict1_keys.intersection(dict2_keys) + # Add gid to the params + source_params['gid'] = target_params['gid'] = 1 + # Keys that are available in source and missing in target. source_only = [] added = dict1_keys - dict2_keys global count for item in added: + if node == 'table': + temp_src_params = copy.deepcopy(source_params) + temp_src_params['tid'] = source_dict[item]['oid'] + temp_src_params['json_resp'] = False + source_ddl = \ + view_object.get_sql_from_table_diff(**temp_src_params) + temp_src_params.update({ + 'diff_schema': target_schema + }) + diff_ddl = view_object.get_sql_from_table_diff(**temp_src_params) + else: + temp_src_params = copy.deepcopy(source_params) + temp_src_params['oid'] = source_dict[item]['oid'] + source_ddl = view_object.get_sql_from_diff(**temp_src_params) + temp_src_params.update({ + 'diff_schema': target_schema + }) + diff_ddl = view_object.get_sql_from_diff(**temp_src_params) + source_only.append({ 'id': count, 'type': node, 'label': node_label, 'title': item, 'oid': source_dict[item]['oid'], - 'status': SchemaDiffModel.COMPARISON_STATUS['source_only'] + 'status': SchemaDiffModel.COMPARISON_STATUS['source_only'], + 'source_ddl': source_ddl, + 'target_ddl': '', + 'diff_ddl': diff_ddl }) count += 1 @@ -55,13 +86,34 @@ def compare_dictionaries(source_dict, target_dict, node, node_label, # Keys that are available in target and missing in source. removed = dict2_keys - dict1_keys for item in removed: + if node == 'table': + temp_tgt_params = copy.deepcopy(target_params) + temp_tgt_params['tid'] = target_dict[item]['oid'] + temp_tgt_params['json_resp'] = False + target_ddl = view_object.get_sql_from_table_diff(**temp_tgt_params) + if 'gid' in temp_tgt_params: + del temp_tgt_params['gid'] + if 'json_resp' in temp_tgt_params: + del temp_tgt_params['json_resp'] + diff_ddl = view_object.get_drop_sql(**temp_tgt_params) + else: + temp_tgt_params = copy.deepcopy(target_params) + temp_tgt_params['oid'] = target_dict[item]['oid'] + target_ddl = view_object.get_sql_from_diff(**temp_tgt_params) + temp_tgt_params.update( + {'drop_sql': True}) + diff_ddl = view_object.get_sql_from_diff(**temp_tgt_params) + target_only.append({ 'id': count, 'type': node, 'label': node_label, 'title': item, 'oid': target_dict[item]['oid'], - 'status': SchemaDiffModel.COMPARISON_STATUS['target_only'] + 'status': SchemaDiffModel.COMPARISON_STATUS['target_only'], + 'source_ddl': '', + 'target_ddl': target_ddl, + 'diff_ddl': diff_ddl }) count += 1 @@ -69,13 +121,6 @@ def compare_dictionaries(source_dict, target_dict, node, node_label, identical = [] different = [] for key in intersect_keys: - # ignore the keys if available. - for ig_key in ignore_keys: - if ig_key in dict1[key]: - dict1[key].pop(ig_key) - if ig_key in dict2[key]: - dict2[key].pop(ig_key) - # Recursively Compare the two dictionary if are_dictionaries_identical(dict1[key], dict2[key], ignore_keys): identical.append({ @@ -89,6 +134,50 @@ def compare_dictionaries(source_dict, target_dict, node, node_label, 'status': SchemaDiffModel.COMPARISON_STATUS['identical'] }) else: + if node == 'table': + temp_src_params = copy.deepcopy(source_params) + temp_tgt_params = copy.deepcopy(target_params) + # Add submodules into the ignore keys so that directory + # difference won't include those in added, deleted and changed + sub_module = ['index', 'rule', 'trigger', 'compound_trigger'] + temp_ignore_keys = view_object.keys_to_ignore + sub_module + + diff_dict = directory_diff( + dict1[key], dict2[key], + ignore_keys=temp_ignore_keys, + difference={} + ) + diff_dict.update(parce_acl(dict1[key], dict2[key])) + + temp_src_params['tid'] = source_dict[key]['oid'] + temp_tgt_params['tid'] = target_dict[key]['oid'] + temp_src_params['json_resp'] = \ + temp_tgt_params['json_resp'] = False + + source_ddl = \ + view_object.get_sql_from_table_diff(**temp_src_params) + target_ddl = \ + view_object.get_sql_from_table_diff(**temp_tgt_params) + diff_ddl = view_object.get_sql_from_submodule_diff( + temp_src_params, temp_tgt_params, target_schema, + dict1[key], dict2[key], diff_dict) + else: + temp_src_params = copy.deepcopy(source_params) + temp_tgt_params = copy.deepcopy(target_params) + diff_dict = directory_diff( + dict1[key], dict2[key], + ignore_keys=view_object.keys_to_ignore, difference={} + ) + diff_dict.update(parce_acl(dict1[key], dict2[key])) + + temp_src_params['oid'] = source_dict[key]['oid'] + temp_tgt_params['oid'] = target_dict[key]['oid'] + source_ddl = view_object.get_sql_from_diff(**temp_src_params) + target_ddl = view_object.get_sql_from_diff(**temp_tgt_params) + temp_tgt_params.update( + {'data': diff_dict}) + diff_ddl = view_object.get_sql_from_diff(**temp_tgt_params) + different.append({ 'id': count, 'type': node, @@ -97,7 +186,10 @@ def compare_dictionaries(source_dict, target_dict, node, node_label, 'oid': source_dict[key]['oid'], 'source_oid': source_dict[key]['oid'], 'target_oid': target_dict[key]['oid'], - 'status': SchemaDiffModel.COMPARISON_STATUS['different'] + 'status': SchemaDiffModel.COMPARISON_STATUS['different'], + 'source_ddl': source_ddl, + 'target_ddl': target_ddl, + 'diff_ddl': diff_ddl }) count += 1 @@ -143,13 +235,6 @@ def are_dictionaries_identical(source_dict, target_dict, ignore_keys): src_keys = set(source_dict.keys()) tar_keys = set(target_dict.keys()) - # ignore the keys if available. - for ig_key in ignore_keys: - if ig_key in src_keys: - source_dict.pop(ig_key) - if ig_key in target_dict: - target_dict.pop(ig_key) - # Keys that are available in source and missing in target. src_only = src_keys - tar_keys # Keys that are available in target and missing in source. @@ -167,6 +252,10 @@ def are_dictionaries_identical(source_dict, target_dict, ignore_keys): return False for key in source_dict.keys(): + # Continue if key is available in ignore_keys + if key in ignore_keys: + continue + if type(source_dict[key]) is dict: if not are_dictionaries_identical(source_dict[key], target_dict[key], ignore_keys): @@ -235,33 +324,32 @@ def directory_diff(source_dict, target_dict, ignore_keys=[], difference={}): # 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_key_array = ['name', 'colname', 'argid'] + for tmp_key in tmp_key_array: + if tmp_key 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 tmp_key in item and \ + item[tmp_key] == \ + source[tmp_key]: + 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 + + 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 @@ -271,7 +359,7 @@ def directory_diff(source_dict, target_dict, ignore_keys=[], difference={}): len(target_dict[key]) > index: difference[key] = source else: - target_dict[key] = source_dict[key] + difference[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: @@ -286,6 +374,34 @@ def directory_diff(source_dict, target_dict, ignore_keys=[], difference={}): else: if source_dict[key] != target_dict[key]: - difference[key] = source_dict[key] + if (key == 'comment' or key == 'description') and \ + source_dict[key] is None: + difference[key] = '' + else: + difference[key] = source_dict[key] return difference + + +def parce_acl(source, target): + key = 'acl' + + if 'datacl' in source: + key = 'datacl' + elif 'relacl' in source: + key = 'relacl' + + tmp_source = source[key] if\ + key in source and source[key] is not None else [] + tmp_target = copy.deepcopy(target[key]) if\ + key in target and target[key] is not None else [] + + diff = {'added': [], 'deleted': []} + for acl in tmp_source: + if acl in tmp_target: + tmp_target.remove(acl) + elif acl not in tmp_target: + diff['added'].append(acl) + diff['deleted'] = tmp_target + + return {key: diff} 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 204c26165..ae3a7eebb 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 @@ -63,6 +63,8 @@ let SchemaDiffSqlControl = }, render: function() { let obj = Backform.SqlFieldControl.prototype.render.apply(this, arguments); + + obj.sqlCtrl.setOption('readOnly', true); if(this.$el.find('.ddl-copy')) this.$el.find('.ddl-copy').on('click', this.copyData); return obj; }, diff --git a/web/pgadmin/tools/schema_diff/static/js/schema_diff_ui.js b/web/pgadmin/tools/schema_diff/static/js/schema_diff_ui.js index a3bfbe4e3..a5008db08 100644 --- a/web/pgadmin/tools/schema_diff/static/js/schema_diff_ui.js +++ b/web/pgadmin/tools/schema_diff/static/js/schema_diff_ui.js @@ -197,7 +197,6 @@ export default class SchemaDiffUI { baseServerUrl = url_for('schema_diff.get_server', {'sid': self.selection['target_sid'], 'did': self.selection['target_did']}), sel_rows = self.grid ? self.grid.getSelectedRows() : [], - sel_rows_data = [], url_params = self.selection, generated_script = undefined, open_query_tool, @@ -261,45 +260,16 @@ export default class SchemaDiffUI { }; if (sel_rows.length > 0) { + let script_body = ''; for (var row = 0; row < sel_rows.length; row++) { let data = self.grid.getData().getItem(sel_rows[row]); - - if (data.type) { - let tmp_data = { - 'node_type': data.type, - 'source_oid': parseInt(data.oid, 10), - 'target_oid': parseInt(data.oid, 10), - 'comp_status': data.status, - }; - - if(data.status && (data.status.toLowerCase() == 'different' || data.status.toLowerCase() == 'identical')) { - tmp_data['target_oid'] = data.target_oid; - } - sel_rows_data.push(tmp_data); + if(!_.isUndefined(data.diff_ddl)) { + script_body += data.diff_ddl + '\n\n'; } } - url_params['sel_rows'] = sel_rows_data; - - let baseUrl = url_for('schema_diff.generate_script', {'trans_id': self.trans_id}); - - $.ajax({ - url: baseUrl, - method: 'POST', - dataType: 'json', - contentType: 'application/json', - data: JSON.stringify(url_params), - }) - .done(function (res) { - if (res) { - generated_script = script_header + 'BEGIN;' + '\n' + res.diff_ddl + '\n' + 'END;'; - } - open_query_tool(); - }) - .fail(function (xhr) { - self.raise_error_on_fail(gettext('Generate script error'), xhr); - $('#diff_fetching_data').addClass('d-none'); - }); + generated_script = script_header + 'BEGIN;' + '\n' + script_body + 'END;'; + open_query_tool(); } else if (!_.isUndefined(self.model.get('diff_ddl'))) { open_query_tool(); } @@ -448,6 +418,7 @@ export default class SchemaDiffUI { render_grid_data(data) { var self = this; self.grid.setSelectedRows([]); + data.sort((a, b) => (a.label > b.label) ? 1 : (a.label === b.label) ? ((a.title > b.title) ? 1 : -1) : -1); self.dataView.beginUpdate(); self.dataView.setItems(data); self.dataView.setFilter(self.filter.bind(self)); @@ -489,8 +460,13 @@ export default class SchemaDiffUI { contentType: 'application/json', }) .done(function (res) { - let msg = res.data.compare_msg + res.data.diff_percentage + '% completed'; - $('#diff_fetching_data').find('.schema-diff-busy-text').text(msg); + let msg = res.data.compare_msg; + if (res.data.diff_percentage != 100) { + msg = msg + ' (this may take a few minutes)...'; + } + + msg = msg + '
'+ res.data.diff_percentage + '% completed.'; + $('#diff_fetching_data').find('.schema-diff-busy-text').html(msg); }) .fail(function (xhr) { self.raise_error_on_fail(gettext('Poll error'), xhr); @@ -528,37 +504,44 @@ export default class SchemaDiffUI { 'diff_ddl': undefined, }); - var url_params = self.selection; - - if(data.status && (data.status.toLowerCase() == 'different' || data.status.toLowerCase() == 'identical')) { + if(data.status && data.status.toLowerCase() == 'identical') { + var url_params = self.selection; target_oid = data.target_oid; + + url_params['trans_id'] = self.trans_id; + url_params['source_oid'] = source_oid; + url_params['target_oid'] = target_oid; + url_params['comp_status'] = data.status; + url_params['node_type'] = node_type; + + _.each(url_params, function(key, val) { + url_params[key] = parseInt(val, 10); + }); + + $('#ddl_comp_fetching_data').removeClass('d-none'); + + var baseUrl = url_for('schema_diff.ddl_compare', url_params); + self.model.url = baseUrl; + + self.model.fetch({ + success: function() { + self.footer.render(); + $('#ddl_comp_fetching_data').addClass('d-none'); + }, + error: function() { + self.footer.render(); + $('#ddl_comp_fetching_data').addClass('d-none'); + }, + }); + } else { + self.model.set({ + 'source_ddl': data.source_ddl, + 'target_ddl': data.target_ddl, + 'diff_ddl': data.diff_ddl, + }); + + self.footer.render(); } - - url_params['trans_id'] = self.trans_id; - url_params['source_oid'] = source_oid; - url_params['target_oid'] = target_oid; - url_params['comp_status'] = data.status; - url_params['node_type'] = node_type; - - _.each(url_params, function(key, val) { - url_params[key] = parseInt(val, 10); - }); - - $('#ddl_comp_fetching_data').removeClass('d-none'); - - var baseUrl = url_for('schema_diff.ddl_compare', url_params); - self.model.url = baseUrl; - - self.model.fetch({ - success: function() { - self.footer.render(); - $('#ddl_comp_fetching_data').addClass('d-none'); - }, - error: function() { - self.footer.render(); - $('#ddl_comp_fetching_data').addClass('d-none'); - }, - }); } render() { diff --git a/web/pgadmin/tools/schema_diff/tests/test_schema_diff_comp.py b/web/pgadmin/tools/schema_diff/tests/test_schema_diff_comp.py index 77ccbb7d3..57dec4599 100644 --- a/web/pgadmin/tools/schema_diff/tests/test_schema_diff_comp.py +++ b/web/pgadmin/tools/schema_diff/tests/test_schema_diff_comp.py @@ -142,16 +142,10 @@ class SchemaDiffTestCase(BaseTestGenerator): file_obj = open(diff_file, 'a') for diff in response_data['data']: - if diff['type'] in self.nodes: - src_obj_oid = tar_obj_oid = None - if diff['status'] == 'Source Only' or\ - diff['status'] == 'Target Only': - src_obj_oid = tar_obj_oid = diff['oid'] - elif diff['status'] == 'Different': - src_obj_oid = diff['source_oid'] - tar_obj_oid = diff['target_oid'] - - if src_obj_oid is not None: + if diff['type'] in self.nodes and diff['status'] == 'Identical': + src_obj_oid = diff['source_oid'] + tar_obj_oid = diff['target_oid'] + if src_obj_oid is not None and tar_obj_oid is not None: url = 'schema_diff/ddl_compare/{0}/{1}/{2}/{3}/{4}/{5}/' \ '{6}/{7}/{8}/{9}/{10}/'.format(self.trans_id, self.server_id,