PostgreSQL Source Code  git master
ts_cache.h File Reference
#include "utils/guc.h"
Include dependency graph for ts_cache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  TSAnyCacheEntry
 
struct  TSParserCacheEntry
 
struct  TSDictionaryCacheEntry
 
struct  ListDictionary
 
struct  TSConfigCacheEntry
 

Typedefs

typedef struct TSAnyCacheEntry TSAnyCacheEntry
 
typedef struct TSParserCacheEntry TSParserCacheEntry
 
typedef struct TSDictionaryCacheEntry TSDictionaryCacheEntry
 

Functions

TSParserCacheEntrylookup_ts_parser_cache (Oid prsId)
 
TSDictionaryCacheEntrylookup_ts_dictionary_cache (Oid dictId)
 
TSConfigCacheEntrylookup_ts_config_cache (Oid cfgId)
 
Oid getTSCurrentConfig (bool emitError)
 
bool check_TSCurrentConfig (char **newval, void **extra, GucSource source)
 
void assign_TSCurrentConfig (const char *newval, void *extra)
 

Variables

char * TSCurrentConfig
 

Typedef Documentation

◆ TSAnyCacheEntry

◆ TSDictionaryCacheEntry

◆ TSParserCacheEntry

Function Documentation

◆ assign_TSCurrentConfig()

void assign_TSCurrentConfig ( const char *  newval,
void *  extra 
)

Definition at line 648 of file ts_cache.c.

References InvalidOid, and TSCurrentConfigCache.

649 {
650  /* Just reset the cache to force a lookup on first use */
652 }
static Oid TSCurrentConfigCache
Definition: ts_cache.c:77
#define InvalidOid
Definition: postgres_ext.h:36

◆ check_TSCurrentConfig()

bool check_TSCurrentConfig ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 588 of file ts_cache.c.

References buf, elog, ereport, errcode(), errmsg(), ERROR, free, get_namespace_name(), get_ts_config_oid(), GETSTRUCT, HeapTupleIsValid, IsTransactionState(), NameStr, NOTICE, ObjectIdGetDatum, OidIsValid, pfree(), PGC_S_TEST, quote_qualified_identifier(), ReleaseSysCache(), SearchSysCache1(), stringToQualifiedNameList(), and TSCONFIGOID.

589 {
590  /*
591  * If we aren't inside a transaction, we cannot do database access so
592  * cannot verify the config name. Must accept it on faith.
593  */
594  if (IsTransactionState())
595  {
596  Oid cfgId;
597  HeapTuple tuple;
598  Form_pg_ts_config cfg;
599  char *buf;
600 
602 
603  /*
604  * When source == PGC_S_TEST, don't throw a hard error for a
605  * nonexistent configuration, only a NOTICE. See comments in guc.h.
606  */
607  if (!OidIsValid(cfgId))
608  {
609  if (source == PGC_S_TEST)
610  {
611  ereport(NOTICE,
612  (errcode(ERRCODE_UNDEFINED_OBJECT),
613  errmsg("text search configuration \"%s\" does not exist", *newval)));
614  return true;
615  }
616  else
617  return false;
618  }
619 
620  /*
621  * Modify the actually stored value to be fully qualified, to ensure
622  * later changes of search_path don't affect it.
623  */
625  if (!HeapTupleIsValid(tuple))
626  elog(ERROR, "cache lookup failed for text search configuration %u",
627  cfgId);
628  cfg = (Form_pg_ts_config) GETSTRUCT(tuple);
629 
630  buf = quote_qualified_identifier(get_namespace_name(cfg->cfgnamespace),
631  NameStr(cfg->cfgname));
632 
633  ReleaseSysCache(tuple);
634 
635  /* GUC wants it malloc'd not palloc'd */
636  free(*newval);
637  *newval = strdup(buf);
638  pfree(buf);
639  if (!*newval)
640  return false;
641  }
642 
643  return true;
644 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:41
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:2639
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
void pfree(void *pointer)
Definition: mcxt.c:936
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3066
static char * buf
Definition: pg_test_fsync.c:67
#define ereport(elevel, rest)
Definition: elog.h:122
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10498
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define NOTICE
Definition: elog.h:37
#define free(a)
Definition: header.h:65
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define newval
bool IsTransactionState(void)
Definition: xact.c:351
List * stringToQualifiedNameList(const char *string)
Definition: regproc.c:1687
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:557
#define elog
Definition: elog.h:219

◆ getTSCurrentConfig()

Oid getTSCurrentConfig ( bool  emitError)

Definition at line 557 of file ts_cache.c.

References elog, ERROR, get_ts_config_oid(), init_ts_config_cache(), InvalidOid, OidIsValid, stringToQualifiedNameList(), TSCurrentConfig, and TSCurrentConfigCache.

Referenced by get_current_ts_config(), json_to_tsvector(), jsonb_to_tsvector(), phraseto_tsquery(), plainto_tsquery(), to_tsquery(), to_tsvector(), ts_headline(), ts_headline_json(), ts_headline_json_opt(), ts_headline_jsonb(), ts_headline_jsonb_opt(), and ts_headline_opt().

558 {
559  /* if we have a cached value, return it */
561  return TSCurrentConfigCache;
562 
563  /* fail if GUC hasn't been set up yet */
564  if (TSCurrentConfig == NULL || *TSCurrentConfig == '\0')
565  {
566  if (emitError)
567  elog(ERROR, "text search configuration isn't set");
568  else
569  return InvalidOid;
570  }
571 
572  if (TSConfigCacheHash == NULL)
573  {
574  /* First time through: initialize the tsconfig inval callback */
576  }
577 
578  /* Look up the config */
581  !emitError);
582 
583  return TSCurrentConfigCache;
584 }
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:2639
#define OidIsValid(objectId)
Definition: c.h:586
char * TSCurrentConfig
Definition: ts_cache.c:75
static Oid TSCurrentConfigCache
Definition: ts_cache.c:77
#define ERROR
Definition: elog.h:43
#define InvalidOid
Definition: postgres_ext.h:36
static void init_ts_config_cache(void)
Definition: ts_cache.c:362
static HTAB * TSConfigCacheHash
Definition: ts_cache.c:69
List * stringToQualifiedNameList(const char *string)
Definition: regproc.c:1687
#define elog
Definition: elog.h:219

◆ lookup_ts_config_cache()

TSConfigCacheEntry* lookup_ts_config_cache ( Oid  cfgId)

Definition at line 386 of file ts_cache.c.

References AccessShareLock, Anum_pg_ts_config_map_mapcfg, Assert, BTEqualStrategyNumber, CacheMemoryContext, TSConfigCacheEntry::cfgId, ListDictionary::dictIds, elog, ERROR, ForwardScanDirection, GETSTRUCT, HASH_ENTER, HASH_FIND, hash_search(), heap_close, heap_open(), HeapTupleIsValid, i, index_close(), index_open(), init_ts_config_cache(), TSConfigCacheEntry::isvalid, lastUsedConfig, ListDictionary::len, TSConfigCacheEntry::lenmap, TSConfigCacheEntry::map, MAXDICTSPERTT, MAXTOKENTYPE, MemoryContextAlloc(), MemSet, ObjectIdGetDatum, OidIsValid, pfree(), TSConfigCacheEntry::prsId, ReleaseSysCache(), ScanKeyInit(), SearchSysCache1(), systable_beginscan_ordered(), systable_endscan_ordered(), systable_getnext_ordered(), TSConfigMapIndexId, TSConfigMapRelationId, and TSCONFIGOID.

Referenced by hlparsetext(), parsetext(), ts_headline_byid_opt(), ts_headline_json_byid_opt(), and ts_headline_jsonb_byid_opt().

387 {
388  TSConfigCacheEntry *entry;
389 
390  if (TSConfigCacheHash == NULL)
391  {
392  /* First time through: initialize the hash table */
394  }
395 
396  /* Check single-entry cache */
397  if (lastUsedConfig && lastUsedConfig->cfgId == cfgId &&
399  return lastUsedConfig;
400 
401  /* Try to look up an existing entry */
403  (void *) &cfgId,
404  HASH_FIND, NULL);
405  if (entry == NULL || !entry->isvalid)
406  {
407  /*
408  * If we didn't find one, we want to make one. But first look up the
409  * object to be sure the OID is real.
410  */
411  HeapTuple tp;
412  Form_pg_ts_config cfg;
413  Relation maprel;
414  Relation mapidx;
415  ScanKeyData mapskey;
416  SysScanDesc mapscan;
417  HeapTuple maptup;
418  ListDictionary maplists[MAXTOKENTYPE + 1];
419  Oid mapdicts[MAXDICTSPERTT];
420  int maxtokentype;
421  int ndicts;
422  int i;
423 
425  if (!HeapTupleIsValid(tp))
426  elog(ERROR, "cache lookup failed for text search configuration %u",
427  cfgId);
428  cfg = (Form_pg_ts_config) GETSTRUCT(tp);
429 
430  /*
431  * Sanity checks
432  */
433  if (!OidIsValid(cfg->cfgparser))
434  elog(ERROR, "text search configuration %u has no parser", cfgId);
435 
436  if (entry == NULL)
437  {
438  bool found;
439 
440  /* Now make the cache entry */
441  entry = (TSConfigCacheEntry *)
443  (void *) &cfgId,
444  HASH_ENTER, &found);
445  Assert(!found); /* it wasn't there a moment ago */
446  }
447  else
448  {
449  /* Cleanup old contents */
450  if (entry->map)
451  {
452  for (i = 0; i < entry->lenmap; i++)
453  if (entry->map[i].dictIds)
454  pfree(entry->map[i].dictIds);
455  pfree(entry->map);
456  }
457  }
458 
459  MemSet(entry, 0, sizeof(TSConfigCacheEntry));
460  entry->cfgId = cfgId;
461  entry->prsId = cfg->cfgparser;
462 
463  ReleaseSysCache(tp);
464 
465  /*
466  * Scan pg_ts_config_map to gather dictionary list for each token type
467  *
468  * Because the index is on (mapcfg, maptokentype, mapseqno), we will
469  * see the entries in maptokentype order, and in mapseqno order for
470  * each token type, even though we didn't explicitly ask for that.
471  */
472  MemSet(maplists, 0, sizeof(maplists));
473  maxtokentype = 0;
474  ndicts = 0;
475 
476  ScanKeyInit(&mapskey,
478  BTEqualStrategyNumber, F_OIDEQ,
479  ObjectIdGetDatum(cfgId));
480 
483  mapscan = systable_beginscan_ordered(maprel, mapidx,
484  NULL, 1, &mapskey);
485 
486  while ((maptup = systable_getnext_ordered(mapscan, ForwardScanDirection)) != NULL)
487  {
489  int toktype = cfgmap->maptokentype;
490 
491  if (toktype <= 0 || toktype > MAXTOKENTYPE)
492  elog(ERROR, "maptokentype value %d is out of range", toktype);
493  if (toktype < maxtokentype)
494  elog(ERROR, "maptokentype entries are out of order");
495  if (toktype > maxtokentype)
496  {
497  /* starting a new token type, but first save the prior data */
498  if (ndicts > 0)
499  {
500  maplists[maxtokentype].len = ndicts;
501  maplists[maxtokentype].dictIds = (Oid *)
503  sizeof(Oid) * ndicts);
504  memcpy(maplists[maxtokentype].dictIds, mapdicts,
505  sizeof(Oid) * ndicts);
506  }
507  maxtokentype = toktype;
508  mapdicts[0] = cfgmap->mapdict;
509  ndicts = 1;
510  }
511  else
512  {
513  /* continuing data for current token type */
514  if (ndicts >= MAXDICTSPERTT)
515  elog(ERROR, "too many pg_ts_config_map entries for one token type");
516  mapdicts[ndicts++] = cfgmap->mapdict;
517  }
518  }
519 
520  systable_endscan_ordered(mapscan);
521  index_close(mapidx, AccessShareLock);
522  heap_close(maprel, AccessShareLock);
523 
524  if (ndicts > 0)
525  {
526  /* save the last token type's dictionaries */
527  maplists[maxtokentype].len = ndicts;
528  maplists[maxtokentype].dictIds = (Oid *)
530  sizeof(Oid) * ndicts);
531  memcpy(maplists[maxtokentype].dictIds, mapdicts,
532  sizeof(Oid) * ndicts);
533  /* and save the overall map */
534  entry->lenmap = maxtokentype + 1;
535  entry->map = (ListDictionary *)
537  sizeof(ListDictionary) * entry->lenmap);
538  memcpy(entry->map, maplists,
539  sizeof(ListDictionary) * entry->lenmap);
540  }
541 
542  entry->isvalid = true;
543  }
544 
545  lastUsedConfig = entry;
546 
547  return entry;
548 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define MAXDICTSPERTT
Definition: ts_cache.c:60
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:41
FormData_pg_ts_config_map * Form_pg_ts_config_map
#define AccessShareLock
Definition: lockdefs.h:36
#define MemSet(start, val, len)
Definition: c.h:877
#define heap_close(r, l)
Definition: heapam.h:97
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:597
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
void pfree(void *pointer)
Definition: mcxt.c:936
#define TSConfigMapRelationId
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define Anum_pg_ts_config_map_mapcfg
#define MAXTOKENTYPE
Definition: ts_cache.c:59
Oid * dictIds
Definition: ts_cache.h:68
ListDictionary * map
Definition: ts_cache.h:80
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:614
static void init_ts_config_cache(void)
Definition: ts_cache.c:362
static HTAB * TSConfigCacheHash
Definition: ts_cache.c:69
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:680
static TSConfigCacheEntry * lastUsedConfig
Definition: ts_cache.c:70
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:533
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:693
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define TSConfigMapIndexId
Definition: indexing.h:264
#define elog
Definition: elog.h:219
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ lookup_ts_dictionary_cache()

