PostgreSQL Source Code git master
Loading...
Searching...
No Matches
ts_cache.h File Reference
#include "fmgr.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)
 

Variables

PGDLLIMPORT charTSCurrentConfig
 

Typedef Documentation

◆ TSAnyCacheEntry

◆ TSDictionaryCacheEntry

◆ TSParserCacheEntry

Function Documentation

◆ getTSCurrentConfig()

Oid getTSCurrentConfig ( bool  emitError)
extern

Definition at line 559 of file ts_cache.c.

560{
561 List *namelist;
562
563 /* if we have a cached value, return it */
566
567 /* fail if GUC hasn't been set up yet */
568 if (TSCurrentConfig == NULL || *TSCurrentConfig == '\0')
569 {
570 if (emitError)
571 elog(ERROR, "text search configuration isn't set");
572 else
573 return InvalidOid;
574 }
575
576 if (TSConfigCacheHash == NULL)
577 {
578 /* First time through: initialize the tsconfig inval callback */
580 }
581
582 /* Look up the config */
583 if (emitError)
584 {
587 }
588 else
589 {
591
593 (Node *) &escontext);
594 if (namelist != NIL)
596 else
597 TSCurrentConfigCache = InvalidOid; /* bad name list syntax */
598 }
599
601}
#define OidIsValid(objectId)
Definition c.h:858
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition namespace.c:3224
#define NIL
Definition pg_list.h:68
#define InvalidOid
static int fb(int x)
List * stringToQualifiedNameList(const char *string, Node *escontext)
Definition regproc.c:1922
Definition pg_list.h:54
Definition nodes.h:135
static void init_ts_config_cache(void)
Definition ts_cache.c:365
static HTAB * TSConfigCacheHash
Definition ts_cache.c:71
char * TSCurrentConfig
Definition ts_cache.c:77
static Oid TSCurrentConfigCache
Definition ts_cache.c:79

References elog, ERROR, fb(), get_ts_config_oid(), init_ts_config_cache(), InvalidOid, NIL, OidIsValid, stringToQualifiedNameList(), TSConfigCacheHash, 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().

◆ lookup_ts_config_cache()

TSConfigCacheEntry * lookup_ts_config_cache ( Oid  cfgId)
extern

Definition at line 388 of file ts_cache.c.

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 &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;
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 &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
481 ObjectIdGetDatum(cfgId));
482
486 NULL, 1, &mapskey);
487
489 {
491 int toktype = cfgmap->maptokentype;
492
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);
507 sizeof(Oid) * ndicts);
508 }
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
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);
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}
#define Assert(condition)
Definition c.h:943
#define MemSet(start, val, len)
Definition c.h:1107
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:889
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:659
void systable_endscan_ordered(SysScanDesc sysscan)
Definition genam.c:767
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition genam.c:742
@ HASH_FIND
Definition hsearch.h:108
@ HASH_ENTER
Definition hsearch.h:109
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:178
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:134
int i
Definition isn.c:77
#define AccessShareLock
Definition lockdefs.h:36
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
void pfree(void *pointer)
Definition mcxt.c:1616
MemoryContext CacheMemoryContext
Definition mcxt.c:169
END_CATALOG_STRUCT typedef FormData_pg_ts_config * Form_pg_ts_config
END_CATALOG_STRUCT typedef FormData_pg_ts_config_map * Form_pg_ts_config_map
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
unsigned int Oid
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
@ ForwardScanDirection
Definition sdir.h:28
#define BTEqualStrategyNumber
Definition stratnum.h:31
Oid * dictIds
Definition ts_cache.h:68
ListDictionary * map
Definition ts_cache.h:80
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
#define MAXTOKENTYPE
Definition ts_cache.c:61
#define MAXDICTSPERTT
Definition ts_cache.c:62
static TSConfigCacheEntry * lastUsedConfig
Definition ts_cache.c:72

