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.

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 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:184
bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
Definition: aclchk.c:5481
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3512
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid GetUserId(void)
Definition: miscinit.c:492
char * NameListToString(List *names)
Definition: namespace.c:3148
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:195
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
@ OBJECT_TSCONFIGURATION
Definition: parsenodes.h:2179
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
unsigned int Oid
Definition: postgres_ext.h:31
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
static ObjectAddress makeConfigurationDependencies(HeapTuple tuple, bool removeOld, Relation mapRel)
Definition: tsearchcmds.c:806
static HeapTuple GetTSConfigTuple(List *names)
Definition: tsearchcmds.c:781
static void DropConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1376
static void MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, HeapTuple tup, Relation relMap)
Definition: tsearchcmds.c:1212

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

◆ AlterTSDictionary()

ObjectAddress AlterTSDictionary ( AlterTSDictionaryStmt stmt)

Definition at line 487 of file tsearchcmds.c.

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 }
bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
Definition: aclchk.c:5454
#define elog(elevel,...)
Definition: elog.h:218
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
List * lappend(List *list, void *datum)
Definition: list.c:336
Oid get_ts_dict_oid(List *names, bool missing_ok)
Definition: namespace.c:2472
@ OBJECT_TSDICTIONARY
Definition: parsenodes.h:2180
#define lfirst(lc)
Definition: pg_list.h:169
#define NIL
Definition: pg_list.h:65
#define foreach_delete_current(lst, cell)
Definition: pg_list.h:369
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52
uintptr_t Datum
Definition: postgres.h:411
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define PointerGetDatum(X)
Definition: postgres.h:600
#define RelationGetDescr(relation)
Definition: rel.h:515
char * defname
Definition: parsenodes.h:765
Node * arg
Definition: parsenodes.h:766
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:51
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1434
@ TSDICTOID
Definition: syscache.h:108
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1510
static void verify_dictoptions(Oid tmplId, List *dictoptions)
Definition: tsearchcmds.c:336
text * serialize_deflist(List *deflist)
Definition: tsearchcmds.c:1454

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

◆ buildDefItem()

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

Definition at line 1723 of file tsearchcmds.c.

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  if (strcmp(val, "true") == 0)
1747  return makeDefElem(pstrdup(name),
1748  (Node *) makeBoolean(true),
1749  -1);
1750  if (strcmp(val, "false") == 0)
1751  return makeDefElem(pstrdup(name),
1752  (Node *) makeBoolean(false),
1753  -1);
1754  }
1755  /* Just make it a string */
1756  return makeDefElem(pstrdup(name),
1757  (Node *) makeString(pstrdup(val)),
1758  -1);
1759 }
const char * name
Definition: encode.c:561
long val
Definition: informix.c:664
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:547
char * pstrdup(const char *in)
Definition: mcxt.c:1305
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:50
Definition: nodes.h:574
Boolean * makeBoolean(bool val)
Definition: value.c:49
Float * makeFloat(char *numericStr)
Definition: value.c:37
String * makeString(char *str)
Definition: value.c:63
Integer * makeInteger(int i)
Definition: value.c:23

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 893 of file tsearchcmds.c.

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 }
AclResult
Definition: acl.h:181
@ ACLCHECK_OK
Definition: acl.h:182
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:5109
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define OidIsValid(objectId)
Definition: c.h:710
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:391
List * defGetQualifiedName(DefElem *def)
Definition: define.c:220
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:598
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:505
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:386
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3326
void namestrcpy(Name name, const char *str)
Definition: name.c:233
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:3041
Oid get_ts_parser_oid(List *names, bool missing_ok)
Definition: namespace.c:2346
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:2725
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:171
@ OBJECT_SCHEMA
Definition: parsenodes.h:2170
#define ACL_CREATE
Definition: parsenodes.h:91
FormData_pg_ts_config_map * Form_pg_ts_config_map
#define NameGetDatum(X)
Definition: postgres.h:639
#define InvalidOid
Definition: postgres_ext.h:36
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:110
Definition: c.h:676
@ TSCONFIGOID
Definition: syscache.h:106

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

Referenced by ProcessUtilitySlow().

◆ DefineTSDictionary()

ObjectAddress DefineTSDictionary ( List names,
List parameters 
)

Definition at line 391 of file tsearchcmds.c.

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 }
Oid get_ts_template_oid(List *names, bool missing_ok)
Definition: namespace.c:2599
static ObjectAddress makeDictionaryDependencies(HeapTuple tuple)
Definition: tsearchcmds.c:301

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

Referenced by ProcessUtilitySlow().

◆ DefineTSParser()

ObjectAddress DefineTSParser ( List names,
List parameters 
)

