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/alter.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_utils.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.

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 int * getTokenTypes (Oid prsId, List *tokennames)
 
textserialize_deflist (List *deflist)
 
Listdeserialize_deflist (Datum txt)
 

Function Documentation

◆ AlterTSConfiguration()

ObjectAddress AlterTSConfiguration ( AlterTSConfigurationStmt stmt)

Definition at line 1109 of file tsearchcmds.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, AlterTSConfigurationStmt::cfgname, AlterTSConfigurationStmt::dicts, DropConfigurationMapping(), ereport, errcode(), errmsg(), ERROR, GETSTRUCT, GetTSConfigTuple(), GetUserId(), HeapTupleIsValid, InvokeObjectPostAlterHook, makeConfigurationDependencies(), MakeConfigurationMapping(), NameListToString(), OBJECT_TSCONFIGURATION, ObjectAddressSet, pg_ts_config_ownercheck(), ReleaseSysCache(), RowExclusiveLock, table_close(), table_open(), and AlterTSConfigurationStmt::tokentype.

Referenced by ProcessUtilitySlow().

1110 {
1111  HeapTuple tup;
1112  Oid cfgId;
1113  Relation relMap;
1114  ObjectAddress address;
1115 
1116  /* Find the configuration */
1117  tup = GetTSConfigTuple(stmt->cfgname);
1118  if (!HeapTupleIsValid(tup))
1119  ereport(ERROR,
1120  (errcode(ERRCODE_UNDEFINED_OBJECT),
1121  errmsg("text search configuration \"%s\" does not exist",
1122  NameListToString(stmt->cfgname))));
1123 
1124  cfgId = ((Form_pg_ts_config) GETSTRUCT(tup))->oid;
1125 
1126  /* must be owner */
1127  if (!pg_ts_config_ownercheck(cfgId, GetUserId()))
1129  NameListToString(stmt->cfgname));
1130 
1131  relMap = table_open(TSConfigMapRelationId, RowExclusiveLock);
1132 
1133  /* Add or drop mappings */
1134  if (stmt->dicts)
1135  MakeConfigurationMapping(stmt, tup, relMap);
1136  else if (stmt->tokentype)
1137  DropConfigurationMapping(stmt, tup, relMap);
1138 
1139  /* Update dependencies */
1140  makeConfigurationDependencies(tup, true, relMap);
1141 
1142  InvokeObjectPostAlterHook(TSConfigRelationId, cfgId, 0);
1143 
1144  ObjectAddressSet(address, TSConfigRelationId, cfgId);
1145 
1146  table_close(relMap, RowExclusiveLock);
1147 
1148  ReleaseSysCache(tup);
1149 
1150  return address;
1151 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
Oid GetUserId(void)
Definition: miscinit.c:476
bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
Definition: aclchk.c:4997
static ObjectAddress makeConfigurationDependencies(HeapTuple tuple, bool removeOld, Relation mapRel)
Definition: tsearchcmds.c:806
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
static void DropConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1376
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
static HeapTuple GetTSConfigTuple(List *names)
Definition: tsearchcmds.c:781
char * NameListToString(List *names)
Definition: namespace.c:3101
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:821
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
static void MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1212

◆ AlterTSDictionary()

ObjectAddress AlterTSDictionary ( AlterTSDictionaryStmt stmt)

Definition at line 487 of file tsearchcmds.c.

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

Referenced by ProcessUtilitySlow().

488 {
489  HeapTuple tup,
490  newtup;
491  Relation rel;
492  Oid dictId;
493  ListCell *pl;
494  List *dictoptions;
495  Datum opt;
496  bool isnull;
497  Datum repl_val[Natts_pg_ts_dict];
498  bool repl_null[Natts_pg_ts_dict];
499  bool repl_repl[Natts_pg_ts_dict];
500  ObjectAddress address;
501 
502  dictId = get_ts_dict_oid(stmt->dictname, false);
503 
504  rel = table_open(TSDictionaryRelationId, RowExclusiveLock);
505 
507 
508  if (!HeapTupleIsValid(tup))
509  elog(ERROR, "cache lookup failed for text search dictionary %u",
510  dictId);
511 
512  /* must be owner */
513  if (!pg_ts_dict_ownercheck(dictId, GetUserId()))
515  NameListToString(stmt->dictname));
516 
517  /* deserialize the existing set of options */
518  opt = SysCacheGetAttr(TSDICTOID, tup,
519  Anum_pg_ts_dict_dictinitoption,
520  &isnull);
521  if (isnull)
522  dictoptions = NIL;
523  else
524  dictoptions = deserialize_deflist(opt);
525 
526  /*
527  * Modify the options list as per specified changes
528  */
529  foreach(pl, stmt->options)
530  {
531  DefElem *defel = (DefElem *) lfirst(pl);
532  ListCell *cell;
533 
534  /*
535  * Remove any matches ...
536  */
537  foreach(cell, dictoptions)
538  {
539  DefElem *oldel = (DefElem *) lfirst(cell);
540 
541  if (strcmp(oldel->defname, defel->defname) == 0)
542  dictoptions = foreach_delete_current(dictoptions, cell);
543  }
544 
545  /*
546  * and add new value if it's got one
547  */
548  if (defel->arg)
549  dictoptions = lappend(dictoptions, defel);
550  }
551 
552  /*
553  * Validate
554  */
555  verify_dictoptions(((Form_pg_ts_dict) GETSTRUCT(tup))->dicttemplate,
556  dictoptions);
557 
558  /*
559  * Looks good, update
560  */
561  memset(repl_val, 0, sizeof(repl_val));
562  memset(repl_null, false, sizeof(repl_null));
563  memset(repl_repl, false, sizeof(repl_repl));
564 
565  if (dictoptions)
566  repl_val[Anum_pg_ts_dict_dictinitoption - 1] =
567  PointerGetDatum(serialize_deflist(dictoptions));
568  else
569  repl_null[Anum_pg_ts_dict_dictinitoption - 1] = true;
570  repl_repl[Anum_pg_ts_dict_dictinitoption - 1] = true;
571 
572  newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
573  repl_val, repl_null, repl_repl);
574 
575  CatalogTupleUpdate(rel, &newtup->t_self, newtup);
576 
577  InvokeObjectPostAlterHook(TSDictionaryRelationId, dictId, 0);
578 
579  ObjectAddressSet(address, TSDictionaryRelationId, dictId);
580 
581  /*
582  * NOTE: because we only support altering the options, not the template,
583  * there is no need to update dependencies. This might have to change if
584  * the options ever reference inside-the-database objects.
585  */
586 
587  heap_freetuple(newtup);
588  ReleaseSysCache(tup);
589 
591 
592  return address;
593 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
Definition: aclchk.c:4970
#define RelationGetDescr(relation)
Definition: rel.h:482
Oid GetUserId(void)
Definition: miscinit.c:476
#define PointerGetDatum(X)
Definition: postgres.h:556
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1510
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define foreach_delete_current(lst, cell)
Definition: pg_list.h:357
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition: namespace.c:2425
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
Node * arg
Definition: parsenodes.h:734
List * lappend(List *list, void *datum)
Definition: list.c:321
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
char * NameListToString(List *names)
Definition: namespace.c:3101
text * serialize_deflist(List *deflist)
Definition: tsearchcmds.c:1454
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
static void verify_dictoptions(Oid tmplId, List *dictoptions)
Definition: tsearchcmds.c:336
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define elog(elevel,...)
Definition: elog.h:214
char * defname
Definition: parsenodes.h:733
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
Definition: pg_list.h:50

◆ buildDefItem()

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

Definition at line 1723 of file tsearchcmds.c.

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

Referenced by deserialize_deflist().

1724 {
1725  /* If input was quoted, always emit as string */
1726  if (!was_quoted && val[0] != '\0')
1727  {
1728  int v;
1729  char *endptr;
1730 
1731  /* Try to parse as an integer */
1732  errno = 0;
1733  v = strtoint(val, &endptr, 10);
1734  if (errno == 0 && *endptr == '\0')
1735  return makeDefElem(pstrdup(name),
1736  (Node *) makeInteger(v),
1737  -1);
1738  /* Nope, how about as a float? */
1739  errno = 0;
1740  (void) strtod(val, &endptr);
1741  if (errno == 0 && *endptr == '\0')
1742  return makeDefElem(pstrdup(name),
1743  (Node *) makeFloat(pstrdup(val)),
1744  -1);
1745  }
1746  /* Just make it a string */
1747  return makeDefElem(pstrdup(name),
1748  (Node *) makeString(pstrdup(val)),
1749  -1);
1750 }
Value * makeString(char *str)
Definition: value.c:53
char * pstrdup(const char *in)
Definition: mcxt.c:1187
Definition: nodes.h:528
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:546
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:50
Value * makeInteger(int i)
Definition: value.c:23
Value * makeFloat(char *numericStr)
Definition: value.c:38
const char * name
Definition: encode.c:561
long val
Definition: informix.c:664