References AccessShareLock, Assert, BTEqualStrategyNumber, CacheMemoryContext, TSConfigCacheEntry::cfgId, ListDictionary::dictIds, elog, ERROR, fb(), Form_pg_ts_config, Form_pg_ts_config_map, ForwardScanDirection, GETSTRUCT(), HASH_ENTER, HASH_FIND, hash_search(), HeapTupleIsValid, i, index_close(), index_open(), init_ts_config_cache(), TSConfigCacheEntry::isvalid, lastUsedConfig, TSConfigCacheEntry::lenmap, TSConfigCacheEntry::map, MAXDICTSPERTT, MAXTOKENTYPE, memcpy(), MemoryContextAlloc(), MemSet, ObjectIdGetDatum(), OidIsValid, pfree(), TSConfigCacheEntry::prsId, ReleaseSysCache(), ScanKeyInit(), SearchSysCache1(), systable_beginscan_ordered(), systable_endscan_ordered(), systable_getnext_ordered(), table_close(), table_open(), and TSConfigCacheHash.

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

◆ lookup_ts_dictionary_cache()

TSDictionaryCacheEntry * lookup_ts_dictionary_cache ( Oid  dictId)
extern

Definition at line 209 of file ts_cache.c.

210{
212
214 {
215 /* First time through: initialize the hash table */
216 HASHCTL ctl;
217
218 ctl.keysize = sizeof(Oid);
219 ctl.entrysize = sizeof(TSDictionaryCacheEntry);
220 TSDictionaryCacheHash = hash_create("Tsearch dictionary cache", 8,
222 /* Flush cache on pg_ts_dict and pg_ts_template changes */
227
228 /* Also make sure CacheMemoryContext exists */
231 }
232
233 /* Check single-entry cache */
234 if (lastUsedDictionary && lastUsedDictionary->dictId == dictId &&
236 return lastUsedDictionary;
237
238 /* Try to look up an existing entry */
240 &dictId,
241 HASH_FIND, NULL);
242 if (entry == NULL || !entry->isvalid)
243 {
244 /*
245 * If we didn't find one, we want to make one. But first look up the
246 * object to be sure the OID is real.
247 */
249 tptmpl;
251 Form_pg_ts_template template;
253
256 elog(ERROR, "cache lookup failed for text search dictionary %u",
257 dictId);
259
260 /*
261 * Sanity checks
262 */
263 if (!OidIsValid(dict->dicttemplate))
264 elog(ERROR, "text search dictionary %u has no template", dictId);
265
266 /*
267 * Retrieve dictionary's template
268 */
270 ObjectIdGetDatum(dict->dicttemplate));
272 elog(ERROR, "cache lookup failed for text search template %u",
273 dict->dicttemplate);
275
276 /*
277 * Sanity checks
278 */
279 if (!OidIsValid(template->tmpllexize))
280 elog(ERROR, "text search template %u has no lexize method",
281 template->tmpllexize);
282
283 if (entry == NULL)
284 {
285 bool found;
286
287 /* Now make the cache entry */
288 entry = (TSDictionaryCacheEntry *)
290 &dictId,
291 HASH_ENTER, &found);
292 Assert(!found); /* it wasn't there a moment ago */
293
294 /* Create private memory context the first time through */
296 "TS dictionary",
299 }
300 else
301 {
302 /* Clear the existing entry's private context */
303 saveCtx = entry->dictCtx;
304 /* Don't let context's ident pointer dangle while we reset it */
308 }
309
310 MemSet(entry, 0, sizeof(TSDictionaryCacheEntry));
311 entry->dictId = dictId;
312 entry->dictCtx = saveCtx;
313
314 entry->lexizeOid = template->tmpllexize;
315
316 if (OidIsValid(template->tmplinit))
317 {
319 Datum opt;
320 bool isnull;
321 MemoryContext oldcontext;
322
323 /*
324 * Init method runs in dictionary's private memory context, and we
325 * make sure the options are stored there too. This typically
326 * results in a small amount of memory leakage, but it's not worth
327 * complicating the API for tmplinit functions to avoid it.
328 */
329 oldcontext = MemoryContextSwitchTo(entry->dictCtx);
330
333 &isnull);
334 if (isnull)
336 else
338
339 entry->dictData =
342
343 MemoryContextSwitchTo(oldcontext);
344 }
345
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 NameStr(name)
Definition c.h:835
void CreateCacheMemoryContext(void)
Definition catcache.c:715
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:360
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition fmgr.c:139
#define OidFunctionCall1(functionId, arg1)
Definition fmgr.h:722
#define HASH_ELEM
Definition hsearch.h:90
#define HASH_BLOBS
Definition hsearch.h:92
void CacheRegisterSyscacheCallback(SysCacheIdentifier cacheid, SyscacheCallbackFunction func, Datum arg)
Definition inval.c:1816
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition mcxt.c:661
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition memutils.h:170
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition memutils.h:101
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
END_CATALOG_STRUCT typedef FormData_pg_ts_dict * Form_pg_ts_dict
Definition pg_ts_dict.h:56
END_CATALOG_STRUCT typedef FormData_pg_ts_template * Form_pg_ts_template
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
tree ctl
Definition radixtree.h:1838
Size keysize
Definition hsearch.h:69
MemoryContext dictCtx
Definition ts_cache.h:61
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596
static TSDictionaryCacheEntry * lastUsedDictionary
Definition ts_cache.c:69
static HTAB * TSDictionaryCacheHash
Definition ts_cache.c:68
static void InvalidateTSCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
Definition ts_cache.c:95
List * deserialize_deflist(Datum txt)

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, CacheMemoryContext, CacheRegisterSyscacheCallback(), CreateCacheMemoryContext(), ctl, DatumGetPointer(), deserialize_deflist(), TSDictionaryCacheEntry::dictCtx, TSDictionaryCacheEntry::dictData, TSDictionaryCacheEntry::dictId, elog, ERROR, fb(), fmgr_info_cxt(), Form_pg_ts_dict, Form_pg_ts_template, 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(), and TSDictionaryCacheHash.

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

