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 651 of file ts_cache.c.

References InvalidOid, and TSCurrentConfigCache.

652 {
653  /* Just reset the cache to force a lookup on first use */
655 }
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 591 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.

592 {
593  /*
594  * If we aren't inside a transaction, we cannot do database access so
595  * cannot verify the config name. Must accept it on faith.
596  */
597  if (IsTransactionState())
598  {
599  Oid cfgId;
600  HeapTuple tuple;
601  Form_pg_ts_config cfg;
602  char *buf;
603 
605 
606  /*
607  * When source == PGC_S_TEST, don't throw a hard error for a
608  * nonexistent configuration, only a NOTICE. See comments in guc.h.
609  */
610  if (!OidIsValid(cfgId))
611  {
612  if (source == PGC_S_TEST)
613  {
614  ereport(NOTICE,
615  (errcode(ERRCODE_UNDEFINED_OBJECT),
616  errmsg("text search configuration \"%s\" does not exist", *newval)));
617  return true;
618  }
619  else
620  return false;
621  }
622 
623  /*
624  * Modify the actually stored value to be fully qualified, to ensure
625  * later changes of search_path don't affect it.
626  */
628  if (!HeapTupleIsValid(tuple))
629  elog(ERROR, "cache lookup failed for text search configuration %u",
630  cfgId);
631  cfg = (Form_pg_ts_config) GETSTRUCT(tuple);
632 
633  buf = quote_qualified_identifier(get_namespace_name(cfg->cfgnamespace),
634  NameStr(cfg->cfgname));
635 
636  ReleaseSysCache(tuple);
637 
638  /* GUC wants it malloc'd not palloc'd */
639  free(*newval);
640  *newval = strdup(buf);
641  pfree(buf);
642  if (!*newval)
643  return false;
644  }
645 
646  return true;
647 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:38
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:2658
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
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:10574
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:78
#define newval
bool IsTransactionState(void)
Definition: xact.c:350
List * stringToQualifiedNameList(const char *string)
Definition: regproc.c:1687
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:576
#define elog
Definition: elog.h:219

◆ getTSCurrentConfig()

Oid getTSCurrentConfig ( bool  emitError)

Definition at line 560 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_string_to_tsvector(), json_to_tsvector(), jsonb_string_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(), ts_headline_opt(), and websearch_to_tsquery().

561 {
562  /* if we have a cached value, return it */
564  return TSCurrentConfigCache;
565 
566  /* fail if GUC hasn't been set up yet */
567  if (TSCurrentConfig == NULL || *TSCurrentConfig == '\0')
568  {
569  if (emitError)
570  elog(ERROR, "text search configuration isn't set");
571  else
572  return InvalidOid;
573  }
574 
575  if (TSConfigCacheHash == NULL)
576  {
577  /* First time through: initialize the tsconfig inval callback */
579  }
580 
581  /* Look up the config */
584  !emitError);
585 
586  return TSCurrentConfigCache;
587 }
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:2658
#define OidIsValid(objectId)
Definition: c.h:605
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:365
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 389 of file ts_cache.c.

References AccessShareLock, 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, and TSCONFIGOID.

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

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

◆ lookup_ts_dictionary_cache()

TSDictionaryCacheEntry* lookup_ts_dictionary_cache ( Oid  dictId)

Definition at line 210 of file ts_cache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, 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, MemoryContextCopyAndSetIdentifier, MemoryContextReset(), MemoryContextSetIdentifier(), 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  "TS dictionary",
300  MemoryContextCopyAndSetIdentifier(saveCtx, NameStr(dict->dictname));
301  }
302  else
303  {
304  /* Clear the existing entry's private context */
305  saveCtx = entry->dictCtx;
306  /* Don't let context's ident pointer dangle while we reset it */
307  MemoryContextSetIdentifier(saveCtx, NULL);
308  MemoryContextReset(saveCtx);
309  MemoryContextCopyAndSetIdentifier(saveCtx, NameStr(dict->dictname));
310  }
311 
312  MemSet(entry, 0, sizeof(TSDictionaryCacheEntry));
313  entry->dictId = dictId;
314  entry->dictCtx = saveCtx;
315 
316  entry->lexizeOid = template->tmpllexize;
317 
318  if (OidIsValid(template->tmplinit))
319  {
320  List *dictoptions;
321  Datum opt;
322  bool isnull;
323  MemoryContext oldcontext;
324 
325  /*
326  * Init method runs in dictionary's private memory context, and we
327  * make sure the options are stored there too
328  */
329  oldcontext = MemoryContextSwitchTo(entry->dictCtx);
330 
331  opt = SysCacheGetAttr(TSDICTOID, tpdict,
332  Anum_pg_ts_dict_dictinitoption,
333  &isnull);
334  if (isnull)
335  dictoptions = NIL;
336  else
337  dictoptions = deserialize_deflist(opt);
338 
339  entry->dictData =
340  DatumGetPointer(OidFunctionCall1(template->tmplinit,
341  PointerGetDatum(dictoptions)));
342 
343  MemoryContextSwitchTo(oldcontext);
344  }
345 
346  ReleaseSysCache(tptmpl);
347  ReleaseSysCache(tpdict);
348 
349  fmgr_info_cxt(entry->lexizeOid, &entry->lexize, entry->dictCtx);
350 
351  entry->isvalid = true;
352  }
353 
354  lastUsedDictionary = entry;
355 
356  return entry;
357 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define HASH_ELEM
Definition: hsearch.h:87
#define PointerGetDatum(X)
Definition: postgres.h:541
static TSDictionaryCacheEntry * lastUsedDictionary
Definition: ts_cache.c:67
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1561
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:908
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:628
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:41
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:96
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
static void InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: ts_cache.c:93
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
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
uintptr_t Datum
Definition: postgres.h:367
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:78
#define Assert(condition)
Definition: c.h:699
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:329
#define DatumGetPointer(X)
Definition: postgres.h:534
FormData_pg_ts_template * Form_pg_ts_template
#define NameStr(name)
Definition: c.h:576
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:47

◆ 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:668
#define HASH_ELEM
Definition: hsearch.h:87
#define PointerGetDatum(X)
Definition: postgres.h:541
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:908
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#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:134
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:53
Size keysize
Definition: hsearch.h:72
static TSParserCacheEntry * lastUsedParser
Definition: ts_cache.c:64
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
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:47
FmgrInfo prsheadline
Definition: ts_cache.h:48

Variable Documentation

◆ TSCurrentConfig

char* TSCurrentConfig

Definition at line 75 of file ts_cache.c.

Referenced by getTSCurrentConfig().