PostgreSQL Source Code git master
tsearchcmds.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_config_map.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "common/string.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_func.h"
#include "tsearch/ts_cache.h"
#include "tsearch/ts_public.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for tsearchcmds.c:

Go to the source code of this file.

Data Structures

struct  TSTokenTypeItem
 

Functions

static void MakeConfigurationMapping (AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
 
static void DropConfigurationMapping (AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
 
static DefElembuildDefItem (const char *name, const char *val, bool was_quoted)
 
static Datum get_ts_parser_func (DefElem *defel, int attnum)
 
static ObjectAddress makeParserDependencies (HeapTuple tuple)
 
ObjectAddress DefineTSParser (List *names, List *parameters)
 
static ObjectAddress makeDictionaryDependencies (HeapTuple tuple)
 
static void verify_dictoptions (Oid tmplId, List *dictoptions)
 
ObjectAddress DefineTSDictionary (List *names, List *parameters)
 
ObjectAddress AlterTSDictionary (AlterTSDictionaryStmt *stmt)
 
static Datum get_ts_template_func (DefElem *defel, int attnum)
 
static ObjectAddress makeTSTemplateDependencies (HeapTuple tuple)
 
ObjectAddress DefineTSTemplate (List *names, List *parameters)
 
static HeapTuple GetTSConfigTuple (List *names)
 
static ObjectAddress makeConfigurationDependencies (HeapTuple tuple, bool removeOld, Relation mapRel)
 
ObjectAddress DefineTSConfiguration (List *names, List *parameters, ObjectAddress *copied)
 
void RemoveTSConfigurationById (Oid cfgId)
 
ObjectAddress AlterTSConfiguration (AlterTSConfigurationStmt *stmt)
 
static bool tstoken_list_member (char *token_name, List *tokens)
 
static ListgetTokenTypes (Oid prsId, List *tokennames)
 
textserialize_deflist (List *deflist)
 
Listdeserialize_deflist (Datum txt)
 

Function Documentation

◆ AlterTSConfiguration()

ObjectAddress AlterTSConfiguration ( AlterTSConfigurationStmt stmt)

Definition at line 1156 of file tsearchcmds.c.

1157{
1158 HeapTuple tup;
1159 Oid cfgId;
1160 Relation relMap;
1161 ObjectAddress address;
1162
1163 /* Find the configuration */
1164 tup = GetTSConfigTuple(stmt->cfgname);
1165 if (!HeapTupleIsValid(tup))
1166 ereport(ERROR,
1167 (errcode(ERRCODE_UNDEFINED_OBJECT),
1168 errmsg("text search configuration \"%s\" does not exist",
1169 NameListToString(stmt->cfgname))));
1170
1171 cfgId = ((Form_pg_ts_config) GETSTRUCT(tup))->oid;
1172
1173 /* must be owner */
1174 if (!object_ownercheck(TSConfigRelationId, cfgId, GetUserId()))
1176 NameListToString(stmt->cfgname));
1177
1178 relMap = table_open(TSConfigMapRelationId, RowExclusiveLock);
1179
1180 /* Add or drop mappings */
1181 if (stmt->dicts)
1182 MakeConfigurationMapping(stmt, tup, relMap);
1183 else if (stmt->tokentype)
1184 DropConfigurationMapping(stmt, tup, relMap);
1185
1186 /* Update dependencies */
1187 makeConfigurationDependencies(tup, true, relMap);
1188
1189 InvokeObjectPostAlterHook(TSConfigRelationId, cfgId, 0);
1190
1191 ObjectAddressSet(address, TSConfigRelationId, cfgId);
1192
1194
1195 ReleaseSysCache(tup);
1196
1197 return address;
1198}
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2622
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4058
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
#define stmt
Definition: indent_codes.h:59
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid GetUserId(void)
Definition: miscinit.c:517
char * NameListToString(const List *names)
Definition: namespace.c:3594
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
@ OBJECT_TSCONFIGURATION
Definition: parsenodes.h:2357
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
unsigned int Oid
Definition: postgres_ext.h:32
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
static ObjectAddress makeConfigurationDependencies(HeapTuple tuple, bool removeOld, Relation mapRel)
Definition: tsearchcmds.c:812
static HeapTuple GetTSConfigTuple(List *names)
Definition: tsearchcmds.c:787
static void DropConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1491
static void MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1288

References aclcheck_error(), ACLCHECK_NOT_OWNER, DropConfigurationMapping(), ereport, errcode(), errmsg(), ERROR, GETSTRUCT(), GetTSConfigTuple(), GetUserId(), HeapTupleIsValid, InvokeObjectPostAlterHook, makeConfigurationDependencies(), MakeConfigurationMapping(), NameListToString(), object_ownercheck(), OBJECT_TSCONFIGURATION, ObjectAddressSet, ReleaseSysCache(), RowExclusiveLock, stmt, table_close(), and table_open().

Referenced by ProcessUtilitySlow().

◆ AlterTSDictionary()

ObjectAddress AlterTSDictionary ( AlterTSDictionaryStmt stmt)

Definition at line 493 of file tsearchcmds.c.

494{
495 HeapTuple tup,
496 newtup;
497 Relation rel;
498 Oid dictId;
499 ListCell *pl;
500 List *dictoptions;
501 Datum opt;
502 bool isnull;
503 Datum repl_val[Natts_pg_ts_dict];
504 bool repl_null[Natts_pg_ts_dict];
505 bool repl_repl[Natts_pg_ts_dict];
506 ObjectAddress address;
507
508 dictId = get_ts_dict_oid(stmt->dictname, false);
509
510 rel = table_open(TSDictionaryRelationId, RowExclusiveLock);
511
512 tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
513
514 if (!HeapTupleIsValid(tup))
515 elog(ERROR, "cache lookup failed for text search dictionary %u",
516 dictId);
517
518 /* must be owner */
519 if (!object_ownercheck(TSDictionaryRelationId, dictId, GetUserId()))
521 NameListToString(stmt->dictname));
522
523 /* deserialize the existing set of options */
524 opt = SysCacheGetAttr(TSDICTOID, tup,
525 Anum_pg_ts_dict_dictinitoption,
526 &isnull);
527 if (isnull)
528 dictoptions = NIL;
529 else
530 dictoptions = deserialize_deflist(opt);
531
532 /*
533 * Modify the options list as per specified changes
534 */
535 foreach(pl, stmt->options)
536 {
537 DefElem *defel = (DefElem *) lfirst(pl);
538 ListCell *cell;
539
540 /*
541 * Remove any matches ...
542 */
543 foreach(cell, dictoptions)
544 {
545 DefElem *oldel = (DefElem *) lfirst(cell);
546
547 if (strcmp(oldel->defname, defel->defname) == 0)
548 dictoptions = foreach_delete_current(dictoptions, cell);
549 }
550
551 /*
552 * and add new value if it's got one
553 */
554 if (defel->arg)
555 dictoptions = lappend(dictoptions, defel);
556 }
557
558 /*
559 * Validate
560 */
561 verify_dictoptions(((Form_pg_ts_dict) GETSTRUCT(tup))->dicttemplate,
562 dictoptions);
563
564 /*
565 * Looks good, update
566 */
567 memset(repl_val, 0, sizeof(repl_val));
568 memset(repl_null, false, sizeof(repl_null));
569 memset(repl_repl, false, sizeof(repl_repl));
570
571 if (dictoptions)
572 repl_val[Anum_pg_ts_dict_dictinitoption - 1] =
574 else
575 repl_null[Anum_pg_ts_dict_dictinitoption - 1] = true;
576 repl_repl[Anum_pg_ts_dict_dictinitoption - 1] = true;
577
578 newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
579 repl_val, repl_null, repl_repl);
580
581 CatalogTupleUpdate(rel, &newtup->t_self, newtup);
582
583 InvokeObjectPostAlterHook(TSDictionaryRelationId, dictId, 0);
584
585 ObjectAddressSet(address, TSDictionaryRelationId, dictId);
586
587 /*
588 * NOTE: because we only support altering the options, not the template,
589 * there is no need to update dependencies. This might have to change if
590 * the options ever reference inside-the-database objects.
591 */
592
593 heap_freetuple(newtup);
594 ReleaseSysCache(tup);
595
597
598 return address;
599}
#define elog(elevel,...)
Definition: elog.h:225
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1210
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
List * lappend(List *list, void *datum)
Definition: list.c:339
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition: namespace.c:2861
@ OBJECT_TSDICTIONARY
Definition: parsenodes.h:2358
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
#define foreach_delete_current(lst, var_or_cell)
Definition: pg_list.h:391
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
#define RelationGetDescr(relation)
Definition: rel.h:538
char * defname
Definition: parsenodes.h:826
Node * arg
Definition: parsenodes.h:827
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:54
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1621
text * serialize_deflist(List *deflist)
Definition: tsearchcmds.c:1565
static void verify_dictoptions(Oid tmplId, List *dictoptions)
Definition: tsearchcmds.c:342

References aclcheck_error(), ACLCHECK_NOT_OWNER, DefElem::arg, CatalogTupleUpdate(), DefElem::defname, deserialize_deflist(), elog, ERROR, foreach_delete_current, get_ts_dict_oid(), GETSTRUCT(), GetUserId(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, lappend(), lfirst, NameListToString(), NIL, object_ownercheck(), OBJECT_TSDICTIONARY, ObjectAddressSet, ObjectIdGetDatum(), PointerGetDatum(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), serialize_deflist(), stmt, SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), and verify_dictoptions().

Referenced by ProcessUtilitySlow().

◆ buildDefItem()

static DefElem * buildDefItem ( const char *  name,
const char *  val,
bool  was_quoted 
)
static

Definition at line 1834 of file tsearchcmds.c.

1835{
1836 /* If input was quoted, always emit as string */
1837 if (!was_quoted && val[0] != '\0')
1838 {
1839 int v;
1840 char *endptr;
1841
1842 /* Try to parse as an integer */
1843 errno = 0;
1844 v = strtoint(val, &endptr, 10);
1845 if (errno == 0 && *endptr == '\0')
1846 return makeDefElem(pstrdup(name),
1847 (Node *) makeInteger(v),
1848 -1);
1849 /* Nope, how about as a float? */
1850 errno = 0;
1851 (void) strtod(val, &endptr);
1852 if (errno == 0 && *endptr == '\0')
1853 return makeDefElem(pstrdup(name),
1854 (Node *) makeFloat(pstrdup(val)),
1855 -1);
1856
1857 if (strcmp(val, "true") == 0)
1858 return makeDefElem(pstrdup(name),
1859 (Node *) makeBoolean(true),
1860 -1);
1861 if (strcmp(val, "false") == 0)
1862 return makeDefElem(pstrdup(name),
1863 (Node *) makeBoolean(false),
1864 -1);
1865 }
1866 /* Just make it a string */
1867 return makeDefElem(pstrdup(name),
1868 (Node *) makeString(pstrdup(val)),
1869 -1);
1870}
long val
Definition: informix.c:689
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:590
char * pstrdup(const char *in)
Definition: mcxt.c:1696
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:50
Definition: nodes.h:129
Integer * makeInteger(int i)
Definition: value.c:23
String * makeString(char *str)
Definition: value.c:63
Float * makeFloat(char *numericStr)
Definition: value.c:37
Boolean * makeBoolean(bool val)
Definition: value.c:49
const char * name

References makeBoolean(), makeDefElem(), makeFloat(), makeInteger(), makeString(), name, pstrdup(), strtoint(), and val.

Referenced by deserialize_deflist().

◆ DefineTSConfiguration()

ObjectAddress DefineTSConfiguration ( List names,
List parameters,
ObjectAddress copied 
)

Definition at line 899 of file tsearchcmds.c.

