PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
ts_cache.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/indexing.h"
#include "catalog/namespace.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 "commands/defrem.h"
#include "tsearch/ts_cache.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/regproc.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for ts_cache.c:

Go to the source code of this file.

Macros

#define MAXTOKENTYPE   256
 
#define MAXDICTSPERTT   100
 

Functions

static void InvalidateTSCacheCallBack (Datum arg, int cacheid, uint32 hashvalue)
 
TSParserCacheEntrylookup_ts_parser_cache (Oid prsId)
 
TSDictionaryCacheEntrylookup_ts_dictionary_cache (Oid dictId)
 
static void init_ts_config_cache (void)
 
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

static HTABTSParserCacheHash = NULL
 
static TSParserCacheEntrylastUsedParser = NULL
 
static HTABTSDictionaryCacheHash = NULL
 
static TSDictionaryCacheEntrylastUsedDictionary = NULL
 
static HTABTSConfigCacheHash = NULL
 
static TSConfigCacheEntrylastUsedConfig = NULL
 
char * TSCurrentConfig = NULL
 
static Oid TSCurrentConfigCache = InvalidOid
 

Macro Definition Documentation

#define MAXDICTSPERTT   100

Definition at line 60 of file ts_cache.c.

Referenced by lookup_ts_config_cache().

#define MAXTOKENTYPE   256

Definition at line 59 of file ts_cache.c.

Referenced by lookup_ts_config_cache().

Function Documentation

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

Definition at line 647 of file ts_cache.c.

References InvalidOid, and TSCurrentConfigCache.

648 {
649  /* Just reset the cache to force a lookup on first use */
651 }
static Oid TSCurrentConfigCache
Definition: ts_cache.c:77
#define InvalidOid
Definition: postgres_ext.h:36
bool check_TSCurrentConfig ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 587 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(), TSCONFIGOID, and catclist::tuple.

