46 #include "utils/fmgroids.h" 76 retTypeId = INTERNALOID;
77 typeId[0] = INTERNALOID;
80 case Anum_pg_ts_parser_prsstart:
84 case Anum_pg_ts_parser_prstoken:
86 typeId[1] = INTERNALOID;
87 typeId[2] = INTERNALOID;
89 case Anum_pg_ts_parser_prsend:
93 case Anum_pg_ts_parser_prsheadline:
95 typeId[1] = INTERNALOID;
96 typeId[2] = TSQUERYOID;
98 case Anum_pg_ts_parser_prslextype:
109 elog(
ERROR,
"unrecognized attribute for text search parser: %d",
117 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
118 errmsg(
"function %s should return type %s",
153 referenced.
objectId = prs->prstoken;
159 referenced.
objectId = prs->prslextype;
164 referenced.
objectId = prs->prsheadline;
185 bool nulls[Natts_pg_ts_parser];
193 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
194 errmsg(
"must be superuser to create text search parsers")));
202 memset(values, 0,
sizeof(values));
203 memset(nulls,
false,
sizeof(nulls));
206 Anum_pg_ts_parser_oid);
209 values[Anum_pg_ts_parser_prsname - 1] =
NameGetDatum(&pname);
210 values[Anum_pg_ts_parser_prsnamespace - 1] =
ObjectIdGetDatum(namespaceoid);
215 foreach(pl, parameters)
219 if (strcmp(defel->
defname,
"start") == 0)
221 values[Anum_pg_ts_parser_prsstart - 1] =
224 else if (strcmp(defel->
defname,
"gettoken") == 0)
226 values[Anum_pg_ts_parser_prstoken - 1] =
229 else if (strcmp(defel->
defname,
"end") == 0)
231 values[Anum_pg_ts_parser_prsend - 1] =
234 else if (strcmp(defel->
defname,
"headline") == 0)
236 values[Anum_pg_ts_parser_prsheadline - 1] =
239 else if (strcmp(defel->
defname,
"lextypes") == 0)
241 values[Anum_pg_ts_parser_prslextype - 1] =
246 (
errcode(ERRCODE_SYNTAX_ERROR),
247 errmsg(
"text search parser parameter \"%s\" not recognized",
256 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
257 errmsg(
"text search parser start method is required")));
261 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
262 errmsg(
"text search parser gettoken method is required")));
266 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
267 errmsg(
"text search parser end method is required")));
271 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
272 errmsg(
"text search parser lextypes method is required")));
354 elog(
ERROR,
"cache lookup failed for text search template %u",
358 initmethod = tform->tmplinit;
365 (
errcode(ERRCODE_SYNTAX_ERROR),
366 errmsg(
"text search template \"%s\" does not accept options",
397 bool nulls[Natts_pg_ts_dict];
419 foreach(pl, parameters)
423 if (strcmp(defel->
defname,
"template") == 0)
430 dictoptions =
lappend(dictoptions, defel);
439 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
440 errmsg(
"text search template is required")));
450 memset(values, 0,
sizeof(values));
451 memset(nulls,
false,
sizeof(nulls));
454 Anum_pg_ts_dict_oid);
457 values[Anum_pg_ts_dict_dictname - 1] =
NameGetDatum(&dname);
462 values[Anum_pg_ts_dict_dictinitoption - 1] =
465 nulls[Anum_pg_ts_dict_dictinitoption - 1] =
true;
497 Datum repl_val[Natts_pg_ts_dict];
498 bool repl_null[Natts_pg_ts_dict];
499 bool repl_repl[Natts_pg_ts_dict];
509 elog(
ERROR,
"cache lookup failed for text search dictionary %u",
519 Anum_pg_ts_dict_dictinitoption,
537 foreach(cell, dictoptions)
549 dictoptions =
lappend(dictoptions, defel);
561 memset(repl_val, 0,
sizeof(repl_val));
562 memset(repl_null,
false,
sizeof(repl_null));
563 memset(repl_repl,
false,
sizeof(repl_repl));
566 repl_val[Anum_pg_ts_dict_dictinitoption - 1] =
569 repl_null[Anum_pg_ts_dict_dictinitoption - 1] =
true;
570 repl_repl[Anum_pg_ts_dict_dictinitoption - 1] =
true;
573 repl_val, repl_null, repl_repl);
611 retTypeId = INTERNALOID;
612 typeId[0] = INTERNALOID;
613 typeId[1] = INTERNALOID;
614 typeId[2] = INTERNALOID;
615 typeId[3] = INTERNALOID;
618 case Anum_pg_ts_template_tmplinit:
621 case Anum_pg_ts_template_tmpllexize:
626 elog(
ERROR,
"unrecognized attribute for text search template: %d",
634 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
635 errmsg(
"function %s should return type %s",
670 referenced.
objectId = tmpl->tmplinit;
690 bool nulls[Natts_pg_ts_template];
700 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
701 errmsg(
"must be superuser to create text search templates")));
708 for (i = 0; i < Natts_pg_ts_template; i++)
715 Anum_pg_ts_dict_oid);
718 values[Anum_pg_ts_template_tmplname - 1] =
NameGetDatum(&dname);
719 values[Anum_pg_ts_template_tmplnamespace - 1] =
ObjectIdGetDatum(namespaceoid);
724 foreach(pl, parameters)
728 if (strcmp(defel->
defname,
"init") == 0)
730 values[Anum_pg_ts_template_tmplinit - 1] =
732 nulls[Anum_pg_ts_template_tmplinit - 1] =
false;
734 else if (strcmp(defel->
defname,
"lexize") == 0)
736 values[Anum_pg_ts_template_tmpllexize - 1] =
738 nulls[Anum_pg_ts_template_tmpllexize - 1] =
false;
742 (
errcode(ERRCODE_SYNTAX_ERROR),
743 errmsg(
"text search template parameter \"%s\" not recognized",
752 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
753 errmsg(
"text search template lexize method is required")));
793 elog(
ERROR,
"cache lookup failed for text search configuration %u",
814 myself.
classId = TSConfigRelationId;
833 referenced.
classId = NamespaceRelationId;
834 referenced.
objectId = cfg->cfgnamespace;
845 referenced.
classId = TSParserRelationId;
846 referenced.
objectId = cfg->cfgparser;
861 Anum_pg_ts_config_map_mapcfg,
872 referenced.
classId = TSDictionaryRelationId;
873 referenced.
objectId = cfgmap->mapdict;
899 bool nulls[Natts_pg_ts_config];
922 foreach(pl, parameters)
926 if (strcmp(defel->
defname,
"parser") == 0)
928 else if (strcmp(defel->
defname,
"copy") == 0)
932 (
errcode(ERRCODE_SYNTAX_ERROR),
933 errmsg(
"text search configuration parameter \"%s\" not recognized",
939 (
errcode(ERRCODE_SYNTAX_ERROR),
940 errmsg(
"cannot specify both PARSER and COPY options")));
959 elog(
ERROR,
"cache lookup failed for text search configuration %u",
965 prsOid = cfg->cfgparser;
975 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
976 errmsg(
"text search parser is required")));
983 memset(values, 0,
sizeof(values));
984 memset(nulls,
false,
sizeof(nulls));
987 Anum_pg_ts_config_oid);
990 values[Anum_pg_ts_config_cfgname - 1] =
NameGetDatum(&cname);
991 values[Anum_pg_ts_config_cfgnamespace - 1] =
ObjectIdGetDatum(namespaceoid);
1011 Anum_pg_ts_config_map_mapcfg,
1022 Datum mapvalues[Natts_pg_ts_config_map];
1023 bool mapnulls[Natts_pg_ts_config_map];
1025 memset(mapvalues, 0,
sizeof(mapvalues));
1026 memset(mapnulls,
false,
sizeof(mapnulls));
1028 mapvalues[Anum_pg_ts_config_map_mapcfg - 1] = cfgOid;
1029 mapvalues[Anum_pg_ts_config_map_maptokentype - 1] = cfgmap->maptokentype;
1030 mapvalues[Anum_pg_ts_config_map_mapseqno - 1] = cfgmap->mapseqno;
1031 mapvalues[Anum_pg_ts_config_map_mapdict - 1] = cfgmap->mapdict;
1075 elog(
ERROR,
"cache lookup failed for text search dictionary %u",
1088 Anum_pg_ts_config_map_mapcfg,
1120 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1121 errmsg(
"text search configuration \"%s\" does not exist",
1169 res = (
int *)
palloc(
sizeof(
int) * ntoken);
1172 elog(
ERROR,
"method lextype isn't defined for text search parser %u",
1180 foreach(tn, tokennames)
1187 while (list && list[j].lexid)
1199 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1200 errmsg(
"token type \"%s\" does not exist",
1230 cfgId = tsform->oid;
1231 prsId = tsform->cfgparser;
1241 for (i = 0; i < ntoken; i++)
1244 Anum_pg_ts_config_map_mapcfg,
1248 Anum_pg_ts_config_map_maptokentype,
1270 foreach(c, stmt->
dicts)
1283 Oid dictOld = dictIds[0],
1284 dictNew = dictIds[1];
1287 Anum_pg_ts_config_map_mapcfg,
1303 bool tokmatch =
false;
1305 for (j = 0; j < ntoken; j++)
1307 if (cfgmap->maptokentype == tokens[j])
1320 if (cfgmap->mapdict == dictOld)
1322 Datum repl_val[Natts_pg_ts_config_map];
1323 bool repl_null[Natts_pg_ts_config_map];
1324 bool repl_repl[Natts_pg_ts_config_map];
1327 memset(repl_val, 0,
sizeof(repl_val));
1328 memset(repl_null,
false,
sizeof(repl_null));
1329 memset(repl_repl,
false,
sizeof(repl_repl));
1332 repl_repl[Anum_pg_ts_config_map_mapdict - 1] =
true;
1336 repl_val, repl_null, repl_repl);
1348 for (i = 0; i < ntoken; i++)
1350 for (j = 0; j < ndict; j++)
1353 bool nulls[Natts_pg_ts_config_map];
1355 memset(nulls,
false,
sizeof(nulls));
1357 values[Anum_pg_ts_config_map_maptokentype - 1] =
Int32GetDatum(tokens[i]);
1358 values[Anum_pg_ts_config_map_mapseqno - 1] =
Int32GetDatum(j + 1);
1390 cfgId = tsform->oid;
1391 prsId = tsform->cfgparser;
1402 Anum_pg_ts_config_map_mapcfg,
1406 Anum_pg_ts_config_map_maptokentype,
1426 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1427 errmsg(
"mapping for token type \"%s\" does not exist",
1433 (
errmsg(
"mapping for token type \"%s\" does not exist, skipping",
1475 if (
IsA(defel->
arg, Integer) ||
IsA(defel->
arg, Float))
1480 if (strchr(val,
'\\'))
1493 if (
lnext(deflist, l) != NULL)
1531 ds_state
state = CS_WAITKEY;
1533 workspace = (
char *)
palloc(len + 1);
1536 for (; ptr < endptr; ptr++)
1541 if (isspace((
unsigned char) *ptr) || *ptr ==
',')
1556 if (isspace((
unsigned char) *ptr))
1561 else if (*ptr ==
'=')
1564 state = CS_WAITVALUE;
1574 if (ptr + 1 < endptr && ptr[1] ==
'"')
1592 state = CS_WAITVALUE;
1593 else if (!isspace((
unsigned char) *ptr))
1595 (
errcode(ERRCODE_SYNTAX_ERROR),
1596 errmsg(
"invalid parameter list format: \"%s\"",
1603 state = CS_INSQVALUE;
1605 else if (*ptr ==
'E' && ptr + 1 < endptr && ptr[1] ==
'\'')
1609 state = CS_INSQVALUE;
1611 else if (*ptr ==
'"')
1614 state = CS_INDQVALUE;
1616 else if (!isspace((
unsigned char) *ptr))
1620 state = CS_INWVALUE;
1626 if (ptr + 1 < endptr && ptr[1] ==
'\'')
1641 else if (*ptr ==
'\\')
1643 if (ptr + 1 < endptr && ptr[1] ==
'\\')
1659 if (ptr + 1 < endptr && ptr[1] ==
'"')
1680 if (*ptr ==
',' || isspace((
unsigned char) *ptr))
1695 elog(
ERROR,
"unrecognized deserialize_deflist state: %d",
1700 if (state == CS_INWVALUE)
1708 else if (state != CS_WAITKEY)
1710 (
errcode(ERRCODE_SYNTAX_ERROR),
1711 errmsg(
"invalid parameter list format: \"%s\"",
1726 if (!was_quoted && val[0] !=
'\0')
1734 if (errno == 0 && *endptr ==
'\0')
1740 (void) strtod(val, &endptr);
1741 if (errno == 0 && *endptr ==
'\0')
Value * makeString(char *str)
ObjectAddress DefineTSParser(List *names, List *parameters)
#define TSTemplateOidIndexId
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
#define IsA(nodeptr, _type_)
ObjectAddress DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
void table_close(Relation relation, LOCKMODE lockmode)
void systable_endscan(SysScanDesc sysscan)
#define InvokeObjectPostCreateHook(classId, objectId, subId)
const char * quote_identifier(const char *ident)
static ListCell * lnext(const List *l, const ListCell *c)
bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
FormData_pg_ts_config * Form_pg_ts_config
#define RelationGetDescr(relation)
void namestrcpy(Name name, const char *str)
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
FormData_pg_ts_config_map * Form_pg_ts_config_map
#define PointerGetDatum(X)
bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
List * deserialize_deflist(Datum txt)
#define DatumGetObjectId(X)
char * pstrdup(const char *in)
static Datum get_ts_template_func(DefElem *defel, int attnum)
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
#define DatumGetTextPP(X)
static ObjectAddress makeConfigurationDependencies(HeapTuple tuple, bool removeOld, Relation mapRel)
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
int errcode(int sqlerrcode)
Oid get_ts_config_oid(List *names, bool missing_ok)
static ObjectAddress makeParserDependencies(HeapTuple tuple)
TSParserCacheEntry * lookup_ts_parser_cache(Oid prsId)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
void heap_freetuple(HeapTuple htup)
#define ESCAPE_STRING_SYNTAX
static void DropConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
#define OidIsValid(objectId)
static ObjectAddress makeDictionaryDependencies(HeapTuple tuple)
DefElem * makeDefElem(char *name, Node *arg, int location)
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Oid get_func_rettype(Oid funcid)
static DefElem * buildDefItem(const char *name, const char *val, bool was_quoted)
#define foreach_delete_current(lst, cell)
Oid get_ts_dict_oid(List *names, bool missing_ok)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
HeapTuple systable_getnext(SysScanDesc sysscan)
void pfree(void *pointer)
void appendStringInfo(StringInfo str, const char *fmt,...)
#define ObjectIdGetDatum(X)
void RemoveTSConfigurationById(Oid cfgId)
char * defGetString(DefElem *def)
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
#define OidFunctionCall1(functionId, arg1)
ObjectAddress AlterTSConfiguration(AlterTSConfigurationStmt *stmt)
FormData_pg_ts_dict * Form_pg_ts_dict
void appendStringInfoString(StringInfo str, const char *s)
static int * getTokenTypes(Oid prsId, List *tokennames)
Oid get_ts_template_oid(List *names, bool missing_ok)
char * get_namespace_name(Oid nspid)
text * cstring_to_text_with_len(const char *s, int len)
ObjectAddress AlterTSDictionary(AlterTSDictionaryStmt *stmt)
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
void EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId, Oid *dictIds, int ndicts)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
List * lappend(List *list, void *datum)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
static HeapTuple GetTSConfigTuple(List *names)
Value * makeInteger(int i)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
char * NameListToString(List *names)
text * serialize_deflist(List *deflist)
void CommandCounterIncrement(void)
void ReleaseSysCache(HeapTuple tuple)
FormData_pg_ts_parser * Form_pg_ts_parser
Value * makeFloat(char *numericStr)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
#define TSConfigOidIndexId
#define ereport(elevel,...)
#define TSConfigMapIndexId
static ObjectAddress makeTSTemplateDependencies(HeapTuple tuple)
#define HeapTupleIsValid(tuple)
Oid get_ts_parser_oid(List *names, bool missing_ok)
ObjectAddress DefineTSDictionary(List *names, List *parameters)
static void verify_dictoptions(Oid tmplId, List *dictoptions)
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
List * defGetQualifiedName(DefElem *def)
static Datum get_ts_parser_func(DefElem *defel, int attnum)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
static int list_length(const List *l)
#define TSParserOidIndexId
#define ObjectAddressSet(addr, class_id, object_id)
#define DatumGetPointer(X)
static Datum values[MAXATTR]
char * text_to_cstring(const text *t)
#define VARSIZE_ANY_EXHDR(PTR)
int errmsg(const char *fmt,...)
FormData_pg_ts_template * Form_pg_ts_template
ObjectAddress DefineTSTemplate(List *names, List *parameters)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
#define SQL_STR_DOUBLE(ch, escape_backslash)
Relation table_open(Oid relationId, LOCKMODE lockmode)
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
static void MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
#define BTEqualStrategyNumber
#define TSDictionaryOidIndexId