900{
901 Relation cfgRel;
902 Relation mapRel = NULL;
903 HeapTuple tup;
904 Datum values[Natts_pg_ts_config];
905 bool nulls[Natts_pg_ts_config];
906 AclResult aclresult;
907 Oid namespaceoid;
908 char *cfgname;
910 Oid sourceOid = InvalidOid;
911 Oid prsOid = InvalidOid;
912 Oid cfgOid;
913 ListCell *pl;
914 ObjectAddress address;
915
916 /* Convert list of names to a name and namespace */
917 namespaceoid = QualifiedNameGetCreationNamespace(names, &cfgname);
918
919 /* Check we have creation rights in target namespace */
920 aclresult = object_aclcheck(NamespaceRelationId, namespaceoid, GetUserId(), ACL_CREATE);
921 if (aclresult != ACLCHECK_OK)
922 aclcheck_error(aclresult, OBJECT_SCHEMA,
923 get_namespace_name(namespaceoid));
924
925 /*
926 * loop over the definition list and extract the information we need.
927 */
928 foreach(pl, parameters)
929 {
930 DefElem *defel = (DefElem *) lfirst(pl);
931
932 if (strcmp(defel->defname, "parser") == 0)
933 prsOid = get_ts_parser_oid(defGetQualifiedName(defel), false);
934 else if (strcmp(defel->defname, "copy") == 0)
935 sourceOid = get_ts_config_oid(defGetQualifiedName(defel), false);
936 else
938 (errcode(ERRCODE_SYNTAX_ERROR),
939 errmsg("text search configuration parameter \"%s\" not recognized",
940 defel->defname)));
941 }
942
943 if (OidIsValid(sourceOid) && OidIsValid(prsOid))
945 (errcode(ERRCODE_SYNTAX_ERROR),
946 errmsg("cannot specify both PARSER and COPY options")));
947
948 /* make copied tsconfig available to callers */
949 if (copied && OidIsValid(sourceOid))
950 {
951 ObjectAddressSet(*copied,
952 TSConfigRelationId,
953 sourceOid);
954 }
955
956 /*
957 * Look up source config if given.
958 */
959 if (OidIsValid(sourceOid))
960 {
962
963 tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(sourceOid));
964 if (!HeapTupleIsValid(tup))
965 elog(ERROR, "cache lookup failed for text search configuration %u",
966 sourceOid);
967
968 cfg = (Form_pg_ts_config) GETSTRUCT(tup);
969
970 /* use source's parser */
971 prsOid = cfg->cfgparser;
972
973 ReleaseSysCache(tup);
974 }
975
976 /*
977 * Validation
978 */
979 if (!OidIsValid(prsOid))
981 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
982 errmsg("text search parser is required")));
983
984 cfgRel = table_open(TSConfigRelationId, RowExclusiveLock);
985
986 /*
987 * Looks good, build tuple and insert
988 */
989 memset(values, 0, sizeof(values));
990 memset(nulls, false, sizeof(nulls));
991
992 cfgOid = GetNewOidWithIndex(cfgRel, TSConfigOidIndexId,
993 Anum_pg_ts_config_oid);
994 values[Anum_pg_ts_config_oid - 1] = ObjectIdGetDatum(cfgOid);
995 namestrcpy(&cname, cfgname);
996 values[Anum_pg_ts_config_cfgname - 1] = NameGetDatum(&cname);
997 values[Anum_pg_ts_config_cfgnamespace - 1] = ObjectIdGetDatum(namespaceoid);
998 values[Anum_pg_ts_config_cfgowner - 1] = ObjectIdGetDatum(GetUserId());
999 values[Anum_pg_ts_config_cfgparser - 1] = ObjectIdGetDatum(prsOid);
1000
1001 tup = heap_form_tuple(cfgRel->rd_att, values, nulls);
1002
1003 CatalogTupleInsert(cfgRel, tup);
1004
1005 if (OidIsValid(sourceOid))
1006 {
1007 /*
1008 * Copy token-dicts map from source config
1009 */
1010 ScanKeyData skey;
1011 SysScanDesc scan;
1012 HeapTuple maptup;
1013 TupleDesc mapDesc;
1014 TupleTableSlot **slot;
1015 CatalogIndexState indstate;
1016 int max_slots,
1017 slot_init_count,
1018 slot_stored_count;
1019
1020 mapRel = table_open(TSConfigMapRelationId, RowExclusiveLock);
1021 mapDesc = RelationGetDescr(mapRel);
1022
1023 indstate = CatalogOpenIndexes(mapRel);
1024
1025 /*
1026 * Allocate the slots to use, but delay costly initialization until we
1027 * know that they will be used.
1028 */
1030 slot = palloc(sizeof(TupleTableSlot *) * max_slots);
1031
1032 ScanKeyInit(&skey,
1033 Anum_pg_ts_config_map_mapcfg,
1034 BTEqualStrategyNumber, F_OIDEQ,
1035 ObjectIdGetDatum(sourceOid));
1036
1037 scan = systable_beginscan(mapRel, TSConfigMapIndexId, true,
1038 NULL, 1, &skey);
1039
1040 /* number of slots currently storing tuples */
1041 slot_stored_count = 0;
1042 /* number of slots currently initialized */
1043 slot_init_count = 0;
1044
1045 while (HeapTupleIsValid((maptup = systable_getnext(scan))))
1046 {
1048
1049 if (slot_init_count < max_slots)
1050 {
1051 slot[slot_stored_count] = MakeSingleTupleTableSlot(mapDesc,
1053 slot_init_count++;
1054 }
1055
1056 ExecClearTuple(slot[slot_stored_count]);
1057
1058 memset(slot[slot_stored_count]->tts_isnull, false,
1059 slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool));
1060
1061 slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_mapcfg - 1] = cfgOid;
1062 slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_maptokentype - 1] = cfgmap->maptokentype;
1063 slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_mapseqno - 1] = cfgmap->mapseqno;
1064 slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_mapdict - 1] = cfgmap->mapdict;
1065
1066 ExecStoreVirtualTuple(slot[slot_stored_count]);
1067 slot_stored_count++;
1068
1069 /* If slots are full, insert a batch of tuples */
1070 if (slot_stored_count == max_slots)
1071 {
1072 CatalogTuplesMultiInsertWithInfo(mapRel, slot, slot_stored_count,
1073 indstate);
1074 slot_stored_count = 0;
1075 }
1076 }
1077
1078 /* Insert any tuples left in the buffer */
1079 if (slot_stored_count > 0)
1080 CatalogTuplesMultiInsertWithInfo(mapRel, slot, slot_stored_count,
1081 indstate);
1082
1083 for (int i = 0; i < slot_init_count; i++)
1085
1086 systable_endscan(scan);
1087 CatalogCloseIndexes(indstate);
1088 }
1089
1090 address = makeConfigurationDependencies(tup, false, mapRel);
1091
1092 /* Post creation hook for new text search configuration */
1093 InvokeObjectPostCreateHook(TSConfigRelationId, cfgOid, 0);
1094
1095 heap_freetuple(tup);
1096
1097 if (mapRel)
1100
1101 return address;
1102}
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3804
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define OidIsValid(objectId)
Definition: c.h:732
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:419
List * defGetQualifiedName(DefElem *def)
Definition: define.c:239
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1425
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1441
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1739
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:85
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:606
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:513
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate)
Definition: indexing.c:273
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:61
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:43
#define MAX_CATALOG_MULTI_INSERT_BYTES
Definition: indexing.h:33
int i
Definition: isn.c:72
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3393
void * palloc(Size size)
Definition: mcxt.c:1317
void namestrcpy(Name name, const char *str)
Definition: name.c:233
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Definition: namespace.c:3487
Oid get_ts_parser_oid(List *names, bool missing_ok)
Definition: namespace.c:2716
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:3152
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
@ OBJECT_SCHEMA
Definition: parsenodes.h:2348
#define ACL_CREATE
Definition: parsenodes.h:85
FormData_pg_ts_config_map * Form_pg_ts_config_map
FormData_pg_ts_config_map
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:378
#define InvalidOid
Definition: postgres_ext.h:37
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
TupleDesc rd_att
Definition: rel.h:112
Datum * tts_values
Definition: tuptable.h:125
Definition: c.h:698
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, BTEqualStrategyNumber, CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTupleInsert(), CatalogTuplesMultiInsertWithInfo(), defGetQualifiedName(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, ExecClearTuple(), ExecDropSingleTupleTableSlot(), ExecStoreVirtualTuple(), FormData_pg_ts_config_map, get_namespace_name(), get_ts_config_oid(), get_ts_parser_oid(), GetNewOidWithIndex(), GETSTRUCT(), GetUserId(), heap_form_tuple(), heap_freetuple(), HeapTupleIsValid, i, InvalidOid, InvokeObjectPostCreateHook, lfirst, makeConfigurationDependencies(), MakeSingleTupleTableSlot(), MAX_CATALOG_MULTI_INSERT_BYTES, NameGetDatum(), namestrcpy(), object_aclcheck(), OBJECT_SCHEMA, ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, palloc(), QualifiedNameGetCreationNamespace(), RelationData::rd_att, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TupleTableSlot::tts_values, TTSOpsHeapTuple, and values.

Referenced by ProcessUtilitySlow().

◆ DefineTSDictionary()

ObjectAddress DefineTSDictionary ( List names,
List parameters 
)

Definition at line 397 of file tsearchcmds.c.

398{
399 ListCell *pl;
400 Relation dictRel;
401 HeapTuple tup;
402 Datum values[Natts_pg_ts_dict];
403 bool nulls[Natts_pg_ts_dict];
404 NameData dname;
405 Oid templId = InvalidOid;
406 List *dictoptions = NIL;
407 Oid dictOid;
408 Oid namespaceoid;
409 AclResult aclresult;
410 char *dictname;
411 ObjectAddress address;
412
413 /* Convert list of names to a name and namespace */
414 namespaceoid = QualifiedNameGetCreationNamespace(names, &dictname);
415
416 /* Check we have creation rights in target namespace */
417 aclresult = object_aclcheck(NamespaceRelationId, namespaceoid, GetUserId(), ACL_CREATE);
418 if (aclresult != ACLCHECK_OK)
419 aclcheck_error(aclresult, OBJECT_SCHEMA,
420 get_namespace_name(namespaceoid));
421
422 /*
423 * loop over the definition list and extract the information we need.
424 */
425 foreach(pl, parameters)
426 {
427 DefElem *defel = (DefElem *) lfirst(pl);
428
429 if (strcmp(defel->defname, "template") == 0)
430 {
431 templId = get_ts_template_oid(defGetQualifiedName(defel), false);
432 }
433 else
434 {
435 /* Assume it's an option for the dictionary itself */
436 dictoptions = lappend(dictoptions, defel);
437 }
438 }
439
440 /*
441 * Validation
442 */
443 if (!OidIsValid(templId))
445 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
446 errmsg("text search template is required")));
447
448 verify_dictoptions(templId, dictoptions);
449
450
451 dictRel = table_open(TSDictionaryRelationId, RowExclusiveLock);
452
453 /*
454 * Looks good, insert
455 */
456 memset(values, 0, sizeof(values));
457 memset(nulls, false, sizeof(nulls));
458
459 dictOid = GetNewOidWithIndex(dictRel, TSDictionaryOidIndexId,
460 Anum_pg_ts_dict_oid);
461 values[Anum_pg_ts_dict_oid - 1] = ObjectIdGetDatum(dictOid);
462 namestrcpy(&dname, dictname);
463 values[Anum_pg_ts_dict_dictname - 1] = NameGetDatum(&dname);
464 values[Anum_pg_ts_dict_dictnamespace - 1] = ObjectIdGetDatum(namespaceoid);
465 values[Anum_pg_ts_dict_dictowner - 1] = ObjectIdGetDatum(GetUserId());
466 values[Anum_pg_ts_dict_dicttemplate - 1] = ObjectIdGetDatum(templId);
467 if (dictoptions)
468 values[Anum_pg_ts_dict_dictinitoption - 1] =
470 else
471 nulls[Anum_pg_ts_dict_dictinitoption - 1] = true;
472
473 tup = heap_form_tuple(dictRel->rd_att, values, nulls);
474
475 CatalogTupleInsert(dictRel, tup);
476
477 address = makeDictionaryDependencies(tup);
478
479 /* Post creation hook for new text search dictionary */
480 InvokeObjectPostCreateHook(TSDictionaryRelationId, dictOid, 0);
481
482 heap_freetuple(tup);
483
485
486 return address;
487}
Oid get_ts_template_oid(List *names, bool missing_ok)
Definition: namespace.c:3007
static ObjectAddress makeDictionaryDependencies(HeapTuple tuple)
Definition: tsearchcmds.c:307

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, CatalogTupleInsert(), defGetQualifiedName(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, get_namespace_name(), get_ts_template_oid(), GetNewOidWithIndex(), GetUserId(), heap_form_tuple(), heap_freetuple(), InvalidOid, InvokeObjectPostCreateHook, lappend(), lfirst, makeDictionaryDependencies(), NameGetDatum(), namestrcpy(), NIL, object_aclcheck(), OBJECT_SCHEMA, ObjectIdGetDatum(), OidIsValid, PointerGetDatum(), QualifiedNameGetCreationNamespace(), RelationData::rd_att, RowExclusiveLock, serialize_deflist(), table_close(), table_open(), values, and verify_dictoptions().

Referenced by ProcessUtilitySlow().

◆ DefineTSParser()

ObjectAddress DefineTSParser ( List names,
List parameters 
)

Definition at line 184 of file tsearchcmds.c.

185{
186 char *prsname;
187 ListCell *pl;
188 Relation prsRel;
189 HeapTuple tup;
190 Datum values[Natts_pg_ts_parser];
191 bool nulls[Natts_pg_ts_parser];
192 NameData pname;
193 Oid prsOid;
194 Oid namespaceoid;
195 ObjectAddress address;
196
197 if (!superuser())
199 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
200 errmsg("must be superuser to create text search parsers")));
201
202 prsRel = table_open(TSParserRelationId, RowExclusiveLock);
203
204 /* Convert list of names to a name and namespace */
205 namespaceoid = QualifiedNameGetCreationNamespace(names, &prsname);
206
207 /* initialize tuple fields with name/namespace */
208 memset(values, 0, sizeof(values));
209 memset(nulls, false, sizeof(nulls));
210
211 prsOid = GetNewOidWithIndex(prsRel, TSParserOidIndexId,
212 Anum_pg_ts_parser_oid);
213 values[Anum_pg_ts_parser_oid - 1] = ObjectIdGetDatum(prsOid);
214 namestrcpy(&pname, prsname);
215 values[Anum_pg_ts_parser_prsname - 1] = NameGetDatum(&pname);
216 values[Anum_pg_ts_parser_prsnamespace - 1] = ObjectIdGetDatum(namespaceoid);
217
218 /*
219 * loop over the definition list and extract the information we need.
220 */
221 foreach(pl, parameters)
222 {
223 DefElem *defel = (DefElem *) lfirst(pl);
224
225 if (strcmp(defel->defname, "start") == 0)
226 {
227 values[Anum_pg_ts_parser_prsstart - 1] =
228 get_ts_parser_func(defel, Anum_pg_ts_parser_prsstart);
229 }
230 else if (strcmp(defel->defname, "gettoken") == 0)
231 {
232 values[Anum_pg_ts_parser_prstoken - 1] =
233 get_ts_parser_func(defel, Anum_pg_ts_parser_prstoken);
234 }
235 else if (strcmp(defel->defname, "end") == 0)
236 {
237 values[Anum_pg_ts_parser_prsend - 1] =
238 get_ts_parser_func(defel, Anum_pg_ts_parser_prsend);
239 }
240 else if (strcmp(defel->defname, "headline") == 0)
241 {
242 values[Anum_pg_ts_parser_prsheadline - 1] =
243 get_ts_parser_func(defel, Anum_pg_ts_parser_prsheadline);
244 }
245 else if (strcmp(defel->defname, "lextypes") == 0)
246 {
247 values[Anum_pg_ts_parser_prslextype - 1] =
248 get_ts_parser_func(defel, Anum_pg_ts_parser_prslextype);
249 }
250 else
252 (errcode(ERRCODE_SYNTAX_ERROR),
253 errmsg("text search parser parameter \"%s\" not recognized",
254 defel->defname)));
255 }
256
257 /*
258 * Validation
259 */
260 if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prsstart - 1])))
262 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
263 errmsg("text search parser start method is required")));
264
265 if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prstoken - 1])))
267 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
268 errmsg("text search parser gettoken method is required")));
269
270 if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prsend - 1])))
272 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
273 errmsg("text search parser end method is required")));
274
275 if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prslextype - 1])))
277 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
278 errmsg("text search parser lextypes method is required")));
279
280 /*
281 * Looks good, insert
282 */
283 tup = heap_form_tuple(prsRel->rd_att, values, nulls);
284
285 CatalogTupleInsert(prsRel, tup);
286
287 address = makeParserDependencies(tup);
288
289 /* Post creation hook for new text search parser */
290 InvokeObjectPostCreateHook(TSParserRelationId, prsOid, 0);
291
292 heap_freetuple(tup);
293
295
296 return address;
297}
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:247
bool superuser(void)
Definition: superuser.c:46
static Datum get_ts_parser_func(DefElem *defel, int attnum)
Definition: tsearchcmds.c:74
static ObjectAddress makeParserDependencies(HeapTuple tuple)
Definition: tsearchcmds.c:137

