Hi Dave, On Tue, Jul 18, 2017 at 1:24 PM, Dave Page <dp...@pgadmin.org> wrote:
> > > On Tue, Jul 18, 2017 at 8:26 AM, Harshal Dhumal < > harshal.dhu...@enterprisedb.com> wrote: > >> Hi Dave, >> >> >> On Mon, Jul 17, 2017 at 9:33 PM, Dave Page <dp...@pgadmin.org> wrote: >> >>> Hi >>> >>> On Mon, Jul 17, 2017 at 1:09 PM, Harshal Dhumal < >>> harshal.dhu...@enterprisedb.com> wrote: >>> >>>> Hi, >>>> >>>> Please find updated patch. Now placeholder string for bytea and bytea[] >>>> data will only appear in datagrid (view all/1000/500 rows). If user >>>> executes query using Query tool then placeholder won't appear (similar to >>>> pgAdminIII behaviour) >>>> >>> >>> I'm getting the following error when testing this: >>> >> >> I ran all feature test cases 5-6 times and each time they ran >> successfully. >> May be this is occasional failure which we get after running test cases >> for many times. >> >> Please let me know if you are getting this failure consistently at your >> end. >> > > I ran it twice and it failed twice. I can't keep running tests over and > over again as they take quite a while to run and I can't use my machine for > anything else at the same time as occasionally the test browser will grab > focus. > Please find updated patch. I have slightly modified feature test case for 'view data dml queries' (though I wasn't getting failure as mentioned). > > -- > Dave Page > Blog: http://pgsnake.blogspot.com > Twitter: @pgsnake > > EnterpriseDB UK: http://www.enterprisedb.com > The Enterprise PostgreSQL Company >
diff --git a/web/pgadmin/feature_tests/view_data_dml_queries.py b/web/pgadmin/feature_tests/view_data_dml_queries.py index 6454a3e..3a14e47 100644 --- a/web/pgadmin/feature_tests/view_data_dml_queries.py +++ b/web/pgadmin/feature_tests/view_data_dml_queries.py @@ -100,6 +100,7 @@ CREATE TABLE public.defaults # Open Object -> View/Edit data self._view_data_grid() + self.page.wait_for_query_tool_loading_indicator_to_disappear() # Run test to insert a new row in table with default values self._add_row() self._verify_row_data(True) @@ -158,6 +159,7 @@ CREATE TABLE public.defaults Returns: None """ + self.wait.until(EC.visibility_of_element_located( (By.XPATH, xpath)), CheckForViewDataTest.TIMEOUT_STRING ) @@ -195,6 +197,8 @@ CREATE TABLE public.defaults self.page.toggle_open_tree_item(self.server['name']) self.page.toggle_open_tree_item('Databases') self.page.toggle_open_tree_item('acceptance_test_db') + # wait until all database dependant modules/js are loaded. + time.sleep(5) self.page.toggle_open_tree_item('Schemas') self.page.toggle_open_tree_item('public') self.page.toggle_open_tree_item('Tables') @@ -261,6 +265,7 @@ CREATE TABLE public.defaults cell_xpath = CheckForViewDataTest._get_cell_xpath( 'r'+str(idx), 1 ) + time.sleep(0.4) self._update_cell(cell_xpath, config_data[str(idx)]) self.page.find_by_id("btn-save").click() # Save data diff --git a/web/pgadmin/tools/datagrid/__init__.py b/web/pgadmin/tools/datagrid/__init__.py index 95c83dd..08b01ab 100644 --- a/web/pgadmin/tools/datagrid/__init__.py +++ b/web/pgadmin/tools/datagrid/__init__.py @@ -117,7 +117,8 @@ def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id): conn_id = str(random.randint(1, 9999999)) try: manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid) - conn = manager.connection(did=did, conn_id=conn_id) + conn = manager.connection(did=did, conn_id=conn_id, + use_binary_placeholder=True) except Exception as e: return internal_server_error(errormsg=str(e)) diff --git a/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js b/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js index 72904a9..ce65f6f 100644 --- a/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js +++ b/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js @@ -578,6 +578,7 @@ define([ name: c.label, display_name: c.display_name, column_type: c.column_type, + column_type_internal: c.column_type_internal, not_null: c.not_null, has_default_val: c.has_default_val }; @@ -744,6 +745,11 @@ define([ // Listener function which will be called before user updates existing cell // This will be used to collect primary key for that row grid.onBeforeEditCell.subscribe(function (e, args) { + if (args.column.column_type_internal == 'bytea' || + args.column.column_type_internal == 'bytea[]') { + return false; + } + var before_data = args.item; // If newly added row is saved but grid is not refreshed, @@ -2000,9 +2006,9 @@ define([ pg_types[pg_types.length - 1][0] : 'unknown'; if (!is_primary_key) - col_type += ' ' + type; + col_type += type; else - col_type += ' [PK] ' + type; + col_type += '[PK] ' + type; if (c.precision && c.precision >= 0 && c.precision != 65535) { col_type += ' (' + c.precision; @@ -2051,6 +2057,7 @@ define([ 'name': c.name, 'display_name': c.display_name, 'column_type': col_type, + 'column_type_internal': type, 'pos': c.pos, 'label': column_label, 'cell': col_cell, diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py b/web/pgadmin/utils/driver/psycopg2/__init__.py index 8a20521..cf6cfbd 100644 --- a/web/pgadmin/utils/driver/psycopg2/__init__.py +++ b/web/pgadmin/utils/driver/psycopg2/__init__.py @@ -120,6 +120,31 @@ def register_string_typecasters(connection): psycopg2.extensions.register_type(unicode_array_type) +def register_binary_typecasters(connection): + psycopg2.extensions.register_type( + psycopg2.extensions.new_type( + ( + # To cast bytea type + 17, + ), + 'BYTEA_PLACEHOLDER', + # Only show placeholder if data actually exists. + lambda value, cursor: '<binary data>' if value is not None else None), + connection + ) + + psycopg2.extensions.register_type( + psycopg2.extensions.new_type( + ( + # To cast bytea[] type + 1001, + ), + 'BYTEA_ARRAY_PLACEHOLDER', + # Only show placeholder if data actually exists. + lambda value, cursor: '<binary data[]>' if value is not None else None), + connection + ) + class Connection(BaseConnection): """ class Connection(object) @@ -201,7 +226,8 @@ class Connection(BaseConnection): """ - def __init__(self, manager, conn_id, db, auto_reconnect=True, async=0): + def __init__(self, manager, conn_id, db, auto_reconnect=True, async=0, + use_binary_placeholder=False): assert (manager is not None) assert (conn_id is not None) @@ -222,6 +248,7 @@ class Connection(BaseConnection): self.wasConnected = False # This flag indicates the connection reconnecting status. self.reconnecting = False + self.use_binary_placeholder = use_binary_placeholder super(Connection, self).__init__() @@ -239,6 +266,7 @@ class Connection(BaseConnection): res['database'] = self.db res['async'] = self.async res['wasConnected'] = self.wasConnected + res['use_binary_placeholder'] = self.use_binary_placeholder return res @@ -397,6 +425,10 @@ Failed to connect to the database server(#{server_id}) for connection ({conn_id} self.conn.autocommit = True register_string_typecasters(self.conn) + + if self.use_binary_placeholder: + register_binary_typecasters(self.conn) + status = _execute(cur, """ SET DateStyle=ISO; SET client_min_messages=notice; @@ -1639,7 +1671,7 @@ class ServerManager(object): def connection( self, database=None, conn_id=None, auto_reconnect=True, did=None, - async=None + async=None, use_binary_placeholder=False ): if database is not None: if hasattr(str, 'decode') and \ @@ -1693,7 +1725,7 @@ WHERE db.oid = {0}""".format(did)) else: async = 1 if async is True else 0 self.connections[my_id] = Connection( - self, my_id, database, auto_reconnect, async + self, my_id, database, auto_reconnect, async, use_binary_placeholder=use_binary_placeholder ) return self.connections[my_id] @@ -1722,7 +1754,8 @@ WHERE db.oid = {0}""".format(did)) conn_info = connections[conn_id] conn = self.connections[conn_info['conn_id']] = Connection( self, conn_info['conn_id'], conn_info['database'], - True, conn_info['async'] + True, conn_info['async'], + use_binary_placeholder=conn_info['use_binary_placeholder'] ) # only try to reconnect if connection was connected previously. if conn_info['wasConnected']: