From 4746fbd34674574bec09113d0240618301fdcebf Mon Sep 17 00:00:00 2001 From: Nikhil Mohite Date: Mon, 19 Jun 2023 19:37:10 +0530 Subject: [PATCH] Fixed an issue where View/Edit data is throwing an error if the user deleted and re-create the same table for which View/Edit data was opened. #6431 --- .../templates/columns/sql/default/nodes.sql | 6 ++++ web/pgadmin/tools/sqleditor/__init__.py | 3 +- web/pgadmin/tools/sqleditor/command.py | 32 +++++++++++++++---- .../sqleditor/sql/11_plus/primary_keys.sql | 21 +++++++++--- .../sqleditor/sql/default/get_columns.sql | 14 +++++--- .../sqleditor/sql/default/primary_keys.sql | 21 +++++++++--- .../tools/sqleditor/utils/get_column_types.py | 24 ++++++++++---- 7 files changed, 91 insertions(+), 30 deletions(-) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/nodes.sql index 51bc13f8c..1167f0886 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/nodes.sql @@ -13,7 +13,13 @@ FROM pg_catalog.pg_attribute att LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=att.attrelid AND des.objsubid=att.attnum AND des.classoid='pg_class'::regclass) LEFT OUTER JOIN pg_catalog.pg_sequence seq ON cs.oid=seq.seqrelid WHERE + +{% if tid %} att.attrelid = {{ tid|qtLiteral(conn) }}::oid +{% endif %} +{% if table_name and table_nspname %} + cl.relname= {{table_name |qtLiteral(conn)}} and na.nspname={{table_nspname|qtLiteral(conn)}} +{% endif %} {% if clid %} AND att.attnum = {{ clid|qtLiteral(conn) }} {% endif %} diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py index 4123491cf..e03c14185 100644 --- a/web/pgadmin/tools/sqleditor/__init__.py +++ b/web/pgadmin/tools/sqleditor/__init__.py @@ -761,6 +761,7 @@ def start_view_data(trans_id): if status and conn is not None and \ trans_obj is not None and session_obj is not None: + # set fetched row count to 0 as we are executing query again. trans_obj.update_fetched_row_cnt(0) @@ -1411,7 +1412,7 @@ def append_filter_exclusive(trans_id): else: filter_sql = driver.qtIdent( conn, column_name - ) + ' IS DISTINCT FROM ' + driver.qtLiteral(column_value) + ) + ' IS DISTINCT FROM ' + driver.qtLiteral(column_value, conn) # Call the append_filter method of transaction object trans_obj.append_filter(filter_sql) diff --git a/web/pgadmin/tools/sqleditor/command.py b/web/pgadmin/tools/sqleditor/command.py index 09e6efca9..5d227bb6d 100644 --- a/web/pgadmin/tools/sqleditor/command.py +++ b/web/pgadmin/tools/sqleditor/command.py @@ -17,7 +17,7 @@ from werkzeug.exceptions import InternalServerError from pgadmin.utils.ajax import forbidden from pgadmin.utils.driver import get_driver from pgadmin.tools.sqleditor.utils.is_query_resultset_updatable \ - import is_query_resultset_updatable + import is_query_resultset_updatable, _check_single_table from pgadmin.tools.sqleditor.utils.save_changed_data import save_changed_data from pgadmin.tools.sqleditor.utils.get_column_types import get_columns_types from pgadmin.utils.preferences import Preferences @@ -394,7 +394,9 @@ class GridCommand(BaseCommand, SQLFilter, FetchedRowTracker): # Fetch the rest of the column names query = render_template( "/".join([self.sql_path, 'get_columns.sql']), - obj_id=self.obj_id + table_name=self.object_name, + table_nspname=self.nsp_name, + conn=conn, ) status, result = conn.execute_dict(query) if not status: @@ -532,7 +534,9 @@ class TableCommand(GridCommand): # Fetch the primary key column names query = render_template( "/".join([self.sql_path, 'primary_keys.sql']), - obj_id=self.obj_id + table_name=self.object_name, + table_nspname=self.nsp_name, + conn=conn, ) status, result = conn.execute_dict(query) @@ -576,7 +580,9 @@ class TableCommand(GridCommand): # Fetch the primary key column names query = render_template( "/".join([self.sql_path, 'primary_keys.sql']), - obj_id=self.obj_id + table_name=self.object_name, + table_nspname=self.nsp_name, + conn=conn, ) status, result = conn.execute_dict(query) @@ -590,7 +596,9 @@ class TableCommand(GridCommand): # Fetch the rest of the column names query = render_template( "/".join([self.sql_path, 'get_columns.sql']), - obj_id=self.obj_id + table_name=self.object_name, + table_nspname=self.nsp_name, + conn=conn, ) status, result = conn.execute_dict(query) if not status: @@ -677,12 +685,22 @@ class TableCommand(GridCommand): def get_columns_types(self, conn): columns_info = conn.get_column_info() has_oids = self.has_oids() - table_oid = self.obj_id + # table_oid = self.obj_id + table_name = None + table_nspname = None + table_oid = _check_single_table(columns_info) + if table_oid is None: + table_name = self.object_name + table_nspname = self.nsp_name + return get_columns_types(conn=conn, columns_info=columns_info, has_oids=has_oids, table_oid=table_oid, - is_query_tool=False) + is_query_tool=False, + table_name=table_name, + table_nspname=table_nspname, + ) class ViewCommand(GridCommand): diff --git a/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/11_plus/primary_keys.sql b/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/11_plus/primary_keys.sql index 173aa60fa..2e51b3641 100644 --- a/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/11_plus/primary_keys.sql +++ b/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/11_plus/primary_keys.sql @@ -1,8 +1,19 @@ -{# ============= Fetch the primary keys for given object id ============= #} -{% if obj_id %} SELECT at.attname, at.attnum, ty.typname FROM pg_catalog.pg_attribute at LEFT JOIN pg_catalog.pg_type ty ON (ty.oid = at.atttypid) -WHERE attrelid={{obj_id}}::oid AND attnum = ANY ( - (SELECT con.conkey FROM pg_catalog.pg_class rel LEFT OUTER JOIN pg_catalog.pg_constraint con ON con.conrelid=rel.oid - AND con.contype='p' WHERE rel.relkind IN ('r','s','t', 'p') AND rel.oid = {{obj_id}}::oid)::oid[]) +JOIN pg_catalog.pg_class as cl ON cl.oid=AT.attrelid +JOIN pg_catalog.pg_namespace as nsp ON nsp.oid=cl.relnamespace +WHERE +{% if obj_id %} + attrelid={{obj_id}}::oid AND +{% elif table_name and table_nspname %} + cl.relname = {{table_name|qtLiteral(conn)}} AND nsp.nspname={{table_nspname|qtLiteral(conn)}} AND {% endif %} +attnum = ANY ( +(SELECT con.conkey FROM pg_catalog.pg_class rel LEFT OUTER JOIN pg_catalog.pg_constraint con ON con.conrelid=rel.oid +JOIN pg_catalog.pg_namespace as nsp ON nsp.oid=REL.relnamespace +AND con.contype='p' WHERE rel.relkind IN ('r','s','t', 'p') AND +{% if obj_id %} + rel.oid = ({{obj_id}})::oid +{% elif table_name and table_nspname%} + rel.relname = {{table_name|qtLiteral(conn)}} AND nsp.nspname={{table_nspname|qtLiteral(conn)}} +{% endif %})::oid[]) diff --git a/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/default/get_columns.sql b/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/default/get_columns.sql index b56ed1c78..5d7cad38f 100644 --- a/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/default/get_columns.sql +++ b/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/default/get_columns.sql @@ -1,9 +1,13 @@ -{# ============= Fetch the columns ============= #} -{% if obj_id %} SELECT at.attname, ty.typname, at.attnum FROM pg_catalog.pg_attribute at LEFT JOIN pg_catalog.pg_type ty ON (ty.oid = at.atttypid) -WHERE attrelid={{obj_id}}::oid - AND at.attnum > 0 - AND at.attisdropped = FALSE + JOIN pg_catalog.pg_class as cl ON cl.oid=at.attrelid + JOIN pg_catalog.pg_namespace as nsp ON nsp.oid=cl.relnamespace +WHERE +{% if obj_id %} + attrelid={{obj_id}}::oid AND +{% elif table_name and table_nspname %} + cl.relname={{table_name|qtLiteral(conn)}} AND nsp.nspname={{table_nspname|qtLiteral(conn)}} AND {% endif %} +at.attnum > 0 +AND at.attisdropped = FALSE diff --git a/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/default/primary_keys.sql b/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/default/primary_keys.sql index 3820077e3..dcfd38c77 100644 --- a/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/default/primary_keys.sql +++ b/web/pgadmin/tools/sqleditor/templates/sqleditor/sql/default/primary_keys.sql @@ -1,8 +1,19 @@ -{# ============= Fetch the primary keys for given object id ============= #} -{% if obj_id %} SELECT at.attname, at.attnum, ty.typname FROM pg_catalog.pg_attribute at LEFT JOIN pg_catalog.pg_type ty ON (ty.oid = at.atttypid) -WHERE attrelid={{obj_id}}::oid AND attnum = ANY ( - (SELECT con.conkey FROM pg_catalog.pg_class rel LEFT OUTER JOIN pg_catalog.pg_constraint con ON con.conrelid=rel.oid - AND con.contype='p' WHERE rel.relkind IN ('r','s','t') AND rel.oid = ({{obj_id}})::oid)::oid[]) +JOIN pg_catalog.pg_class as cl ON cl.oid=AT.attrelid +JOIN pg_catalog.pg_namespace as nsp ON nsp.oid=cl.relnamespace +WHERE +{% if obj_id %} + attrelid={{obj_id}}::oid AND +{% elif table_name and table_nspname %} + cl.relname = {{table_name|qtLiteral(conn)}} AND nsp.nspname={{table_nspname|qtLiteral(conn)}} AND {% endif %} +attnum = ANY ( +(SELECT con.conkey FROM pg_catalog.pg_class LEFT OUTER JOIN pg_catalog.pg_constraint con ON con.conrelid=rel.oid +JOIN pg_catalog.pg_namespace as nsp ON nsp.oid=REL.relnamespace +AND con.contype='p' WHERE rel.relkind IN ('r','s','t') AND +{% if obj_id %} + rel.oid = ({{obj_id}})::oid +{% elif table_name and table_nspname%} + rel.relname = {{table_name|qtLiteral(conn)}} AND nsp.nspname={{table_nspname|qtLiteral(conn)}} +{% endif %})::oid[]) diff --git a/web/pgadmin/tools/sqleditor/utils/get_column_types.py b/web/pgadmin/tools/sqleditor/utils/get_column_types.py index 9c40c9fa1..761205f61 100644 --- a/web/pgadmin/tools/sqleditor/utils/get_column_types.py +++ b/web/pgadmin/tools/sqleditor/utils/get_column_types.py @@ -16,19 +16,29 @@ from flask_babel import gettext from pgadmin.utils.exception import ExecuteError, ObjectGone -def get_columns_types(is_query_tool, columns_info, table_oid, conn, has_oids): +def get_columns_types(is_query_tool, columns_info, table_oid, conn, has_oids, + table_name=None, table_nspname=None): nodes_sqlpath = 'columns/sql/#{0}#'.format(conn.manager.version) + param = { + 'has_oids': has_oids, + } + if table_name and table_nspname: + param.update({ + 'table_name': table_name, + 'table_nspname': table_nspname, + }) + else: + param.update({ + 'tid': table_oid + }) + query = render_template( "/".join([nodes_sqlpath, 'nodes.sql']), - tid=table_oid, - has_oids=has_oids, - conn=conn + conn=conn, + **param ) colst, rset = conn.execute_2darray(query) - # If no record found consider table is deleted, raise error - if len(rset['rows']) == 0: - raise ObjectGone(gettext("The specified object could not be found.")) if not colst: raise ExecuteError(rset)