References CatalogTupleInsert(), DatumGetObjectId(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, get_ts_parser_func(), GetNewOidWithIndex(), heap_form_tuple(), heap_freetuple(), InvokeObjectPostCreateHook, lfirst, makeParserDependencies(), NameGetDatum(), namestrcpy(), ObjectIdGetDatum(), OidIsValid, QualifiedNameGetCreationNamespace(), RelationData::rd_att, RowExclusiveLock, superuser(), table_close(), table_open(), and values.

Referenced by ProcessUtilitySlow().

◆ DefineTSTemplate()

ObjectAddress DefineTSTemplate ( List names,
List parameters 
)

Definition at line 690 of file tsearchcmds.c.

691{
692 ListCell *pl;
693 Relation tmplRel;
694 HeapTuple tup;
695 Datum values[Natts_pg_ts_template];
696 bool nulls[Natts_pg_ts_template];
697 NameData dname;
698 int i;
699 Oid tmplOid;
700 Oid namespaceoid;
701 char *tmplname;
702 ObjectAddress address;
703
704 if (!superuser())
706 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
707 errmsg("must be superuser to create text search templates")));
708
709 /* Convert list of names to a name and namespace */
710 namespaceoid = QualifiedNameGetCreationNamespace(names, &tmplname);
711
712 tmplRel = table_open(TSTemplateRelationId, RowExclusiveLock);
713
714 for (i = 0; i < Natts_pg_ts_template; i++)
715 {
716 nulls[i] = false;
718 }
719
720 tmplOid = GetNewOidWithIndex(tmplRel, TSTemplateOidIndexId,
721 Anum_pg_ts_dict_oid);
722 values[Anum_pg_ts_template_oid - 1] = ObjectIdGetDatum(tmplOid);
723 namestrcpy(&dname, tmplname);
724 values[Anum_pg_ts_template_tmplname - 1] = NameGetDatum(&dname);
725 values[Anum_pg_ts_template_tmplnamespace - 1] = ObjectIdGetDatum(namespaceoid);
726
727 /*
728 * loop over the definition list and extract the information we need.
729 */
730 foreach(pl, parameters)
731 {
732 DefElem *defel = (DefElem *) lfirst(pl);
733
734 if (strcmp(defel->defname, "init") == 0)
735 {
736 values[Anum_pg_ts_template_tmplinit - 1] =
737 get_ts_template_func(defel, Anum_pg_ts_template_tmplinit);
738 nulls[Anum_pg_ts_template_tmplinit - 1] = false;
739 }
740 else if (strcmp(defel->defname, "lexize") == 0)
741 {
742 values[Anum_pg_ts_template_tmpllexize - 1] =
743 get_ts_template_func(defel, Anum_pg_ts_template_tmpllexize);
744 nulls[Anum_pg_ts_template_tmpllexize - 1] = false;
745 }
746 else
748 (errcode(ERRCODE_SYNTAX_ERROR),
749 errmsg("text search template parameter \"%s\" not recognized",
750 defel->defname)));
751 }
752
753 /*
754 * Validation
755 */
756 if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_template_tmpllexize - 1])))
758 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
759 errmsg("text search template lexize method is required")));
760
761 /*
762 * Looks good, insert
763 */
764 tup = heap_form_tuple(tmplRel->rd_att, values, nulls);
765
766 CatalogTupleInsert(tmplRel, tup);
767
768 address = makeTSTemplateDependencies(tup);
769
770 /* Post creation hook for new text search template */
771 InvokeObjectPostCreateHook(TSTemplateRelationId, tmplOid, 0);
772
773 heap_freetuple(tup);
774
776
777 return address;
778}
static ObjectAddress makeTSTemplateDependencies(HeapTuple tuple)
Definition: tsearchcmds.c:652
static Datum get_ts_template_func(DefElem *defel, int attnum)
Definition: tsearchcmds.c:609

References CatalogTupleInsert(), DatumGetObjectId(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, get_ts_template_func(), GetNewOidWithIndex(), heap_form_tuple(), heap_freetuple(), i, InvalidOid, InvokeObjectPostCreateHook, lfirst, makeTSTemplateDependencies(), NameGetDatum(), namestrcpy(), ObjectIdGetDatum(), OidIsValid, QualifiedNameGetCreationNamespace(), RelationData::rd_att, RowExclusiveLock, superuser(), table_close(), table_open(), and values.

Referenced by ProcessUtilitySlow().

◆ deserialize_deflist()

List * deserialize_deflist ( Datum  txt)

Definition at line 1621 of file tsearchcmds.c.

1622{
1623 text *in = DatumGetTextPP(txt); /* in case it's toasted */
1624 List *result = NIL;
1625 int len = VARSIZE_ANY_EXHDR(in);
1626 char *ptr,
1627 *endptr,
1628 *workspace,
1629 *wsptr = NULL,
1630 *startvalue = NULL;
1631 typedef enum
1632 {
1633 CS_WAITKEY,
1634 CS_INKEY,
1635 CS_INQKEY,
1636 CS_WAITEQ,
1637 CS_WAITVALUE,
1638 CS_INSQVALUE,
1639 CS_INDQVALUE,
1640 CS_INWVALUE
1641 } ds_state;
1642 ds_state state = CS_WAITKEY;
1643
1644 workspace = (char *) palloc(len + 1); /* certainly enough room */
1645 ptr = VARDATA_ANY(in);
1646 endptr = ptr + len;
1647 for (; ptr < endptr; ptr++)
1648 {
1649 switch (state)
1650 {
1651 case CS_WAITKEY:
1652 if (isspace((unsigned char) *ptr) || *ptr == ',')
1653 continue;
1654 if (*ptr == '"')
1655 {
1656 wsptr = workspace;
1657 state = CS_INQKEY;
1658 }
1659 else
1660 {
1661 wsptr = workspace;
1662 *wsptr++ = *ptr;
1663 state = CS_INKEY;
1664 }
1665 break;
1666 case CS_INKEY:
1667 if (isspace((unsigned char) *ptr))
1668 {
1669 *wsptr++ = '\0';
1670 state = CS_WAITEQ;
1671 }
1672 else if (*ptr == '=')
1673 {
1674 *wsptr++ = '\0';
1675 state = CS_WAITVALUE;
1676 }
1677 else
1678 {
1679 *wsptr++ = *ptr;
1680 }
1681 break;
1682 case CS_INQKEY:
1683 if (*ptr == '"')
1684 {
1685 if (ptr + 1 < endptr && ptr[1] == '"')
1686 {
1687 /* copy only one of the two quotes */
1688 *wsptr++ = *ptr++;
1689 }
1690 else
1691 {
1692 *wsptr++ = '\0';
1693 state = CS_WAITEQ;
1694 }
1695 }
1696 else
1697 {
1698 *wsptr++ = *ptr;
1699 }
1700 break;
1701 case CS_WAITEQ:
1702 if (*ptr == '=')
1703 state = CS_WAITVALUE;
1704 else if (!isspace((unsigned char) *ptr))
1705 ereport(ERROR,
1706 (errcode(ERRCODE_SYNTAX_ERROR),
1707 errmsg("invalid parameter list format: \"%s\"",
1708 text_to_cstring(in))));
1709 break;
1710 case CS_WAITVALUE:
1711 if (*ptr == '\'')
1712 {
1713 startvalue = wsptr;
1714 state = CS_INSQVALUE;
1715 }
1716 else if (*ptr == 'E' && ptr + 1 < endptr && ptr[1] == '\'')
1717 {
1718 ptr++;
1719 startvalue = wsptr;
1720 state = CS_INSQVALUE;
1721 }
1722 else if (*ptr == '"')
1723 {
1724 startvalue = wsptr;
1725 state = CS_INDQVALUE;
1726 }
1727 else if (!isspace((unsigned char) *ptr))
1728 {
1729 startvalue = wsptr;
1730 *wsptr++ = *ptr;
1731 state = CS_INWVALUE;
1732 }
1733 break;
1734 case CS_INSQVALUE:
1735 if (*ptr == '\'')
1736 {
1737 if (ptr + 1 < endptr && ptr[1] == '\'')
1738 {
1739 /* copy only one of the two quotes */
1740 *wsptr++ = *ptr++;
1741 }
1742 else
1743 {
1744 *wsptr++ = '\0';
1745 result = lappend(result,
1746 buildDefItem(workspace,
1747 startvalue,
1748 true));
1749 state = CS_WAITKEY;
1750 }
1751 }
1752 else if (*ptr == '\\')
1753 {
1754 if (ptr + 1 < endptr && ptr[1] == '\\')
1755 {
1756 /* copy only one of the two backslashes */
1757 *wsptr++ = *ptr++;
1758 }
1759 else
1760 *wsptr++ = *ptr;
1761 }
1762 else
1763 {
1764 *wsptr++ = *ptr;
1765 }
1766 break;
1767 case CS_INDQVALUE:
1768 if (*ptr == '"')
1769 {
1770 if (ptr + 1 < endptr && ptr[1] == '"')
1771 {
1772 /* copy only one of the two quotes */
1773 *wsptr++ = *ptr++;
1774 }
1775 else
1776 {
1777 *wsptr++ = '\0';
1778 result = lappend(result,
1779 buildDefItem(workspace,
1780 startvalue,
1781 true));
1782 state = CS_WAITKEY;
1783 }
1784 }
1785 else
1786 {
1787 *wsptr++ = *ptr;
1788 }
1789 break;
1790 case CS_INWVALUE:
1791 if (*ptr == ',' || isspace((unsigned char) *ptr))
1792 {
1793 *wsptr++ = '\0';
1794 result = lappend(result,
1795 buildDefItem(workspace,
1796 startvalue,
1797 false));
1798 state = CS_WAITKEY;
1799 }
1800 else
1801 {
1802 *wsptr++ = *ptr;
1803 }
1804 break;
1805 default:
1806 elog(ERROR, "unrecognized deserialize_deflist state: %d",
1807 state);
1808 }
1809 }
1810
1811 if (state == CS_INWVALUE)
1812 {
1813 *wsptr++ = '\0';
1814 result = lappend(result,
1815 buildDefItem(workspace,
1816 startvalue,
1817 false));
1818 }
1819 else if (state != CS_WAITKEY)
1820 ereport(ERROR,
1821 (errcode(ERRCODE_SYNTAX_ERROR),
1822 errmsg("invalid parameter list format: \"%s\"",
1823 text_to_cstring(in))));
1824
1825 pfree(workspace);
1826
1827 return result;
1828}
#define DatumGetTextPP(X)
Definition: fmgr.h:292
void pfree(void *pointer)
Definition: mcxt.c:1521
const void size_t len
Definition: regguts.h:323
Definition: c.h:644
static DefElem * buildDefItem(const char *name, const char *val, bool was_quoted)
Definition: tsearchcmds.c:1834
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
char * text_to_cstring(const text *t)
Definition: varlena.c:217

References buildDefItem(), DatumGetTextPP, elog, ereport, errcode(), errmsg(), ERROR, lappend(), len, NIL, palloc(), pfree(), text_to_cstring(), VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by AlterTSDictionary(), lookup_ts_dictionary_cache(), ts_headline_byid_opt(), ts_headline_json_byid_opt(), and ts_headline_jsonb_byid_opt().

◆ DropConfigurationMapping()

static void DropConfigurationMapping ( AlterTSConfigurationStmt stmt,
HeapTuple  tup,
Relation  relMap 
)
static

Definition at line 1491 of file tsearchcmds.c.

1493{
1494 Form_pg_ts_config tsform;
1495 Oid cfgId;
1496 ScanKeyData skey[2];
1497 SysScanDesc scan;
1498 HeapTuple maptup;
1499 Oid prsId;
1500 List *tokens = NIL;
1501 ListCell *c;
1502
1503 tsform = (Form_pg_ts_config) GETSTRUCT(tup);
1504 cfgId = tsform->oid;
1505 prsId = tsform->cfgparser;
1506
1507 tokens = getTokenTypes(prsId, stmt->tokentype);
1508
1509 foreach(c, tokens)
1510 {
1512 bool found = false;
1513
1514 ScanKeyInit(&skey[0],
1515 Anum_pg_ts_config_map_mapcfg,
1516 BTEqualStrategyNumber, F_OIDEQ,
1517 ObjectIdGetDatum(cfgId));
1518 ScanKeyInit(&skey[1],
1519 Anum_pg_ts_config_map_maptokentype,
1520 BTEqualStrategyNumber, F_INT4EQ,
1521 Int32GetDatum(ts->num));
1522
1523 scan = systable_beginscan(relMap, TSConfigMapIndexId, true,
1524 NULL, 2, skey);
1525
1526 while (HeapTupleIsValid((maptup = systable_getnext(scan))))
1527 {
1528 CatalogTupleDelete(relMap, &maptup->t_self);
1529 found = true;
1530 }
1531
1532 systable_endscan(scan);
1533
1534 if (!found)
1535 {
1536 if (!stmt->missing_ok)
1537 {
1538 ereport(ERROR,
1539 (errcode(ERRCODE_UNDEFINED_OBJECT),
1540 errmsg("mapping for token type \"%s\" does not exist",
1541 ts->name)));
1542 }
1543 else
1544 {
1546 (errmsg("mapping for token type \"%s\" does not exist, skipping",
1547 ts->name)));
1548 }
1549 }
1550 }
1551
1552 EventTriggerCollectAlterTSConfig(stmt, cfgId, NULL, 0);
1553}
#define NOTICE
Definition: elog.h:35
void EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId, Oid *dictIds, int ndicts)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
char * c
static List * getTokenTypes(Oid prsId, List *tokennames)
Definition: tsearchcmds.c:1229

References BTEqualStrategyNumber, CatalogTupleDelete(), ereport, errcode(), errmsg(), ERROR, EventTriggerCollectAlterTSConfig(), GETSTRUCT(), getTokenTypes(), HeapTupleIsValid, Int32GetDatum(), lfirst, TSTokenTypeItem::name, NIL, NOTICE, TSTokenTypeItem::num, ObjectIdGetDatum(), ScanKeyInit(), stmt, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by AlterTSConfiguration().

◆ get_ts_parser_func()

static Datum get_ts_parser_func ( DefElem defel,
int  attnum 
)
static

Definition at line 74 of file tsearchcmds.c.

75{
76 List *funcName = defGetQualifiedName(defel);
77 Oid typeId[3];
78 Oid retTypeId;
79 int nargs;
80 Oid procOid;
81
82 retTypeId = INTERNALOID; /* correct for most */
83 typeId[0] = INTERNALOID;
84 switch (attnum)
85 {
86 case Anum_pg_ts_parser_prsstart:
87 nargs = 2;
88 typeId[1] = INT4OID;
89 break;
90 case Anum_pg_ts_parser_prstoken:
91 nargs = 3;
92 typeId[1] = INTERNALOID;
93 typeId[2] = INTERNALOID;
94 break;
95 case Anum_pg_ts_parser_prsend:
96 nargs = 1;
97 retTypeId = VOIDOID;
98 break;
99 case Anum_pg_ts_parser_prsheadline:
100 nargs = 3;
101 typeId[1] = INTERNALOID;
102 typeId[2] = TSQUERYOID;
103 break;
104 case Anum_pg_ts_parser_prslextype:
105 nargs = 1;
106
107 /*
108 * Note: because the lextype method returns type internal, it must
109 * have an internal-type argument for security reasons. The
110 * argument is not actually used, but is just passed as a zero.
111 */
112 break;
113 default:
114 /* should not be here */
115 elog(ERROR, "unrecognized attribute for text search parser: %d",
116 attnum);
117 nargs = 0; /* keep compiler quiet */
118 }
119
120 procOid = LookupFuncName(funcName, nargs, typeId, false);
121 if (get_func_rettype(procOid) != retTypeId)
123 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
124 errmsg("function %s should return type %s",
125 func_signature_string(funcName, nargs, NIL, typeId),
126 format_type_be(retTypeId))));
127
128 return ObjectIdGetDatum(procOid);
129}
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1682
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2030
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2144
int16 attnum
Definition: pg_attribute.h:74

