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:76
#define InvalidOid
Definition: postgres_ext.h:36

◆ check_TSCurrentConfig()

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

Definition at line 590 of file ts_cache.c.

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

591 {
592  /*
593  * If we aren't inside a transaction, or connected to a database, we
594  * cannot do the catalog accesses necessary to verify the config name.
595  * Must accept it on faith.
596  */
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:655
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
int errcode(int sqlerrcode)
Definition: elog.c:691
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:2678
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:706
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3196
static char * buf
Definition: pg_test_fsync.c:68
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11018
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:155
#define NOTICE
Definition: elog.h:37
#define free(a)
Definition: header.h:65
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static rewind_source * source
Definition: pg_rewind.c:79
#define newval
bool IsTransactionState(void)
Definition: xact.c:371
List * stringToQualifiedNameList(const char *string)
Definition: regproc.c:1876
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:677

◆ getTSCurrentConfig()

Oid getTSCurrentConfig ( bool  emitError)

Definition at line 559 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().

560 {
561  /* if we have a cached value, return it */
563  return TSCurrentConfigCache;
564 
565  /* fail if GUC hasn't been set up yet */
566  if (TSCurrentConfig == NULL || *TSCurrentConfig == '\0')
567  {
568  if (emitError)
569  elog(ERROR, "text search configuration isn't set");
570  else
571  return InvalidOid;
572  }
573 
574  if (TSConfigCacheHash == NULL)
575  {
576  /* First time through: initialize the tsconfig inval callback */
578  }
579 
580  /* Look up the config */
583  !emitError);
584 
585  return TSCurrentConfigCache;
586 }
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:2678
#define OidIsValid(objectId)
Definition: c.h:706
char * TSCurrentConfig
Definition: ts_cache.c:74
static Oid TSCurrentConfigCache
Definition: ts_cache.c:76
#define ERROR
Definition: elog.h:43
#define InvalidOid
Definition: postgres_ext.h:36
static void init_ts_config_cache(void)
Definition: ts_cache.c:364
static HTAB * TSConfigCacheHash
Definition: ts_cache.c:68
List * stringToQualifiedNameList(const char *string)
Definition: regproc.c:1876
#define elog(elevel,...)
Definition: elog.h:228

◆ lookup_ts_config_cache()

TSConfigCacheEntry* lookup_ts_config_cache ( Oid  cfgId)

Definition at line 388 of file ts_cache.c.

References AccessShareLock, Assert, BTEqualStrategyNumber, CacheMemoryContext, TSConfigCacheEntry::cfgId, ListDictionary::dictIds, elog, ERROR, ForwardScanDirection, GETSTRUCT, HASH_ENTER, HASH_FIND, hash_search(), 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(), table_close(), table_open(), TSConfigMapIndexId, and TSCONFIGOID.

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

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

