Hi Dave,

On Tue, Jul 18, 2017 at 8:31 PM, Dave Page <dp...@pgadmin.org> wrote:

>
>
> On Tue, Jul 18, 2017 at 2:40 PM, Harshal Dhumal <
> harshal.dhu...@enterprisedb.com> wrote:
>
>> 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).
>>
>>
> Thanks, that passes.
>
> Now I've played with it though, I think that the query tool should also
> hide the binary data.  I don't see a good reason to see it in one place but
> not another - ultimately it's still not human readable.
>
> Also, we need to make it look like the [null] placeholder I think; e.g.
> use [ ] instead of < > and give it a lighter colour.
>
> Please find updated patch. I have fixed all of above review comments.


>
> --
> 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/pg_datatype_validation_test.py b/web/pgadmin/feature_tests/pg_datatype_validation_test.py
index 149a496..703f0c5 100644
--- a/web/pgadmin/feature_tests/pg_datatype_validation_test.py
+++ b/web/pgadmin/feature_tests/pg_datatype_validation_test.py
@@ -103,7 +103,7 @@ class PGDataypeFeatureTest(BaseFeatureTest):
             '922337203685.922337203685', '-92233720368547758.08',
             '{1,2,3}', '{NaN,NaN,NaN}',
             'Infinity', '{Infinity}',
-            r'\336\255\276\357', r'{"\\336\\255\\276\\357","\\336\\255\\276\\357"}'
+            r'[binary data]', r'[binary data[]]'
         ]
 
         self.page.open_query_tool()
@@ -122,7 +122,7 @@ class PGDataypeFeatureTest(BaseFeatureTest):
         cells.pop(0)
         for val, cell in zip(expected_output, cells):
             try:
-                source_code = cell.get_attribute('innerHTML')
+                source_code = cell.text
 
                 PGDataypeFeatureTest.check_result(
                     source_code,
diff --git a/web/pgadmin/feature_tests/view_data_dml_queries.py b/web/pgadmin/feature_tests/view_data_dml_queries.py
index 622387e..e8cf598 100644
--- a/web/pgadmin/feature_tests/view_data_dml_queries.py
+++ b/web/pgadmin/feature_tests/view_data_dml_queries.py
@@ -101,6 +101,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)
@@ -160,6 +161,7 @@ CREATE TABLE public.defaults
         Returns: None
 
         """
+
         self.wait.until(EC.visibility_of_element_located(
             (By.XPATH, xpath)), CheckForViewDataTest.TIMEOUT_STRING
         )
@@ -197,6 +199,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')
@@ -263,6 +267,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/static/js/slickgrid/slick.pgadmin.formatters.js b/web/pgadmin/static/js/slickgrid/slick.pgadmin.formatters.js
index d14b181..1a0d60b 100644
--- a/web/pgadmin/static/js/slickgrid/slick.pgadmin.formatters.js
+++ b/web/pgadmin/static/js/slickgrid/slick.pgadmin.formatters.js
@@ -92,6 +92,9 @@
       (_.isUndefined(value) || _.isNull(value))
     ) {
       return "<span class='pull-left disabled_cell'>[null]</span>";
+    } else if(columnDef.column_type_internal == 'bytea' ||
+      columnDef.column_type_internal == 'bytea[]') {
+      return "<span class='pull-left disabled_cell'>[" + _.escape(value) + "]</span>";
     }
     else {
       return _.escape(value);
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/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py
index 762765e..2ffc74a 100644
--- a/web/pgadmin/tools/sqleditor/__init__.py
+++ b/web/pgadmin/tools/sqleditor/__init__.py
@@ -257,7 +257,8 @@ def check_transaction_status(trans_id):
 
     try:
         manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(trans_obj.sid)
-        conn = manager.connection(did=trans_obj.did, conn_id=trans_obj.conn_id)
+        conn = manager.connection(did=trans_obj.did, conn_id=trans_obj.conn_id,
+                                  use_binary_placeholder=True)
     except Exception as e:
         return False, internal_server_error(errormsg=str(e)), None, None, None
 
@@ -396,7 +397,8 @@ def start_query_tool(trans_id):
 
         try:
             manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(trans_obj.sid)
-            conn = manager.connection(did=trans_obj.did, conn_id=conn_id)
+            conn = manager.connection(did=trans_obj.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 ff98563..b3ce2f0 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('tools.querytool', [
               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('tools.querytool', [
         // 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,
@@ -2074,9 +2080,9 @@ define('tools.querytool', [
                            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;
@@ -2125,6 +2131,7 @@ define('tools.querytool', [
               '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..5301f73 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,8 @@ 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 +1755,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']:

Reply via email to