From a826ab300507721861fced5642dc509872219d55 Mon Sep 17 00:00:00 2001 From: "tender.wang" Date: Fri, 26 Jan 2024 14:01:52 +0800 Subject: [PATCH] Fix reporting error when process duplicate token type. Now we don't Remove Duplicates in tokenname list, so we may see this error "tuple already updated by self". By the way, it should report NOTICE not ERROR if IF EXISTS specified when we DROP MAPPING. So change the getTokenTypes() interface. --- src/backend/commands/tsearchcmds.c | 87 +++++++++++---------------- src/test/regress/expected/tsdicts.out | 5 ++ src/test/regress/sql/tsdicts.sql | 7 +++ 3 files changed, 46 insertions(+), 53 deletions(-) diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index 07671720ea..dc76f7a465 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -1194,20 +1194,19 @@ AlterTSConfiguration(AlterTSConfigurationStmt *stmt) /* * Translate a list of token type names to an array of token type numbers */ -static int * -getTokenTypes(Oid prsId, List *tokennames) +static List * +getTokenTypes(Oid prsId, AlterTSConfigurationStmt *stmt) { TSParserCacheEntry *prs = lookup_ts_parser_cache(prsId); LexDescr *list; - int *res, - i, - ntoken; + List *res = NIL; + int ntoken; ListCell *tn; + List *tokennames = stmt->tokentype; ntoken = list_length(tokennames); if (ntoken == 0) - return NULL; - res = (int *) palloc(sizeof(int) * ntoken); + return NIL; if (!OidIsValid(prs->lextypeOid)) elog(ERROR, "method lextype isn't defined for text search parser %u", @@ -1217,7 +1216,6 @@ getTokenTypes(Oid prsId, List *tokennames) list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid, (Datum) 0)); - i = 0; foreach(tn, tokennames) { String *val = lfirst_node(String, tn); @@ -1229,18 +1227,26 @@ getTokenTypes(Oid prsId, List *tokennames) { if (strcmp(strVal(val), list[j].alias) == 0) { - res[i] = list[j].lexid; + res = list_append_unique_int(res, list[j].lexid); found = true; break; } j++; } if (!found) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("token type \"%s\" does not exist", - strVal(val)))); - i++; + { + if (!stmt->missing_ok) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("token type \"%s\" does not exist", + strVal(val)))); + else + { + ereport(NOTICE, + (errmsg("token type \"%s\" does not exist, skipping", + strVal(val)))); + } + } } return res; @@ -1261,8 +1267,8 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, int i; int j; Oid prsId; - int *tokens, - ntoken; + List *tokens = NIL; + int ntoken; Oid *dictIds; int ndict; ListCell *c; @@ -1272,15 +1278,15 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, cfgId = tsform->oid; prsId = tsform->cfgparser; - tokens = getTokenTypes(prsId, stmt->tokentype); - ntoken = list_length(stmt->tokentype); + tokens = getTokenTypes(prsId, stmt); + ntoken = list_length(tokens); if (stmt->override) { /* * delete maps for tokens if they exist and command was ALTER */ - for (i = 0; i < ntoken; i++) + foreach(c, tokens) { ScanKeyInit(&skey[0], Anum_pg_ts_config_map_mapcfg, @@ -1289,7 +1295,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, ScanKeyInit(&skey[1], Anum_pg_ts_config_map_maptokentype, BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(tokens[i])); + Int32GetDatum(lfirst_int(c))); scan = systable_beginscan(relMap, TSConfigMapIndexId, true, NULL, 2, skey); @@ -1346,9 +1352,9 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, { bool tokmatch = false; - for (j = 0; j < ntoken; j++) + foreach(c, tokens) { - if (cfgmap->maptokentype == tokens[j]) + if (cfgmap->maptokentype == lfirst_int(c)) { tokmatch = true; break; @@ -1401,7 +1407,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, /* * Insertion of new entries */ - for (i = 0; i < ntoken; i++) + foreach(c, tokens) { for (j = 0; j < ndict; j++) { @@ -1411,7 +1417,7 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool)); slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapcfg - 1] = ObjectIdGetDatum(cfgId); - slot[slotCount]->tts_values[Anum_pg_ts_config_map_maptokentype - 1] = Int32GetDatum(tokens[i]); + slot[slotCount]->tts_values[Anum_pg_ts_config_map_maptokentype - 1] = Int32GetDatum(lfirst_int(c)); slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapseqno - 1] = Int32GetDatum(j + 1); slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictIds[j]); @@ -1455,23 +1461,18 @@ DropConfigurationMapping(AlterTSConfigurationStmt *stmt, ScanKeyData skey[2]; SysScanDesc scan; HeapTuple maptup; - int i; Oid prsId; - int *tokens; + List *tokens = NIL; ListCell *c; tsform = (Form_pg_ts_config) GETSTRUCT(tup); cfgId = tsform->oid; prsId = tsform->cfgparser; - tokens = getTokenTypes(prsId, stmt->tokentype); + tokens = getTokenTypes(prsId, stmt); - i = 0; - foreach(c, stmt->tokentype) + foreach(c, tokens) { - String *val = lfirst_node(String, c); - bool found = false; - ScanKeyInit(&skey[0], Anum_pg_ts_config_map_mapcfg, BTEqualStrategyNumber, F_OIDEQ, @@ -1479,7 +1480,7 @@ DropConfigurationMapping(AlterTSConfigurationStmt *stmt, ScanKeyInit(&skey[1], Anum_pg_ts_config_map_maptokentype, BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(tokens[i])); + Int32GetDatum(lfirst_int(c))); scan = systable_beginscan(relMap, TSConfigMapIndexId, true, NULL, 2, skey); @@ -1487,29 +1488,9 @@ DropConfigurationMapping(AlterTSConfigurationStmt *stmt, while (HeapTupleIsValid((maptup = systable_getnext(scan)))) { CatalogTupleDelete(relMap, &maptup->t_self); - found = true; } systable_endscan(scan); - - if (!found) - { - if (!stmt->missing_ok) - { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("mapping for token type \"%s\" does not exist", - strVal(val)))); - } - else - { - ereport(NOTICE, - (errmsg("mapping for token type \"%s\" does not exist, skipping", - strVal(val)))); - } - } - - i++; } EventTriggerCollectAlterTSConfig(stmt, cfgId, NULL, 0); diff --git a/src/test/regress/expected/tsdicts.out b/src/test/regress/expected/tsdicts.out index c804293142..af69197306 100644 --- a/src/test/regress/expected/tsdicts.out +++ b/src/test/regress/expected/tsdicts.out @@ -687,3 +687,8 @@ CREATE TEXT SEARCH DICTIONARY tsdict_case "AffFile" = ispell_sample ); ERROR: unrecognized Ispell parameter: "DictFile" +-- test duplicate token type +CREATE TEXT SEARCH CONFIGURATION dup_ispell_tst (COPY=english); +ALTER TEXT SEARCH CONFIGURATION dup_ispell_tst ALTER MAPPING FOR word, word WITH ispell; +ALTER TEXT SEARCH CONFIGURATION dup_ispell_tst DROP MAPPING IF EXISTS FOR hello; +NOTICE: token type "hello" does not exist, skipping diff --git a/src/test/regress/sql/tsdicts.sql b/src/test/regress/sql/tsdicts.sql index ddc6c7f445..d4302abebd 100644 --- a/src/test/regress/sql/tsdicts.sql +++ b/src/test/regress/sql/tsdicts.sql @@ -251,3 +251,10 @@ CREATE TEXT SEARCH DICTIONARY tsdict_case "DictFile" = ispell_sample, "AffFile" = ispell_sample ); + +-- test duplicate token type +CREATE TEXT SEARCH CONFIGURATION dup_ispell_tst (COPY=english); + +ALTER TEXT SEARCH CONFIGURATION dup_ispell_tst ALTER MAPPING FOR word, word WITH ispell; + +ALTER TEXT SEARCH CONFIGURATION dup_ispell_tst DROP MAPPING IF EXISTS FOR hello; -- 2.25.1