TSDictionaryCacheEntry* lookup_ts_dictionary_cache ( Oid  dictId)

Definition at line 210 of file ts_cache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreateExtended(), Anum_pg_ts_dict_dictinitoption, Assert, CacheMemoryContext, CacheRegisterSyscacheCallback(), CreateCacheMemoryContext(), DatumGetPointer, deserialize_deflist(), TSDictionaryCacheEntry::dictCtx, TSDictionaryCacheEntry::dictData, TSDictionaryCacheEntry::dictId, elog, HASHCTL::entrysize, ERROR, fmgr_info_cxt(), GETSTRUCT, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, HASH_FIND, hash_search(), HeapTupleIsValid, InvalidateTSCacheCallBack(), TSDictionaryCacheEntry::isvalid, HASHCTL::keysize, lastUsedDictionary, TSDictionaryCacheEntry::lexize, TSDictionaryCacheEntry::lexizeOid, MEMCONTEXT_COPY_NAME, MemoryContextResetAndDeleteChildren, MemoryContextSwitchTo(), MemSet, NameStr, NIL, ObjectIdGetDatum, OidFunctionCall1, OidIsValid, PointerGetDatum, ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), TSDICTOID, and TSTEMPLATEOID.

Referenced by LexizeExec(), thesaurus_init(), thesaurus_lexize(), ts_lexize(), and unaccent_dict().