◆ DefineTSConfiguration()

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

Definition at line 893 of file tsearchcmds.c.

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, BTEqualStrategyNumber, CatalogTupleInsert(), defGetQualifiedName(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, get_namespace_name(), get_ts_config_oid(), get_ts_parser_oid(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), heap_form_tuple(), heap_freetuple(), HeapTupleIsValid, InvalidOid, InvokeObjectPostCreateHook, lfirst, makeConfigurationDependencies(), NameGetDatum, namestrcpy(), OBJECT_SCHEMA, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, pg_namespace_aclcheck(), QualifiedNameGetCreationNamespace(), RelationData::rd_att, ReleaseSysCache(), RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TSConfigMapIndexId, TSCONFIGOID, TSConfigOidIndexId, and values.

Referenced by ProcessUtilitySlow().

894 {
895  Relation cfgRel;
896  Relation mapRel = NULL;
897  HeapTuple tup;
898  Datum values[Natts_pg_ts_config];
899  bool nulls[Natts_pg_ts_config];
900  AclResult aclresult;
901  Oid namespaceoid;
902  char *cfgname;
903  NameData cname;
904  Oid sourceOid = InvalidOid;
905  Oid prsOid = InvalidOid;
906  Oid cfgOid;
907  ListCell *pl;
908  ObjectAddress address;
909 
910  /* Convert list of names to a name and namespace */
911  namespaceoid = QualifiedNameGetCreationNamespace(names, &cfgname);
912 
913  /* Check we have creation rights in target namespace */
914  aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
915  if (aclresult != ACLCHECK_OK)
916  aclcheck_error(aclresult, OBJECT_SCHEMA,
917  get_namespace_name(namespaceoid));
918 
919  /*
920  * loop over the definition list and extract the information we need.
921  */
922  foreach(pl, parameters)
923  {
924  DefElem *defel = (DefElem *) lfirst(pl);
925 
926  if (strcmp(defel->defname, "parser") == 0)
927  prsOid = get_ts_parser_oid(defGetQualifiedName(defel), false);
928  else if (strcmp(defel->defname, "copy") == 0)
929  sourceOid = get_ts_config_oid(defGetQualifiedName(defel), false);
930  else
931  ereport(ERROR,
932  (errcode(ERRCODE_SYNTAX_ERROR),
933  errmsg("text search configuration parameter \"%s\" not recognized",
934  defel->defname)));
935  }
936 
937  if (OidIsValid(sourceOid) && OidIsValid(prsOid))
938  ereport(ERROR,
939  (errcode(ERRCODE_SYNTAX_ERROR),
940  errmsg("cannot specify both PARSER and COPY options")));
941 
942  /* make copied tsconfig available to callers */
943  if (copied && OidIsValid(sourceOid))
944  {
945  ObjectAddressSet(*copied,
946  TSConfigRelationId,
947  sourceOid);
948  }
949 
950  /*
951  * Look up source config if given.
952  */
953  if (OidIsValid(sourceOid))
954  {
955  Form_pg_ts_config cfg;
956 
957  tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(sourceOid));
958  if (!HeapTupleIsValid(tup))
959  elog(ERROR, "cache lookup failed for text search configuration %u",
960  sourceOid);
961 
962  cfg = (Form_pg_ts_config) GETSTRUCT(tup);
963 
964  /* use source's parser */
965  prsOid = cfg->cfgparser;
966 
967  ReleaseSysCache(tup);
968  }
969 
970  /*
971  * Validation
972  */
973  if (!OidIsValid(prsOid))
974  ereport(ERROR,
975  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
976  errmsg("text search parser is required")));
977 
978  cfgRel = table_open(TSConfigRelationId, RowExclusiveLock);
979 
980  /*
981  * Looks good, build tuple and insert
982  */
983  memset(values, 0, sizeof(values));
984  memset(nulls, false, sizeof(nulls));
985 
986  cfgOid = GetNewOidWithIndex(cfgRel, TSConfigOidIndexId,
987  Anum_pg_ts_config_oid);
988  values[Anum_pg_ts_config_oid - 1] = ObjectIdGetDatum(cfgOid);
989  namestrcpy(&cname, cfgname);
990  values[Anum_pg_ts_config_cfgname - 1] = NameGetDatum(&cname);
991  values[Anum_pg_ts_config_cfgnamespace - 1] = ObjectIdGetDatum(namespaceoid);
992  values[Anum_pg_ts_config_cfgowner - 1] = ObjectIdGetDatum(GetUserId());
993  values[Anum_pg_ts_config_cfgparser - 1] = ObjectIdGetDatum(prsOid);
994 
995  tup = heap_form_tuple(cfgRel->rd_att, values, nulls);
996 
997  CatalogTupleInsert(cfgRel, tup);
998 
999  if (OidIsValid(sourceOid))
1000  {
1001  /*
1002  * Copy token-dicts map from source config
1003  */
1004  ScanKeyData skey;
1005  SysScanDesc scan;
1006  HeapTuple maptup;
1007 
1008  mapRel = table_open(TSConfigMapRelationId, RowExclusiveLock);
1009 
1010  ScanKeyInit(&skey,
1011  Anum_pg_ts_config_map_mapcfg,
1012  BTEqualStrategyNumber, F_OIDEQ,
1013  ObjectIdGetDatum(sourceOid));
1014 
1015  scan = systable_beginscan(mapRel, TSConfigMapIndexId, true,
1016  NULL, 1, &skey);
1017 
1018  while (HeapTupleIsValid((maptup = systable_getnext(scan))))
1019  {
1021  HeapTuple newmaptup;
1022  Datum mapvalues[Natts_pg_ts_config_map];
1023  bool mapnulls[Natts_pg_ts_config_map];
1024 
1025  memset(mapvalues, 0, sizeof(mapvalues));
1026  memset(mapnulls, false, sizeof(mapnulls));
1027 
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;
1032 
1033  newmaptup = heap_form_tuple(mapRel->rd_att, mapvalues, mapnulls);
1034 
1035  CatalogTupleInsert(mapRel, newmaptup);
1036 
1037  heap_freetuple(newmaptup);
1038  }
1039 
1040  systable_endscan(scan);
1041  }
1042 
1043  address = makeConfigurationDependencies(tup, false, mapRel);
1044 
1045  /* Post creation hook for new text search configuration */
1046  InvokeObjectPostCreateHook(TSConfigRelationId, cfgOid, 0);
1047 
1048  heap_freetuple(tup);
1049 
1050  if (mapRel)
1051  table_close(mapRel, RowExclusiveLock);
1052  table_close(cfgRel, RowExclusiveLock);
1053 
1054  return address;
1055 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:317
#define NameGetDatum(X)
Definition: postgres.h:595
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
Oid GetUserId(void)
Definition: miscinit.c:476
void namestrcpy(Name name, const char *str)
Definition: name.c:233
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
FormData_pg_ts_config_map * Form_pg_ts_config_map
static ObjectAddress makeConfigurationDependencies(HeapTuple tuple, bool removeOld, Relation mapRel)
Definition: tsearchcmds.c:806
int errcode(int sqlerrcode)
Definition: elog.c:610
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:2678
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:652
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4625
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
Definition: c.h:617
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
#define RowExclusiveLock
Definition: lockdefs.h:38
#define TSConfigOidIndexId
Definition: indexing.h:276
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
TupleDesc rd_att
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
Oid get_ts_parser_oid(List *names, bool missing_ok)
Definition: namespace.c:2299
#define lfirst(lc)
Definition: pg_list.h:169
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static Datum values[MAXATTR]
Definition: bootstrap.c:165
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define TSConfigMapIndexId
Definition: indexing.h:279
char * defname
Definition: parsenodes.h:733
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ DefineTSDictionary()

ObjectAddress DefineTSDictionary ( List names,
List parameters 
)

Definition at line 391 of file tsearchcmds.c.

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_SCHEMA, ObjectIdGetDatum, OidIsValid, pg_namespace_aclcheck(), PointerGetDatum, QualifiedNameGetCreationNamespace(), RelationData::rd_att, RowExclusiveLock, serialize_deflist(), table_close(), table_open(), TSDictionaryOidIndexId, values, and verify_dictoptions().

Referenced by ProcessUtilitySlow().

392 {
393  ListCell *pl;
394  Relation dictRel;
395  HeapTuple tup;
396  Datum values[Natts_pg_ts_dict];
397  bool nulls[Natts_pg_ts_dict];
398  NameData dname;
399  Oid templId = InvalidOid;
400  List *dictoptions = NIL;
401  Oid dictOid;
402  Oid namespaceoid;
403  AclResult aclresult;
404  char *dictname;
405  ObjectAddress address;
406 
407  /* Convert list of names to a name and namespace */
408  namespaceoid = QualifiedNameGetCreationNamespace(names, &dictname);
409 
410  /* Check we have creation rights in target namespace */
411  aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
412  if (aclresult != ACLCHECK_OK)
413  aclcheck_error(aclresult, OBJECT_SCHEMA,
414  get_namespace_name(namespaceoid));
415 
416  /*
417  * loop over the definition list and extract the information we need.
418  */
419  foreach(pl, parameters)
420  {
421  DefElem *defel = (DefElem *) lfirst(pl);
422 
423  if (strcmp(defel->defname, "template") == 0)
424  {
425  templId = get_ts_template_oid(defGetQualifiedName(defel), false);
426  }
427  else
428  {
429  /* Assume it's an option for the dictionary itself */
430  dictoptions = lappend(dictoptions, defel);
431  }
432  }
433 
434  /*
435  * Validation
436  */
437  if (!OidIsValid(templId))
438  ereport(ERROR,
439  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
440  errmsg("text search template is required")));
441 
442  verify_dictoptions(templId, dictoptions);
443 
444 
445  dictRel = table_open(TSDictionaryRelationId, RowExclusiveLock);
446 
447  /*
448  * Looks good, insert
449  */
450  memset(values, 0, sizeof(values));
451  memset(nulls, false, sizeof(nulls));
452 
453  dictOid = GetNewOidWithIndex(dictRel, TSDictionaryOidIndexId,
454  Anum_pg_ts_dict_oid);
455  values[Anum_pg_ts_dict_oid - 1] = ObjectIdGetDatum(dictOid);
456  namestrcpy(&dname, dictname);
457  values[Anum_pg_ts_dict_dictname - 1] = NameGetDatum(&dname);
458  values[Anum_pg_ts_dict_dictnamespace - 1] = ObjectIdGetDatum(namespaceoid);
459  values[Anum_pg_ts_dict_dictowner - 1] = ObjectIdGetDatum(GetUserId());
460  values[Anum_pg_ts_dict_dicttemplate - 1] = ObjectIdGetDatum(templId);
461  if (dictoptions)
462  values[Anum_pg_ts_dict_dictinitoption - 1] =
463  PointerGetDatum(serialize_deflist(dictoptions));
464  else
465  nulls[Anum_pg_ts_dict_dictinitoption - 1] = true;
466 
467  tup = heap_form_tuple(dictRel->rd_att, values, nulls);
468 
469  CatalogTupleInsert(dictRel, tup);
470 
471  address = makeDictionaryDependencies(tup);
472 
473  /* Post creation hook for new text search dictionary */
474  InvokeObjectPostCreateHook(TSDictionaryRelationId, dictOid, 0);
475 
476  heap_freetuple(tup);
477 
478  table_close(dictRel, RowExclusiveLock);
479 
480  return address;
481 }
#define NIL
Definition: pg_list.h:65
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:317
#define NameGetDatum(X)
Definition: postgres.h:595
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
Oid GetUserId(void)
Definition: miscinit.c:476
void namestrcpy(Name name, const char *str)
Definition: name.c:233
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:610
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:652
static ObjectAddress makeDictionaryDependencies(HeapTuple tuple)
Definition: tsearchcmds.c:301
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4625
#define TSDictionaryOidIndexId
Definition: indexing.h:284
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
Definition: c.h:617
Oid get_ts_template_oid(List *names, bool missing_ok)
Definition: namespace.c:2552
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
#define RowExclusiveLock
Definition: lockdefs.h:38
List * lappend(List *list, void *datum)
Definition: list.c:321
AclResult
Definition: acl.h:177
text * serialize_deflist(List *deflist)
Definition: tsearchcmds.c:1454
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
#define lfirst(lc)
Definition: pg_list.h:169
static void verify_dictoptions(Oid tmplId, List *dictoptions)
Definition: tsearchcmds.c:336
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
static Datum values[MAXATTR]
Definition: bootstrap.c:165
int errmsg(const char *fmt,...)
Definition: elog.c:821
char * defname
Definition: parsenodes.h:733
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ DefineTSParser()

ObjectAddress DefineTSParser ( List names,
List parameters 
)

Definition at line 178 of file tsearchcmds.c.

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(), TSParserOidIndexId, and values.

Referenced by ProcessUtilitySlow().

179 {
180  char *prsname;
181  ListCell *pl;
182  Relation prsRel;
183  HeapTuple tup;
184  Datum values[Natts_pg_ts_parser];
185  bool nulls[Natts_pg_ts_parser];
186  NameData pname;
187  Oid prsOid;
188  Oid namespaceoid;
189  ObjectAddress address;
190 
191  if (!superuser())
192  ereport(ERROR,
193  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
194  errmsg("must be superuser to create text search parsers")));
195 
196  prsRel = table_open(TSParserRelationId, RowExclusiveLock);
197 
198  /* Convert list of names to a name and namespace */
199  namespaceoid = QualifiedNameGetCreationNamespace(names, &prsname);
200 
201  /* initialize tuple fields with name/namespace */
202  memset(values, 0, sizeof(values));
203  memset(nulls, false, sizeof(nulls));
204 
205  prsOid = GetNewOidWithIndex(prsRel, TSParserOidIndexId,
206  Anum_pg_ts_parser_oid);
207  values[Anum_pg_ts_parser_oid - 1] = ObjectIdGetDatum(prsOid);
208  namestrcpy(&pname, prsname);
209  values[Anum_pg_ts_parser_prsname - 1] = NameGetDatum(&pname);
210  values[Anum_pg_ts_parser_prsnamespace - 1] = ObjectIdGetDatum(namespaceoid);
211 
212  /*
213  * loop over the definition list and extract the information we need.
214  */
215  foreach(pl, parameters)
216  {
217  DefElem *defel = (DefElem *) lfirst(pl);
218 
219  if (strcmp(defel->defname, "start") == 0)
220  {
221  values[Anum_pg_ts_parser_prsstart - 1] =
222  get_ts_parser_func(defel, Anum_pg_ts_parser_prsstart);
223  }
224  else if (strcmp(defel->defname, "gettoken") == 0)
225  {
226  values[Anum_pg_ts_parser_prstoken - 1] =
227  get_ts_parser_func(defel, Anum_pg_ts_parser_prstoken);
228  }
229  else if (strcmp(defel->defname, "end") == 0)
230  {
231  values[Anum_pg_ts_parser_prsend - 1] =
232  get_ts_parser_func(defel, Anum_pg_ts_parser_prsend);
233  }
234  else if (strcmp(defel->defname, "headline") == 0)
235  {
236  values[Anum_pg_ts_parser_prsheadline - 1] =
237  get_ts_parser_func(defel, Anum_pg_ts_parser_prsheadline);
238  }
239  else if (strcmp(defel->defname, "lextypes") == 0)
240  {
241  values[Anum_pg_ts_parser_prslextype - 1] =
242  get_ts_parser_func(defel, Anum_pg_ts_parser_prslextype);
243  }
244  else
245  ereport(ERROR,
246  (errcode(ERRCODE_SYNTAX_ERROR),
247  errmsg("text search parser parameter \"%s\" not recognized",
248  defel->defname)));
249  }
250 
251  /*
252  * Validation
253  */
254  if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prsstart - 1])))
255  ereport(ERROR,
256  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
257  errmsg("text search parser start method is required")));
258 
259  if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prstoken - 1])))
260  ereport(ERROR,
261  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
262  errmsg("text search parser gettoken method is required")));
263 
264  if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prsend - 1])))
265  ereport(ERROR,
266  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
267  errmsg("text search parser end method is required")));
268 
269  if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prslextype - 1])))
270  ereport(ERROR,
271  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
272  errmsg("text search parser lextypes method is required")));
273 
274  /*
275  * Looks good, insert
276  */
277  tup = heap_form_tuple(prsRel->rd_att, values, nulls);
278 
279  CatalogTupleInsert(prsRel, tup);
280 
281  address = makeParserDependencies(tup);
282 
283  /* Post creation hook for new text search parser */
284  InvokeObjectPostCreateHook(TSParserRelationId, prsOid, 0);
285 
286  heap_freetuple(tup);
287 
288  table_close(prsRel, RowExclusiveLock);
289 
290  return address;
291 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:317
#define NameGetDatum(X)
Definition: postgres.h:595
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
void namestrcpy(Name name, const char *str)
Definition: name.c:233
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
#define DatumGetObjectId(X)
Definition: postgres.h:500
int errcode(int sqlerrcode)
Definition: elog.c:610
bool superuser(void)
Definition: superuser.c:46
static ObjectAddress makeParserDependencies(HeapTuple tuple)
Definition: tsearchcmds.c:131
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:652
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Definition: c.h:617
#define RowExclusiveLock
Definition: lockdefs.h:38
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
#define ereport(elevel,...)
Definition: elog.h:144
#define lfirst(lc)
Definition: pg_list.h:169
static Datum get_ts_parser_func(DefElem *defel, int attnum)
Definition: tsearchcmds.c:68
#define TSParserOidIndexId
Definition: indexing.h:289
static Datum values[MAXATTR]
Definition: bootstrap.c:165
int errmsg(const char *fmt,...)
Definition: elog.c:821
char * defname
Definition: parsenodes.h:733
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ DefineTSTemplate()

ObjectAddress DefineTSTemplate ( List names,
List parameters 
)

Definition at line 684 of file tsearchcmds.c.

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(), TSTemplateOidIndexId, and values.

Referenced by ProcessUtilitySlow().

685 {
686  ListCell *pl;
687  Relation tmplRel;
688  HeapTuple tup;
689  Datum values[Natts_pg_ts_template];
690  bool nulls[Natts_pg_ts_template];
691  NameData dname;
692  int i;
693  Oid tmplOid;
694  Oid namespaceoid;
695  char *tmplname;
696  ObjectAddress address;
697 
698  if (!superuser())
699  ereport(ERROR,
700  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
701  errmsg("must be superuser to create text search templates")));
702 
703  /* Convert list of names to a name and namespace */
704  namespaceoid = QualifiedNameGetCreationNamespace(names, &tmplname);
705 
706  tmplRel = table_open(TSTemplateRelationId, RowExclusiveLock);
707 
708  for (i = 0; i < Natts_pg_ts_template; i++)
709  {
710  nulls[i] = false;
711  values[i] = ObjectIdGetDatum(InvalidOid);
712  }
713 
714  tmplOid = GetNewOidWithIndex(tmplRel, TSTemplateOidIndexId,
715  Anum_pg_ts_dict_oid);
716  values[Anum_pg_ts_template_oid - 1] = ObjectIdGetDatum(tmplOid);
717  namestrcpy(&dname, tmplname);
718  values[Anum_pg_ts_template_tmplname - 1] = NameGetDatum(&dname);
719  values[Anum_pg_ts_template_tmplnamespace - 1] = ObjectIdGetDatum(namespaceoid);
720 
721  /*
722  * loop over the definition list and extract the information we need.
723  */
724  foreach(pl, parameters)
725  {
726  DefElem *defel = (DefElem *) lfirst(pl);
727 
728  if (strcmp(defel->defname, "init") == 0)
729  {
730  values[Anum_pg_ts_template_tmplinit - 1] =
731  get_ts_template_func(defel, Anum_pg_ts_template_tmplinit);
732  nulls[Anum_pg_ts_template_tmplinit - 1] = false;
733  }
734  else if (strcmp(defel->defname, "lexize") == 0)
735  {
736  values[Anum_pg_ts_template_tmpllexize - 1] =
737  get_ts_template_func(defel, Anum_pg_ts_template_tmpllexize);
738  nulls[Anum_pg_ts_template_tmpllexize - 1] = false;
739  }
740  else
741  ereport(ERROR,
742  (errcode(ERRCODE_SYNTAX_ERROR),
743  errmsg("text search template parameter \"%s\" not recognized",
744  defel->defname)));
745  }
746 
747  /*
748  * Validation
749  */
750  if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_template_tmpllexize - 1])))
751  ereport(ERROR,
752  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
753  errmsg("text search template lexize method is required")));
754 
755  /*
756  * Looks good, insert
757  */
758  tup = heap_form_tuple(tmplRel->rd_att, values, nulls);
759 
760  CatalogTupleInsert(tmplRel, tup);
761 
762  address = makeTSTemplateDependencies(tup);
763 
764  /* Post creation hook for new text search template */
765  InvokeObjectPostCreateHook(TSTemplateRelationId, tmplOid, 0);
766 
767  heap_freetuple(tup);
768 
769  table_close(tmplRel, RowExclusiveLock);
770 
771  return address;
772 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:317
#define NameGetDatum(X)
Definition: postgres.h:595
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
void namestrcpy(Name name, const char *str)
Definition: name.c:233
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
#define DatumGetObjectId(X)
Definition: postgres.h:500
static Datum get_ts_template_func(DefElem *defel, int attnum)
Definition: tsearchcmds.c:603
int errcode(int sqlerrcode)
Definition: elog.c:610
bool superuser(void)
Definition: superuser.c:46
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:652
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Definition: c.h:617
#define RowExclusiveLock
Definition: lockdefs.h:38
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
static ObjectAddress makeTSTemplateDependencies(HeapTuple tuple)
Definition: tsearchcmds.c:646
#define lfirst(lc)
Definition: pg_list.h:169
static Datum values[MAXATTR]
Definition: bootstrap.c:165
int errmsg(const char *fmt,...)
Definition: elog.c:821
int i
char * defname
Definition: parsenodes.h:733
#define TSTemplateOidIndexId
Definition: indexing.h:294
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ deserialize_deflist()

List* deserialize_deflist ( Datum  txt)

Definition at line 1510 of file tsearchcmds.c.

References buildDefItem(), DatumGetTextPP, elog, ereport, errcode(), errmsg(), ERROR, lappend(), 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().

1511 {
1512  text *in = DatumGetTextPP(txt); /* in case it's toasted */
1513  List *result = NIL;
1514  int len = VARSIZE_ANY_EXHDR(in);
1515  char *ptr,
1516  *endptr,
1517  *workspace,
1518  *wsptr = NULL,
1519  *startvalue = NULL;
1520  typedef enum
1521  {
1522  CS_WAITKEY,
1523  CS_INKEY,
1524  CS_INQKEY,
1525  CS_WAITEQ,
1526  CS_WAITVALUE,
1527  CS_INSQVALUE,
1528  CS_INDQVALUE,
1529  CS_INWVALUE
1530  } ds_state;
1531  ds_state state = CS_WAITKEY;
1532 
1533  workspace = (char *) palloc(len + 1); /* certainly enough room */
1534  ptr = VARDATA_ANY(in);
1535  endptr = ptr + len;
1536  for (; ptr < endptr; ptr++)
1537  {
1538  switch (state)
1539  {
1540  case CS_WAITKEY:
1541  if (isspace((unsigned char) *ptr) || *ptr == ',')
1542  continue;
1543  if (*ptr == '"')
1544  {
1545  wsptr = workspace;
1546  state = CS_INQKEY;
1547  }
1548  else
1549  {
1550  wsptr = workspace;
1551  *wsptr++ = *ptr;
1552  state = CS_INKEY;
1553  }
1554  break;
1555  case CS_INKEY:
1556  if (isspace((unsigned char) *ptr))
1557  {
1558  *wsptr++ = '\0';
1559  state = CS_WAITEQ;
1560  }
1561  else if (*ptr == '=')
1562  {
1563  *wsptr++ = '\0';
1564  state = CS_WAITVALUE;
1565  }
1566  else
1567  {
1568  *wsptr++ = *ptr;
1569  }
1570  break;
1571  case CS_INQKEY:
1572  if (*ptr == '"')
1573  {
1574  if (ptr + 1 < endptr && ptr[1] == '"')
1575  {
1576  /* copy only one of the two quotes */
1577  *wsptr++ = *ptr++;
1578  }
1579  else
1580  {
1581  *wsptr++ = '\0';
1582  state = CS_WAITEQ;
1583  }
1584  }
1585  else
1586  {
1587  *wsptr++ = *ptr;
1588  }
1589  break;
1590  case CS_WAITEQ:
1591  if (*ptr == '=')
1592  state = CS_WAITVALUE;
1593  else if (!isspace((unsigned char) *ptr))
1594  ereport(ERROR,
1595  (errcode(ERRCODE_SYNTAX_ERROR),
1596  errmsg("invalid parameter list format: \"%s\"",
1597  text_to_cstring(in))));
1598  break;
1599  case CS_WAITVALUE:
1600  if (*ptr == '\'')
1601  {
1602  startvalue = wsptr;
1603  state = CS_INSQVALUE;
1604  }
1605  else if (*ptr == 'E' && ptr + 1 < endptr && ptr[1] == '\'')
1606  {
1607  ptr++;
1608  startvalue = wsptr;
1609  state = CS_INSQVALUE;
1610  }
1611  else if (*ptr == '"')
1612  {
1613  startvalue = wsptr;
1614  state = CS_INDQVALUE;
1615  }
1616  else if (!isspace((unsigned char) *ptr))
1617  {
1618  startvalue = wsptr;
1619  *wsptr++ = *ptr;
1620  state = CS_INWVALUE;
1621  }
1622  break;
1623  case CS_INSQVALUE:
1624  if (*ptr == '\'')
1625  {
1626  if (ptr + 1 < endptr && ptr[1] == '\'')
1627  {
1628  /* copy only one of the two quotes */
1629  *wsptr++ = *ptr++;
1630  }
1631  else
1632  {
1633  *wsptr++ = '\0';
1634  result = lappend(result,
1635  buildDefItem(workspace,
1636  startvalue,
1637  true));
1638  state = CS_WAITKEY;
1639  }
1640  }
1641  else if (*ptr == '\\')
1642  {
1643  if (ptr + 1 < endptr && ptr[1] == '\\')
1644  {
1645  /* copy only one of the two backslashes */
1646  *wsptr++ = *ptr++;
1647  }
1648  else
1649  *wsptr++ = *ptr;
1650  }
1651  else
1652  {
1653  *wsptr++ = *ptr;
1654  }
1655  break;
1656  case CS_INDQVALUE:
1657  if (*ptr == '"')
1658  {
1659  if (ptr + 1 < endptr && ptr[1] == '"')
1660  {
1661  /* copy only one of the two quotes */
1662  *wsptr++ = *ptr++;
1663  }
1664  else
1665  {
1666  *wsptr++ = '\0';
1667  result = lappend(result,
1668  buildDefItem(workspace,
1669  startvalue,
1670  true));
1671  state = CS_WAITKEY;
1672  }
1673  }
1674  else
1675  {
1676  *wsptr++ = *ptr;
1677  }
1678  break;
1679  case CS_INWVALUE:
1680  if (*ptr == ',' || isspace((unsigned char) *ptr))
1681  {
1682  *wsptr++ = '\0';
1683  result = lappend(result,
1684  buildDefItem(workspace,
1685  startvalue,
1686  false));
1687  state = CS_WAITKEY;
1688  }
1689  else
1690  {
1691  *wsptr++ = *ptr;
1692  }
1693  break;
1694  default:
1695  elog(ERROR, "unrecognized deserialize_deflist state: %d",
1696  state);
1697  }
1698  }
1699 
1700  if (state == CS_INWVALUE)
1701  {
1702  *wsptr++ = '\0';
1703  result = lappend(result,
1704  buildDefItem(workspace,
1705  startvalue,
1706  false));
1707  }
1708  else if (state != CS_WAITKEY)
1709  ereport(ERROR,
1710  (errcode(ERRCODE_SYNTAX_ERROR),
1711  errmsg("invalid parameter list format: \"%s\"",
1712  text_to_cstring(in))));
1713 
1714  pfree(workspace);
1715 
1716  return result;
1717 }
#define NIL
Definition: pg_list.h:65
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
#define DatumGetTextPP(X)
Definition: fmgr.h:291
int errcode(int sqlerrcode)
Definition: elog.c:610
static DefElem * buildDefItem(const char *name, const char *val, bool was_quoted)
Definition: tsearchcmds.c:1723
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:43
List * lappend(List *list, void *datum)
Definition: list.c:321
#define ereport(elevel,...)
Definition: elog.h:144
Definition: regguts.h:298
char * text_to_cstring(const text *t)
Definition: varlena.c:221
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define elog(elevel,...)
Definition: elog.h:214
Definition: c.h:563
Definition: pg_list.h:50

◆ DropConfigurationMapping()

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

Definition at line 1376 of file tsearchcmds.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), ereport, errcode(), errmsg(), ERROR, EventTriggerCollectAlterTSConfig(), GETSTRUCT, getTokenTypes(), HeapTupleIsValid, i, Int32GetDatum, lfirst, AlterTSConfigurationStmt::missing_ok, NOTICE, ObjectIdGetDatum, ScanKeyInit(), strVal, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, AlterTSConfigurationStmt::tokentype, TSConfigMapIndexId, and val.

Referenced by AlterTSConfiguration().

1378 {
1379  Form_pg_ts_config tsform;
1380  Oid cfgId;
1381  ScanKeyData skey[2];
1382  SysScanDesc scan;
1383  HeapTuple maptup;
1384  int i;
1385  Oid prsId;
1386  int *tokens;
1387  ListCell *c;
1388 
1389  tsform = (Form_pg_ts_config) GETSTRUCT(tup);
1390  cfgId = tsform->oid;
1391  prsId = tsform->cfgparser;
1392 
1393  tokens = getTokenTypes(prsId, stmt->tokentype);
1394 
1395  i = 0;
1396  foreach(c, stmt->tokentype)
1397  {
1398  Value *val = (Value *) lfirst(c);
1399  bool found = false;
1400 
1401  ScanKeyInit(&skey[0],
1402  Anum_pg_ts_config_map_mapcfg,
1403  BTEqualStrategyNumber, F_OIDEQ,
1404  ObjectIdGetDatum(cfgId));
1405  ScanKeyInit(&skey[1],
1406  Anum_pg_ts_config_map_maptokentype,
1407  BTEqualStrategyNumber, F_INT4EQ,
1408  Int32GetDatum(tokens[i]));
1409 
1410  scan = systable_beginscan(relMap, TSConfigMapIndexId, true,
1411  NULL, 2, skey);
1412 
1413  while (HeapTupleIsValid((maptup = systable_getnext(scan))))
1414  {
1415  CatalogTupleDelete(relMap, &maptup->t_self);
1416  found = true;
1417  }
1418 
1419  systable_endscan(scan);
1420 
1421  if (!found)
1422  {
1423  if (!stmt->missing_ok)
1424  {
1425  ereport(ERROR,
1426  (errcode(ERRCODE_UNDEFINED_OBJECT),
1427  errmsg("mapping for token type \"%s\" does not exist",
1428  strVal(val))));
1429  }
1430  else
1431  {
1432  ereport(NOTICE,
1433  (errmsg("mapping for token type \"%s\" does not exist, skipping",
1434  strVal(val))));
1435  }
1436  }
1437 
1438  i++;
1439  }
1440 
1441  EventTriggerCollectAlterTSConfig(stmt, cfgId, NULL, 0);
1442 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:610
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
static int * getTokenTypes(Oid prsId, List *tokennames)
Definition: tsearchcmds.c:1157
char * c
void EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId, Oid *dictIds, int ndicts)
#define ereport(elevel,...)
Definition: elog.h:144
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
Definition: value.h:42
#define Int32GetDatum(X)
Definition: postgres.h:479
int errmsg(const char *fmt,...)
Definition: elog.c:821
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define TSConfigMapIndexId
Definition: indexing.h:279
long val
Definition: informix.c:664
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ get_ts_parser_func()

static Datum get_ts_parser_func ( DefElem defel,
int  attnum 
)
static

Definition at line 68 of file tsearchcmds.c.

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

Referenced by DefineTSParser().

