Hi Dave,
On Tue, Jul 18, 2017 at 1:24 PM, Dave Page <[email protected]> wrote:
>
>
> On Tue, Jul 18, 2017 at 8:26 AM, Harshal Dhumal <
> [email protected]> wrote:
>
>> Hi Dave,
>>
>>
>> On Mon, Jul 17, 2017 at 9:33 PM, Dave Page <[email protected]> wrote:
>>
>>> Hi
>>>
>>> On Mon, Jul 17, 2017 at 1:09 PM, Harshal Dhumal <
>>> [email protected]> 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']: