#include "utils/guc.h"
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 | |
TSParserCacheEntry * | lookup_ts_parser_cache (Oid prsId) |
TSDictionaryCacheEntry * | lookup_ts_dictionary_cache (Oid dictId) |
TSConfigCacheEntry * | lookup_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 struct TSAnyCacheEntry TSAnyCacheEntry |
typedef struct TSDictionaryCacheEntry TSDictionaryCacheEntry |
typedef struct TSParserCacheEntry TSParserCacheEntry |
void assign_TSCurrentConfig | ( | const char * | newval, | |
void * | extra | |||
) |
Definition at line 654 of file ts_cache.c.
References TSCurrentConfigCache.
{ /* Just reset the cache to force a lookup on first use */ TSCurrentConfigCache = InvalidOid; }
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(), TSCONFIGOID, and catclist::tuple.
{ /* * If we aren't inside a transaction, we cannot do database access so * cannot verify the config name. Must accept it on faith. */ if (IsTransactionState()) { Oid cfgId; HeapTuple tuple; Form_pg_ts_config cfg; char *buf; cfgId = get_ts_config_oid(stringToQualifiedNameList(*newval), true); /* * When source == PGC_S_TEST, we are checking the argument of an ALTER * DATABASE SET or ALTER USER SET command. It could be that the * intended use of the setting is for some other database, so we * should not error out if the text search configuration is not * present in the current database. We issue a NOTICE instead. */ if (!OidIsValid(cfgId)) { if (source == PGC_S_TEST) { ereport(NOTICE, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("text search configuration \"%s\" does not exist", *newval))); return true; } else return false; } /* * Modify the actually stored value to be fully qualified, to ensure * later changes of search_path don't affect it. */ tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgId)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for text search configuration %u", cfgId); cfg = (Form_pg_ts_config) GETSTRUCT(tuple); buf = quote_qualified_identifier(get_namespace_name(cfg->cfgnamespace), NameStr(cfg->cfgname)); ReleaseSysCache(tuple); /* GUC wants it malloc'd not palloc'd */ free(*newval); *newval = strdup(buf); pfree(buf); if (!*newval) return false; } return true; }
Definition at line 560 of file ts_cache.c.
References elog, ERROR, get_ts_config_oid(), init_ts_config_cache(), NULL, OidIsValid, stringToQualifiedNameList(), TSCurrentConfig, and TSCurrentConfigCache.
Referenced by get_current_ts_config(), plainto_tsquery(), to_tsquery(), to_tsvector(), ts_headline(), and ts_headline_opt().
{ /* if we have a cached value, return it */ if (OidIsValid(TSCurrentConfigCache)) return TSCurrentConfigCache; /* fail if GUC hasn't been set up yet */ if (TSCurrentConfig == NULL || *TSCurrentConfig == '\0') { if (emitError) elog(ERROR, "text search configuration isn't set"); else return InvalidOid; } if (TSConfigCacheHash == NULL) { /* First time through: initialize the tsconfig inval callback */ init_ts_config_cache(); } /* Look up the config */ TSCurrentConfigCache = get_ts_config_oid(stringToQualifiedNameList(TSCurrentConfig), !emitError); return TSCurrentConfigCache; }
TSConfigCacheEntry* lookup_ts_config_cache | ( | Oid | cfgId | ) |
Definition at line 389 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_search(), heap_close, heap_open(), HeapTupleIsValid, i, index_close(), index_open(), init_ts_config_cache(), TSConfigCacheEntry::isvalid, ListDictionary::len, TSConfigCacheEntry::lenmap, TSConfigCacheEntry::map, MAXDICTSPERTT, MAXTOKENTYPE, MemoryContextAlloc(), MemSet, NULL, ObjectIdGetDatum, OidIsValid, pfree(), TSConfigCacheEntry::prsId, ReleaseSysCache(), ScanKeyInit(), SearchSysCache1, SnapshotNow, systable_beginscan_ordered(), systable_endscan_ordered(), systable_getnext_ordered(), TSConfigMapIndexId, TSConfigMapRelationId, and TSCONFIGOID.
Referenced by hlparsetext(), parsetext(), and ts_headline_byid_opt().
{ TSConfigCacheEntry *entry; if (TSConfigCacheHash == NULL) { /* First time through: initialize the hash table */ init_ts_config_cache(); } /* Check single-entry cache */ if (lastUsedConfig && lastUsedConfig->cfgId == cfgId && lastUsedConfig->isvalid) return lastUsedConfig; /* Try to look up an existing entry */ entry = (TSConfigCacheEntry *) hash_search(TSConfigCacheHash, (void *) &cfgId, HASH_FIND, NULL); if (entry == NULL || !entry->isvalid) { /* * If we didn't find one, we want to make one. But first look up the * object to be sure the OID is real. */ HeapTuple tp; Form_pg_ts_config cfg; Relation maprel; Relation mapidx; ScanKeyData mapskey; SysScanDesc mapscan; HeapTuple maptup; ListDictionary maplists[MAXTOKENTYPE + 1]; Oid mapdicts[MAXDICTSPERTT]; int maxtokentype; int ndicts; int i; tp = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgId)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for text search configuration %u", cfgId); cfg = (Form_pg_ts_config) GETSTRUCT(tp); /* * Sanity checks */ if (!OidIsValid(cfg->cfgparser)) elog(ERROR, "text search configuration %u has no parser", cfgId); if (entry == NULL) { bool found; /* Now make the cache entry */ entry = (TSConfigCacheEntry *) hash_search(TSConfigCacheHash, (void *) &cfgId, HASH_ENTER, &found); Assert(!found); /* it wasn't there a moment ago */ } else { /* Cleanup old contents */ if (entry->map) { for (i = 0; i < entry->lenmap; i++) if (entry->map[i].dictIds) pfree(entry->map[i].dictIds); pfree(entry->map); } } MemSet(entry, 0, sizeof(TSConfigCacheEntry)); entry->cfgId = cfgId; entry->prsId = cfg->cfgparser; ReleaseSysCache(tp); /* * Scan pg_ts_config_map to gather dictionary list for each token type * * Because the index is on (mapcfg, maptokentype, mapseqno), we will * see the entries in maptokentype order, and in mapseqno order for * each token type, even though we didn't explicitly ask for that. */ MemSet(maplists, 0, sizeof(maplists)); maxtokentype = 0; ndicts = 0; ScanKeyInit(&mapskey, Anum_pg_ts_config_map_mapcfg, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(cfgId)); maprel = heap_open(TSConfigMapRelationId, AccessShareLock); mapidx = index_open(TSConfigMapIndexId, AccessShareLock); mapscan = systable_beginscan_ordered(maprel, mapidx, SnapshotNow, 1, &mapskey); while ((maptup = systable_getnext_ordered(mapscan, ForwardScanDirection)) != NULL) { Form_pg_ts_config_map cfgmap = (Form_pg_ts_config_map) GETSTRUCT(maptup); int toktype = cfgmap->maptokentype; if (toktype <= 0 || toktype > MAXTOKENTYPE) elog(ERROR, "maptokentype value %d is out of range", toktype); if (toktype < maxtokentype) elog(ERROR, "maptokentype entries are out of order"); if (toktype > maxtokentype) { /* starting a new token type, but first save the prior data */ if (ndicts > 0) { maplists[maxtokentype].len = ndicts; maplists[maxtokentype].dictIds = (Oid *) MemoryContextAlloc(CacheMemoryContext, sizeof(Oid) * ndicts); memcpy(maplists[maxtokentype].dictIds, mapdicts, sizeof(Oid) * ndicts); } maxtokentype = toktype; mapdicts[0] = cfgmap->mapdict; ndicts = 1; } else { /* continuing data for current token type */ if (ndicts >= MAXDICTSPERTT) elog(ERROR, "too many pg_ts_config_map entries for one token type"); mapdicts[ndicts++] = cfgmap->mapdict; } } systable_endscan_ordered(mapscan); index_close(mapidx, AccessShareLock); heap_close(maprel, AccessShareLock); if (ndicts > 0) { /* save the last token type's dictionaries */ maplists[maxtokentype].len = ndicts; maplists[maxtokentype].dictIds = (Oid *) MemoryContextAlloc(CacheMemoryContext, sizeof(Oid) * ndicts); memcpy(maplists[maxtokentype].dictIds, mapdicts, sizeof(Oid) * ndicts); /* and save the overall map */ entry->lenmap = maxtokentype + 1; entry->map = (ListDictionary *) MemoryContextAlloc(CacheMemoryContext, sizeof(ListDictionary) * entry->lenmap); memcpy(entry->map, maplists, sizeof(ListDictionary) * entry->lenmap); } entry->isvalid = true; } lastUsedConfig = entry; return entry; }
TSDictionaryCacheEntry* lookup_ts_dictionary_cache | ( | Oid | dictId | ) |
Definition at line 210 of file ts_cache.c.
References ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE, ALLOCSET_SMALL_MINSIZE, 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, HASHCTL::hash, hash_create(), HASH_ELEM, HASH_FUNCTION, hash_search(), HeapTupleIsValid, InvalidateTSCacheCallBack(), TSDictionaryCacheEntry::isvalid, HASHCTL::keysize, TSDictionaryCacheEntry::lexize, TSDictionaryCacheEntry::lexizeOid, MemoryContextResetAndDeleteChildren(), MemoryContextSwitchTo(), MemSet, NameStr, NULL, ObjectIdGetDatum, OidFunctionCall1, OidIsValid, PointerGetDatum, ReleaseSysCache(), SearchSysCache1, SysCacheGetAttr(), TSDICTOID, and TSTEMPLATEOID.
Referenced by LexizeExec(), thesaurus_init(), thesaurus_lexize(), ts_lexize(), and unaccent_dict().
{ TSDictionaryCacheEntry *entry; if (TSDictionaryCacheHash == NULL) { /* First time through: initialize the hash table */ HASHCTL ctl; MemSet(&ctl, 0, sizeof(ctl)); ctl.keysize = sizeof(Oid); ctl.entrysize = sizeof(TSDictionaryCacheEntry); ctl.hash = oid_hash; TSDictionaryCacheHash = hash_create("Tsearch dictionary cache", 8, &ctl, HASH_ELEM | HASH_FUNCTION); /* Flush cache on pg_ts_dict and pg_ts_template changes */ CacheRegisterSyscacheCallback(TSDICTOID, InvalidateTSCacheCallBack, PointerGetDatum(TSDictionaryCacheHash)); CacheRegisterSyscacheCallback(TSTEMPLATEOID, InvalidateTSCacheCallBack, PointerGetDatum(TSDictionaryCacheHash)); /* Also make sure CacheMemoryContext exists */ if (!CacheMemoryContext) CreateCacheMemoryContext(); } /* Check single-entry cache */ if (lastUsedDictionary && lastUsedDictionary->dictId == dictId && lastUsedDictionary->isvalid) return lastUsedDictionary; /* Try to look up an existing entry */ entry = (TSDictionaryCacheEntry *) hash_search(TSDictionaryCacheHash, (void *) &dictId, HASH_FIND, NULL); if (entry == NULL || !entry->isvalid) { /* * If we didn't find one, we want to make one. But first look up the * object to be sure the OID is real. */ HeapTuple tpdict, tptmpl; Form_pg_ts_dict dict; Form_pg_ts_template template; MemoryContext saveCtx; tpdict = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId)); if (!HeapTupleIsValid(tpdict)) elog(ERROR, "cache lookup failed for text search dictionary %u", dictId); dict = (Form_pg_ts_dict) GETSTRUCT(tpdict); /* * Sanity checks */ if (!OidIsValid(dict->dicttemplate)) elog(ERROR, "text search dictionary %u has no template", dictId); /* * Retrieve dictionary's template */ tptmpl = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(dict->dicttemplate)); if (!HeapTupleIsValid(tptmpl)) elog(ERROR, "cache lookup failed for text search template %u", dict->dicttemplate); template = (Form_pg_ts_template) GETSTRUCT(tptmpl); /* * Sanity checks */ if (!OidIsValid(template->tmpllexize)) elog(ERROR, "text search template %u has no lexize method", template->tmpllexize); if (entry == NULL) { bool found; /* Now make the cache entry */ entry = (TSDictionaryCacheEntry *) hash_search(TSDictionaryCacheHash, (void *) &dictId, HASH_ENTER, &found); Assert(!found); /* it wasn't there a moment ago */ /* Create private memory context the first time through */ saveCtx = AllocSetContextCreate(CacheMemoryContext, NameStr(dict->dictname), ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE); } else { /* Clear the existing entry's private context */ saveCtx = entry->dictCtx; MemoryContextResetAndDeleteChildren(saveCtx); } MemSet(entry, 0, sizeof(TSDictionaryCacheEntry)); entry->dictId = dictId; entry->dictCtx = saveCtx; entry->lexizeOid = template->tmpllexize; if (OidIsValid(template->tmplinit)) { List *dictoptions; Datum opt; bool isnull; MemoryContext oldcontext; /* * Init method runs in dictionary's private memory context, and we * make sure the options are stored there too */ oldcontext = MemoryContextSwitchTo(entry->dictCtx); opt = SysCacheGetAttr(TSDICTOID, tpdict, Anum_pg_ts_dict_dictinitoption, &isnull); if (isnull) dictoptions = NIL; else dictoptions = deserialize_deflist(opt); entry->dictData = DatumGetPointer(OidFunctionCall1(template->tmplinit, PointerGetDatum(dictoptions))); MemoryContextSwitchTo(oldcontext); } ReleaseSysCache(tptmpl); ReleaseSysCache(tpdict); fmgr_info_cxt(entry->lexizeOid, &entry->lexize, entry->dictCtx); entry->isvalid = true; } lastUsedDictionary = entry; return entry; }
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, HASHCTL::hash, hash_create(), HASH_ELEM, HASH_FUNCTION, hash_search(), TSParserCacheEntry::headlineOid, HeapTupleIsValid, InvalidateTSCacheCallBack(), TSParserCacheEntry::isvalid, HASHCTL::keysize, 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(), and tt_setup_firstcall().
{ TSParserCacheEntry *entry; if (TSParserCacheHash == NULL) { /* First time through: initialize the hash table */ HASHCTL ctl; MemSet(&ctl, 0, sizeof(ctl)); ctl.keysize = sizeof(Oid); ctl.entrysize = sizeof(TSParserCacheEntry); ctl.hash = oid_hash; TSParserCacheHash = hash_create("Tsearch parser cache", 4, &ctl, HASH_ELEM | HASH_FUNCTION); /* Flush cache on pg_ts_parser changes */ CacheRegisterSyscacheCallback(TSPARSEROID, InvalidateTSCacheCallBack, PointerGetDatum(TSParserCacheHash)); /* Also make sure CacheMemoryContext exists */ if (!CacheMemoryContext) CreateCacheMemoryContext(); } /* Check single-entry cache */ if (lastUsedParser && lastUsedParser->prsId == prsId && lastUsedParser->isvalid) return lastUsedParser; /* Try to look up an existing entry */ entry = (TSParserCacheEntry *) hash_search(TSParserCacheHash, (void *) &prsId, HASH_FIND, NULL); if (entry == NULL || !entry->isvalid) { /* * If we didn't find one, we want to make one. But first look up the * object to be sure the OID is real. */ HeapTuple tp; Form_pg_ts_parser prs; tp = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(prsId)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for text search parser %u", prsId); prs = (Form_pg_ts_parser) GETSTRUCT(tp); /* * Sanity checks */ if (!OidIsValid(prs->prsstart)) elog(ERROR, "text search parser %u has no prsstart method", prsId); if (!OidIsValid(prs->prstoken)) elog(ERROR, "text search parser %u has no prstoken method", prsId); if (!OidIsValid(prs->prsend)) elog(ERROR, "text search parser %u has no prsend method", prsId); if (entry == NULL) { bool found; /* Now make the cache entry */ entry = (TSParserCacheEntry *) hash_search(TSParserCacheHash, (void *) &prsId, HASH_ENTER, &found); Assert(!found); /* it wasn't there a moment ago */ } MemSet(entry, 0, sizeof(TSParserCacheEntry)); entry->prsId = prsId; entry->startOid = prs->prsstart; entry->tokenOid = prs->prstoken; entry->endOid = prs->prsend; entry->headlineOid = prs->prsheadline; entry->lextypeOid = prs->prslextype; ReleaseSysCache(tp); fmgr_info_cxt(entry->startOid, &entry->prsstart, CacheMemoryContext); fmgr_info_cxt(entry->tokenOid, &entry->prstoken, CacheMemoryContext); fmgr_info_cxt(entry->endOid, &entry->prsend, CacheMemoryContext); if (OidIsValid(entry->headlineOid)) fmgr_info_cxt(entry->headlineOid, &entry->prsheadline, CacheMemoryContext); entry->isvalid = true; } lastUsedParser = entry; return entry; }
char* TSCurrentConfig |
Definition at line 74 of file ts_cache.c.
Referenced by getTSCurrentConfig().