69 {
70  List *funcName = defGetQualifiedName(defel);
71  Oid typeId[3];
72  Oid retTypeId;
73  int nargs;
74  Oid procOid;
75 
76  retTypeId = INTERNALOID; /* correct for most */
77  typeId[0] = INTERNALOID;
78  switch (attnum)
79  {
80  case Anum_pg_ts_parser_prsstart:
81  nargs = 2;
82  typeId[1] = INT4OID;
83  break;
84  case Anum_pg_ts_parser_prstoken:
85  nargs = 3;
86  typeId[1] = INTERNALOID;
87  typeId[2] = INTERNALOID;
88  break;
89  case Anum_pg_ts_parser_prsend:
90  nargs = 1;
91  retTypeId = VOIDOID;
92  break;
93  case Anum_pg_ts_parser_prsheadline:
94  nargs = 3;
95  typeId[1] = INTERNALOID;
96  typeId[2] = TSQUERYOID;
97  break;
98  case Anum_pg_ts_parser_prslextype:
99  nargs = 1;
100 
101  /*
102  * Note: because the lextype method returns type internal, it must
103  * have an internal-type argument for security reasons. The
104  * argument is not actually used, but is just passed as a zero.
105  */
106  break;
107  default:
108  /* should not be here */
109  elog(ERROR, "unrecognized attribute for text search parser: %d",
110  attnum);
111  nargs = 0; /* keep compiler quiet */
112  }
113 
114  procOid = LookupFuncName(funcName, nargs, typeId, false);
115  if (get_func_rettype(procOid) != retTypeId)
116  ereport(ERROR,
117  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
118  errmsg("function %s should return type %s",
119  func_signature_string(funcName, nargs, NIL, typeId),
120  format_type_be(retTypeId))));
121 
122  return ObjectIdGetDatum(procOid);
123 }
#define NIL
Definition: pg_list.h:65
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1567
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2103
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2015
int16 attnum
Definition: pg_attribute.h:79
#define ereport(elevel,...)
Definition: elog.h:144
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define elog(elevel,...)
Definition: elog.h:214
Definition: pg_list.h:50

◆ get_ts_template_func()

static Datum get_ts_template_func ( DefElem defel,
int  attnum 
)
static

Definition at line 603 of file tsearchcmds.c.

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

Referenced by DefineTSTemplate().

604 {
605  List *funcName = defGetQualifiedName(defel);
606  Oid typeId[4];
607  Oid retTypeId;
608  int nargs;
609  Oid procOid;
610 
611  retTypeId = INTERNALOID;
612  typeId[0] = INTERNALOID;
613  typeId[1] = INTERNALOID;
614  typeId[2] = INTERNALOID;
615  typeId[3] = INTERNALOID;
616  switch (attnum)
617  {
618  case Anum_pg_ts_template_tmplinit:
619  nargs = 1;
620  break;
621  case Anum_pg_ts_template_tmpllexize:
622  nargs = 4;
623  break;
624  default:
625  /* should not be here */
626  elog(ERROR, "unrecognized attribute for text search template: %d",
627  attnum);
628  nargs = 0; /* keep compiler quiet */
629  }
630 
631  procOid = LookupFuncName(funcName, nargs, typeId, false);
632  if (get_func_rettype(procOid) != retTypeId)
633  ereport(ERROR,
634  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
635  errmsg("function %s should return type %s",
636  func_signature_string(funcName, nargs, NIL, typeId),
637  format_type_be(retTypeId))));
638 
639  return ObjectIdGetDatum(procOid);
640 }
#define NIL
Definition: pg_list.h:65
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1567
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2103
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2015
int16 attnum
Definition: pg_attribute.h:79
#define ereport(elevel,...)
Definition: elog.h:144
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define elog(elevel,...)
Definition: elog.h:214
Definition: pg_list.h:50

◆ getTokenTypes()

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

Definition at line 1157 of file tsearchcmds.c.

References LexDescr::alias, DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, i, LexDescr::lexid, TSParserCacheEntry::lextypeOid, lfirst, sort-test::list, list_length(), lookup_ts_parser_cache(), OidFunctionCall1, OidIsValid, palloc(), strVal, and val.

Referenced by DropConfigurationMapping(), and MakeConfigurationMapping().

1158 {
1160  LexDescr *list;
1161  int *res,
1162  i,
1163  ntoken;
1164  ListCell *tn;
1165 
1166  ntoken = list_length(tokennames);
1167  if (ntoken == 0)
1168  return NULL;
1169  res = (int *) palloc(sizeof(int) * ntoken);
1170 
1171  if (!OidIsValid(prs->lextypeOid))
1172  elog(ERROR, "method lextype isn't defined for text search parser %u",
1173  prsId);
1174 
1175  /* lextype takes one dummy argument */
1177  (Datum) 0));
1178 
1179  i = 0;
1180  foreach(tn, tokennames)
1181  {
1182  Value *val = (Value *) lfirst(tn);
1183  bool found = false;
1184  int j;
1185 
1186  j = 0;
1187  while (list && list[j].lexid)
1188  {
1189  if (strcmp(strVal(val), list[j].alias) == 0)
1190  {
1191  res[i] = list[j].lexid;
1192  found = true;
1193  break;
1194  }
1195  j++;
1196  }
1197  if (!found)
1198  ereport(ERROR,
1199  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1200  errmsg("token type \"%s\" does not exist",
1201  strVal(val))));
1202  i++;
1203  }
1204 
1205  return res;
1206 }
char * alias
Definition: ts_public.h:28
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:610
TSParserCacheEntry * lookup_ts_parser_cache(Oid prsId)
Definition: ts_cache.c:112
#define OidIsValid(objectId)
Definition: c.h:652
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:662
int lexid
Definition: ts_public.h:27
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:144
#define lfirst(lc)
Definition: pg_list.h:169
Definition: value.h:42
static int list_length(const List *l)
Definition: pg_list.h:149
#define DatumGetPointer(X)
Definition: postgres.h:549
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define elog(elevel,...)
Definition: elog.h:214
int i
long val
Definition: informix.c:664

◆ GetTSConfigTuple()

static HeapTuple GetTSConfigTuple ( List names)
static

Definition at line 781 of file tsearchcmds.c.

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

Referenced by AlterTSConfiguration().

782 {
783  HeapTuple tup;
784  Oid cfgId;
785 
786  cfgId = get_ts_config_oid(names, true);
787  if (!OidIsValid(cfgId))
788  return NULL;
789 
791 
792  if (!HeapTupleIsValid(tup)) /* should not happen */
793  elog(ERROR, "cache lookup failed for text search configuration %u",
794  cfgId);
795 
796  return tup;
797 }
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:2678
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:652
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214

◆ makeConfigurationDependencies()

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

Definition at line 806 of file tsearchcmds.c.

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(), systable_getnext(), and TSConfigMapIndexId.

Referenced by AlterTSConfiguration(), and DefineTSConfiguration().