588 {
589  /*
590  * If we aren't inside a transaction, we cannot do database access so
591  * cannot verify the config name. Must accept it on faith.
592  */
593  if (IsTransactionState())
594  {
595  Oid cfgId;
596  HeapTuple tuple;
597  Form_pg_ts_config cfg;
598  char *buf;
599 
601 
602  /*
603  * When source == PGC_S_TEST, don't throw a hard error for a
604  * nonexistent configuration, only a NOTICE. See comments in guc.h.
605  */
606  if (!OidIsValid(cfgId))
607  {
608  if (source == PGC_S_TEST)
609  {
610  ereport(NOTICE,
611  (errcode(ERRCODE_UNDEFINED_OBJECT),
612  errmsg("text search configuration \"%s\" does not exist", *newval)));
613  return true;
614  }
615  else
616  return false;
617  }
618 
619  /*
620  * Modify the actually stored value to be fully qualified, to ensure
621  * later changes of search_path don't affect it.
622  */
624  if (!HeapTupleIsValid(tuple))
625  elog(ERROR, "cache lookup failed for text search configuration %u",
626  cfgId);
627  cfg = (Form_pg_ts_config) GETSTRUCT(tuple);
628 
629  buf = quote_qualified_identifier(get_namespace_name(cfg->cfgnamespace),
630  NameStr(cfg->cfgname));
631 
632  ReleaseSysCache(tuple);
633 
634  /* GUC wants it malloc'd not palloc'd */
635  free(*newval);
636  *newval = strdup(buf);
637  pfree(buf);
638  if (!*newval)
639  return false;
640  }
641 
642  return true;
643 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
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:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
void pfree(void *pointer)
Definition: mcxt.c:950
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
static char * buf
Definition: pg_test_fsync.c:66
#define ereport(elevel, rest)
Definition: elog.h:122
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:10490
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#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: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:499
#define elog
Definition: elog.h:219
Oid getTSCurrentConfig ( bool  emitError)

Definition at line 556 of file ts_cache.c.

References elog, ERROR, get_ts_config_oid(), init_ts_config_cache(), InvalidOid, NULL, 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().

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

Definition at line 361 of file ts_cache.c.

References CacheMemoryContext, CacheRegisterSyscacheCallback(), CreateCacheMemoryContext(), HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, InvalidateTSCacheCallBack(), HASHCTL::keysize, MemSet, PointerGetDatum, TSCONFIGMAP, and TSCONFIGOID.

Referenced by getTSCurrentConfig(), and lookup_ts_config_cache().

362 {
363  HASHCTL ctl;
364 
365  MemSet(&ctl, 0, sizeof(ctl));
366  ctl.keysize = sizeof(Oid);
367  ctl.entrysize = sizeof(TSConfigCacheEntry);
368  TSConfigCacheHash = hash_create("Tsearch configuration cache", 16,
369  &ctl, HASH_ELEM | HASH_BLOBS);
370  /* Flush cache on pg_ts_config and pg_ts_config_map changes */
375 
376  /* Also make sure CacheMemoryContext exists */
377  if (!CacheMemoryContext)
379 }
#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:857
unsigned int Oid
Definition: postgres_ext.h:31
static void InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: ts_cache.c:93
#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:301
Size keysize
Definition: hsearch.h:72
static HTAB * TSConfigCacheHash
Definition: ts_cache.c:69
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static void InvalidateTSCacheCallBack ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 93 of file ts_cache.c.

References DatumGetPointer, hash(), hash_seq_init(), hash_seq_search(), InvalidOid, TSAnyCacheEntry::isvalid, NULL, status(), and TSCurrentConfigCache.

Referenced by init_ts_config_cache(), lookup_ts_dictionary_cache(), and lookup_ts_parser_cache().

94 {
97  TSAnyCacheEntry *entry;
98 
99  hash_seq_init(&status, hash);
100  while ((entry = (TSAnyCacheEntry *) hash_seq_search(&status)) != NULL)
101  entry->isvalid = false;
102 
103  /* Also invalidate the current-config cache if it's pg_ts_config */
104  if (hash == TSConfigCacheHash)
106 }
static Oid TSCurrentConfigCache
Definition: ts_cache.c:77
Definition: dynahash.c:193
#define InvalidOid
Definition: postgres_ext.h:36
static HTAB * TSConfigCacheHash
Definition: ts_cache.c:69
#define NULL
Definition: c.h:229
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1351
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1341
#define DatumGetPointer(X)
Definition: postgres.h:555
void * arg
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:541
TSConfigCacheEntry* lookup_ts_config_cache ( Oid  cfgId)

Definition at line 385 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, NULL, 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().

386 {
387  TSConfigCacheEntry *entry;
388 
389  if (TSConfigCacheHash == NULL)
390  {
391  /* First time through: initialize the hash table */
393  }
394 
395  /* Check single-entry cache */
396  if (lastUsedConfig && lastUsedConfig->cfgId == cfgId &&
398  return lastUsedConfig;
399 
400  /* Try to look up an existing entry */
402  (void *) &cfgId,
403  HASH_FIND, NULL);
404  if (entry == NULL || !entry->isvalid)
405  {
406  /*
407  * If we didn't find one, we want to make one. But first look up the
408  * object to be sure the OID is real.
409  */
410  HeapTuple tp;
411  Form_pg_ts_config cfg;
412  Relation maprel;
413  Relation mapidx;
414  ScanKeyData mapskey;
415  SysScanDesc mapscan;
416  HeapTuple maptup;
417  ListDictionary maplists[MAXTOKENTYPE + 1];
418  Oid mapdicts[MAXDICTSPERTT];
419  int maxtokentype;
420  int ndicts;
421  int i;
422 
424  if (!HeapTupleIsValid(tp))
425  elog(ERROR, "cache lookup failed for text search configuration %u",
426  cfgId);
427  cfg = (Form_pg_ts_config) GETSTRUCT(tp);
428 
429  /*
430  * Sanity checks
431  */
432  if (!OidIsValid(cfg->cfgparser))
433  elog(ERROR, "text search configuration %u has no parser", cfgId);
434 
435  if (entry == NULL)
436  {
437  bool found;
438 
439  /* Now make the cache entry */
440  entry = (TSConfigCacheEntry *)
442  (void *) &cfgId,
443  HASH_ENTER, &found);
444  Assert(!found); /* it wasn't there a moment ago */
445  }
446  else
447  {
448  /* Cleanup old contents */
449  if (entry->map)
450  {
451  for (i = 0; i < entry->lenmap; i++)
452  if (entry->map[i].dictIds)
453  pfree(entry->map[i].dictIds);
454  pfree(entry->map);
455  }
456  }
457 
458  MemSet(entry, 0, sizeof(TSConfigCacheEntry));
459  entry->cfgId = cfgId;
460  entry->prsId = cfg->cfgparser;
461 
462  ReleaseSysCache(tp);
463 
464  /*
465  * Scan pg_ts_config_map to gather dictionary list for each token type
466  *
467  * Because the index is on (mapcfg, maptokentype, mapseqno), we will
468  * see the entries in maptokentype order, and in mapseqno order for
469  * each token type, even though we didn't explicitly ask for that.
470  */
471  MemSet(maplists, 0, sizeof(maplists));
472  maxtokentype = 0;
473  ndicts = 0;
474 
475  ScanKeyInit(&mapskey,
477  BTEqualStrategyNumber, F_OIDEQ,
478  ObjectIdGetDatum(cfgId));
479 
482  mapscan = systable_beginscan_ordered(maprel, mapidx,
483  NULL, 1, &mapskey);
484 
485  while ((maptup = systable_getnext_ordered(mapscan, ForwardScanDirection)) != NULL)
486  {
488  int toktype = cfgmap->maptokentype;
489 
490  if (toktype <= 0 || toktype > MAXTOKENTYPE)
491  elog(ERROR, "maptokentype value %d is out of range", toktype);
492  if (toktype < maxtokentype)
493  elog(ERROR, "maptokentype entries are out of order");
494  if (toktype > maxtokentype)
495  {
496  /* starting a new token type, but first save the prior data */
497  if (ndicts > 0)
498  {
499  maplists[maxtokentype].len = ndicts;
500  maplists[maxtokentype].dictIds = (Oid *)
502  sizeof(Oid) * ndicts);
503  memcpy(maplists[maxtokentype].dictIds, mapdicts,
504  sizeof(Oid) * ndicts);
505  }
506  maxtokentype = toktype;
507  mapdicts[0] = cfgmap->mapdict;
508  ndicts = 1;
509  }
510  else
511  {
512  /* continuing data for current token type */
513  if (ndicts >= MAXDICTSPERTT)
514  elog(ERROR, "too many pg_ts_config_map entries for one token type");
515  mapdicts[ndicts++] = cfgmap->mapdict;
516  }
517  }
518 
519  systable_endscan_ordered(mapscan);
520  index_close(mapidx, AccessShareLock);
521  heap_close(maprel, AccessShareLock);
522 
523  if (ndicts > 0)
524  {
525  /* save the last token type's dictionaries */
526  maplists[maxtokentype].len = ndicts;
527  maplists[maxtokentype].dictIds = (Oid *)
529  sizeof(Oid) * ndicts);
530  memcpy(maplists[maxtokentype].dictIds, mapdicts,
531  sizeof(Oid) * ndicts);
532  /* and save the overall map */
533  entry->lenmap = maxtokentype + 1;
534  entry->map = (ListDictionary *)
536  sizeof(ListDictionary) * entry->lenmap);
537  memcpy(entry->map, maplists,
538  sizeof(ListDictionary) * entry->lenmap);
539  }
540 
541  entry->isvalid = true;
542  }
543 
544  lastUsedConfig = entry;
545 
546  return entry;
547 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#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:857
#define heap_close(r, l)
Definition: heapam.h:97
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
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:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
void pfree(void *pointer)
Definition: mcxt.c:950
#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
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:614
static void init_ts_config_cache(void)
Definition: ts_cache.c:361
static HTAB * TSConfigCacheHash
Definition: ts_cache.c:69
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
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:707
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
TSDictionaryCacheEntry* lookup_ts_dictionary_cache ( Oid  dictId)

