CREATE SCHEMA text_search; CREATE SCHEMA text_search2; SET search_path TO text_search; -- create a new configuration from scratch CREATE TEXT SEARCH CONFIGURATION my_text_search_config ( parser = default ); CREATE TABLE t1(id int, name text); CREATE INDEX t1_search_name ON t1 USING gin (to_tsvector('text_search.my_text_search_config'::regconfig, (COALESCE(name, ''::character varying))::text)); SELECT create_distributed_table('t1', 'name'); create_distributed_table --------------------------------------------------------------------- (1 row) DROP TABLE t1; DROP TEXT SEARCH CONFIGURATION my_text_search_config; -- try to create table and index in 1 transaction BEGIN; CREATE TEXT SEARCH CONFIGURATION my_text_search_config ( parser = default ); CREATE TABLE t1(id int, name text); CREATE INDEX t1_search_name ON t1 USING gin (to_tsvector('text_search.my_text_search_config'::regconfig, (COALESCE(name, ''::character varying))::text)); SELECT create_distributed_table('t1', 'name'); create_distributed_table --------------------------------------------------------------------- (1 row) ABORT; -- try again, should not fail with my_text_search_config being retained on the worker BEGIN; CREATE TEXT SEARCH CONFIGURATION my_text_search_config ( parser = default ); COMMENT ON TEXT SEARCH CONFIGURATION my_text_search_config IS 'on demand propagation of text search object with a comment'; CREATE TABLE t1(id int, name text); CREATE INDEX t1_search_name ON t1 USING gin (to_tsvector('text_search.my_text_search_config'::regconfig, (COALESCE(name, ''::character varying))::text)); SELECT create_distributed_table('t1', 'name'); create_distributed_table --------------------------------------------------------------------- (1 row) -- verify that we can change the object COMMENT ON TEXT SEARCH CONFIGURATION my_text_search_config IS 'this comment can be set right now'; COMMIT; SELECT * FROM run_command_on_workers($$ SELECT obj_description('text_search.my_text_search_config'::regconfig); $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | this comment can be set right now localhost | 57638 | t | this comment can be set right now (2 rows) DROP TABLE t1; -- create an index on an already distributed table BEGIN; CREATE TEXT SEARCH CONFIGURATION my_text_search_config2 ( parser = default ); COMMENT ON TEXT SEARCH CONFIGURATION my_text_search_config2 IS 'on demand propagation of text search object with a comment 2'; CREATE TABLE t1(id int, name text); SELECT create_distributed_table('t1', 'name'); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE INDEX t1_search_name ON t1 USING gin (to_tsvector('text_search.my_text_search_config2'::regconfig, (COALESCE(name, ''::character varying))::text)); COMMIT; SELECT * FROM run_command_on_workers($$ SELECT obj_description('text_search.my_text_search_config2'::regconfig); $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | on demand propagation of text search object with a comment 2 localhost | 57638 | t | on demand propagation of text search object with a comment 2 (2 rows) DROP TABLE t1; -- should be able to create a configuration based on a copy of an existing configuration CREATE TEXT SEARCH CONFIGURATION french_noaccent ( COPY = french ); CREATE TABLE t2(id int, name text); CREATE INDEX t2_search_name ON t2 USING gin (to_tsvector('text_search.french_noaccent'::regconfig, (COALESCE(name, ''::character varying))::text)); SELECT create_distributed_table('t2', 'id'); create_distributed_table --------------------------------------------------------------------- (1 row) -- spot check that french_noaccent copied settings from french SELECT * FROM run_command_on_workers($$ SELECT ROW(alias,dictionary) FROM ts_debug('text_search.french_noaccent', 'comment tu t''appelle') WHERE alias = 'asciiword' LIMIT 1; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | (asciiword,french_stem) localhost | 57638 | t | (asciiword,french_stem) (2 rows) -- makes no sense, however we expect that the dictionary for the first token changes accordingly ALTER TEXT SEARCH CONFIGURATION french_noaccent ALTER MAPPING FOR asciiword WITH dutch_stem; SELECT * FROM run_command_on_workers($$ SELECT ROW(alias,dictionary) FROM ts_debug('text_search.french_noaccent', 'comment tu t''appelle') WHERE alias = 'asciiword' LIMIT 1; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | (asciiword,dutch_stem) localhost | 57638 | t | (asciiword,dutch_stem) (2 rows) -- do the same but we will replace all french dictionaries SELECT * FROM run_command_on_workers($$ SELECT ROW(alias,dictionary) FROM ts_debug('text_search.french_noaccent', 'un chou-fleur') WHERE alias = 'asciihword' LIMIT 1; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | (asciihword,french_stem) localhost | 57638 | t | (asciihword,french_stem) (2 rows) ALTER TEXT SEARCH CONFIGURATION french_noaccent ALTER MAPPING REPLACE french_stem WITH dutch_stem; SELECT * FROM run_command_on_workers($$ SELECT ROW(alias,dictionary) FROM ts_debug('text_search.french_noaccent', 'un chou-fleur') WHERE alias = 'asciihword' LIMIT 1; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | (asciihword,dutch_stem) localhost | 57638 | t | (asciihword,dutch_stem) (2 rows) -- once more but now back via yet a different DDL command ALTER TEXT SEARCH CONFIGURATION french_noaccent ALTER MAPPING FOR asciihword REPLACE dutch_stem WITH french_stem; SELECT * FROM run_command_on_workers($$ SELECT ROW(alias,dictionary) FROM ts_debug('text_search.french_noaccent', 'un chou-fleur') WHERE alias = 'asciihword' LIMIT 1; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | (asciihword,french_stem) localhost | 57638 | t | (asciihword,french_stem) (2 rows) -- drop a mapping ALTER TEXT SEARCH CONFIGURATION french_noaccent DROP MAPPING FOR asciihword; SELECT * FROM run_command_on_workers($$ SELECT ROW(alias,dictionary) FROM ts_debug('text_search.french_noaccent', 'un chou-fleur') WHERE alias = 'asciihword' LIMIT 1; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | (asciihword,) localhost | 57638 | t | (asciihword,) (2 rows) -- also with exists, doesn't change anything, but should not error ALTER TEXT SEARCH CONFIGURATION french_noaccent DROP MAPPING IF EXISTS FOR asciihword; NOTICE: mapping for token type "asciihword" does not exist, skipping -- Comment on a text search configuration COMMENT ON TEXT SEARCH CONFIGURATION french_noaccent IS 'a text configuration that is butchered to test all edge cases'; SELECT * FROM run_command_on_workers($$ SELECT obj_description('text_search.french_noaccent'::regconfig); $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | a text configuration that is butchered to test all edge cases localhost | 57638 | t | a text configuration that is butchered to test all edge cases (2 rows) -- Remove a comment COMMENT ON TEXT SEARCH CONFIGURATION french_noaccent IS NULL; SELECT * FROM run_command_on_workers($$ SELECT obj_description('text_search.french_noaccent'::regconfig); $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | localhost | 57638 | t | (2 rows) -- verify adding 2 dictionaries for two tokes at once ALTER TEXT SEARCH CONFIGURATION french_noaccent DROP MAPPING IF EXISTS FOR asciiword, asciihword; NOTICE: mapping for token type "asciihword" does not exist, skipping ALTER TEXT SEARCH CONFIGURATION french_noaccent ADD MAPPING FOR asciiword, asciihword WITH french_stem, dutch_stem; SELECT * FROM run_command_on_workers($$ SELECT ROW(alias,dictionaries) FROM ts_debug('text_search.french_noaccent', 'un chou-fleur') WHERE alias = 'asciiword' LIMIT 1; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | (asciiword,"{french_stem,dutch_stem}") localhost | 57638 | t | (asciiword,"{french_stem,dutch_stem}") (2 rows) SELECT * FROM run_command_on_workers($$ SELECT ROW(alias,dictionaries) FROM ts_debug('text_search.french_noaccent', 'un chou-fleur') WHERE alias = 'asciihword' LIMIT 1; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | (asciihword,"{french_stem,dutch_stem}") localhost | 57638 | t | (asciihword,"{french_stem,dutch_stem}") (2 rows) --verify we can drop cascade a configuration that is in use -- verify it is in use DROP TEXT SEARCH CONFIGURATION text_search.french_noaccent; ERROR: cannot drop text search configuration french_noaccent because other objects depend on it DETAIL: index t2_search_name depends on text search configuration french_noaccent HINT: Use DROP ... CASCADE to drop the dependent objects too. -- drop cascade DROP TEXT SEARCH CONFIGURATION text_search.french_noaccent CASCADE; NOTICE: drop cascades to index t2_search_name -- verify the configuration is dropped from the workers SELECT * FROM run_command_on_workers($$ SELECT 'text_search.french_noaccent'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | f | ERROR: text search configuration "text_search.french_noaccent" does not exist localhost | 57638 | f | ERROR: text search configuration "text_search.french_noaccent" does not exist (2 rows) SET client_min_messages TO 'warning'; CREATE ROLE text_search_owner; RESET client_min_messages; CREATE TEXT SEARCH CONFIGURATION changed_owner ( PARSER = default ); SELECT * FROM run_command_on_workers($$ SELECT cfgowner::regrole FROM pg_ts_config WHERE oid = 'text_search.changed_owner'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | postgres localhost | 57638 | t | postgres (2 rows) ALTER TEXT SEARCH CONFIGURATION changed_owner OWNER TO text_search_owner; SELECT * FROM run_command_on_workers($$ SELECT cfgowner::regrole FROM pg_ts_config WHERE oid = 'text_search.changed_owner'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | text_search_owner localhost | 57638 | t | text_search_owner (2 rows) -- redo test with propagating object after it was created and changed of owner SET citus.enable_ddl_propagation TO off; CREATE TEXT SEARCH CONFIGURATION changed_owner2 ( PARSER = default ); ALTER TEXT SEARCH CONFIGURATION changed_owner2 OWNER TO text_search_owner; RESET citus.enable_ddl_propagation; -- verify object doesn't exist before propagating SELECT * FROM run_command_on_workers($$ SELECT 'text_search.changed_owner2'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | f | ERROR: text search configuration "text_search.changed_owner2" does not exist localhost | 57638 | f | ERROR: text search configuration "text_search.changed_owner2" does not exist (2 rows) -- distribute configuration CREATE TABLE t3(id int, name text); CREATE INDEX t3_search_name ON t3 USING gin (to_tsvector('text_search.changed_owner2'::regconfig, (COALESCE(name, ''::character varying))::text)); SELECT create_distributed_table('t3', 'name'); create_distributed_table --------------------------------------------------------------------- (1 row) -- verify config owner SELECT * FROM run_command_on_workers($$ SELECT cfgowner::regrole FROM pg_ts_config WHERE oid = 'text_search.changed_owner2'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | text_search_owner localhost | 57638 | t | text_search_owner (2 rows) -- rename tests CREATE TEXT SEARCH CONFIGURATION change_name ( PARSER = default ); SELECT * FROM run_command_on_workers($$ -- verify the name exists on the worker SELECT 'text_search.change_name'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | text_search.change_name localhost | 57638 | t | text_search.change_name (2 rows) ALTER TEXT SEARCH CONFIGURATION change_name RENAME TO changed_name; SELECT * FROM run_command_on_workers($$ -- verify the name exists on the worker SELECT 'text_search.changed_name'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | text_search.changed_name localhost | 57638 | t | text_search.changed_name (2 rows) -- test move of schema CREATE TEXT SEARCH CONFIGURATION change_schema ( PARSER = default ); SELECT * FROM run_command_on_workers($$ -- verify the name exists on the worker SELECT 'text_search.change_schema'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | text_search.change_schema localhost | 57638 | t | text_search.change_schema (2 rows) ALTER TEXT SEARCH CONFIGURATION change_schema SET SCHEMA text_search2; SELECT * FROM run_command_on_workers($$ -- verify the name exists on the worker SELECT 'text_search2.change_schema'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | text_search2.change_schema localhost | 57638 | t | text_search2.change_schema (2 rows) -- verify we get an error that the configuration change_schema is not found, even though the object address will be -- found in its new schema, and is distributed ALTER TEXT SEARCH CONFIGURATION change_schema SET SCHEMA text_search2; ERROR: text search configuration "change_schema" does not exist -- should tell us that text_search.does_not_exist does not exist, covers a complex edgecase -- in resolving the object address ALTER TEXT SEARCH CONFIGURATION text_search.does_not_exist SET SCHEMA text_search2; ERROR: text search configuration "text_search.does_not_exist" does not exist -- verify edgecases in deparsers CREATE TEXT SEARCH CONFIGURATION config1 ( PARSER = default ); CREATE TEXT SEARCH CONFIGURATION config2 ( PARSER = default ); SET citus.enable_ddl_propagation TO off; CREATE TEXT SEARCH CONFIGURATION config3 ( PARSER = default ); RESET citus.enable_ddl_propagation; -- verify config1, config2 exist on workers, config3 not SELECT * FROM run_command_on_workers($$ SELECT 'text_search.config1'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | text_search.config1 localhost | 57638 | t | text_search.config1 (2 rows) SELECT * FROM run_command_on_workers($$ SELECT 'text_search.config2'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | text_search.config2 localhost | 57638 | t | text_search.config2 (2 rows) SELECT * FROM run_command_on_workers($$ SELECT 'text_search.config3'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | f | ERROR: text search configuration "text_search.config3" does not exist localhost | 57638 | f | ERROR: text search configuration "text_search.config3" does not exist (2 rows) -- DROP all config's, only 1&2 are distributed, they should propagate well to remotes DROP TEXT SEARCH CONFIGURATION config1, config2, config3; -- verify all existing ones have been removed (checking config3 for consistency) SELECT * FROM run_command_on_workers($$ SELECT 'text_search.config1'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | f | ERROR: text search configuration "text_search.config1" does not exist localhost | 57638 | f | ERROR: text search configuration "text_search.config1" does not exist (2 rows) SELECT * FROM run_command_on_workers($$ SELECT 'text_search.config2'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | f | ERROR: text search configuration "text_search.config2" does not exist localhost | 57638 | f | ERROR: text search configuration "text_search.config2" does not exist (2 rows) SELECT * FROM run_command_on_workers($$ SELECT 'text_search.config3'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | f | ERROR: text search configuration "text_search.config3" does not exist localhost | 57638 | f | ERROR: text search configuration "text_search.config3" does not exist (2 rows) -- verify they are all removed locally SELECT 1 FROM pg_ts_config WHERE cfgname = 'config1' AND cfgnamespace = 'text_search'::regnamespace; ?column? --------------------------------------------------------------------- (0 rows) SELECT 1 FROM pg_ts_config WHERE cfgname = 'config2' AND cfgnamespace = 'text_search'::regnamespace; ?column? --------------------------------------------------------------------- (0 rows) SELECT 1 FROM pg_ts_config WHERE cfgname = 'config3' AND cfgnamespace = 'text_search'::regnamespace; ?column? --------------------------------------------------------------------- (0 rows) -- verify that indexes created concurrently that would propagate a TEXT SEARCH CONFIGURATION object SET citus.enable_ddl_propagation TO off; CREATE TEXT SEARCH CONFIGURATION concurrent_index_config ( PARSER = default ); RESET citus.enable_ddl_propagation; -- verify it doesn't exist on the workers SELECT * FROM run_command_on_workers($$ SELECT 'text_search.concurrent_index_config'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | f | ERROR: text search configuration "text_search.concurrent_index_config" does not exist localhost | 57638 | f | ERROR: text search configuration "text_search.concurrent_index_config" does not exist (2 rows) -- create distributed table that then concurrently would have an index created. CREATE TABLE t4(id int, name text); SELECT create_distributed_table('t4', 'name'); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE INDEX CONCURRENTLY t4_search_name ON t4 USING gin (to_tsvector('text_search.concurrent_index_config'::regconfig, (COALESCE(name, ''::character varying))::text)); -- now the configuration should be on the worker, and the above index creation shouldn't have failed. SELECT * FROM run_command_on_workers($$ SELECT 'text_search.concurrent_index_config'::regconfig; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | text_search.concurrent_index_config localhost | 57638 | t | text_search.concurrent_index_config (2 rows) -- verify the objid is correctly committed locally due to the somewhat convoluted commit and new transaction starting when creating an index concurrently SELECT pg_catalog.pg_identify_object_as_address(classid, objid, objsubid) FROM pg_catalog.pg_dist_object WHERE classid = 3602 AND objid = 'text_search.concurrent_index_config'::regconfig::oid; pg_identify_object_as_address --------------------------------------------------------------------- ("text search configuration","{text_search,concurrent_index_config}",{}) (1 row) -- verify old text search configurations get renamed if they are not the same as the newly propagated configuration. -- We do this by creating configurations on the workers as a copy from a different existing catalog. SELECT * FROM run_command_on_workers($$ set citus.enable_metadata_sync TO off; CREATE TEXT SEARCH CONFIGURATION text_search.manually_created_wrongly ( copy = dutch ); reset citus.enable_metadata_sync; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | SET localhost | 57638 | t | SET (2 rows) CREATE TEXT SEARCH CONFIGURATION text_search.manually_created_wrongly ( copy = french ); -- now we expect manually_created_wrongly(citus_backup_XXX) to show up when querying the configurations SELECT * FROM run_command_on_workers($$ SELECT array_agg(cfgname ORDER BY cfgname) FROM pg_ts_config WHERE cfgname LIKE 'manually_created_wrongly%'; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | {manually_created_wrongly,manually_created_wrongly(citus_backup_0)} localhost | 57638 | t | {manually_created_wrongly,manually_created_wrongly(citus_backup_0)} (2 rows) -- verify the objects get reused appropriately when the specification is the same SELECT * FROM run_command_on_workers($$ set citus.enable_metadata_sync TO off; CREATE TEXT SEARCH CONFIGURATION text_search.manually_created_correct ( copy = french ); reset citus.enable_metadata_sync; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | SET localhost | 57638 | t | SET (2 rows) CREATE TEXT SEARCH CONFIGURATION text_search.manually_created_correct ( copy = french ); -- now we don't expect manually_created_correct(citus_backup_XXX) to show up when querying the configurations as the -- original one is reused SELECT * FROM run_command_on_workers($$ SELECT array_agg(cfgname ORDER BY cfgname) FROM pg_ts_config WHERE cfgname LIKE 'manually_created_correct%'; $$) ORDER BY 1,2; nodename | nodeport | success | result --------------------------------------------------------------------- localhost | 57637 | t | {manually_created_correct} localhost | 57638 | t | {manually_created_correct} (2 rows) CREATE SCHEMA "Text Search Requiring Quote's"; CREATE TEXT SEARCH CONFIGURATION "Text Search Requiring Quote's"."Quoted Config Name" ( parser = default ); CREATE TABLE t5(id int, name text); CREATE INDEX t5_search_name ON t5 USING gin (to_tsvector('"Text Search Requiring Quote''s"."Quoted Config Name"'::regconfig, (COALESCE(name, ''::character varying))::text)); SELECT create_distributed_table('t5', 'name'); create_distributed_table --------------------------------------------------------------------- (1 row) -- make sure partial indices propagate their dependencies -- first have a TEXT SEARCH CONFIGURATION that is not distributed SET citus.enable_ddl_propagation TO off; CREATE TEXT SEARCH CONFIGURATION partial_index_test_config ( parser = default ); RESET citus.enable_ddl_propagation; CREATE TABLE sensors( measureid integer, eventdatetime date, measure_data jsonb, name text, PRIMARY KEY (measureid, eventdatetime, measure_data) ) PARTITION BY RANGE(eventdatetime); CREATE TABLE sensors_a_partition PARTITION OF sensors FOR VALUES FROM ('2000-01-01') TO ('2020-01-01'); CREATE INDEX sensors_search_name ON sensors USING gin (to_tsvector('partial_index_test_config'::regconfig, (COALESCE(name, ''::character varying))::text)); SELECT create_distributed_table('sensors', 'measureid'); create_distributed_table --------------------------------------------------------------------- (1 row) -- create a new dictionary from scratch CREATE TEXT SEARCH DICTIONARY my_english_dict ( template = snowball, language = english, stopwords = english ); -- verify that the dictionary definition is the same in all nodes SELECT result FROM run_command_on_all_nodes($$ SELECT ROW(dictname, dictnamespace::regnamespace, dictowner::regrole, tmplname, dictinitoption) FROM pg_ts_dict d JOIN pg_ts_template t ON ( d.dicttemplate = t.oid ) WHERE dictname = 'my_english_dict'; $$); result --------------------------------------------------------------------- (my_english_dict,text_search,postgres,snowball,"language = 'english', stopwords = 'english'") (my_english_dict,text_search,postgres,snowball,"language = 'english', stopwords = 'english'") (my_english_dict,text_search,postgres,snowball,"language = 'english', stopwords = 'english'") (3 rows) -- use the new dictionary in a configuration mapping CREATE TEXT SEARCH CONFIGURATION my_english_config ( COPY = english ); ALTER TEXT SEARCH CONFIGURATION my_english_config ALTER MAPPING FOR asciiword WITH my_english_dict; -- verify that the dictionary is available on the worker nodes SELECT result FROM run_command_on_all_nodes($$ SELECT ROW(alias,dictionary) FROM ts_debug('text_search.my_english_config', 'The Brightest supernovaes') WHERE alias = 'asciiword' LIMIT 1; $$); result --------------------------------------------------------------------- (asciiword,text_search.my_english_dict) (asciiword,text_search.my_english_dict) (asciiword,text_search.my_english_dict) (3 rows) -- comment on a text search dictionary COMMENT ON TEXT SEARCH DICTIONARY my_english_dict IS 'a text search dictionary that is butchered to test all edge cases'; SELECT result FROM run_command_on_all_nodes($$ SELECT obj_description('text_search.my_english_dict'::regdictionary); $$); result --------------------------------------------------------------------- a text search dictionary that is butchered to test all edge cases a text search dictionary that is butchered to test all edge cases a text search dictionary that is butchered to test all edge cases (3 rows) -- remove a comment COMMENT ON TEXT SEARCH DICTIONARY my_english_dict IS NULL; SELECT result FROM run_command_on_all_nodes($$ SELECT obj_description('text_search.my_english_dict'::regdictionary); $$); result --------------------------------------------------------------------- (3 rows) -- test various ALTER TEXT SEARCH DICTIONARY commands ALTER TEXT SEARCH DICTIONARY my_english_dict RENAME TO my_turkish_dict; ALTER TEXT SEARCH DICTIONARY my_turkish_dict (language = turkish, stopwords); ALTER TEXT SEARCH DICTIONARY my_turkish_dict OWNER TO text_search_owner; ALTER TEXT SEARCH DICTIONARY my_turkish_dict SET SCHEMA "Text Search Requiring Quote's"; -- verify that the dictionary definition is the same in all nodes SELECT result FROM run_command_on_all_nodes($$ SELECT ROW(dictname, dictnamespace::regnamespace, dictowner::regrole, tmplname, dictinitoption) FROM pg_ts_dict d JOIN pg_ts_template t ON ( d.dicttemplate = t.oid ) WHERE dictname = 'my_turkish_dict'; $$); result --------------------------------------------------------------------- (my_turkish_dict,"""Text Search Requiring Quote's""",text_search_owner,snowball,"language = 'turkish'") (my_turkish_dict,"""Text Search Requiring Quote's""",text_search_owner,snowball,"language = 'turkish'") (my_turkish_dict,"""Text Search Requiring Quote's""",text_search_owner,snowball,"language = 'turkish'") (3 rows) -- verify that the configuration dictionary is changed in all nodes SELECT result FROM run_command_on_all_nodes($$ SELECT ROW(alias,dictionary) FROM ts_debug('text_search.my_english_config', 'The Brightest supernovaes') WHERE alias = 'asciiword' LIMIT 1; $$); result --------------------------------------------------------------------- (asciiword,"""Text Search Requiring Quote's"".my_turkish_dict") (asciiword,"""Text Search Requiring Quote's"".my_turkish_dict") (asciiword,"""Text Search Requiring Quote's"".my_turkish_dict") (3 rows) -- before testing drops, check that the dictionary exists on all nodes SELECT result FROM run_command_on_all_nodes($$ SELECT '"Text Search Requiring Quote''s".my_turkish_dict'::regdictionary; $$); result --------------------------------------------------------------------- "Text Search Requiring Quote's".my_turkish_dict "Text Search Requiring Quote's".my_turkish_dict "Text Search Requiring Quote's".my_turkish_dict (3 rows) ALTER TEXT SEARCH DICTIONARY "Text Search Requiring Quote's".my_turkish_dict SET SCHEMA text_search; -- verify that we can drop the dictionary only with cascade option DROP TEXT SEARCH DICTIONARY my_turkish_dict; ERROR: cannot drop text search dictionary my_turkish_dict because other objects depend on it DETAIL: text search configuration my_english_config depends on text search dictionary my_turkish_dict HINT: Use DROP ... CASCADE to drop the dependent objects too. DROP TEXT SEARCH DICTIONARY my_turkish_dict CASCADE; NOTICE: drop cascades to text search configuration my_english_config -- verify that it is dropped now SELECT result FROM run_command_on_all_nodes($$ SELECT 'my_turkish_dict'::regdictionary; $$); result --------------------------------------------------------------------- ERROR: text search dictionary "my_turkish_dict" does not exist ERROR: text search dictionary "my_turkish_dict" does not exist ERROR: text search dictionary "my_turkish_dict" does not exist (3 rows) -- test different templates that are used in dictionaries CREATE TEXT SEARCH DICTIONARY simple_dict ( TEMPLATE = pg_catalog.simple, STOPWORDS = english, accept = false ); SELECT COUNT(DISTINCT result)=1 FROM run_command_on_all_nodes($$ SELECT ROW(dictname, dictnamespace::regnamespace, dictowner::regrole, tmplname, dictinitoption) FROM pg_ts_dict d JOIN pg_ts_template t ON ( d.dicttemplate = t.oid ) WHERE dictname = 'simple_dict'; $$); ?column? --------------------------------------------------------------------- t (1 row) CREATE TEXT SEARCH DICTIONARY synonym_dict ( template=synonym, synonyms='synonym_sample', casesensitive=1 ); SELECT COUNT(DISTINCT result)=1 FROM run_command_on_all_nodes($$ SELECT ROW(dictname, dictnamespace::regnamespace, dictowner::regrole, tmplname, dictinitoption) FROM pg_ts_dict d JOIN pg_ts_template t ON ( d.dicttemplate = t.oid ) WHERE dictname = 'synonym_dict'; $$); ?column? --------------------------------------------------------------------- t (1 row) CREATE TEXT SEARCH DICTIONARY thesaurus_dict ( TEMPLATE = thesaurus, DictFile = thesaurus_sample, Dictionary = pg_catalog.english_stem ); SELECT COUNT(DISTINCT result)=1 FROM run_command_on_all_nodes($$ SELECT ROW(dictname, dictnamespace::regnamespace, dictowner::regrole, tmplname, dictinitoption) FROM pg_ts_dict d JOIN pg_ts_template t ON ( d.dicttemplate = t.oid ) WHERE dictname = 'thesaurus_dict'; $$); ?column? --------------------------------------------------------------------- t (1 row) CREATE TEXT SEARCH DICTIONARY ispell_dict ( TEMPLATE = ispell, DictFile = ispell_sample, AffFile = ispell_sample, Stopwords = english ); SELECT COUNT(DISTINCT result)=1 FROM run_command_on_all_nodes($$ SELECT ROW(dictname, dictnamespace::regnamespace, dictowner::regrole, tmplname, dictinitoption) FROM pg_ts_dict d JOIN pg_ts_template t ON ( d.dicttemplate = t.oid ) WHERE dictname = 'ispell_dict'; $$); ?column? --------------------------------------------------------------------- t (1 row) CREATE TEXT SEARCH DICTIONARY snowball_dict ( TEMPLATE = snowball, Language = english, StopWords = english ); SELECT COUNT(DISTINCT result)=1 FROM run_command_on_all_nodes($$ SELECT ROW(dictname, dictnamespace::regnamespace, dictowner::regrole, tmplname, dictinitoption) FROM pg_ts_dict d JOIN pg_ts_template t ON ( d.dicttemplate = t.oid ) WHERE dictname = 'snowball_dict'; $$); ?column? --------------------------------------------------------------------- t (1 row) -- will skip trying to propagate the text search configuration due to temp schema CREATE TEXT SEARCH CONFIGURATION pg_temp.temp_text_search_config ( parser = default ); WARNING: "text search configuration pg_temp_xxx.temp_text_search_config" has dependency on unsupported object "schema pg_temp_xxx" DETAIL: "text search configuration pg_temp_xxx.temp_text_search_config" will be created only locally -- will skip trying to propagate the text search dictionary due to temp schema CREATE TEXT SEARCH DICTIONARY pg_temp.temp_text_search_dict ( template = snowball, language = english, stopwords = english ); WARNING: "text search dictionary pg_temp_xxx.temp_text_search_dict" has dependency on unsupported object "schema pg_temp_xxx" DETAIL: "text search dictionary pg_temp_xxx.temp_text_search_dict" will be created only locally SET client_min_messages TO 'warning'; DROP SCHEMA text_search, text_search2, "Text Search Requiring Quote's" CASCADE; DROP ROLE text_search_owner;