808 {
810  ObjectAddresses *addrs;
811  ObjectAddress myself,
812  referenced;
813 
814  myself.classId = TSConfigRelationId;
815  myself.objectId = cfg->oid;
816  myself.objectSubId = 0;
817 
818  /* for ALTER case, first flush old dependencies, except extension deps */
819  if (removeOld)
820  {
821  deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
823  }
824 
825  /*
826  * We use an ObjectAddresses list to remove possible duplicate
827  * dependencies from the config map info. The pg_ts_config items
828  * shouldn't be duplicates, but might as well fold them all into one call.
829  */
830  addrs = new_object_addresses();
831 
832  /* dependency on namespace */
833  referenced.classId = NamespaceRelationId;
834  referenced.objectId = cfg->cfgnamespace;
835  referenced.objectSubId = 0;
836  add_exact_object_address(&referenced, addrs);
837 
838  /* dependency on owner */
839  recordDependencyOnOwner(myself.classId, myself.objectId, cfg->cfgowner);
840 
841  /* dependency on extension */
842  recordDependencyOnCurrentExtension(&myself, removeOld);
843 
844  /* dependency on parser */
845  referenced.classId = TSParserRelationId;
846  referenced.objectId = cfg->cfgparser;
847  referenced.objectSubId = 0;
848  add_exact_object_address(&referenced, addrs);
849 
850  /* dependencies on dictionaries listed in config map */
851  if (mapRel)
852  {
853  ScanKeyData skey;
854  SysScanDesc scan;
855  HeapTuple maptup;
856 
857  /* CCI to ensure we can see effects of caller's changes */
859 
860  ScanKeyInit(&skey,
861  Anum_pg_ts_config_map_mapcfg,
862  BTEqualStrategyNumber, F_OIDEQ,
863  ObjectIdGetDatum(myself.objectId));
864 
865  scan = systable_beginscan(mapRel, TSConfigMapIndexId, true,
866  NULL, 1, &skey);
867 
868  while (HeapTupleIsValid((maptup = systable_getnext(scan))))
869  {
871 
872  referenced.classId = TSDictionaryRelationId;
873  referenced.objectId = cfgmap->mapdict;
874  referenced.objectSubId = 0;
875  add_exact_object_address(&referenced, addrs);
876  }
877 
878  systable_endscan(scan);
879  }
880 
881  /* Record 'em (this includes duplicate elimination) */
883 
884  free_object_addresses(addrs);
885 
886  return myself;
887 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
FormData_pg_ts_config_map * Form_pg_ts_config_map
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2676
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:232
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2467
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:164
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2412
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2707
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:945
void CommandCounterIncrement(void)
Definition: xact.c:1021
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:180
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define TSConfigMapIndexId
Definition: indexing.h:279
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ MakeConfigurationMapping()

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

Definition at line 1212 of file tsearchcmds.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleInsert(), CatalogTupleUpdate(), AlterTSConfigurationStmt::dicts, EventTriggerCollectAlterTSConfig(), get_ts_dict_oid(), GETSTRUCT, getTokenTypes(), heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, i, Int32GetDatum, lfirst, list_length(), ObjectIdGetDatum, AlterTSConfigurationStmt::override, palloc(), RelationData::rd_att, RelationGetDescr, AlterTSConfigurationStmt::replace, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, AlterTSConfigurationStmt::tokentype, TSConfigMapIndexId, and values.

Referenced by AlterTSConfiguration().

1214 {
1215  Form_pg_ts_config tsform;
1216  Oid cfgId;
1217  ScanKeyData skey[2];
1218  SysScanDesc scan;
1219  HeapTuple maptup;
1220  int i;
1221  int j;
1222  Oid prsId;
1223  int *tokens,
1224  ntoken;
1225  Oid *dictIds;
1226  int ndict;
1227  ListCell *c;
1228 
1229  tsform = (Form_pg_ts_config) GETSTRUCT(tup);
1230  cfgId = tsform->oid;
1231  prsId = tsform->cfgparser;
1232 
1233  tokens = getTokenTypes(prsId, stmt->tokentype);
1234  ntoken = list_length(stmt->tokentype);
1235 
1236  if (stmt->override)
1237  {
1238  /*
1239  * delete maps for tokens if they exist and command was ALTER
1240  */
1241  for (i = 0; i < ntoken; i++)
1242  {
1243  ScanKeyInit(&skey[0],
1244  Anum_pg_ts_config_map_mapcfg,
1245  BTEqualStrategyNumber, F_OIDEQ,
1246  ObjectIdGetDatum(cfgId));
1247  ScanKeyInit(&skey[1],
1248  Anum_pg_ts_config_map_maptokentype,
1249  BTEqualStrategyNumber, F_INT4EQ,
1250  Int32GetDatum(tokens[i]));
1251 
1252  scan = systable_beginscan(relMap, TSConfigMapIndexId, true,
1253  NULL, 2, skey);
1254 
1255  while (HeapTupleIsValid((maptup = systable_getnext(scan))))
1256  {
1257  CatalogTupleDelete(relMap, &maptup->t_self);
1258  }
1259 
1260  systable_endscan(scan);
1261  }
1262  }
1263 
1264  /*
1265  * Convert list of dictionary names to array of dict OIDs
1266  */
1267  ndict = list_length(stmt->dicts);
1268  dictIds = (Oid *) palloc(sizeof(Oid) * ndict);
1269  i = 0;
1270  foreach(c, stmt->dicts)
1271  {
1272  List *names = (List *) lfirst(c);
1273 
1274  dictIds[i] = get_ts_dict_oid(names, false);
1275  i++;
1276  }
1277 
1278  if (stmt->replace)
1279  {
1280  /*
1281  * Replace a specific dictionary in existing entries
1282  */
1283  Oid dictOld = dictIds[0],
1284  dictNew = dictIds[1];
1285 
1286  ScanKeyInit(&skey[0],
1287  Anum_pg_ts_config_map_mapcfg,
1288  BTEqualStrategyNumber, F_OIDEQ,
1289  ObjectIdGetDatum(cfgId));
1290 
1291  scan = systable_beginscan(relMap, TSConfigMapIndexId, true,
1292  NULL, 1, skey);
1293 
1294  while (HeapTupleIsValid((maptup = systable_getnext(scan))))
1295  {
1297 
1298  /*
1299  * check if it's one of target token types
1300  */
1301  if (tokens)
1302  {
1303  bool tokmatch = false;
1304 
1305  for (j = 0; j < ntoken; j++)
1306  {
1307  if (cfgmap->maptokentype == tokens[j])
1308  {
1309  tokmatch = true;
1310  break;
1311  }
1312  }
1313  if (!tokmatch)
1314  continue;
1315  }
1316 
1317  /*
1318  * replace dictionary if match
1319  */
1320  if (cfgmap->mapdict == dictOld)
1321  {
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];
1325  HeapTuple newtup;
1326 
1327  memset(repl_val, 0, sizeof(repl_val));
1328  memset(repl_null, false, sizeof(repl_null));
1329  memset(repl_repl, false, sizeof(repl_repl));
1330 
1331  repl_val[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictNew);
1332  repl_repl[Anum_pg_ts_config_map_mapdict - 1] = true;
1333 
1334  newtup = heap_modify_tuple(maptup,
1335  RelationGetDescr(relMap),
1336  repl_val, repl_null, repl_repl);
1337  CatalogTupleUpdate(relMap, &newtup->t_self, newtup);
1338  }
1339  }
1340 
1341  systable_endscan(scan);
1342  }
1343  else
1344  {
1345  /*
1346  * Insertion of new entries
1347  */
1348  for (i = 0; i < ntoken; i++)
1349  {
1350  for (j = 0; j < ndict; j++)
1351  {
1352  Datum values[Natts_pg_ts_config_map];
1353  bool nulls[Natts_pg_ts_config_map];
1354 
1355  memset(nulls, false, sizeof(nulls));
1356  values[Anum_pg_ts_config_map_mapcfg - 1] = ObjectIdGetDatum(cfgId);
1357  values[Anum_pg_ts_config_map_maptokentype - 1] = Int32GetDatum(tokens[i]);
1358  values[Anum_pg_ts_config_map_mapseqno - 1] = Int32GetDatum(j + 1);
1359  values[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictIds[j]);
1360 
1361  tup = heap_form_tuple(relMap->rd_att, values, nulls);
1362  CatalogTupleInsert(relMap, tup);
1363 
1364  heap_freetuple(tup);
1365  }
1366  }
1367  }
1368 
1369  EventTriggerCollectAlterTSConfig(stmt, cfgId, dictIds, ndict);
1370 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
#define RelationGetDescr(relation)
Definition: rel.h:482
FormData_pg_ts_config_map * Form_pg_ts_config_map
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition: namespace.c:2425
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
static int * getTokenTypes(Oid prsId, List *tokennames)
Definition: tsearchcmds.c:1157
char * c
void EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId, Oid *dictIds, int ndicts)
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
static int list_length(const List *l)
Definition: pg_list.h:149
static Datum values[MAXATTR]
Definition: bootstrap.c:165
#define Int32GetDatum(X)
Definition: postgres.h:479
void * palloc(Size size)
Definition: mcxt.c:950
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define TSConfigMapIndexId
Definition: indexing.h:279
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
Definition: pg_list.h:50
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ makeDictionaryDependencies()

static ObjectAddress makeDictionaryDependencies ( HeapTuple  tuple)
static

Definition at line 301 of file tsearchcmds.c.

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().

