Added schema-qualified dictionary names in FTS configuration to avoid confusion of duplicate names. Fixes #4709

This commit is contained in:
Ganesh Jaybhay 2020-04-16 12:47:00 +05:30 committed by Akshay Joshi
parent 738c421edf
commit 7493649893
10 changed files with 179 additions and 10 deletions

View File

@ -34,6 +34,7 @@ Bug fixes
| `Issue #4292 <https://redmine.postgresql.org/issues/4292>`_ - Added dark mode support for the configuration dialog on Windows/macOS runtime.
| `Issue #4445 <https://redmine.postgresql.org/issues/4445>`_ - Ensure all object names in the title line of the reverse-engineered SQL are not quoted.
| `Issue #4512 <https://redmine.postgresql.org/issues/4512>`_ - Fixed calendar opening issue on the exception tab inside the schedules tab of pgAgent.
| `Issue #4709 <https://redmine.postgresql.org/issues/4709>`_ - Added schema-qualified dictionary names in FTS configuration to avoid confusion of duplicate names.
| `Issue #4856 <https://redmine.postgresql.org/issues/4856>`_ - Enable the save button by default when a query tool is opened with CREATE or other scripts.
| `Issue #4858 <https://redmine.postgresql.org/issues/4858>`_ - Fixed python exception error when user tries to download the CSV and there is a connection issue.
| `Issue #4864 <https://redmine.postgresql.org/issues/4864>`_ - Make the configuration window in runtime to auto-resize.

View File

@ -1,7 +1,8 @@
{# FETCH DICTIONARIES statement #}
SELECT
dictname
FROM
pg_ts_dict
ORDER BY
dictname
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;

View File

@ -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

View File

@ -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 %}
{% endif %}

View File

@ -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;

View File

@ -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
);

View File

@ -0,0 +1,3 @@
ALTER TEXT SEARCH CONFIGURATION test."test_fts_conf_$%{}[]()&*^!@""'`\/#"
ADD MAPPING FOR asciiword
WITH test.test_dic;

View File

@ -0,0 +1,3 @@
CREATE TEXT SEARCH DICTIONARY test.test_dic (
TEMPLATE = simple
);

View File

@ -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": "<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",

View File

@ -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)