Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions | Variables

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/syscache.h"
#include "utils/tqual.h"
Include dependency graph for ts_cache.c:

Go to the source code of this file.

Defines

#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

Define Documentation

#define MAXDICTSPERTT   100

Definition at line 59 of file ts_cache.c.

Referenced by lookup_ts_config_cache().

#define MAXTOKENTYPE   256

Definition at line 58 of file ts_cache.c.

Referenced by lookup_ts_config_cache().


Function Documentation

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;
}

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

Definition at line 591 of file ts_cache.c.

References buf, elog, ereport, errcode(), errmsg(), ERROR, free, get_namespace_name(), get_ts_config_oid(), GETSTRUCT, HeapTupleIsValid, IsTransactionState(), NameStr, NOTICE, ObjectIdGetDatum, OidIsValid, pfree(), PGC_S_TEST, quote_qualified_identifier(), ReleaseSysCache(), SearchSysCache1, stringToQualifiedNameList(), 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;
}

Oid getTSCurrentConfig ( bool  emitError  ) 

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;
}

static void init_ts_config_cache ( void   )  [static]
static void InvalidateTSCacheCallBack ( Datum  arg,
int  cacheid,
uint32  hashvalue 
) [static]

Definition at line 92 of file ts_cache.c.

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

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

{
    HTAB       *hash = (HTAB *) DatumGetPointer(arg);
    HASH_SEQ_STATUS status;
    TSAnyCacheEntry *entry;

    hash_seq_init(&status, hash);
    while ((entry = (TSAnyCacheEntry *) hash_seq_search(&status)) != NULL)
        entry->isvalid = false;

    /* Also invalidate the current-config cache if it's pg_ts_config */
    if (hash == TSConfigCacheHash)
        TSCurrentConfigCache = InvalidOid;
}

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;
}


Variable Documentation

Definition at line 69 of file ts_cache.c.

Definition at line 66 of file ts_cache.c.

Definition at line 63 of file ts_cache.c.

HTAB* TSConfigCacheHash = NULL [static]

Definition at line 68 of file ts_cache.c.

char* TSCurrentConfig = NULL

Definition at line 74 of file ts_cache.c.

Referenced by getTSCurrentConfig().

Oid TSCurrentConfigCache = InvalidOid [static]
HTAB* TSDictionaryCacheHash = NULL [static]

Definition at line 65 of file ts_cache.c.

HTAB* TSParserCacheHash = NULL [static]

Definition at line 62 of file ts_cache.c.