302 {
303  Form_pg_ts_dict dict = (Form_pg_ts_dict) GETSTRUCT(tuple);
304  ObjectAddress myself,
305  referenced;
306  ObjectAddresses *addrs;
307 
308  ObjectAddressSet(myself, TSDictionaryRelationId, dict->oid);
309 
310  /* dependency on owner */
311  recordDependencyOnOwner(myself.classId, myself.objectId, dict->dictowner);
312 
313  /* dependency on extension */
314  recordDependencyOnCurrentExtension(&myself, false);
315 
316  addrs = new_object_addresses();
317 
318  /* dependency on namespace */
319  ObjectAddressSet(referenced, NamespaceRelationId, dict->dictnamespace);
320  add_exact_object_address(&referenced, addrs);
321 
322  /* dependency on template */
323  ObjectAddressSet(referenced, TSTemplateRelationId, dict->dicttemplate);
324  add_exact_object_address(&referenced, addrs);
325 
327  free_object_addresses(addrs);
328 
329  return myself;
330 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2676
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2467
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:164
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2412
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2707
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:180
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40

◆ makeParserDependencies()

static ObjectAddress makeParserDependencies ( HeapTuple  tuple)
static

Definition at line 131 of file tsearchcmds.c.

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().

132 {
134  ObjectAddress myself,
135  referenced;
136  ObjectAddresses *addrs;
137 
138  ObjectAddressSet(myself, TSParserRelationId, prs->oid);
139 
140  /* dependency on extension */
141  recordDependencyOnCurrentExtension(&myself, false);
142 
143  addrs = new_object_addresses();
144 
145  /* dependency on namespace */
146  ObjectAddressSet(referenced, NamespaceRelationId, prs->prsnamespace);
147  add_exact_object_address(&referenced, addrs);
148 
149  /* dependencies on functions */
150  ObjectAddressSet(referenced, ProcedureRelationId, prs->prsstart);
151  add_exact_object_address(&referenced, addrs);
152 
153  referenced.objectId = prs->prstoken;
154  add_exact_object_address(&referenced, addrs);
155 
156  referenced.objectId = prs->prsend;
157  add_exact_object_address(&referenced, addrs);
158 
159  referenced.objectId = prs->prslextype;
160  add_exact_object_address(&referenced, addrs);
161 
162  if (OidIsValid(prs->prsheadline))
163  {
164  referenced.objectId = prs->prsheadline;
165  add_exact_object_address(&referenced, addrs);
166  }
167 
169  free_object_addresses(addrs);
170 
171  return myself;
172 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2676
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2467
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2412
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2707
#define OidIsValid(objectId)
Definition: c.h:652
FormData_pg_ts_parser * Form_pg_ts_parser
Definition: pg_ts_parser.h:55
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:180
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40

◆ makeTSTemplateDependencies()

static ObjectAddress makeTSTemplateDependencies ( HeapTuple  tuple)
static

Definition at line 646 of file tsearchcmds.c.

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().

647 {
649  ObjectAddress myself,
650  referenced;
651  ObjectAddresses *addrs;
652 
653  ObjectAddressSet(myself, TSTemplateRelationId, tmpl->oid);
654 
655  /* dependency on extension */
656  recordDependencyOnCurrentExtension(&myself, false);
657 
658  addrs = new_object_addresses();
659 
660  /* dependency on namespace */
661  ObjectAddressSet(referenced, NamespaceRelationId, tmpl->tmplnamespace);
662  add_exact_object_address(&referenced, addrs);
663 
664  /* dependencies on functions */
665  ObjectAddressSet(referenced, ProcedureRelationId, tmpl->tmpllexize);
666  add_exact_object_address(&referenced, addrs);
667 
668  if (OidIsValid(tmpl->tmplinit))
669  {
670  referenced.objectId = tmpl->tmplinit;
671  add_exact_object_address(&referenced, addrs);
672  }
673 
675  free_object_addresses(addrs);
676 
677  return myself;
678 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2676
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2467
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2412
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2707
#define OidIsValid(objectId)
Definition: c.h:652
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:180
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
FormData_pg_ts_template * Form_pg_ts_template

◆ RemoveTSConfigurationById()

void RemoveTSConfigurationById ( Oid  cfgId)

Definition at line 1061 of file tsearchcmds.c.

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

Referenced by doDeletion().

1062 {
1063  Relation relCfg,
1064  relMap;
1065  HeapTuple tup;
1066  ScanKeyData skey;
1067  SysScanDesc scan;
1068 
1069  /* Remove the pg_ts_config entry */
1070  relCfg = table_open(TSConfigRelationId, RowExclusiveLock);
1071 
1073 
1074  if (!HeapTupleIsValid(tup))
1075  elog(ERROR, "cache lookup failed for text search dictionary %u",
1076  cfgId);
1077 
1078  CatalogTupleDelete(relCfg, &tup->t_self);
1079 
1080  ReleaseSysCache(tup);
1081 
1082  table_close(relCfg, RowExclusiveLock);
1083 
1084  /* Remove any pg_ts_config_map entries */
1085  relMap = table_open(TSConfigMapRelationId, RowExclusiveLock);
1086 
1087  ScanKeyInit(&skey,
1088  Anum_pg_ts_config_map_mapcfg,
1089  BTEqualStrategyNumber, F_OIDEQ,
1090  ObjectIdGetDatum(cfgId));
1091 
1092  scan = systable_beginscan(relMap, TSConfigMapIndexId, true,
1093  NULL, 1, &skey);
1094 
1095  while (HeapTupleIsValid((tup = systable_getnext(scan))))
1096  {
1097  CatalogTupleDelete(relMap, &tup->t_self);
1098  }
1099 
1100  systable_endscan(scan);
1101 
1102  table_close(relMap, RowExclusiveLock);
1103 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define TSConfigMapIndexId
Definition: indexing.h:279
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ serialize_deflist()

text* serialize_deflist ( List deflist)

Definition at line 1454 of file tsearchcmds.c.

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

Referenced by AlterTSDictionary(), and DefineTSDictionary().

1455 {
1456  text *result;
1458  ListCell *l;
1459 
1460  initStringInfo(&buf);
1461 
1462  foreach(l, deflist)
1463  {
1464  DefElem *defel = (DefElem *) lfirst(l);
1465  char *val = defGetString(defel);
1466 
1467  appendStringInfo(&buf, "%s = ",
1468  quote_identifier(defel->defname));
1469 
1470  /*
1471  * If the value is a T_Integer or T_Float, emit it without quotes,
1472  * otherwise with quotes. This is essential to allow correct
1473  * reconstruction of the node type as well as the value.
1474  */
1475  if (IsA(defel->arg, Integer) || IsA(defel->arg, Float))
1476  appendStringInfoString(&buf, val);
1477  else
1478  {
1479  /* If backslashes appear, force E syntax to quote them safely */
1480  if (strchr(val, '\\'))
1482  appendStringInfoChar(&buf, '\'');
1483  while (*val)
1484  {
1485  char ch = *val++;
1486 
1487  if (SQL_STR_DOUBLE(ch, true))
1488  appendStringInfoChar(&buf, ch);
1489  appendStringInfoChar(&buf, ch);
1490  }
1491  appendStringInfoChar(&buf, '\'');
1492  }
1493  if (lnext(deflist, l) != NULL)
1494  appendStringInfoString(&buf, ", ");
1495  }
1496 
1497  result = cstring_to_text_with_len(buf.data, buf.len);
1498  pfree(buf.data);
1499  return result;
1500 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10709
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:310
#define ESCAPE_STRING_SYNTAX
Definition: c.h:1109
void pfree(void *pointer)
Definition: mcxt.c:1057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
char * defGetString(DefElem *def)
Definition: define.c:49
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:200
Node * arg
Definition: parsenodes.h:734
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define lfirst(lc)
Definition: pg_list.h:169
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1106
Definition: c.h:563
char * defname
Definition: parsenodes.h:733
long val
Definition: informix.c:664

◆ verify_dictoptions()

static void verify_dictoptions ( Oid  tmplId,
List dictoptions 
)
static

Definition at line 336 of file tsearchcmds.c.

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

Referenced by AlterTSDictionary(), and DefineTSDictionary().

337 {
338  HeapTuple tup;
339  Form_pg_ts_template tform;
340  Oid initmethod;
341 
342  /*
343  * Suppress this test when running in a standalone backend. This is a
344  * hack to allow initdb to create prefab dictionaries that might not
345  * actually be usable in template1's encoding (due to using external files
346  * that can't be translated into template1's encoding). We want to create
347  * them anyway, since they might be usable later in other databases.
348  */
349  if (!IsUnderPostmaster)
350  return;
351 
353  if (!HeapTupleIsValid(tup)) /* should not happen */
354  elog(ERROR, "cache lookup failed for text search template %u",
355  tmplId);
356  tform = (Form_pg_ts_template) GETSTRUCT(tup);
357 
358  initmethod = tform->tmplinit;
359 
360  if (!OidIsValid(initmethod))
361  {
362  /* If there is no init method, disallow any options */
363  if (dictoptions)
364  ereport(ERROR,
365  (errcode(ERRCODE_SYNTAX_ERROR),
366  errmsg("text search template \"%s\" does not accept options",
367  NameStr(tform->tmplname))));
368  }
369  else
370  {
371  /*
372  * Copy the options just in case init method thinks it can scribble on
373  * them ...
374  */
375  dictoptions = copyObject(dictoptions);
376 
377  /*
378  * Call the init method and see if it complains. We don't worry about
379  * it leaking memory, since our command will soon be over anyway.
380  */
381  (void) OidFunctionCall1(initmethod, PointerGetDatum(dictoptions));
382  }
383 
384  ReleaseSysCache(tup);
385 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:652
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:662
bool IsUnderPostmaster
Definition: globals.c:109
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int errmsg(const char *fmt,...)
Definition: elog.c:821
FormData_pg_ts_template * Form_pg_ts_template
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:623
#define copyObject(obj)
Definition: nodes.h:644