211 {
212  TSDictionaryCacheEntry *entry;
213 
214  if (TSDictionaryCacheHash == NULL)
215  {
216  /* First time through: initialize the hash table */
217  HASHCTL ctl;
218 
219  MemSet(&ctl, 0, sizeof(ctl));
220  ctl.keysize = sizeof(Oid);
221  ctl.entrysize = sizeof(TSDictionaryCacheEntry);
222  TSDictionaryCacheHash = hash_create("Tsearch dictionary cache", 8,
223  &ctl, HASH_ELEM | HASH_BLOBS);
224  /* Flush cache on pg_ts_dict and pg_ts_template changes */
229 
230  /* Also make sure CacheMemoryContext exists */
231  if (!CacheMemoryContext)
233  }
234 
235  /* Check single-entry cache */
236  if (lastUsedDictionary && lastUsedDictionary->dictId == dictId &&
238  return lastUsedDictionary;
239 
240  /* Try to look up an existing entry */
242  (void *) &dictId,
243  HASH_FIND, NULL);
244  if (entry == NULL || !entry->isvalid)
245  {
246  /*
247  * If we didn't find one, we want to make one. But first look up the
248  * object to be sure the OID is real.
249  */
250  HeapTuple tpdict,
251  tptmpl;
252  Form_pg_ts_dict dict;
253  Form_pg_ts_template template;
254  MemoryContext saveCtx;
255 
256  tpdict = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
257  if (!HeapTupleIsValid(tpdict))
258  elog(ERROR, "cache lookup failed for text search dictionary %u",
259  dictId);
260  dict = (Form_pg_ts_dict) GETSTRUCT(tpdict);
261 
262  /*
263  * Sanity checks
264  */
265  if (!OidIsValid(dict->dicttemplate))
266  elog(ERROR, "text search dictionary %u has no template", dictId);
267 
268  /*
269  * Retrieve dictionary's template
270  */
272  ObjectIdGetDatum(dict->dicttemplate));
273  if (!HeapTupleIsValid(tptmpl))
274  elog(ERROR, "cache lookup failed for text search template %u",
275  dict->dicttemplate);
276  template = (Form_pg_ts_template) GETSTRUCT(tptmpl);
277 
278  /*
279  * Sanity checks
280  */
281  if (!OidIsValid(template->tmpllexize))
282  elog(ERROR, "text search template %u has no lexize method",
283  template->tmpllexize);
284 
285  if (entry == NULL)
286  {
287  bool found;
288 
289  /* Now make the cache entry */
290  entry = (TSDictionaryCacheEntry *)
292  (void *) &dictId,
293  HASH_ENTER, &found);
294  Assert(!found); /* it wasn't there a moment ago */
295 
296  /* Create private memory context the first time through */
298  NameStr(dict->dictname),
301  }
302  else
303  {
304  /* Clear the existing entry's private context */
305  saveCtx = entry->dictCtx;
307  }
308 
309  MemSet(entry, 0, sizeof(TSDictionaryCacheEntry));
310  entry->dictId = dictId;
311  entry->dictCtx = saveCtx;
312 
313  entry->lexizeOid = template->tmpllexize;
314 
315  if (OidIsValid(template->tmplinit))
316  {
317  List *dictoptions;
318  Datum opt;
319  bool isnull;
320  MemoryContext oldcontext;
321 
322  /*
323  * Init method runs in dictionary's private memory context, and we
324  * make sure the options are stored there too
325  */
326  oldcontext = MemoryContextSwitchTo(entry->dictCtx);
327 
328  opt = SysCacheGetAttr(TSDICTOID, tpdict,
330  &isnull);
331  if (isnull)
332  dictoptions = NIL;
333  else
334  dictoptions = deserialize_deflist(opt);
335 
336  entry->dictData =
337  DatumGetPointer(OidFunctionCall1(template->tmplinit,
338  PointerGetDatum(dictoptions)));
339 
340  MemoryContextSwitchTo(oldcontext);
341  }
342 
343  ReleaseSysCache(tptmpl);
344  ReleaseSysCache(tpdict);
345 
346  fmgr_info_cxt(entry->lexizeOid, &entry->lexize, entry->dictCtx);
347 
348  entry->isvalid = true;
349  }
350 
351  lastUsedDictionary = entry;
352 
353  return entry;
354 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define HASH_ELEM
Definition: hsearch.h:87
#define MEMCONTEXT_COPY_NAME
Definition: memutils.h:188
#define PointerGetDatum(X)
Definition: postgres.h:562
static TSDictionaryCacheEntry * lastUsedDictionary
Definition: ts_cache.c:67
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1562
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:207
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:877
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
MemoryContext AllocSetContextCreateExtended(MemoryContext parent, const char *name, int flags, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:394
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:623
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:45
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
static void InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: ts_cache.c:93
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67
#define HASH_BLOBS
Definition: hsearch.h:88
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1389
uintptr_t Datum
Definition: postgres.h:372
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Size keysize
Definition: hsearch.h:72
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:680
#define Anum_pg_ts_dict_dictinitoption
Definition: pg_ts_dict.h:56
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
#define DatumGetPointer(X)
Definition: postgres.h:555
FormData_pg_ts_template * Form_pg_ts_template
#define NameStr(name)
Definition: c.h:557
static HTAB * TSDictionaryCacheHash
Definition: ts_cache.c:66
#define elog
Definition: elog.h:219
struct TSDictionaryCacheEntry TSDictionaryCacheEntry
Definition: pg_list.h:45
MemoryContext dictCtx
Definition: ts_cache.h:61
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ lookup_ts_parser_cache()

TSParserCacheEntry* lookup_ts_parser_cache ( Oid  prsId)

Definition at line 112 of file ts_cache.c.

References Assert, CacheMemoryContext, CacheRegisterSyscacheCallback(), CreateCacheMemoryContext(), elog, TSParserCacheEntry::endOid, HASHCTL::entrysize, ERROR, fmgr_info_cxt(), GETSTRUCT, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, HASH_FIND, hash_search(), TSParserCacheEntry::headlineOid, HeapTupleIsValid, InvalidateTSCacheCallBack(), TSParserCacheEntry::isvalid, HASHCTL::keysize, lastUsedParser, TSParserCacheEntry::lextypeOid, MemSet, ObjectIdGetDatum, OidIsValid, PointerGetDatum, TSParserCacheEntry::prsend, TSParserCacheEntry::prsheadline, TSParserCacheEntry::prsId, TSParserCacheEntry::prsstart, TSParserCacheEntry::prstoken, ReleaseSysCache(), SearchSysCache1(), TSParserCacheEntry::startOid, TSParserCacheEntry::tokenOid, and TSPARSEROID.

Referenced by getTokenTypes(), hlparsetext(), parsetext(), prs_setup_firstcall(), ts_headline_byid_opt(), ts_headline_json_byid_opt(), ts_headline_jsonb_byid_opt(), and tt_setup_firstcall().

113 {
114  TSParserCacheEntry *entry;
115 
116  if (TSParserCacheHash == NULL)
117  {
118  /* First time through: initialize the hash table */
119  HASHCTL ctl;
120 
121  MemSet(&ctl, 0, sizeof(ctl));
122  ctl.keysize = sizeof(Oid);
123  ctl.entrysize = sizeof(TSParserCacheEntry);
124  TSParserCacheHash = hash_create("Tsearch parser cache", 4,
125  &ctl, HASH_ELEM | HASH_BLOBS);
126  /* Flush cache on pg_ts_parser changes */
129 
130  /* Also make sure CacheMemoryContext exists */
131  if (!CacheMemoryContext)
133  }
134 
135  /* Check single-entry cache */
136  if (lastUsedParser && lastUsedParser->prsId == prsId &&
138  return lastUsedParser;
139 
140  /* Try to look up an existing entry */
142  (void *) &prsId,
143  HASH_FIND, NULL);
144  if (entry == NULL || !entry->isvalid)
145  {
146  /*
147  * If we didn't find one, we want to make one. But first look up the
148  * object to be sure the OID is real.
149  */
150  HeapTuple tp;
151  Form_pg_ts_parser prs;
152 
154  if (!HeapTupleIsValid(tp))
155  elog(ERROR, "cache lookup failed for text search parser %u",
156  prsId);
157  prs = (Form_pg_ts_parser) GETSTRUCT(tp);
158 
159  /*
160  * Sanity checks
161  */
162  if (!OidIsValid(prs->prsstart))
163  elog(ERROR, "text search parser %u has no prsstart method", prsId);
164  if (!OidIsValid(prs->prstoken))
165  elog(ERROR, "text search parser %u has no prstoken method", prsId);
166  if (!OidIsValid(prs->prsend))
167  elog(ERROR, "text search parser %u has no prsend method", prsId);
168 
169  if (entry == NULL)
170  {
171  bool found;
172 
173  /* Now make the cache entry */
174  entry = (TSParserCacheEntry *)
176  (void *) &prsId,
177  HASH_ENTER, &found);
178  Assert(!found); /* it wasn't there a moment ago */
179  }
180 
181  MemSet(entry, 0, sizeof(TSParserCacheEntry));
182  entry->prsId = prsId;
183  entry->startOid = prs->prsstart;
184  entry->tokenOid = prs->prstoken;
185  entry->endOid = prs->prsend;
186  entry->headlineOid = prs->prsheadline;
187  entry->lextypeOid = prs->prslextype;
188 
189  ReleaseSysCache(tp);
190 
193  fmgr_info_cxt(entry->endOid, &entry->prsend, CacheMemoryContext);
194  if (OidIsValid(entry->headlineOid))
195  fmgr_info_cxt(entry->headlineOid, &entry->prsheadline,
197 
198  entry->isvalid = true;
199  }
200 
201  lastUsedParser = entry;
202 
203  return entry;
204 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define HASH_ELEM
Definition: hsearch.h:87
#define PointerGetDatum(X)
Definition: postgres.h:562
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:877
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
FmgrInfo prsend
Definition: ts_cache.h:47
static HTAB * TSParserCacheHash
Definition: ts_cache.c:63
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
static void InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: ts_cache.c:93
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define HASH_BLOBS
Definition: hsearch.h:88
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1389
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
FormData_pg_ts_parser * Form_pg_ts_parser
Definition: pg_ts_parser.h:44
Size keysize
Definition: hsearch.h:72
static TSParserCacheEntry * lastUsedParser
Definition: ts_cache.c:64
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:680
FmgrInfo prstoken
Definition: ts_cache.h:46
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
FmgrInfo prsstart
Definition: ts_cache.h:45
struct TSParserCacheEntry TSParserCacheEntry
#define elog
Definition: elog.h:219
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
FmgrInfo prsheadline
Definition: ts_cache.h:48

Variable Documentation

◆ TSCurrentConfig

char* TSCurrentConfig

Definition at line 75 of file ts_cache.c.

Referenced by getTSCurrentConfig().