References attnum, defGetQualifiedName(), elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), func_signature_string(), get_func_rettype(), LookupFuncName(), NIL, and ObjectIdGetDatum().

Referenced by DefineTSParser().

◆ get_ts_template_func()

static Datum get_ts_template_func ( DefElem defel,
int  attnum 
)
static

Definition at line 609 of file tsearchcmds.c.

610{
611 List *funcName = defGetQualifiedName(defel);
612 Oid typeId[4];
613 Oid retTypeId;
614 int nargs;
615 Oid procOid;
616
617 retTypeId = INTERNALOID;
618 typeId[0] = INTERNALOID;
619 typeId[1] = INTERNALOID;
620 typeId[2] = INTERNALOID;
621 typeId[3] = INTERNALOID;
622 switch (attnum)
623 {
624 case Anum_pg_ts_template_tmplinit:
625 nargs = 1;
626 break;
627 case Anum_pg_ts_template_tmpllexize:
628 nargs = 4;
629 break;
630 default:
631 /* should not be here */
632 elog(ERROR, "unrecognized attribute for text search template: %d",
633 attnum);
634 nargs = 0; /* keep compiler quiet */
635 }
636
637 procOid = LookupFuncName(funcName, nargs, typeId, false);
638 if (get_func_rettype(procOid) != retTypeId)
640 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
641 errmsg("function %s should return type %s",
642 func_signature_string(funcName, nargs, NIL, typeId),
643 format_type_be(retTypeId))));
644
645 return ObjectIdGetDatum(procOid);
646}

References attnum, defGetQualifiedName(), elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), func_signature_string(), get_func_rettype(), LookupFuncName(), NIL, and ObjectIdGetDatum().

Referenced by DefineTSTemplate().

◆ getTokenTypes()

static List * getTokenTypes ( Oid  prsId,
List tokennames 
)
static

Definition at line 1229 of file tsearchcmds.c.

1230{
1232 LexDescr *list;
1233 List *result = NIL;
1234 int ntoken;
1235 ListCell *tn;
1236
1237 ntoken = list_length(tokennames);
1238 if (ntoken == 0)
1239 return NIL;
1240
1241 if (!OidIsValid(prs->lextypeOid))
1242 elog(ERROR, "method lextype isn't defined for text search parser %u",
1243 prsId);
1244
1245 /* lextype takes one dummy argument */
1247 (Datum) 0));
1248
1249 foreach(tn, tokennames)
1250 {
1251 String *val = lfirst_node(String, tn);
1252 bool found = false;
1253 int j;
1254
1255 /* Skip if this token is already in the result */
1256 if (tstoken_list_member(strVal(val), result))
1257 continue;
1258
1259 j = 0;
1260 while (list && list[j].lexid)
1261 {
1262 if (strcmp(strVal(val), list[j].alias) == 0)
1263 {
1265
1266 ts->num = list[j].lexid;
1267 ts->name = pstrdup(strVal(val));
1268 result = lappend(result, ts);
1269 found = true;
1270 break;
1271 }
1272 j++;
1273 }
1274 if (!found)
1275 ereport(ERROR,
1276 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1277 errmsg("token type \"%s\" does not exist",
1278 strVal(val))));
1279 }
1280
1281 return result;
1282}
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:679
int j
Definition: isn.c:73
void * palloc0(Size size)
Definition: mcxt.c:1347
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
Definition: value.h:64
TSParserCacheEntry * lookup_ts_parser_cache(Oid prsId)
Definition: ts_cache.c:113
static bool tstoken_list_member(char *token_name, List *tokens)
Definition: tsearchcmds.c:1204
#define strVal(v)
Definition: value.h:82

References DatumGetPointer(), elog, ereport, errcode(), errmsg(), ERROR, j, lappend(), TSParserCacheEntry::lextypeOid, lfirst_node, sort-test::list, list_length(), lookup_ts_parser_cache(), TSTokenTypeItem::name, NIL, TSTokenTypeItem::num, OidFunctionCall1, OidIsValid, palloc0(), pstrdup(), strVal, tstoken_list_member(), and val.

Referenced by DropConfigurationMapping(), and MakeConfigurationMapping().

◆ GetTSConfigTuple()

static HeapTuple GetTSConfigTuple ( List names)
static

Definition at line 787 of file tsearchcmds.c.

788{
789 HeapTuple tup;
790 Oid cfgId;
791
792 cfgId = get_ts_config_oid(names, true);
793 if (!OidIsValid(cfgId))
794 return NULL;
795
796 tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgId));
797
798 if (!HeapTupleIsValid(tup)) /* should not happen */
799 elog(ERROR, "cache lookup failed for text search configuration %u",
800 cfgId);
801
802 return tup;
803}

References elog, ERROR, get_ts_config_oid(), HeapTupleIsValid, ObjectIdGetDatum(), OidIsValid, and SearchSysCache1().

Referenced by AlterTSConfiguration().

◆ makeConfigurationDependencies()

static ObjectAddress makeConfigurationDependencies ( HeapTuple  tuple,
bool  removeOld,
Relation  mapRel 
)
static

Definition at line 812 of file tsearchcmds.c.

814{
816 ObjectAddresses *addrs;
817 ObjectAddress myself,
818 referenced;
819
820 myself.classId = TSConfigRelationId;
821 myself.objectId = cfg->oid;
822 myself.objectSubId = 0;
823
824 /* for ALTER case, first flush old dependencies, except extension deps */
825 if (removeOld)
826 {
827 deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
829 }
830
831 /*
832 * We use an ObjectAddresses list to remove possible duplicate
833 * dependencies from the config map info. The pg_ts_config items
834 * shouldn't be duplicates, but might as well fold them all into one call.
835 */
836 addrs = new_object_addresses();
837
838 /* dependency on namespace */
839 referenced.classId = NamespaceRelationId;
840 referenced.objectId = cfg->cfgnamespace;
841 referenced.objectSubId = 0;
842 add_exact_object_address(&referenced, addrs);
843
844 /* dependency on owner */
845 recordDependencyOnOwner(myself.classId, myself.objectId, cfg->cfgowner);
846
847 /* dependency on extension */
848 recordDependencyOnCurrentExtension(&myself, removeOld);
849
850 /* dependency on parser */
851 referenced.classId = TSParserRelationId;
852 referenced.objectId = cfg->cfgparser;
853 referenced.objectSubId = 0;
854 add_exact_object_address(&referenced, addrs);
855
856 /* dependencies on dictionaries listed in config map */
857 if (mapRel)
858 {
859 ScanKeyData skey;
860 SysScanDesc scan;
861 HeapTuple maptup;
862
863 /* CCI to ensure we can see effects of caller's changes */
865
866 ScanKeyInit(&skey,
867 Anum_pg_ts_config_map_mapcfg,
868 BTEqualStrategyNumber, F_OIDEQ,
869 ObjectIdGetDatum(myself.objectId));
870
871 scan = systable_beginscan(mapRel, TSConfigMapIndexId, true,
872 NULL, 1, &skey);
873
874 while (HeapTupleIsValid((maptup = systable_getnext(scan))))
875 {
877
878 referenced.classId = TSDictionaryRelationId;
879 referenced.objectId = cfgmap->mapdict;
880 referenced.objectSubId = 0;
881 add_exact_object_address(&referenced, addrs);
882 }
883
884 systable_endscan(scan);
885 }
886
887 /* Record 'em (this includes duplicate elimination) */
889
891
892 return myself;
893}
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2757
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2548
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2502
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2788
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:301
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:193
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1047
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:168
void CommandCounterIncrement(void)
Definition: xact.c:1099

References add_exact_object_address(), BTEqualStrategyNumber, ObjectAddress::classId, CommandCounterIncrement(), deleteDependencyRecordsFor(), deleteSharedDependencyRecordsFor(), DEPENDENCY_NORMAL, free_object_addresses(), GETSTRUCT(), HeapTupleIsValid, new_object_addresses(), ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, record_object_address_dependencies(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by AlterTSConfiguration(), and DefineTSConfiguration().

◆ MakeConfigurationMapping()

static void MakeConfigurationMapping ( AlterTSConfigurationStmt stmt,
HeapTuple  tup,
Relation  relMap 
)
static

Definition at line 1288 of file tsearchcmds.c.

1290{
1291 Form_pg_ts_config tsform;
1292 Oid cfgId;
1293 ScanKeyData skey[2];
1294 SysScanDesc scan;
1295 HeapTuple maptup;
1296 int i;
1297 int j;
1298 Oid prsId;
1299 List *tokens = NIL;
1300 int ntoken;
1301 Oid *dictIds;
1302 int ndict;
1303 ListCell *c;
1304 CatalogIndexState indstate;
1305
1306 tsform = (Form_pg_ts_config) GETSTRUCT(tup);
1307 cfgId = tsform->oid;
1308 prsId = tsform->cfgparser;
1309
1310 tokens = getTokenTypes(prsId, stmt->tokentype);
1311 ntoken = list_length(tokens);
1312
1313 if (stmt->override)
1314 {
1315 /*
1316 * delete maps for tokens if they exist and command was ALTER
1317 */
1318 foreach(c, tokens)
1319 {
1321
1322 ScanKeyInit(&skey[0],
1323 Anum_pg_ts_config_map_mapcfg,
1324 BTEqualStrategyNumber, F_OIDEQ,
1325 ObjectIdGetDatum(cfgId));
1326 ScanKeyInit(&skey[1],
1327 Anum_pg_ts_config_map_maptokentype,
1328 BTEqualStrategyNumber, F_INT4EQ,
1329 Int32GetDatum(ts->num));
1330
1331 scan = systable_beginscan(relMap, TSConfigMapIndexId, true,
1332 NULL, 2, skey);
1333
1334 while (HeapTupleIsValid((maptup = systable_getnext(scan))))
1335 {
1336 CatalogTupleDelete(relMap, &maptup->t_self);
1337 }
1338
1339 systable_endscan(scan);
1340 }
1341 }
1342
1343 /*
1344 * Convert list of dictionary names to array of dict OIDs
1345 */
1346 ndict = list_length(stmt->dicts);
1347 dictIds = (Oid *) palloc(sizeof(Oid) * ndict);
1348 i = 0;
1349 foreach(c, stmt->dicts)
1350 {
1351 List *names = (List *) lfirst(c);
1352
1353 dictIds[i] = get_ts_dict_oid(names, false);
1354 i++;
1355 }
1356
1357 indstate = CatalogOpenIndexes(relMap);
1358
1359 if (stmt->replace)
1360 {
1361 /*
1362 * Replace a specific dictionary in existing entries
1363 */
1364 Oid dictOld = dictIds[0],
1365 dictNew = dictIds[1];
1366
1367 ScanKeyInit(&skey[0],
1368 Anum_pg_ts_config_map_mapcfg,
1369 BTEqualStrategyNumber, F_OIDEQ,
1370 ObjectIdGetDatum(cfgId));
1371
1372 scan = systable_beginscan(relMap, TSConfigMapIndexId, true,
1373 NULL, 1, skey);
1374
1375 while (HeapTupleIsValid((maptup = systable_getnext(scan))))
1376 {
1378
1379 /*
1380 * check if it's one of target token types
1381 */
1382 if (tokens)
1383 {
1384 bool tokmatch = false;
1385
1386 foreach(c, tokens)
1387 {
1389
1390 if (cfgmap->maptokentype == ts->num)
1391 {
1392 tokmatch = true;
1393 break;
1394 }
1395 }
1396 if (!tokmatch)
1397 continue;
1398 }
1399
1400 /*
1401 * replace dictionary if match
1402 */
1403 if (cfgmap->mapdict == dictOld)
1404 {
1405 Datum repl_val[Natts_pg_ts_config_map];
1406 bool repl_null[Natts_pg_ts_config_map];
1407 bool repl_repl[Natts_pg_ts_config_map];
1408 HeapTuple newtup;
1409
1410 memset(repl_val, 0, sizeof(repl_val));
1411 memset(repl_null, false, sizeof(repl_null));
1412 memset(repl_repl, false, sizeof(repl_repl));
1413
1414 repl_val[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictNew);
1415 repl_repl[Anum_pg_ts_config_map_mapdict - 1] = true;
1416
1417 newtup = heap_modify_tuple(maptup,
1418 RelationGetDescr(relMap),
1419 repl_val, repl_null, repl_repl);
1420 CatalogTupleUpdateWithInfo(relMap, &newtup->t_self, newtup, indstate);
1421 }
1422 }
1423
1424 systable_endscan(scan);
1425 }
1426 else
1427 {
1428 TupleTableSlot **slot;
1429 int slotCount = 0;
1430 int nslots;
1431
1432 /* Allocate the slots to use and initialize them */
1433 nslots = Min(ntoken * ndict,
1435 slot = palloc(sizeof(TupleTableSlot *) * nslots);
1436 for (i = 0; i < nslots; i++)
1439
1440 /*
1441 * Insertion of new entries
1442 */
1443 foreach(c, tokens)
1444 {
1446
1447 for (j = 0; j < ndict; j++)
1448 {
1449 ExecClearTuple(slot[slotCount]);
1450
1451 memset(slot[slotCount]->tts_isnull, false,
1452 slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool));
1453
1454 slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapcfg - 1] = ObjectIdGetDatum(cfgId);
1455 slot[slotCount]->tts_values[Anum_pg_ts_config_map_maptokentype - 1] = Int32GetDatum(ts->num);
1456 slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapseqno - 1] = Int32GetDatum(j + 1);
1457 slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictIds[j]);
1458
1459 ExecStoreVirtualTuple(slot[slotCount]);
1460 slotCount++;
1461
1462 /* If slots are full, insert a batch of tuples */
1463 if (slotCount == nslots)
1464 {
1465 CatalogTuplesMultiInsertWithInfo(relMap, slot, slotCount,
1466 indstate);
1467 slotCount = 0;
1468 }
1469 }
1470 }
1471
1472 /* Insert any tuples left in the buffer */
1473 if (slotCount > 0)
1474 CatalogTuplesMultiInsertWithInfo(relMap, slot, slotCount,
1475 indstate);
1476
1477 for (i = 0; i < nslots; i++)
1479 }
1480
1481 /* clean up */
1482 CatalogCloseIndexes(indstate);
1483
1484 EventTriggerCollectAlterTSConfig(stmt, cfgId, dictIds, ndict);
1485}
#define Min(x, y)
Definition: c.h:961
void CatalogTupleUpdateWithInfo(Relation heapRel, ItemPointer otid, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:337

References BTEqualStrategyNumber, CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTupleDelete(), CatalogTuplesMultiInsertWithInfo(), CatalogTupleUpdateWithInfo(), EventTriggerCollectAlterTSConfig(), ExecClearTuple(), ExecDropSingleTupleTableSlot(), ExecStoreVirtualTuple(), FormData_pg_ts_config_map, get_ts_dict_oid(), GETSTRUCT(), getTokenTypes(), heap_modify_tuple(), HeapTupleIsValid, i, Int32GetDatum(), j, lfirst, list_length(), MakeSingleTupleTableSlot(), MAX_CATALOG_MULTI_INSERT_BYTES, Min, NIL, TSTokenTypeItem::num, ObjectIdGetDatum(), palloc(), RelationGetDescr, ScanKeyInit(), stmt, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, TupleTableSlot::tts_values, and TTSOpsHeapTuple.

Referenced by AlterTSConfiguration().

◆ makeDictionaryDependencies()

static ObjectAddress makeDictionaryDependencies ( HeapTuple  tuple)
static

Definition at line 307 of file tsearchcmds.c.

308{
310 ObjectAddress myself,
311 referenced;
312 ObjectAddresses *addrs;
313
314 ObjectAddressSet(myself, TSDictionaryRelationId, dict->oid);
315
316 /* dependency on owner */
317 recordDependencyOnOwner(myself.classId, myself.objectId, dict->dictowner);
318
319 /* dependency on extension */
321
322 addrs = new_object_addresses();
323
324 /* dependency on namespace */
325 ObjectAddressSet(referenced, NamespaceRelationId, dict->dictnamespace);
326 add_exact_object_address(&referenced, addrs);
327
328 /* dependency on template */
329 ObjectAddressSet(referenced, TSTemplateRelationId, dict->dicttemplate);
330 add_exact_object_address(&referenced, addrs);
331
334
335 return myself;
336}

References add_exact_object_address(), ObjectAddress::classId, DEPENDENCY_NORMAL, free_object_addresses(), GETSTRUCT(), new_object_addresses(), ObjectAddressSet, ObjectAddress::objectId, record_object_address_dependencies(), recordDependencyOnCurrentExtension(), and recordDependencyOnOwner().

Referenced by DefineTSDictionary().

◆ makeParserDependencies()

static ObjectAddress makeParserDependencies ( HeapTuple  tuple)
static

Definition at line 137 of file tsearchcmds.c.

138{
140 ObjectAddress myself,
141 referenced;
142 ObjectAddresses *addrs;
143
144 ObjectAddressSet(myself, TSParserRelationId, prs->oid);
145
146 /* dependency on extension */
148
149 addrs = new_object_addresses();
150
151 /* dependency on namespace */
152 ObjectAddressSet(referenced, NamespaceRelationId, prs->prsnamespace);
153 add_exact_object_address(&referenced, addrs);
154
155 /* dependencies on functions */
156 ObjectAddressSet(referenced, ProcedureRelationId, prs->prsstart);
157 add_exact_object_address(&referenced, addrs);
158
159 referenced.objectId = prs->prstoken;
160 add_exact_object_address(&referenced, addrs);
161
162 referenced.objectId = prs->prsend;
163 add_exact_object_address(&referenced, addrs);
164
165 referenced.objectId = prs->prslextype;
166 add_exact_object_address(&referenced, addrs);
167
168 if (OidIsValid(prs->prsheadline))
169 {
170 referenced.objectId = prs->prsheadline;
171 add_exact_object_address(&referenced, addrs);
172 }
173
176
177 return myself;
178}
FormData_pg_ts_parser * Form_pg_ts_parser
Definition: pg_ts_parser.h:55

References add_exact_object_address(), DEPENDENCY_NORMAL, free_object_addresses(), GETSTRUCT(), new_object_addresses(), ObjectAddressSet, ObjectAddress::objectId, OidIsValid, record_object_address_dependencies(), and recordDependencyOnCurrentExtension().

Referenced by DefineTSParser().

◆ makeTSTemplateDependencies()

static ObjectAddress makeTSTemplateDependencies ( HeapTuple  tuple)
static

Definition at line 652 of file tsearchcmds.c.

653{
655 ObjectAddress myself,
656 referenced;
657 ObjectAddresses *addrs;
658
659 ObjectAddressSet(myself, TSTemplateRelationId, tmpl->oid);
660
661 /* dependency on extension */
663
664 addrs = new_object_addresses();
665
666 /* dependency on namespace */
667 ObjectAddressSet(referenced, NamespaceRelationId, tmpl->tmplnamespace);
668 add_exact_object_address(&referenced, addrs);
669
670 /* dependencies on functions */
671 ObjectAddressSet(referenced, ProcedureRelationId, tmpl->tmpllexize);
672 add_exact_object_address(&referenced, addrs);
673
674 if (OidIsValid(tmpl->tmplinit))
675 {
676 referenced.objectId = tmpl->tmplinit;
677 add_exact_object_address(&referenced, addrs);
678 }
679
682
683 return myself;
684}
FormData_pg_ts_template * Form_pg_ts_template

References add_exact_object_address(), DEPENDENCY_NORMAL, free_object_addresses(), GETSTRUCT(), new_object_addresses(), ObjectAddressSet, ObjectAddress::objectId, OidIsValid, record_object_address_dependencies(), and recordDependencyOnCurrentExtension().

Referenced by DefineTSTemplate().

◆ RemoveTSConfigurationById()

void RemoveTSConfigurationById ( Oid  cfgId)

Definition at line 1108 of file tsearchcmds.c.

1109{
1110 Relation relCfg,
1111 relMap;
1112 HeapTuple tup;
1113 ScanKeyData skey;
1114 SysScanDesc scan;
1115
1116 /* Remove the pg_ts_config entry */
1117 relCfg = table_open(TSConfigRelationId, RowExclusiveLock);
1118
1119 tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgId));
1120
1121 if (!HeapTupleIsValid(tup))
1122 elog(ERROR, "cache lookup failed for text search dictionary %u",
1123 cfgId);
1124
1125 CatalogTupleDelete(relCfg, &tup->t_self);
1126
1127 ReleaseSysCache(tup);
1128
1130
1131 /* Remove any pg_ts_config_map entries */
1132 relMap = table_open(TSConfigMapRelationId, RowExclusiveLock);
1133
1134 ScanKeyInit(&skey,
1135 Anum_pg_ts_config_map_mapcfg,
1136 BTEqualStrategyNumber, F_OIDEQ,
1137 ObjectIdGetDatum(cfgId));
1138
1139 scan = systable_beginscan(relMap, TSConfigMapIndexId, true,
1140 NULL, 1, &skey);
1141
1142 while (HeapTupleIsValid((tup = systable_getnext(scan))))
1143 {
1144 CatalogTupleDelete(relMap, &tup->t_self);
1145 }
1146
1147 systable_endscan(scan);
1148
1150}