Definition at line 210 of file ts_cache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), 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, MemoryContextResetAndDeleteChildren, MemoryContextSwitchTo(), MemSet, NameStr, NIL, NULL, 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 
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),
300  }
301  else
302  {
303  /* Clear the existing entry's private context */
304  saveCtx = entry->dictCtx;
306  }
307 
308  MemSet(entry, 0, sizeof(TSDictionaryCacheEntry));
309  entry->dictId = dictId;
310  entry->dictCtx = saveCtx;
311 
312  entry->lexizeOid = template->tmpllexize;
313 
314  if (OidIsValid(template->tmplinit))
315  {
316  List *dictoptions;
317  Datum opt;
318  bool isnull;
319  MemoryContext oldcontext;
320 
321  /*
322  * Init method runs in dictionary's private memory context, and we
323  * make sure the options are stored there too
324  */
325  oldcontext = MemoryContextSwitchTo(entry->dictCtx);
326 
327  opt = SysCacheGetAttr(TSDICTOID, tpdict,
329  &isnull);
330  if (isnull)
331  dictoptions = NIL;
332  else
333  dictoptions = deserialize_deflist(opt);
334 
335  entry->dictData =
336  DatumGetPointer(OidFunctionCall1(template->tmplinit,
337  PointerGetDatum(dictoptions)));
338 
339  MemoryContextSwitchTo(oldcontext);
340  }
341 
342  ReleaseSysCache(tptmpl);
343  ReleaseSysCache(tpdict);
344 
345  fmgr_info_cxt(entry->lexizeOid, &entry->lexize, entry->dictCtx);
346 
347  entry->isvalid = true;
348  }
349 
350  lastUsedDictionary = entry;
351 
352  return entry;
353 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define HASH_ELEM
Definition: hsearch.h:87
#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:175
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:857
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:622
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:137
static void InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: ts_cache.c:93
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67
#define HASH_BLOBS
Definition: hsearch.h:88
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
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:301
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
Size keysize
Definition: hsearch.h:72
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define Anum_pg_ts_dict_dictinitoption
Definition: pg_ts_dict.h:56
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
#define DatumGetPointer(X)
Definition: postgres.h:555
FormData_pg_ts_template * Form_pg_ts_template
#define NameStr(name)
Definition: c.h:499
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
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, NULL, 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:656
#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:857
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#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:137
static void InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: ts_cache.c:93
#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:301
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
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 NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
FmgrInfo prstoken
Definition: ts_cache.h:46
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
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

TSConfigCacheEntry* lastUsedConfig = NULL
static

Definition at line 70 of file ts_cache.c.

Referenced by lookup_ts_config_cache().

TSDictionaryCacheEntry* lastUsedDictionary = NULL
static

Definition at line 67 of file ts_cache.c.

Referenced by lookup_ts_dictionary_cache().

TSParserCacheEntry* lastUsedParser = NULL
static

Definition at line 64 of file ts_cache.c.

Referenced by lookup_ts_parser_cache().

HTAB* TSConfigCacheHash = NULL
static

Definition at line 69 of file ts_cache.c.

char* TSCurrentConfig = NULL

Definition at line 75 of file ts_cache.c.

Referenced by getTSCurrentConfig().

Oid TSCurrentConfigCache = InvalidOid
static
HTAB* TSDictionaryCacheHash = NULL
static

Definition at line 66 of file ts_cache.c.

HTAB* TSParserCacheHash = NULL
static

Definition at line 63 of file ts_cache.c.