From 7493649893c167e2923ca8a42760baa46ba9c255 Mon Sep 17 00:00:00 2001 From: Ganesh Jaybhay Date: Thu, 16 Apr 2020 12:47:00 +0530 Subject: [PATCH] =?UTF-8?q?Added=20schema-qualified=20dictionary=20names?= =?UTF-8?q?=20in=20FTS=20configuration=20to=20avoid=C2=A0confusion=20of=20?= =?UTF-8?q?duplicate=C2=A0names.=20Fixes=20#4709?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en_US/release_notes_4_21.rst | 1 + .../sql/default/dictionaries.sql | 11 +- .../fts_configurations/sql/default/sql.sql | 9 +- .../sql/default/tokenDictList.sql | 9 +- ...alter_fts_conf_add_token_verify_schema.sql | 8 ++ .../tests/default/create_fts_dictionary.sql | 7 ++ ...alter_fts_conf_add_token_verify_schema.sql | 3 + .../default/msql_create_fts_dictionary.sql | 3 + .../tests/default/test.json | 30 ++++- .../tests/test_fts_configuration_put.py | 108 ++++++++++++++++++ 10 files changed, 179 insertions(+), 10 deletions(-) create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/alter_fts_conf_add_token_verify_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/create_fts_dictionary.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/msql_alter_fts_conf_add_token_verify_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/msql_create_fts_dictionary.sql diff --git a/docs/en_US/release_notes_4_21.rst b/docs/en_US/release_notes_4_21.rst index 798d2caa1..0c1df690a 100644 --- a/docs/en_US/release_notes_4_21.rst +++ b/docs/en_US/release_notes_4_21.rst @@ -34,6 +34,7 @@ Bug fixes | `Issue #4292 `_ - Added dark mode support for the configuration dialog on Windows/macOS runtime. | `Issue #4445 `_ - Ensure all object names in the title line of the reverse-engineered SQL are not quoted. | `Issue #4512 `_ - Fixed calendar opening issue on the exception tab inside the schedules tab of pgAgent. +| `Issue #4709 `_ - Added schema-qualified dictionary names in FTS configuration to avoid confusion of duplicate names. | `Issue #4856 `_ - Enable the save button by default when a query tool is opened with CREATE or other scripts. | `Issue #4858 `_ - Fixed python exception error when user tries to download the CSV and there is a connection issue. | `Issue #4864 `_ - Make the configuration window in runtime to auto-resize. diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/dictionaries.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/dictionaries.sql index f0e7b0fea..944a8a013 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/dictionaries.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/dictionaries.sql @@ -1,7 +1,8 @@ {# FETCH DICTIONARIES statement #} SELECT - dictname -FROM - pg_ts_dict -ORDER BY - dictname \ No newline at end of file + CASE WHEN (pg_ns.nspname != 'pg_catalog') THEN + CONCAT(pg_ns.nspname, '.', pg_td.dictname) + ELSE pg_td.dictname END AS dictname +FROM pg_ts_dict pg_td +LEFT OUTER JOIN pg_namespace pg_ns +ON pg_td.dictnamespace = pg_ns.oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/sql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/sql.sql index 76ed60e9a..06d5af3fc 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/sql.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/sql.sql @@ -24,10 +24,14 @@ FROM array_to_string( array( SELECT - 'ALTER TEXT SEARCH CONFIGURATION ' || quote_ident(nspname) || + 'ALTER TEXT SEARCH CONFIGURATION ' || quote_ident(b.nspname) || E'.' || quote_ident(cfg.cfgname) || ' ADD MAPPING FOR ' || t.alias || ' WITH ' || - array_to_string(array_agg(dict.dictname), ', ') || ';' + array_to_string(array_agg( + CASE WHEN (pg_ns.nspname != 'pg_catalog') THEN + CONCAT(pg_ns.nspname, '.', dict.dictname) + ELSE + dict.dictname END), ', ') || ';' FROM pg_ts_config_map map LEFT JOIN ( @@ -38,6 +42,7 @@ FROM pg_catalog.ts_token_type(cfg.cfgparser) ) t ON (t.tokid = map.maptokentype) LEFT OUTER JOIN pg_ts_dict dict ON (map.mapdict = dict.oid) + LEFT OUTER JOIN pg_namespace pg_ns ON (pg_ns.oid = dict.dictnamespace) WHERE map.mapcfg = cfg.oid GROUP BY t.alias diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/tokenDictList.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/tokenDictList.sql index e8a2d5bf8..7c52ce61f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/tokenDictList.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/tokenDictList.sql @@ -9,15 +9,20 @@ SELECT WHERE t.tokid = maptokentype ) AS token, - array_agg(dictname) AS dictname + array_agg( + CASE WHEN (pg_ns.nspname != 'pg_catalog') THEN + CONCAT(pg_ns.nspname, '.', pg_ts_dict.dictname) + ELSE + pg_ts_dict.dictname END) AS dictname FROM pg_ts_config_map LEFT OUTER JOIN pg_ts_config ON mapcfg = pg_ts_config.oid LEFT OUTER JOIN pg_ts_dict ON mapdict = pg_ts_dict.oid + LEFT OUTER JOIN pg_namespace pg_ns ON pg_ns.oid = pg_ts_dict.dictnamespace WHERE mapcfg={{cfgid}}::OID GROUP BY token ORDER BY 1 -{% endif %} \ No newline at end of file +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/alter_fts_conf_add_token_verify_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/alter_fts_conf_add_token_verify_schema.sql new file mode 100644 index 000000000..99f974108 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/alter_fts_conf_add_token_verify_schema.sql @@ -0,0 +1,8 @@ +-- Text Search CONFIGURATION: test.test_fts_conf_$%{}[]()&*^!@"'`\/# + +-- DROP TEXT SEARCH CONFIGURATION test."test_fts_conf_$%{}[]()&*^!@""'`\/#" + +CREATE TEXT SEARCH CONFIGURATION test."test_fts_conf_$%{}[]()&*^!@""'`\/#" ( + PARSER = default +); +ALTER TEXT SEARCH CONFIGURATION test."test_fts_conf_$%{}[]()&*^!@""'`\/#" ADD MAPPING FOR asciiword WITH test.test_dic; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/create_fts_dictionary.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/create_fts_dictionary.sql new file mode 100644 index 000000000..155ba9115 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/create_fts_dictionary.sql @@ -0,0 +1,7 @@ +-- Text Search Dictionary: test.test_dic + +-- DROP TEXT SEARCH DICTIONARY test.test_dic; + +CREATE TEXT SEARCH DICTIONARY test.test_dic ( + TEMPLATE = simple +); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/msql_alter_fts_conf_add_token_verify_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/msql_alter_fts_conf_add_token_verify_schema.sql new file mode 100644 index 000000000..a2619e3a5 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/msql_alter_fts_conf_add_token_verify_schema.sql @@ -0,0 +1,3 @@ +ALTER TEXT SEARCH CONFIGURATION test."test_fts_conf_$%{}[]()&*^!@""'`\/#" + ADD MAPPING FOR asciiword + WITH test.test_dic; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/msql_create_fts_dictionary.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/msql_create_fts_dictionary.sql new file mode 100644 index 000000000..7e8098529 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/msql_create_fts_dictionary.sql @@ -0,0 +1,3 @@ +CREATE TEXT SEARCH DICTIONARY test.test_dic ( + TEMPLATE = simple +); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/test.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/test.json index b3b1b5122..6b2273237 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/test.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/default/test.json @@ -1,5 +1,22 @@ { - "scenarios": [{ + "scenarios": [ + { + "type": "create", + "name": "Create FTS Dictionary", + "endpoint": "NODE-fts_dictionary.obj", + "sql_endpoint": "NODE-fts_dictionary.sql_id", + "msql_endpoint": "NODE-fts_dictionary.msql", + "data": { + "name": "test_dic", + "template": "simple", + "options": [], + "schema": "test", + "schema_id": "", + "owner": "postgres" + }, + "expected_sql_file": "create_fts_dictionary.sql", + "expected_msql_file": "msql_create_fts_dictionary.sql" + }, { "type": "create", "name": "Create FTS Configuration", "endpoint": "NODE-fts_configuration.obj", @@ -14,6 +31,17 @@ }, "expected_sql_file": "create_fts_conf.sql", "expected_msql_file": "msql_create_fts_conf.sql" + }, { + "type": "alter", + "name": "Alter FTS Configuration add token to verify schema qualified names", + "endpoint": "NODE-fts_configuration.obj_id", + "sql_endpoint": "NODE-fts_configuration.sql_id", + "msql_endpoint": "NODE-fts_configuration.msql_id", + "data": { + "tokens": {"added": [{"token": "asciiword", "dictname": ["test.test_dic"]}]} + }, + "expected_sql_file": "alter_fts_conf_add_token_verify_schema.sql", + "expected_msql_file": "msql_alter_fts_conf_add_token_verify_schema.sql" }, { "type": "delete", "name": "Drop FTS Configuration", diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/test_fts_configuration_put.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/test_fts_configuration_put.py index 3faa0678a..d79031c59 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/test_fts_configuration_put.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/tests/test_fts_configuration_put.py @@ -22,6 +22,8 @@ from pgadmin.utils.route import BaseTestGenerator from regression import parent_node_dict from regression.python_test_utils import test_utils as utils from . import utils as fts_configuration_utils +from pgadmin.browser.server_groups.servers.databases.schemas \ + .fts_dictionaries.tests import utils as fts_dict_utils class FTSConfPutTestCase(BaseTestGenerator): @@ -96,3 +98,109 @@ class FTSConfPutTestCase(BaseTestGenerator): self.fts_conf_name) database_utils.disconnect_database(self, self.server_id, self.db_id) + + +class FTSConfDictPutTestCase(BaseTestGenerator): + """ This class will update the tokens/dictionaries of + added FTS configuration under schema node. """ + + scenarios = [ + # Fetching default URL for fts_configuration node. + ('Fetch FTS configuration Node URL', + dict(url='/browser/fts_configuration/obj/')) + ] + + def setUp(self): + """ This function will create FTS configuration.""" + + schema_data = parent_node_dict['schema'][-1] + self.schema_name = schema_data['schema_name'] + self.schema_id = schema_data['schema_id'] + self.server_id = schema_data['server_id'] + self.db_id = schema_data['db_id'] + self.db_name = parent_node_dict["database"][-1]["db_name"] + self.fts_conf_name = "fts_conf_%s" % str(uuid.uuid4())[1:8] + + self.fts_conf_id = fts_configuration_utils.create_fts_configuration( + self.server, self.db_name, self.schema_name, self.fts_conf_name) + + self.fts_dict_name = "fts_dict_%s" % str(uuid.uuid4())[1:8] + + # first add dictionary for update + self.fts_dict_id = fts_dict_utils.create_fts_dictionary( + self.server, + self.db_name, + self.schema_name, + self.fts_dict_name) + + def runTest(self): + """ This function will update tokens of new FTS configuration.""" + + db_con = database_utils.connect_database(self, + utils.SERVER_GROUP, + self.server_id, + self.db_id) + + if not db_con["info"] == "Database connected.": + raise Exception("Could not connect to database.") + + schema_response = schema_utils.verify_schemas(self.server, + self.db_name, + self.schema_name) + if not schema_response: + raise Exception("Could not find the schema.") + + fts_conf_response = fts_configuration_utils.verify_fts_configuration( + self.server, self.db_name, self.fts_conf_name + ) + + if not fts_conf_response: + raise Exception("Could not find the FTS Configuration.") + + dictname = self.schema_name + '.' + self.fts_dict_name + + data = { + "oid": self.fts_conf_id, + "tokens": { + "added": + [{ + "token": "asciihword", + "dictname": [dictname] + }] + } + } + + put_response = self.tester.put( + self.url + str(utils.SERVER_GROUP) + '/' + + str(self.server_id) + '/' + + str(self.db_id) + '/' + + str(self.schema_id) + '/' + + str(self.fts_conf_id), + data=json.dumps(data), + follow_redirects=True) + self.assertEquals(put_response.status_code, 200) + + # check again whether dictionary is schema qualified + get_response = self.tester.get( + self.url + str(utils.SERVER_GROUP) + '/' + + str(self.server_id) + '/' + + str(self.db_id) + '/' + + str(self.schema_id) + '/' + + str(self.fts_conf_id), + content_type='html/json') + response_data = json.loads(get_response.data) + res_dictname = response_data["tokens"][0]["dictname"] + + self.assertEquals(dictname, res_dictname[0]) + + def tearDown(self): + """This function delete the fts_config and disconnect the test + database.""" + fts_config_utils.delete_fts_configurations(self.server, self.db_name, + self.schema_name, + self.fts_conf_name) + fts_dict_utils.delete_fts_dictionaries(self.server, self.db_name, + self.schema_name, + self.fts_dict_name) + database_utils.disconnect_database(self, self.server_id, + self.db_id)