References BTEqualStrategyNumber, CatalogTupleDelete(), elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

◆ serialize_deflist()

text * serialize_deflist ( List deflist)

Definition at line 1565 of file tsearchcmds.c.

1566{
1567 text *result;
1569 ListCell *l;
1570
1572
1573 foreach(l, deflist)
1574 {
1575 DefElem *defel = (DefElem *) lfirst(l);
1576 char *val = defGetString(defel);
1577
1578 appendStringInfo(&buf, "%s = ",
1579 quote_identifier(defel->defname));
1580
1581 /*
1582 * If the value is a T_Integer or T_Float, emit it without quotes,
1583 * otherwise with quotes. This is essential to allow correct
1584 * reconstruction of the node type as well as the value.
1585 */
1586 if (IsA(defel->arg, Integer) || IsA(defel->arg, Float))
1588 else
1589 {
1590 /* If backslashes appear, force E syntax to quote them safely */
1591 if (strchr(val, '\\'))
1593 appendStringInfoChar(&buf, '\'');
1594 while (*val)
1595 {
1596 char ch = *val++;
1597
1598 if (SQL_STR_DOUBLE(ch, true))
1601 }
1602 appendStringInfoChar(&buf, '\'');
1603 }
1604 if (lnext(deflist, l) != NULL)
1606 }
1607
1608 result = cstring_to_text_with_len(buf.data, buf.len);
1609 pfree(buf.data);
1610 return result;
1611}
#define ESCAPE_STRING_SYNTAX
Definition: c.h:1123
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1120
char * defGetString(DefElem *def)
Definition: define.c:35
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
static char * buf
Definition: pg_test_fsync.c:72
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12940
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
Definition: value.h:48
Definition: value.h:29
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), DefElem::arg, buf, cstring_to_text_with_len(), defGetString(), DefElem::defname, ESCAPE_STRING_SYNTAX, initStringInfo(), IsA, lfirst, lnext(), pfree(), quote_identifier(), SQL_STR_DOUBLE, and val.

Referenced by AlterTSDictionary(), and DefineTSDictionary().

◆ tstoken_list_member()

static bool tstoken_list_member ( char *  token_name,
List tokens 
)
static

Definition at line 1204 of file tsearchcmds.c.

1205{
1206 ListCell *c;
1207 bool found = false;
1208
1209 foreach(c, tokens)
1210 {
1212
1213 if (strcmp(token_name, ts->name) == 0)
1214 {
1215 found = true;
1216 break;
1217 }
1218 }
1219
1220 return found;
1221}

References lfirst, and TSTokenTypeItem::name.

Referenced by getTokenTypes().

◆ verify_dictoptions()

static void verify_dictoptions ( Oid  tmplId,
List dictoptions 
)
static

Definition at line 342 of file tsearchcmds.c.

343{
344 HeapTuple tup;
346 Oid initmethod;
347
348 /*
349 * Suppress this test when running in a standalone backend. This is a
350 * hack to allow initdb to create prefab dictionaries that might not
351 * actually be usable in template1's encoding (due to using external files
352 * that can't be translated into template1's encoding). We want to create
353 * them anyway, since they might be usable later in other databases.
354 */
356 return;
357
358 tup = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(tmplId));
359 if (!HeapTupleIsValid(tup)) /* should not happen */
360 elog(ERROR, "cache lookup failed for text search template %u",
361 tmplId);
362 tform = (Form_pg_ts_template) GETSTRUCT(tup);
363
364 initmethod = tform->tmplinit;
365
366 if (!OidIsValid(initmethod))
367 {
368 /* If there is no init method, disallow any options */
369 if (dictoptions)
371 (errcode(ERRCODE_SYNTAX_ERROR),
372 errmsg("text search template \"%s\" does not accept options",
373 NameStr(tform->tmplname))));
374 }
375 else
376 {
377 /*
378 * Copy the options just in case init method thinks it can scribble on
379 * them ...
380 */
381 dictoptions = copyObject(dictoptions);
382
383 /*
384 * Call the init method and see if it complains. We don't worry about
385 * it leaking memory, since our command will soon be over anyway.
386 */
387 (void) OidFunctionCall1(initmethod, PointerGetDatum(dictoptions));
388 }
389
390 ReleaseSysCache(tup);
391}
#define NameStr(name)
Definition: c.h:703
bool IsUnderPostmaster
Definition: globals.c:119
#define copyObject(obj)
Definition: nodes.h:224

References copyObject, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT(), HeapTupleIsValid, IsUnderPostmaster, NameStr, ObjectIdGetDatum(), OidFunctionCall1, OidIsValid, PointerGetDatum(), ReleaseSysCache(), and SearchSysCache1().

Referenced by AlterTSDictionary(), and DefineTSDictionary().