Definition at line 178 of file tsearchcmds.c.

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 }
#define DatumGetObjectId(X)
Definition: postgres.h:544
bool superuser(void)
Definition: superuser.c:46
static Datum get_ts_parser_func(DefElem *defel, int attnum)
Definition: tsearchcmds.c:68
static ObjectAddress makeParserDependencies(HeapTuple tuple)
Definition: tsearchcmds.c:131

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 684 of file tsearchcmds.c.

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;
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 }
int i
Definition: isn.c:73
static ObjectAddress makeTSTemplateDependencies(HeapTuple tuple)
Definition: tsearchcmds.c:646
static Datum get_ts_template_func(DefElem *defel, int attnum)
Definition: tsearchcmds.c:603

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 1510 of file tsearchcmds.c.

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 DatumGetTextPP(X)
Definition: fmgr.h:292
void pfree(void *pointer)
Definition: mcxt.c:1175
void * palloc(Size size)
Definition: mcxt.c:1068
const void size_t len
#define VARDATA_ANY(PTR)
Definition: postgres.h:361
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354
Definition: regguts.h:318
Definition: c.h:622
static DefElem * buildDefItem(const char *name, const char *val, bool was_quoted)
Definition: tsearchcmds.c:1723
char * text_to_cstring(const text *t)
Definition: varlena.c:221

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 1376 of file tsearchcmds.c.

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  String *val = lfirst_node(String, 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 }
#define NOTICE
Definition: elog.h:29
void EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId, Oid *dictIds, int ndicts)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define lfirst_node(type, lc)
Definition: pg_list.h:172
#define Int32GetDatum(X)
Definition: postgres.h:523
char * c
Definition: value.h:58
static int * getTokenTypes(Oid prsId, List *tokennames)
Definition: tsearchcmds.c:1157
#define strVal(v)
Definition: value.h:72

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

Referenced by AlterTSConfiguration().

◆ get_ts_parser_func()

static Datum get_ts_parser_func ( DefElem defel,
int  attnum 
)
static

Definition at line 68 of file tsearchcmds.c.

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 }
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1636
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2031
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2145
int16 attnum
Definition: pg_attribute.h:83

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 603 of file tsearchcmds.c.

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 }

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 int* getTokenTypes ( Oid  prsId,
List tokennames 
)
static

Definition at line 1157 of file tsearchcmds.c.

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  String *val = lfirst_node(String, 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 }
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:669
int j
Definition: isn.c:74
static int list_length(const List *l)
Definition: pg_list.h:149
#define DatumGetPointer(X)
Definition: postgres.h:593
TSParserCacheEntry * lookup_ts_parser_cache(Oid prsId)
Definition: ts_cache.c:111

References DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, i, j, TSParserCacheEntry::lextypeOid, lfirst_node, sort-test::list, list_length(), lookup_ts_parser_cache(), OidFunctionCall1, OidIsValid, palloc(), res, strVal, and val.

Referenced by DropConfigurationMapping(), and MakeConfigurationMapping().

◆ GetTSConfigTuple()

static HeapTuple GetTSConfigTuple ( List names)
static

Definition at line 781 of file tsearchcmds.c.

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 }

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

Referenced by AlterTSConfiguration().

◆ makeConfigurationDependencies()

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

Definition at line 806 of file tsearchcmds.c.

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 record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2711
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2447
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2502
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2742
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:243
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:191
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1001
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:164
void CommandCounterIncrement(void)
Definition: xact.c:1074

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 1212 of file tsearchcmds.c.

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 }

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, j, 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, and values.

Referenced by AlterTSConfiguration().

◆ makeDictionaryDependencies()

static ObjectAddress makeDictionaryDependencies ( HeapTuple  tuple)
static

Definition at line 301 of file tsearchcmds.c.

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 }

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 131 of file tsearchcmds.c.

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 }
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 646 of file tsearchcmds.c.

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 }
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 1061 of file tsearchcmds.c.

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 }

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

Referenced by doDeletion().

◆ serialize_deflist()

text* serialize_deflist ( List deflist)

Definition at line 1454 of file tsearchcmds.c.

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))
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 ESCAPE_STRING_SYNTAX
Definition: c.h:1164
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1161
char * defGetString(DefElem *def)
Definition: define.c:49
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
static char * buf
Definition: pg_test_fsync.c:67
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12192
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
Definition: value.h:46
Definition: value.h:29
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:200

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

◆ verify_dictoptions()

static void verify_dictoptions ( Oid  tmplId,
List dictoptions 
)
static

Definition at line 336 of file tsearchcmds.c.

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 NameStr(name)
Definition: c.h:681
bool IsUnderPostmaster
Definition: globals.c:113
#define copyObject(obj)
Definition: nodes.h:689
@ TSTEMPLATEOID
Definition: syscache.h:112

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

Referenced by AlterTSDictionary(), and DefineTSDictionary().