Hi Hackers, Please ignore previous patch. Fixed some linter issues. PFA updated patch.
Thanks and Regards, Aditya Toshniwal Software Engineer | EnterpriseDB Software Solutions | Pune "Don't Complain about Heat, Plant a tree" On Mon, Jun 4, 2018 at 10:53 AM, Aditya Toshniwal < aditya.toshni...@enterprisedb.com> wrote: > Hi Hackers, > > PFA the updated patch on this. I have tried to add test cases to check for > different encoding database. In the test run, it will create a database, > fire a query for a string, check if we get the output and drops the > database. > Kindly review. > > Thanks and Regards, > Aditya Toshniwal > Software Engineer | EnterpriseDB Software Solutions | Pune > "Don't Complain about Heat, Plant a tree" > > On Thu, May 31, 2018 at 6:42 PM, Dave Page <dp...@pgadmin.org> wrote: > >> Hi >> >> On Thu, May 31, 2018 at 1:20 AM, Aditya Toshniwal < >> aditya.toshni...@enterprisedb.com> wrote: >> >>> Hi Victoria/Joao, >>> >>> On Thu, May 31, 2018 at 2:06 AM, Joao De Almeida Pereira < >>> jdealmeidapere...@pivotal.io> wrote: >>> >>>> Hello Aditya, >>>> >>>> It looks ok and it passes CI. >>>> >>>> We have some recommendations: >>>> - These look like 2 different changes so they should be in separated >>>> commits >>>> >>> >>> If you are talking of set client_encoding, then its not a bug. Its a >>> choice given to Postgres DB user to change the encoding of the characters. >>> Postgres will translate characters from Server Encoding to Client Encoding, >>> and will throw error like mentioned previously. This link will help better >>> - https://www.postgresql.org/docs/10/static/multibyte.html >>> The actual bug was, even after changing the client encoding to >>> SQL_ASCII, pgAdmin4 was not able to show the output as it was failing in >>> encoding by psycopg2. The patch is for resolving that. >>> >>> >>>> - Do we have test coverage for the bug that you are talking about? If >>>> not we should, to ensure this problem does not happen again in a future >>>> change. >>>> >>> >>> It is not possible adding test cases for encoding related stuff, as >>> Postgres support a lot many different types of encoding and conversions >>> (refer above link) >>> >> >> I was going to ask the same thing. Per https://www.postgresql.org >> /docs/10/static/multibyte.html#id-1.6.10.5.7, every characterset except >> SQL_ASCII can be converted to UTF-8, so we only need to test that UTF-8 and >> some other charactersets besides SQL_ASCII work, and then separately that >> SQL_ASCII with characters known not to be in UTF-8 work. >> >> >>> >>>> Thanks >>>> Victoria && Joao >>>> >>>> On Wed, May 30, 2018 at 3:06 AM Aditya Toshniwal < >>>> aditya.toshni...@enterprisedb.com> wrote: >>>> >>>>> Hi Hackers, >>>>> >>>>> PFA updated patch after all the permutations, combinations for >>>>> encoding for SQL_ASCII database. Also fixed a small glitch for sql >>>>> editor connection status check. >>>>> >>>>> Please note, ERROR: invalid byte sequence for encoding "UTF8": 0xe9 >>>>> 0x73 is a Postgres DB error and not pgAdmin4 error. >>>>> >>>>> <Image Deleted> >>>>> >>>>> You need to change client_encoding to the appropriate. After changing >>>>> client_encoding using command - set client_encoding='XYZ', it will give >>>>> not >>>>> give error. >>>>> >>>>> <Image Deleted> >>>>> >>>>> Thanks and Regards, >>>>> Aditya Toshniwal >>>>> Software Engineer | EnterpriseDB Software Solutions | Pune >>>>> "Don't Complain about Heat, Plant a tree" >>>>> >>>>> On Wed, May 23, 2018 at 10:13 AM, Aditya Toshniwal < >>>>> aditya.toshni...@enterprisedb.com> wrote: >>>>> >>>>>> Thank you Victoria, Anthony. >>>>>> >>>>>> Thanks and Regards, >>>>>> Aditya Toshniwal >>>>>> Software Engineer | EnterpriseDB Software Solutions | Pune >>>>>> "Don't Complain about Heat, Plant a tree" >>>>>> >>>>>> On Tue, May 22, 2018 at 7:15 PM, Victoria Henry <vhe...@pivotal.io> >>>>>> wrote: >>>>>> >>>>>>> Hi Aditya, >>>>>>> >>>>>>> We made a minor change to make the patch so the python linter can >>>>>>> pass. Attached is the change we made. >>>>>>> Everything else looks good. >>>>>>> >>>>>>> Sincerely, >>>>>>> >>>>>>> Victoria & Anthony >>>>>>> >>>>>>> On Tue, May 22, 2018 at 4:46 AM Aditya Toshniwal < >>>>>>> aditya.toshni...@enterprisedb.com> wrote: >>>>>>> >>>>>>>> Hi, >>>>>>>> >>>>>>>> PFA updated patch. Linter issues are fixed ( we dont have any >>>>>>>> linter setup for python :-( ) >>>>>>>> Regarding test cases, they run successfully on my system and the >>>>>>>> reason it failed for pivotal is timeout exception. I am sorry I can't >>>>>>>> help >>>>>>>> with that. >>>>>>>> >>>>>>>> Traceback (most recent call last): >>>>>>>> File >>>>>>>> "/tmp/build/a453582b/pgadmin-repo/web/pgadmin/feature_tests/keyboard_shortcut_test.py", >>>>>>>> line 52, in runTest >>>>>>>> self._check_shortcuts() >>>>>>>> File >>>>>>>> "/tmp/build/a453582b/pgadmin-repo/web/pgadmin/feature_tests/keyboard_shortcut_test.py", >>>>>>>> line 77, in _check_shortcuts >>>>>>>> ") and contains(@class, 'open')]") >>>>>>>> File "/root/.pyenv/versions/pgadmin36/lib/python3.6/site-packages >>>>>>>> /selenium/webdriver/support/wait.py", line 80, in until >>>>>>>> raise TimeoutException(message, screen, stacktrace) >>>>>>>> selenium.common.exceptions.TimeoutException: Message: >>>>>>>> >>>>>>>> Thanks and Regards, >>>>>>>> Aditya Toshniwal >>>>>>>> Software Engineer | EnterpriseDB Software Solutions | Pune >>>>>>>> "Don't Complain about Heat, Plant a tree" >>>>>>>> >>>>>>>> On Tue, May 22, 2018 at 1:37 PM, Dave Page <dp...@pgadmin.org> >>>>>>>> wrote: >>>>>>>> >>>>>>>>> Hi >>>>>>>>> >>>>>>>>> Pivotal's buildbot is showing problems with this patch: >>>>>>>>> >>>>>>>>> https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines >>>>>>>>> /pgadmin-patch/jobs/run-linter/builds/66 (linter failed) >>>>>>>>> https://gpdb-dev.bosh.pivotalci.info/teams/pgadmin/pipelines >>>>>>>>> /pgadmin-patch/jobs/run-tests/builds/84 (tests failed) >>>>>>>>> >>>>>>>>> >>>>>>>>> On Tue, May 22, 2018 at 7:05 AM, Aditya Toshniwal < >>>>>>>>> aditya.toshni...@enterprisedb.com> wrote: >>>>>>>>> >>>>>>>>>> Hi Hackers, >>>>>>>>>> >>>>>>>>>> PFA patch for RM#3289 where decode error was thrown on querying a >>>>>>>>>> SQL_ASCII database table. Please note, this problem occurs only on >>>>>>>>>> windows. >>>>>>>>>> Sample insert - insert into test_tab values ('é'); >>>>>>>>>> >>>>>>>>>> psycopg2 has a encodings dictionary where Postgres Database >>>>>>>>>> Encodings are mapped to python equivalent. It uses 'ascii' decoder of >>>>>>>>>> python to decode for SQL_ASCII encoding. If data has characters >>>>>>>>>> beyond the >>>>>>>>>> limit of ascii then it failed. The solution would be to use utf_8 >>>>>>>>>> decoder >>>>>>>>>> instead of ascii. I tried setting the client_encoding using >>>>>>>>>> set_client_encoding('UTF8') method of a psycopg2 connection but no >>>>>>>>>> luck >>>>>>>>>> (also its not allowed for async connection). I also tried executing >>>>>>>>>> "SET >>>>>>>>>> CLIENT_ENCODING='UTF8'" but it didn't work too. >>>>>>>>>> So, as in the patch, I had to set encodings dict value directly >>>>>>>>>> to 'utf_8' and it seems to be working. Please note, the same is >>>>>>>>>> added to >>>>>>>>>> psycopg3 milestones >>>>>>>>>> https://github.com/psycopg/psycopg2/milestone/4 >>>>>>>>>> >>>>>>>>>> Also fixed a small glitch for sql editor connection status check. >>>>>>>>>> >>>>>>>>>> Kindly review. >>>>>>>>>> >>>>>>>>>> Thanks and Regards, >>>>>>>>>> Aditya Toshniwal >>>>>>>>>> Software Engineer | EnterpriseDB Software Solutions | Pune >>>>>>>>>> "Don't Complain about Heat, Plant a tree" >>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> -- >>>>>>>>> Dave Page >>>>>>>>> Blog: http://pgsnake.blogspot.com >>>>>>>>> Twitter: @pgsnake >>>>>>>>> >>>>>>>>> EnterpriseDB UK: http://www.enterprisedb.com >>>>>>>>> The Enterprise PostgreSQL Company >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>> >>>>> >>> >> >> >> -- >> Dave Page >> Blog: http://pgsnake.blogspot.com >> Twitter: @pgsnake >> >> EnterpriseDB UK: http://www.enterprisedb.com >> The Enterprise PostgreSQL Company >> > >
diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py index 013e4dc..a9460dd 100644 --- a/web/pgadmin/tools/sqleditor/__init__.py +++ b/web/pgadmin/tools/sqleditor/__init__.py @@ -1480,19 +1480,24 @@ def query_tool_status(trans_id): if conn and trans_obj and session_obj: status = conn.transaction_status() - # Check for the asynchronous notifies statements. - conn.check_notifies(True) - notifies = conn.get_notifies() + if status is not None: + # Check for the asynchronous notifies statements. + conn.check_notifies(True) + notifies = conn.get_notifies() - return make_json_response( - data={ - 'status': status, - 'message': gettext( - CONNECTION_STATUS_MESSAGE_MAPPING.get(status), - ), - 'notifies': notifies - } - ) + return make_json_response( + data={ + 'status': status, + 'message': gettext( + CONNECTION_STATUS_MESSAGE_MAPPING.get(status), + ), + 'notifies': notifies + } + ) + else: + return internal_server_error( + errormsg=gettext("Transaction status check failed.") + ) else: return internal_server_error( errormsg=gettext("Transaction status check failed.") diff --git a/web/pgadmin/tools/sqleditor/tests/test_encoding_charset.py b/web/pgadmin/tools/sqleditor/tests/test_encoding_charset.py new file mode 100644 index 0000000..64155bf --- /dev/null +++ b/web/pgadmin/tools/sqleditor/tests/test_encoding_charset.py @@ -0,0 +1,132 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2018, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + +import os +import re + +from flask import Flask, render_template +from jinja2 import FileSystemLoader + +from pgadmin import VersionedTemplateLoader +from pgadmin.utils.route import BaseTestGenerator +from pgadmin.utils.driver import get_driver +from config import PG_DEFAULT_DRIVER +from pgadmin.browser.server_groups.servers.databases.tests import utils as \ + database_utils + +from regression import parent_node_dict +from regression.python_test_utils import test_utils +import json + + +class TestEncodingCharset(BaseTestGenerator): + """ + This class validates character support in pgAdmin4 for + different PostgresDB encodings + """ + scenarios = [ + ( + 'With Encoding UTF8', + dict( + db_encoding='UTF8', + lc_collate='C', + test_str='A', + set_client_encoding=False + )), + ( + 'With Encoding WIN1252', + dict( + db_encoding='WIN1252', + lc_collate='C', + test_str='A', + set_client_encoding=False + )), + ( + 'With Encoding EUC_CN', + dict( + db_encoding='EUC_CN', + lc_collate='C', + test_str='A', + set_client_encoding=False + )), + ( + 'With Encoding SQL_ASCII', + dict( + db_encoding='SQL_ASCII', + lc_collate='C', + test_str='\\255', + set_client_encoding=True + )), + ] + + def setUp(self): + server_details = parent_node_dict['server'][-1] + server = server_details['server'] + self.main_conn = test_utils.get_db_connection( + server['db'], + server['username'], + server['db_password'], + server['host'], + server['port'], + server['sslmode'] + ) + self.encode_db_name = 'encoding_test' + self.encode_sid = server_details['server_id'] + self.encode_did = test_utils.create_database( + self.server, self.encode_db_name, + (self.db_encoding, self.lc_collate)) + + def runTest(self): + + db_con = database_utils.connect_database(self, + test_utils.SERVER_GROUP, + self.encode_sid, + self.encode_did) + if not db_con["info"] == "Database connected.": + raise Exception("Could not connect to the database.") + + # Initialize query tool + url = '/datagrid/initialize/query_tool/{0}/{1}/{2}'.format( + test_utils.SERVER_GROUP, self.encode_sid, self.encode_did) + response = self.tester.post(url) + self.assertEquals(response.status_code, 200) + + response_data = json.loads(response.data.decode('utf-8')) + self.trans_id = response_data['data']['gridTransId'] + + if self.set_client_encoding: + # Change Client Encoding + url = "/sqleditor/query_tool/start/{0}".format(self.trans_id) + sql = "set client_encoding = '{0}';".format(self.db_encoding) + response = self.tester.post(url, data=json.dumps({"sql": sql}), + content_type='html/json') + self.assertEquals(response.status_code, 200) + url = '/sqleditor/poll/{0}'.format(self.trans_id) + response = self.tester.get(url) + self.assertEquals(response.status_code, 200) + response_data = json.loads(response.data.decode('utf-8')) + + # Check character + url = "/sqleditor/query_tool/start/{0}".format(self.trans_id) + sql = "select E'{0}';".format(self.test_str) + response = self.tester.post(url, data=json.dumps({"sql": sql}), + content_type='html/json') + self.assertEquals(response.status_code, 200) + url = '/sqleditor/poll/{0}'.format(self.trans_id) + response = self.tester.get(url) + self.assertEquals(response.status_code, 200) + response_data = json.loads(response.data.decode('utf-8')) + self.assertEquals(response_data['data']['rows_fetched_to'], 1) + + database_utils.disconnect_database(self, self.encode_sid, + self.encode_did) + + def tearDown(self): + test_utils.drop_database(self.main_conn, self.encode_db_name) + self.main_conn.close() diff --git a/web/pgadmin/utils/driver/psycopg2/connection.py b/web/pgadmin/utils/driver/psycopg2/connection.py index cfd161a..e8ca886 100644 --- a/web/pgadmin/utils/driver/psycopg2/connection.py +++ b/web/pgadmin/utils/driver/psycopg2/connection.py @@ -51,6 +51,12 @@ else: _ = gettext +# Replace default ascii encoder with unicode-escape +# which translates characters to unicode format. +# Escape special characters to ASCII based on unicode +encodings['SQL_ASCII'] = 'unicode-escape' +encodings['SQLASCII'] = 'unicode-escape' + # Register global type caster which will be applicable to all connections. register_global_typecasters() diff --git a/web/pgadmin/utils/driver/psycopg2/typecast.py b/web/pgadmin/utils/driver/psycopg2/typecast.py index f136604..ccebb2f 100644 --- a/web/pgadmin/utils/driver/psycopg2/typecast.py +++ b/web/pgadmin/utils/driver/psycopg2/typecast.py @@ -164,7 +164,7 @@ def register_global_typecasters(): def register_string_typecasters(connection): - if connection.encoding != 'UTF8': + if connection.encoding not in ('UTF8', 'SQLASCII', 'SQL_ASCII'): # In python3 when database encoding is other than utf-8 and client # encoding is set to UNICODE then we need to map data from database # encoding to utf-8. diff --git a/web/regression/python_test_utils/test_utils.py b/web/regression/python_test_utils/test_utils.py index 3e517b6..464a09e 100644 --- a/web/regression/python_test_utils/test_utils.py +++ b/web/regression/python_test_utils/test_utils.py @@ -116,7 +116,7 @@ def clear_node_info_dict(): del node_info_dict[node][:] -def create_database(server, db_name): +def create_database(server, db_name, encoding=None): """This function used to create database and returns the database id""" try: connection = get_db_connection( @@ -130,8 +130,14 @@ def create_database(server, db_name): old_isolation_level = connection.isolation_level connection.set_isolation_level(0) pg_cursor = connection.cursor() - pg_cursor.execute( - '''CREATE DATABASE "%s" TEMPLATE template0''' % db_name) + if encoding is None: + pg_cursor.execute( + '''CREATE DATABASE "%s" TEMPLATE template0''' % db_name) + else: + pg_cursor.execute( + '''CREATE DATABASE "%s" TEMPLATE template0 + ENCODING='%s' LC_COLLATE='%s' LC_CTYPE='%s' ''' % + (db_name, encoding[0], encoding[1], encoding[1])) connection.set_isolation_level(old_isolation_level) connection.commit()