210 {
211  TSDictionaryCacheEntry *entry;
212 
213  if (TSDictionaryCacheHash == NULL)
214  {
215  /* First time through: initialize the hash table */
216  HASHCTL ctl;
217 
218  MemSet(&ctl, 0, sizeof(ctl));
219  ctl.keysize = sizeof(Oid);
220  ctl.entrysize = sizeof(TSDictionaryCacheEntry);
221  TSDictionaryCacheHash = hash_create("Tsearch dictionary cache", 8,
222  &ctl, HASH_ELEM | HASH_BLOBS);
223  /* Flush cache on pg_ts_dict and pg_ts_template changes */
228 
229  /* Also make sure CacheMemoryContext exists */
230  if (!CacheMemoryContext)
232  }
233 
234  /* Check single-entry cache */
235  if (lastUsedDictionary && lastUsedDictionary->dictId == dictId &&
237  return lastUsedDictionary;
238 
239  /* Try to look up an existing entry */
241  (void *) &dictId,
242  HASH_FIND, NULL);
243  if (entry == NULL || !entry->isvalid)
244  {
245  /*
246  * If we didn't find one, we want to make one. But first look up the
247  * object to be sure the OID is real.
248  */
249  HeapTuple tpdict,
250  tptmpl;
251  Form_pg_ts_dict dict;
252  Form_pg_ts_template template;
253  MemoryContext saveCtx;
254 
255  tpdict = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
256  if (!HeapTupleIsValid(tpdict))
257  elog(ERROR, "cache lookup failed for text search dictionary %u",
258  dictId);
259  dict = (Form_pg_ts_dict) GETSTRUCT(tpdict);
260 
261  /*
262  * Sanity checks
263  */
264  if (!OidIsValid(dict->dicttemplate))
265  elog(ERROR, "text search dictionary %u has no template", dictId);
266 
267  /*
268  * Retrieve dictionary's template
269  */
271  ObjectIdGetDatum(dict->dicttemplate));
272  if (!HeapTupleIsValid(tptmpl))
273  elog(ERROR, "cache lookup failed for text search template %u",
274  dict->dicttemplate);
275  template = (Form_pg_ts_template) GETSTRUCT(tptmpl);
276 
277  /*
278  * Sanity checks
279  */
280  if (!OidIsValid(template->tmpllexize))
281  elog(ERROR, "text search template %u has no lexize method",
282  template->tmpllexize);
283 
284  if (entry == NULL)
285  {
286  bool found;
287 
288  /* Now make the cache entry */
289  entry = (TSDictionaryCacheEntry *)
291  (void *) &dictId,
292  HASH_ENTER, &found);
293  Assert(!found); /* it wasn't there a moment ago */
294 
295  /* Create private memory context the first time through */
297  "TS dictionary",
299  MemoryContextCopyAndSetIdentifier(saveCtx, NameStr(dict->dictname));
300  }
301  else
302  {
303  /* Clear the existing entry's private context */
304  saveCtx = entry->dictCtx;
305  /* Don't let context's ident pointer dangle while we reset it */
306  MemoryContextSetIdentifier(saveCtx, NULL);
307  MemoryContextReset(saveCtx);
308  MemoryContextCopyAndSetIdentifier(saveCtx, NameStr(dict->dictname));
309  }
310 
311  MemSet(entry, 0, sizeof(TSDictionaryCacheEntry));
312  entry->dictId = dictId;
313  entry->dictCtx = saveCtx;
314 
315  entry->lexizeOid = template->tmpllexize;
316 
317  if (OidIsValid(template->tmplinit))
318  {
319  List *dictoptions;
320  Datum opt;
321  bool isnull;
322  MemoryContext oldcontext;
323 
324  /*
325  * Init method runs in dictionary's private memory context, and we
326  * make sure the options are stored there too
327  */
328  oldcontext = MemoryContextSwitchTo(entry->dictCtx);
329 
330  opt = SysCacheGetAttr(TSDICTOID, tpdict,
331  Anum_pg_ts_dict_dictinitoption,
332  &isnull);
333  if (isnull)
334  dictoptions = NIL;
335  else
336  dictoptions = deserialize_deflist(opt);
337 
338  entry->dictData =
339  DatumGetPointer(OidFunctionCall1(template->tmplinit,
340  PointerGetDatum(dictoptions)));
341 
342  MemoryContextSwitchTo(oldcontext);
343  }
344 
345  ReleaseSysCache(tptmpl);
346  ReleaseSysCache(tpdict);
347 
348  fmgr_info_cxt(entry->lexizeOid, &entry->lexize, entry->dictCtx);
349 
350  entry->isvalid = true;
351  }
352 
353  lastUsedDictionary = entry;
354 
355  return entry;
356 }
#define NIL
Definition: pg_list.h:65
#define AllocSetContextCreate
Definition: memutils.h:170
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define HASH_ELEM
Definition: hsearch.h:85
#define PointerGetDatum(X)
Definition: postgres.h:556
static TSDictionaryCacheEntry * lastUsedDictionary
Definition: ts_cache.c:66
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1510
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:72
#define MemSet(start, val, len)
Definition: c.h:1004
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:137
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:706
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:664
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:97
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
static void InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: ts_cache.c:92
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
#define HASH_BLOBS
Definition: hsearch.h:86
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1434
uintptr_t Datum
Definition: postgres.h:367
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:326
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1376
Size keysize
Definition: hsearch.h:71
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:800
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:330
#define DatumGetPointer(X)
Definition: postgres.h:549
FormData_pg_ts_template * Form_pg_ts_template
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:677
static HTAB * TSDictionaryCacheHash
Definition: ts_cache.c:65
struct TSDictionaryCacheEntry TSDictionaryCacheEntry
Definition: pg_list.h:50
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 111 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().

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

Variable Documentation

◆ TSCurrentConfig

char* TSCurrentConfig

Definition at line 74 of file ts_cache.c.

Referenced by getTSCurrentConfig().