◆ lookup_ts_parser_cache()

TSParserCacheEntry * lookup_ts_parser_cache ( Oid  prsId)
extern

Definition at line 114 of file ts_cache.c.

115{
116 TSParserCacheEntry *entry;
117
118 if (TSParserCacheHash == NULL)
119 {
120 /* First time through: initialize the hash table */
121 HASHCTL ctl;
122
123 ctl.keysize = sizeof(Oid);
124 ctl.entrysize = sizeof(TSParserCacheEntry);
125 TSParserCacheHash = hash_create("Tsearch parser cache", 4,
127 /* Flush cache on pg_ts_parser changes */
130
131 /* Also make sure CacheMemoryContext exists */
134 }
135
136 /* Check single-entry cache */
137 if (lastUsedParser && lastUsedParser->prsId == prsId &&
139 return lastUsedParser;
140
141 /* Try to look up an existing entry */
143 &prsId,
144 HASH_FIND, NULL);
145 if (entry == NULL || !entry->isvalid)
146 {
147 /*
148 * If we didn't find one, we want to make one. But first look up the
149 * object to be sure the OID is real.
150 */
151 HeapTuple tp;
153
155 if (!HeapTupleIsValid(tp))
156 elog(ERROR, "cache lookup failed for text search parser %u",
157 prsId);
158 prs = (Form_pg_ts_parser) GETSTRUCT(tp);
159
160 /*
161 * Sanity checks
162 */
163 if (!OidIsValid(prs->prsstart))
164 elog(ERROR, "text search parser %u has no prsstart method", prsId);
165 if (!OidIsValid(prs->prstoken))
166 elog(ERROR, "text search parser %u has no prstoken method", prsId);
167 if (!OidIsValid(prs->prsend))
168 elog(ERROR, "text search parser %u has no prsend method", prsId);
169
170 if (entry == NULL)
171 {
172 bool found;
173
174 /* Now make the cache entry */
175 entry = (TSParserCacheEntry *)
176 hash_search(TSParserCacheHash, &prsId, 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
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}
END_CATALOG_STRUCT typedef FormData_pg_ts_parser * Form_pg_ts_parser
FmgrInfo prstoken
Definition ts_cache.h:46
FmgrInfo prsstart
Definition ts_cache.h:45
FmgrInfo prsheadline
Definition ts_cache.h:48
FmgrInfo prsend
Definition ts_cache.h:47
static TSParserCacheEntry * lastUsedParser
Definition ts_cache.c:66
static HTAB * TSParserCacheHash
Definition ts_cache.c:65

References Assert, CacheMemoryContext, CacheRegisterSyscacheCallback(), CreateCacheMemoryContext(), ctl, elog, TSParserCacheEntry::endOid, ERROR, fb(), fmgr_info_cxt(), Form_pg_ts_parser, 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 TSParserCacheHash.

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

Variable Documentation

◆ TSCurrentConfig

PGDLLIMPORT char* TSCurrentConfig
extern

Definition at line 77 of file ts_cache.c.

Referenced by getTSCurrentConfig().