Header And Logo

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

Data Structures | Defines | Typedefs | Functions

ts_utils.h File Reference

#include "tsearch/ts_type.h"
#include "tsearch/ts_public.h"
#include "nodes/pg_list.h"
Include dependency graph for ts_utils.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ParsedWord
struct  ParsedText
struct  QTNode

Defines

#define TSearchStrategyNumber   1
#define TSearchWithClassStrategyNumber   2
#define QTN_NEEDFREE   0x01
#define QTN_NOCHANGE   0x02
#define QTN_WORDFREE   0x04
#define TSQS_SIGLEN   (sizeof(TSQuerySign)*BITS_PER_BYTE)
#define TSQuerySignGetDatum(X)   Int64GetDatum((int64) (X))
#define DatumGetTSQuerySign(X)   ((TSQuerySign) DatumGetInt64(X))
#define PG_RETURN_TSQUERYSIGN(X)   return TSQuerySignGetDatum(X)
#define PG_GETARG_TSQUERYSIGN(n)   DatumGetTSQuerySign(PG_GETARG_DATUM(n))

Typedefs

typedef struct
TSVectorParseStateData
TSVectorParseState
typedef struct
TSQueryParserStateData
TSQueryParserState
typedef void(* PushFunction )(Datum opaque, TSQueryParserState state, char *token, int tokenlen, int16 tokenweights, bool prefix)
typedef struct QTNode QTNode
typedef uint64 TSQuerySign

Functions

TSVectorParseState init_tsvector_parser (char *input, bool oprisdelim, bool is_tsquery)
void reset_tsvector_parser (TSVectorParseState state, char *input)
bool gettoken_tsvector (TSVectorParseState state, char **token, int *len, WordEntryPos **pos, int *poslen, char **endptr)
void close_tsvector_parser (TSVectorParseState state)
TSQuery parse_tsquery (char *buf, PushFunction pushval, Datum opaque, bool isplain)
void pushValue (TSQueryParserState state, char *strval, int lenval, int16 weight, bool prefix)
void pushStop (TSQueryParserState state)
void pushOperator (TSQueryParserState state, int8 oper)
void parsetext (Oid cfgId, ParsedText *prs, char *buf, int32 buflen)
void hlparsetext (Oid cfgId, HeadlineParsedText *prs, TSQuery query, char *buf, int32 buflen)
textgenerateHeadline (HeadlineParsedText *prs)
bool TS_execute (QueryItem *curitem, void *checkval, bool calcnot, bool(*chkcond)(void *checkval, QueryOperand *val))
bool tsquery_requires_match (QueryItem *curitem)
TSVector make_tsvector (ParsedText *prs)
int32 tsCompareString (char *a, int lena, char *b, int lenb, bool prefix)
Datum to_tsvector_byid (PG_FUNCTION_ARGS)
Datum to_tsvector (PG_FUNCTION_ARGS)
Datum to_tsquery_byid (PG_FUNCTION_ARGS)
Datum to_tsquery (PG_FUNCTION_ARGS)
Datum plainto_tsquery_byid (PG_FUNCTION_ARGS)
Datum plainto_tsquery (PG_FUNCTION_ARGS)
Datum gtsvector_compress (PG_FUNCTION_ARGS)
Datum gtsvector_decompress (PG_FUNCTION_ARGS)
Datum gtsvector_consistent (PG_FUNCTION_ARGS)
Datum gtsvector_union (PG_FUNCTION_ARGS)
Datum gtsvector_same (PG_FUNCTION_ARGS)
Datum gtsvector_penalty (PG_FUNCTION_ARGS)
Datum gtsvector_picksplit (PG_FUNCTION_ARGS)
Datum gtsvectorin (PG_FUNCTION_ARGS)
Datum gtsvectorout (PG_FUNCTION_ARGS)
Datum gin_extract_tsvector (PG_FUNCTION_ARGS)
Datum gin_cmp_tslexeme (PG_FUNCTION_ARGS)
Datum gin_cmp_prefix (PG_FUNCTION_ARGS)
Datum gin_extract_tsquery (PG_FUNCTION_ARGS)
Datum gin_tsquery_consistent (PG_FUNCTION_ARGS)
Datum gin_extract_tsvector_2args (PG_FUNCTION_ARGS)
Datum gin_extract_tsquery_5args (PG_FUNCTION_ARGS)
Datum gin_tsquery_consistent_6args (PG_FUNCTION_ARGS)
QueryItemclean_NOT (QueryItem *ptr, int32 *len)
QueryItemclean_fakeval (QueryItem *ptr, int32 *len)
QTNodeQT2QTN (QueryItem *in, char *operand)
TSQuery QTN2QT (QTNode *in)
void QTNFree (QTNode *in)
void QTNSort (QTNode *in)
void QTNTernary (QTNode *in)
void QTNBinary (QTNode *in)
int QTNodeCompare (QTNode *an, QTNode *bn)
QTNodeQTNCopy (QTNode *in)
void QTNClearFlags (QTNode *in, uint32 flags)
bool QTNEq (QTNode *a, QTNode *b)
TSQuerySign makeTSQuerySign (TSQuery a)
QTNodefindsubquery (QTNode *root, QTNode *ex, QTNode *subs, bool *isfind)
Datum gtsquery_compress (PG_FUNCTION_ARGS)
Datum gtsquery_decompress (PG_FUNCTION_ARGS)
Datum gtsquery_consistent (PG_FUNCTION_ARGS)
Datum gtsquery_union (PG_FUNCTION_ARGS)
Datum gtsquery_same (PG_FUNCTION_ARGS)
Datum gtsquery_penalty (PG_FUNCTION_ARGS)
Datum gtsquery_picksplit (PG_FUNCTION_ARGS)
Datum ts_token_type_byid (PG_FUNCTION_ARGS)
Datum ts_token_type_byname (PG_FUNCTION_ARGS)
Datum ts_parse_byid (PG_FUNCTION_ARGS)
Datum ts_parse_byname (PG_FUNCTION_ARGS)
Datum prsd_start (PG_FUNCTION_ARGS)
Datum prsd_nexttoken (PG_FUNCTION_ARGS)
Datum prsd_end (PG_FUNCTION_ARGS)
Datum prsd_headline (PG_FUNCTION_ARGS)
Datum prsd_lextype (PG_FUNCTION_ARGS)
Datum ts_lexize (PG_FUNCTION_ARGS)
Datum dsimple_init (PG_FUNCTION_ARGS)
Datum dsimple_lexize (PG_FUNCTION_ARGS)
Datum dsynonym_init (PG_FUNCTION_ARGS)
Datum dsynonym_lexize (PG_FUNCTION_ARGS)
Datum dispell_init (PG_FUNCTION_ARGS)
Datum dispell_lexize (PG_FUNCTION_ARGS)
Datum thesaurus_init (PG_FUNCTION_ARGS)
Datum thesaurus_lexize (PG_FUNCTION_ARGS)
Datum ts_headline_byid_opt (PG_FUNCTION_ARGS)
Datum ts_headline_byid (PG_FUNCTION_ARGS)
Datum ts_headline (PG_FUNCTION_ARGS)
Datum ts_headline_opt (PG_FUNCTION_ARGS)
Datum get_current_ts_config (PG_FUNCTION_ARGS)

Define Documentation

#define DatumGetTSQuerySign (   X  )     ((TSQuerySign) DatumGetInt64(X))

Definition at line 190 of file ts_utils.h.

Referenced by gtsquery_consistent(), and gtsquery_penalty().

#define PG_GETARG_TSQUERYSIGN (   n  )     DatumGetTSQuerySign(PG_GETARG_DATUM(n))

Definition at line 192 of file ts_utils.h.

Referenced by gtsquery_same().

#define PG_RETURN_TSQUERYSIGN (   X  )     return TSQuerySignGetDatum(X)

Definition at line 191 of file ts_utils.h.

Referenced by gtsquery_union().

#define QTN_NEEDFREE   0x01

Definition at line 181 of file ts_utils.h.

Referenced by QTNFree(), and QTNTernary().

#define QTN_NOCHANGE   0x02

Definition at line 182 of file ts_utils.h.

Referenced by dofindsubquery(), findeq(), and tsquery_rewrite_query().

#define QTN_WORDFREE   0x04

Definition at line 183 of file ts_utils.h.

Referenced by QTNFree().

#define TSearchStrategyNumber   1

Definition at line 161 of file ts_utils.h.

#define TSearchWithClassStrategyNumber   2

Definition at line 162 of file ts_utils.h.

#define TSQS_SIGLEN   (sizeof(TSQuerySign)*BITS_PER_BYTE)

Definition at line 187 of file ts_utils.h.

#define TSQuerySignGetDatum (   X  )     Int64GetDatum((int64) (X))

Definition at line 189 of file ts_utils.h.

Referenced by gtsquery_compress(), and gtsquery_picksplit().


Typedef Documentation

typedef void(* PushFunction)(Datum opaque, TSQueryParserState state, char *token, int tokenlen, int16 tokenweights,bool prefix)

Definition at line 43 of file ts_utils.h.

typedef struct QTNode QTNode

Definition at line 41 of file ts_utils.h.

typedef uint64 TSQuerySign

Definition at line 185 of file ts_utils.h.

Definition at line 26 of file ts_utils.h.


Function Documentation

QueryItem* clean_fakeval ( QueryItem ptr,
int32 len 
)
QueryItem* clean_NOT ( QueryItem ptr,
int32 len 
)
void close_tsvector_parser ( TSVectorParseState  state  ) 

Definition at line 74 of file tsvector_parser.c.

References pfree(), and TSVectorParseStateData::word.

Referenced by parse_tsquery(), and tsvectorin().

{
    pfree(state->word);
    pfree(state);
}

Datum dispell_init ( PG_FUNCTION_ARGS   ) 

Definition at line 29 of file dict_ispell.c.

References defGetString(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, get_tsearch_config_filename(), lfirst, lowerstr(), NIFinishBuild(), NIImportAffixes(), NIImportDictionary(), NISortAffixes(), NISortDictionary(), NIStartBuild(), DictISpell::obj, palloc0(), PG_GETARG_POINTER, PG_RETURN_POINTER, pg_strcasecmp(), readstoplist(), and DictISpell::stoplist.

{
    List       *dictoptions = (List *) PG_GETARG_POINTER(0);
    DictISpell *d;
    bool        affloaded = false,
                dictloaded = false,
                stoploaded = false;
    ListCell   *l;

    d = (DictISpell *) palloc0(sizeof(DictISpell));

    NIStartBuild(&(d->obj));

    foreach(l, dictoptions)
    {
        DefElem    *defel = (DefElem *) lfirst(l);

        if (pg_strcasecmp(defel->defname, "DictFile") == 0)
        {
            if (dictloaded)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("multiple DictFile parameters")));
            NIImportDictionary(&(d->obj),
                             get_tsearch_config_filename(defGetString(defel),
                                                         "dict"));
            dictloaded = true;
        }
        else if (pg_strcasecmp(defel->defname, "AffFile") == 0)
        {
            if (affloaded)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("multiple AffFile parameters")));
            NIImportAffixes(&(d->obj),
                            get_tsearch_config_filename(defGetString(defel),
                                                        "affix"));
            affloaded = true;
        }
        else if (pg_strcasecmp(defel->defname, "StopWords") == 0)
        {
            if (stoploaded)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("multiple StopWords parameters")));
            readstoplist(defGetString(defel), &(d->stoplist), lowerstr);
            stoploaded = true;
        }
        else
        {
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("unrecognized Ispell parameter: \"%s\"",
                            defel->defname)));
        }
    }

    if (affloaded && dictloaded)
    {
        NISortDictionary(&(d->obj));
        NISortAffixes(&(d->obj));
    }
    else if (!affloaded)
    {
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("missing AffFile parameter")));
    }
    else
    {
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("missing DictFile parameter")));
    }

    NIFinishBuild(&(d->obj));

    PG_RETURN_POINTER(d);
}

Datum dispell_lexize ( PG_FUNCTION_ARGS   ) 

Definition at line 110 of file dict_ispell.c.

References TSLexeme::lexeme, lowerstr_with_len(), NINormalizeWord(), NULL, DictISpell::obj, pfree(), PG_GETARG_INT32, PG_GETARG_POINTER, PG_RETURN_POINTER, searchstoplist(), and DictISpell::stoplist.

{
    DictISpell *d = (DictISpell *) PG_GETARG_POINTER(0);
    char       *in = (char *) PG_GETARG_POINTER(1);
    int32       len = PG_GETARG_INT32(2);
    char       *txt;
    TSLexeme   *res;
    TSLexeme   *ptr,
               *cptr;

    if (len <= 0)
        PG_RETURN_POINTER(NULL);

    txt = lowerstr_with_len(in, len);
    res = NINormalizeWord(&(d->obj), txt);

    if (res == NULL)
        PG_RETURN_POINTER(NULL);

    ptr = cptr = res;
    while (ptr->lexeme)
    {
        if (searchstoplist(&(d->stoplist), ptr->lexeme))
        {
            pfree(ptr->lexeme);
            ptr->lexeme = NULL;
            ptr++;
        }
        else
        {
            memcpy(cptr, ptr, sizeof(TSLexeme));
            cptr++;
            ptr++;
        }
    }
    cptr->lexeme = NULL;

    PG_RETURN_POINTER(res);
}

Datum dsimple_init ( PG_FUNCTION_ARGS   ) 

Definition at line 29 of file dict_simple.c.

References DictSimple::accept, defGetBoolean(), defGetString(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, lfirst, lowerstr(), palloc0(), PG_GETARG_POINTER, PG_RETURN_POINTER, pg_strcasecmp(), readstoplist(), and DictSimple::stoplist.

{
    List       *dictoptions = (List *) PG_GETARG_POINTER(0);
    DictSimple *d = (DictSimple *) palloc0(sizeof(DictSimple));
    bool        stoploaded = false,
                acceptloaded = false;
    ListCell   *l;

    d->accept = true;           /* default */

    foreach(l, dictoptions)
    {
        DefElem    *defel = (DefElem *) lfirst(l);

        if (pg_strcasecmp("StopWords", defel->defname) == 0)
        {
            if (stoploaded)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("multiple StopWords parameters")));
            readstoplist(defGetString(defel), &d->stoplist, lowerstr);
            stoploaded = true;
        }
        else if (pg_strcasecmp("Accept", defel->defname) == 0)
        {
            if (acceptloaded)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("multiple Accept parameters")));
            d->accept = defGetBoolean(defel);
            acceptloaded = true;
        }
        else
        {
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                   errmsg("unrecognized simple dictionary parameter: \"%s\"",
                          defel->defname)));
        }
    }

    PG_RETURN_POINTER(d);
}

Datum dsimple_lexize ( PG_FUNCTION_ARGS   ) 

Definition at line 74 of file dict_simple.c.

References DictSimple::accept, TSLexeme::lexeme, lowerstr_with_len(), NULL, palloc0(), pfree(), PG_GETARG_INT32, PG_GETARG_POINTER, PG_RETURN_POINTER, searchstoplist(), and DictSimple::stoplist.

{
    DictSimple *d = (DictSimple *) PG_GETARG_POINTER(0);
    char       *in = (char *) PG_GETARG_POINTER(1);
    int32       len = PG_GETARG_INT32(2);
    char       *txt;
    TSLexeme   *res;

    txt = lowerstr_with_len(in, len);

    if (*txt == '\0' || searchstoplist(&(d->stoplist), txt))
    {
        /* reject as stopword */
        pfree(txt);
        res = palloc0(sizeof(TSLexeme) * 2);
        PG_RETURN_POINTER(res);
    }
    else if (d->accept)
    {
        /* accept */
        res = palloc0(sizeof(TSLexeme) * 2);
        res[0].lexeme = txt;
        PG_RETURN_POINTER(res);
    }
    else
    {
        /* report as unrecognized */
        pfree(txt);
        PG_RETURN_POINTER(NULL);
    }
}

Datum dsynonym_init ( PG_FUNCTION_ARGS   ) 

Definition at line 91 of file dict_synonym.c.

References DictSyn::case_sensitive, compareSyn(), cur, defGetBoolean(), defGetString(), DefElem::defname, end, ereport, errcode(), errmsg(), ERROR, filename, findwrd(), Syn::flags, get_tsearch_config_filename(), Syn::in, DictSyn::len, lfirst, lowerstr(), NULL, Syn::out, Syn::outlen, palloc(), palloc0(), pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, pg_strcasecmp(), pstrdup(), qsort, repalloc(), DictSyn::syn, tsearch_readline(), tsearch_readline_begin(), and tsearch_readline_end().

{
    List       *dictoptions = (List *) PG_GETARG_POINTER(0);
    DictSyn    *d;
    ListCell   *l;
    char       *filename = NULL;
    bool        case_sensitive = false;
    tsearch_readline_state trst;
    char       *starti,
               *starto,
               *end = NULL;
    int         cur = 0;
    char       *line = NULL;
    uint16      flags = 0;

    foreach(l, dictoptions)
    {
        DefElem    *defel = (DefElem *) lfirst(l);

        if (pg_strcasecmp("Synonyms", defel->defname) == 0)
            filename = defGetString(defel);
        else if (pg_strcasecmp("CaseSensitive", defel->defname) == 0)
            case_sensitive = defGetBoolean(defel);
        else
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("unrecognized synonym parameter: \"%s\"",
                            defel->defname)));
    }

    if (!filename)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("missing Synonyms parameter")));

    filename = get_tsearch_config_filename(filename, "syn");

    if (!tsearch_readline_begin(&trst, filename))
        ereport(ERROR,
                (errcode(ERRCODE_CONFIG_FILE_ERROR),
                 errmsg("could not open synonym file \"%s\": %m",
                        filename)));

    d = (DictSyn *) palloc0(sizeof(DictSyn));

    while ((line = tsearch_readline(&trst)) != NULL)
    {
        starti = findwrd(line, &end, NULL);
        if (!starti)
        {
            /* Empty line */
            goto skipline;
        }
        if (*end == '\0')
        {
            /* A line with only one word. Ignore silently. */
            goto skipline;
        }
        *end = '\0';

        starto = findwrd(end + 1, &end, &flags);
        if (!starto)
        {
            /* A line with only one word (+whitespace). Ignore silently. */
            goto skipline;
        }
        *end = '\0';

        /*
         * starti now points to the first word, and starto to the second word
         * on the line, with a \0 terminator at the end of both words.
         */

        if (cur >= d->len)
        {
            if (d->len == 0)
            {
                d->len = 64;
                d->syn = (Syn *) palloc(sizeof(Syn) * d->len);
            }
            else
            {
                d->len *= 2;
                d->syn = (Syn *) repalloc(d->syn, sizeof(Syn) * d->len);
            }
        }

        if (case_sensitive)
        {
            d->syn[cur].in = pstrdup(starti);
            d->syn[cur].out = pstrdup(starto);
        }
        else
        {
            d->syn[cur].in = lowerstr(starti);
            d->syn[cur].out = lowerstr(starto);
        }

        d->syn[cur].outlen = strlen(starto);
        d->syn[cur].flags = flags;

        cur++;

skipline:
        pfree(line);
    }

    tsearch_readline_end(&trst);

    d->len = cur;
    qsort(d->syn, d->len, sizeof(Syn), compareSyn);

    d->case_sensitive = case_sensitive;

    PG_RETURN_POINTER(d);
}

Datum dsynonym_lexize ( PG_FUNCTION_ARGS   ) 

Definition at line 209 of file dict_synonym.c.

References DictSyn::case_sensitive, Syn::flags, TSLexeme::flags, Syn::in, DictSyn::len, TSLexeme::lexeme, lowerstr_with_len(), NULL, Syn::out, Syn::outlen, palloc0(), pfree(), PG_GETARG_INT32, PG_GETARG_POINTER, PG_RETURN_POINTER, pnstrdup(), and DictSyn::syn.

{
    DictSyn    *d = (DictSyn *) PG_GETARG_POINTER(0);
    char       *in = (char *) PG_GETARG_POINTER(1);
    int32       len = PG_GETARG_INT32(2);
    Syn         key,
               *found;
    TSLexeme   *res;

    /* note: d->len test protects against Solaris bsearch-of-no-items bug */
    if (len <= 0 || d->len <= 0)
        PG_RETURN_POINTER(NULL);

    if (d->case_sensitive)
        key.in = pnstrdup(in, len);
    else
        key.in = lowerstr_with_len(in, len);

    key.out = NULL;

    found = (Syn *) bsearch(&key, d->syn, d->len, sizeof(Syn), compareSyn);
    pfree(key.in);

    if (!found)
        PG_RETURN_POINTER(NULL);

    res = palloc0(sizeof(TSLexeme) * 2);
    res[0].lexeme = pnstrdup(found->out, found->outlen);
    res[0].flags = found->flags;

    PG_RETURN_POINTER(res);
}

QTNode* findsubquery ( QTNode root,
QTNode ex,
QTNode subs,
bool isfind 
)

Definition at line 237 of file tsquery_rewrite.c.

References dofindsubquery(), and dropvoidsubtree().

Referenced by tsa_rewrite_accum(), tsquery_rewrite(), and tsquery_rewrite_query().

{
    bool        DidFind = false;

    root = dofindsubquery(root, ex, subs, &DidFind);

    if (!subs && DidFind)
        root = dropvoidsubtree(root);

    if (isfind)
        *isfind = DidFind;

    return root;
}

text* generateHeadline ( HeadlineParsedText prs  ) 

Definition at line 589 of file ts_parse.c.

References HeadlineParsedText::curwords, HeadlineParsedText::fragdelim, HeadlineParsedText::fragdelimlen, HeadlineWordEntry::in, HeadlineWordEntry::len, palloc(), pfree(), repalloc(), HeadlineWordEntry::repeated, HeadlineWordEntry::replace, HeadlineWordEntry::selected, SET_VARSIZE, HeadlineWordEntry::skip, HeadlineParsedText::startsel, HeadlineParsedText::startsellen, HeadlineParsedText::stopsel, HeadlineParsedText::stopsellen, HeadlineWordEntry::word, and HeadlineParsedText::words.

Referenced by ts_headline_byid_opt().

{
    text       *out;
    char       *ptr;
    int         len = 128;
    int         numfragments = 0;
    int16       infrag = 0;

    HeadlineWordEntry *wrd = prs->words;

    out = (text *) palloc(len);
    ptr = ((char *) out) + VARHDRSZ;

    while (wrd - prs->words < prs->curwords)
    {
        while (wrd->len + prs->stopsellen + prs->startsellen + prs->fragdelimlen + (ptr - ((char *) out)) >= len)
        {
            int         dist = ptr - ((char *) out);

            len *= 2;
            out = (text *) repalloc(out, len);
            ptr = ((char *) out) + dist;
        }

        if (wrd->in && !wrd->repeated)
        {
            if (!infrag)
            {

                /* start of a new fragment */
                infrag = 1;
                numfragments++;
                /* add a fragment delimitor if this is after the first one */
                if (numfragments > 1)
                {
                    memcpy(ptr, prs->fragdelim, prs->fragdelimlen);
                    ptr += prs->fragdelimlen;
                }

            }
            if (wrd->replace)
            {
                *ptr = ' ';
                ptr++;
            }
            else if (!wrd->skip)
            {
                if (wrd->selected)
                {
                    memcpy(ptr, prs->startsel, prs->startsellen);
                    ptr += prs->startsellen;
                }
                memcpy(ptr, wrd->word, wrd->len);
                ptr += wrd->len;
                if (wrd->selected)
                {
                    memcpy(ptr, prs->stopsel, prs->stopsellen);
                    ptr += prs->stopsellen;
                }
            }
        }
        else if (!wrd->repeated)
        {
            if (infrag)
                infrag = 0;
            pfree(wrd->word);
        }

        wrd++;
    }

    SET_VARSIZE(out, ptr - ((char *) out));
    return out;
}

Datum get_current_ts_config ( PG_FUNCTION_ARGS   ) 

Definition at line 22 of file to_tsany.c.

References getTSCurrentConfig(), and PG_RETURN_OID.

bool gettoken_tsvector ( TSVectorParseState  state,
char **  token,
int *  len,
WordEntryPos **  pos,
int *  poslen,
char **  endptr 
)

Definition at line 155 of file tsvector_parser.c.

References Assert, TSVectorParseStateData::bufstart, COPYCHAR, elog, ereport, errcode(), errmsg(), ERROR, INPOSINFO, ISOPERATOR, LIMITPOS, TSVectorParseStateData::oprisdelim, palloc(), pg_mblen(), TSVectorParseStateData::prsbuf, repalloc(), t_isdigit, t_iseq, t_isspace, WAITCHARCMPLX, WAITENDCMPLX, WAITENDWORD, WAITNEXTCHAR, WAITPOSDELIM, WAITPOSINFO, WAITWORD, WEP_GETPOS, WEP_GETWEIGHT, WEP_SETPOS, WEP_SETWEIGHT, and TSVectorParseStateData::word.

Referenced by gettoken_query(), and tsvectorin().

{
    int         oldstate = 0;
    char       *curpos = state->word;
    int         statecode = WAITWORD;

    /*
     * pos is for collecting the comma delimited list of positions followed by
     * the actual token.
     */
    WordEntryPos *pos = NULL;
    int         npos = 0;       /* elements of pos used */
    int         posalen = 0;    /* allocated size of pos */

    while (1)
    {
        if (statecode == WAITWORD)
        {
            if (*(state->prsbuf) == '\0')
                return false;
            else if (t_iseq(state->prsbuf, '\''))
                statecode = WAITENDCMPLX;
            else if (t_iseq(state->prsbuf, '\\'))
            {
                statecode = WAITNEXTCHAR;
                oldstate = WAITENDWORD;
            }
            else if (state->oprisdelim && ISOPERATOR(state->prsbuf))
                PRSSYNTAXERROR;
            else if (!t_isspace(state->prsbuf))
            {
                COPYCHAR(curpos, state->prsbuf);
                curpos += pg_mblen(state->prsbuf);
                statecode = WAITENDWORD;
            }
        }
        else if (statecode == WAITNEXTCHAR)
        {
            if (*(state->prsbuf) == '\0')
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("there is no escaped character: \"%s\"",
                                state->bufstart)));
            else
            {
                RESIZEPRSBUF;
                COPYCHAR(curpos, state->prsbuf);
                curpos += pg_mblen(state->prsbuf);
                Assert(oldstate != 0);
                statecode = oldstate;
            }
        }
        else if (statecode == WAITENDWORD)
        {
            if (t_iseq(state->prsbuf, '\\'))
            {
                statecode = WAITNEXTCHAR;
                oldstate = WAITENDWORD;
            }
            else if (t_isspace(state->prsbuf) || *(state->prsbuf) == '\0' ||
                     (state->oprisdelim && ISOPERATOR(state->prsbuf)))
            {
                RESIZEPRSBUF;
                if (curpos == state->word)
                    PRSSYNTAXERROR;
                *(curpos) = '\0';
                RETURN_TOKEN;
            }
            else if (t_iseq(state->prsbuf, ':'))
            {
                if (curpos == state->word)
                    PRSSYNTAXERROR;
                *(curpos) = '\0';
                if (state->oprisdelim)
                    RETURN_TOKEN;
                else
                    statecode = INPOSINFO;
            }
            else
            {
                RESIZEPRSBUF;
                COPYCHAR(curpos, state->prsbuf);
                curpos += pg_mblen(state->prsbuf);
            }
        }
        else if (statecode == WAITENDCMPLX)
        {
            if (t_iseq(state->prsbuf, '\''))
            {
                statecode = WAITCHARCMPLX;
            }
            else if (t_iseq(state->prsbuf, '\\'))
            {
                statecode = WAITNEXTCHAR;
                oldstate = WAITENDCMPLX;
            }
            else if (*(state->prsbuf) == '\0')
                PRSSYNTAXERROR;
            else
            {
                RESIZEPRSBUF;
                COPYCHAR(curpos, state->prsbuf);
                curpos += pg_mblen(state->prsbuf);
            }
        }
        else if (statecode == WAITCHARCMPLX)
        {
            if (t_iseq(state->prsbuf, '\''))
            {
                RESIZEPRSBUF;
                COPYCHAR(curpos, state->prsbuf);
                curpos += pg_mblen(state->prsbuf);
                statecode = WAITENDCMPLX;
            }
            else
            {
                RESIZEPRSBUF;
                *(curpos) = '\0';
                if (curpos == state->word)
                    PRSSYNTAXERROR;
                if (state->oprisdelim)
                {
                    /* state->prsbuf+=pg_mblen(state->prsbuf); */
                    RETURN_TOKEN;
                }
                else
                    statecode = WAITPOSINFO;
                continue;       /* recheck current character */
            }
        }
        else if (statecode == WAITPOSINFO)
        {
            if (t_iseq(state->prsbuf, ':'))
                statecode = INPOSINFO;
            else
                RETURN_TOKEN;
        }
        else if (statecode == INPOSINFO)
        {
            if (t_isdigit(state->prsbuf))
            {
                if (posalen == 0)
                {
                    posalen = 4;
                    pos = (WordEntryPos *) palloc(sizeof(WordEntryPos) * posalen);
                    npos = 0;
                }
                else if (npos + 1 >= posalen)
                {
                    posalen *= 2;
                    pos = (WordEntryPos *) repalloc(pos, sizeof(WordEntryPos) * posalen);
                }
                npos++;
                WEP_SETPOS(pos[npos - 1], LIMITPOS(atoi(state->prsbuf)));
                /* we cannot get here in tsquery, so no need for 2 errmsgs */
                if (WEP_GETPOS(pos[npos - 1]) == 0)
                    ereport(ERROR,
                            (errcode(ERRCODE_SYNTAX_ERROR),
                             errmsg("wrong position info in tsvector: \"%s\"",
                                    state->bufstart)));
                WEP_SETWEIGHT(pos[npos - 1], 0);
                statecode = WAITPOSDELIM;
            }
            else
                PRSSYNTAXERROR;
        }
        else if (statecode == WAITPOSDELIM)
        {
            if (t_iseq(state->prsbuf, ','))
                statecode = INPOSINFO;
            else if (t_iseq(state->prsbuf, 'a') || t_iseq(state->prsbuf, 'A') || t_iseq(state->prsbuf, '*'))
            {
                if (WEP_GETWEIGHT(pos[npos - 1]))
                    PRSSYNTAXERROR;
                WEP_SETWEIGHT(pos[npos - 1], 3);
            }
            else if (t_iseq(state->prsbuf, 'b') || t_iseq(state->prsbuf, 'B'))
            {
                if (WEP_GETWEIGHT(pos[npos - 1]))
                    PRSSYNTAXERROR;
                WEP_SETWEIGHT(pos[npos - 1], 2);
            }
            else if (t_iseq(state->prsbuf, 'c') || t_iseq(state->prsbuf, 'C'))
            {
                if (WEP_GETWEIGHT(pos[npos - 1]))
                    PRSSYNTAXERROR;
                WEP_SETWEIGHT(pos[npos - 1], 1);
            }
            else if (t_iseq(state->prsbuf, 'd') || t_iseq(state->prsbuf, 'D'))
            {
                if (WEP_GETWEIGHT(pos[npos - 1]))
                    PRSSYNTAXERROR;
                WEP_SETWEIGHT(pos[npos - 1], 0);
            }
            else if (t_isspace(state->prsbuf) ||
                     *(state->prsbuf) == '\0')
                RETURN_TOKEN;
            else if (!t_isdigit(state->prsbuf))
                PRSSYNTAXERROR;
        }
        else    /* internal error */
            elog(ERROR, "unrecognized state in gettoken_tsvector: %d",
                 statecode);

        /* get next char */
        state->prsbuf += pg_mblen(state->prsbuf);
    }
}

Datum gin_cmp_prefix ( PG_FUNCTION_ARGS   ) 

Definition at line 40 of file tsginidx.c.

References PG_FREE_IF_COPY, PG_GETARG_POINTER, PG_GETARG_TEXT_PP, PG_GETARG_UINT16, PG_RETURN_INT32, tsCompareString(), VARDATA_ANY, and VARSIZE_ANY_EXHDR.

{
    text       *a = PG_GETARG_TEXT_PP(0);
    text       *b = PG_GETARG_TEXT_PP(1);

#ifdef NOT_USED
    StrategyNumber strategy = PG_GETARG_UINT16(2);
    Pointer     extra_data = PG_GETARG_POINTER(3);
#endif
    int         cmp;

    cmp = tsCompareString(VARDATA_ANY(a), VARSIZE_ANY_EXHDR(a),
                          VARDATA_ANY(b), VARSIZE_ANY_EXHDR(b),
                          true);

    if (cmp < 0)
        cmp = 1;                /* prevent continue scan */

    PG_FREE_IF_COPY(a, 0);
    PG_FREE_IF_COPY(b, 1);
    PG_RETURN_INT32(cmp);
}

Datum gin_cmp_tslexeme ( PG_FUNCTION_ARGS   ) 
Datum gin_extract_tsquery ( PG_FUNCTION_ARGS   ) 

Definition at line 94 of file tsginidx.c.

References cstring_to_text_with_len(), QueryOperand::distance, GETOPERAND, GETQUERY, i, QueryOperand::length, palloc(), palloc0(), PG_FREE_IF_COPY, PG_GETARG_POINTER, PG_GETARG_TSQUERY, PG_RETURN_POINTER, PointerGetDatum, QueryOperand::prefix, QI_VAL, QueryItem::qoperand, TSQueryData::size, tsquery_requires_match(), and val.

Referenced by gin_extract_tsquery_5args().

{
    TSQuery     query = PG_GETARG_TSQUERY(0);
    int32      *nentries = (int32 *) PG_GETARG_POINTER(1);

    /* StrategyNumber strategy = PG_GETARG_UINT16(2); */
    bool      **ptr_partialmatch = (bool **) PG_GETARG_POINTER(3);
    Pointer   **extra_data = (Pointer **) PG_GETARG_POINTER(4);

    /* bool   **nullFlags = (bool **) PG_GETARG_POINTER(5); */
    int32      *searchMode = (int32 *) PG_GETARG_POINTER(6);
    Datum      *entries = NULL;

    *nentries = 0;

    if (query->size > 0)
    {
        QueryItem  *item = GETQUERY(query);
        int32       i,
                    j;
        bool       *partialmatch;
        int        *map_item_operand;

        /*
         * If the query doesn't have any required positive matches (for
         * instance, it's something like '! foo'), we have to do a full index
         * scan.
         */
        if (tsquery_requires_match(item))
            *searchMode = GIN_SEARCH_MODE_DEFAULT;
        else
            *searchMode = GIN_SEARCH_MODE_ALL;

        /* count number of VAL items */
        j = 0;
        for (i = 0; i < query->size; i++)
        {
            if (item[i].type == QI_VAL)
                j++;
        }
        *nentries = j;

        entries = (Datum *) palloc(sizeof(Datum) * j);
        partialmatch = *ptr_partialmatch = (bool *) palloc(sizeof(bool) * j);

        /*
         * Make map to convert item's number to corresponding operand's (the
         * same, entry's) number. Entry's number is used in check array in
         * consistent method. We use the same map for each entry.
         */
        *extra_data = (Pointer *) palloc(sizeof(Pointer) * j);
        map_item_operand = (int *) palloc0(sizeof(int) * query->size);

        /* Now rescan the VAL items and fill in the arrays */
        j = 0;
        for (i = 0; i < query->size; i++)
        {
            if (item[i].type == QI_VAL)
            {
                QueryOperand *val = &item[i].qoperand;
                text       *txt;

                txt = cstring_to_text_with_len(GETOPERAND(query) + val->distance,
                                               val->length);
                entries[j] = PointerGetDatum(txt);
                partialmatch[j] = val->prefix;
                (*extra_data)[j] = (Pointer) map_item_operand;
                map_item_operand[i] = j;
                j++;
            }
        }
    }

    PG_FREE_IF_COPY(query, 0);

    PG_RETURN_POINTER(entries);
}

Datum gin_extract_tsquery_5args ( PG_FUNCTION_ARGS   ) 

Definition at line 257 of file tsginidx.c.

References elog, ERROR, gin_extract_tsquery(), and PG_NARGS.

{
    if (PG_NARGS() < 7)         /* should not happen */
        elog(ERROR, "gin_extract_tsquery requires seven arguments");
    return gin_extract_tsquery(fcinfo);
}

Datum gin_extract_tsvector ( PG_FUNCTION_ARGS   ) 

Definition at line 64 of file tsginidx.c.

References ARRPTR, cstring_to_text_with_len(), i, WordEntry::len, palloc(), PG_FREE_IF_COPY, PG_GETARG_POINTER, PG_GETARG_TSVECTOR, PG_RETURN_POINTER, PointerGetDatum, WordEntry::pos, TSVectorData::size, and STRPTR.

Referenced by gin_extract_tsvector_2args().

{
    TSVector    vector = PG_GETARG_TSVECTOR(0);
    int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
    Datum      *entries = NULL;

    *nentries = vector->size;
    if (vector->size > 0)
    {
        int         i;
        WordEntry  *we = ARRPTR(vector);

        entries = (Datum *) palloc(sizeof(Datum) * vector->size);

        for (i = 0; i < vector->size; i++)
        {
            text       *txt;

            txt = cstring_to_text_with_len(STRPTR(vector) + we->pos, we->len);
            entries[i] = PointerGetDatum(txt);

            we++;
        }
    }

    PG_FREE_IF_COPY(vector, 0);
    PG_RETURN_POINTER(entries);
}

Datum gin_extract_tsvector_2args ( PG_FUNCTION_ARGS   ) 

Definition at line 245 of file tsginidx.c.

References elog, ERROR, gin_extract_tsvector(), and PG_NARGS.

{
    if (PG_NARGS() < 3)         /* should not happen */
        elog(ERROR, "gin_extract_tsvector requires three arguments");
    return gin_extract_tsvector(fcinfo);
}

Datum gin_tsquery_consistent ( PG_FUNCTION_ARGS   ) 

Definition at line 198 of file tsginidx.c.

References GinChkVal::check, checkcondition_gin(), GinChkVal::first_item, GETQUERY, GinChkVal::map_item_operand, GinChkVal::need_recheck, PG_GETARG_POINTER, PG_GETARG_TSQUERY, PG_RETURN_BOOL, TSQueryData::size, and TS_execute().

Referenced by gin_tsquery_consistent_6args().

{
    bool       *check = (bool *) PG_GETARG_POINTER(0);

    /* StrategyNumber strategy = PG_GETARG_UINT16(1); */
    TSQuery     query = PG_GETARG_TSQUERY(2);

    /* int32    nkeys = PG_GETARG_INT32(3); */
    Pointer    *extra_data = (Pointer *) PG_GETARG_POINTER(4);
    bool       *recheck = (bool *) PG_GETARG_POINTER(5);
    bool        res = FALSE;

    /* The query requires recheck only if it involves weights */
    *recheck = false;

    if (query->size > 0)
    {
        QueryItem  *item;
        GinChkVal   gcv;

        /*
         * check-parameter array has one entry for each value (operand) in the
         * query.
         */
        gcv.first_item = item = GETQUERY(query);
        gcv.check = check;
        gcv.map_item_operand = (int *) (extra_data[0]);
        gcv.need_recheck = recheck;

        res = TS_execute(GETQUERY(query),
                         &gcv,
                         true,
                         checkcondition_gin);
    }

    PG_RETURN_BOOL(res);
}

Datum gin_tsquery_consistent_6args ( PG_FUNCTION_ARGS   ) 

Definition at line 269 of file tsginidx.c.

References elog, ERROR, gin_tsquery_consistent(), and PG_NARGS.

{
    if (PG_NARGS() < 8)         /* should not happen */
        elog(ERROR, "gin_tsquery_consistent requires eight arguments");
    return gin_tsquery_consistent(fcinfo);
}

Datum gtsquery_compress ( PG_FUNCTION_ARGS   ) 
Datum gtsquery_consistent ( PG_FUNCTION_ARGS   ) 

Definition at line 52 of file tsquery_gist.c.

References DatumGetTSQuerySign, GIST_LEAF, GISTENTRY::key, makeTSQuerySign(), PG_GETARG_POINTER, PG_GETARG_TSQUERY, PG_GETARG_UINT16, PG_RETURN_BOOL, RTContainedByStrategyNumber, and RTContainsStrategyNumber.

{
    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    TSQuery     query = PG_GETARG_TSQUERY(1);
    StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);

    /* Oid      subtype = PG_GETARG_OID(3); */
    bool       *recheck = (bool *) PG_GETARG_POINTER(4);
    TSQuerySign key = DatumGetTSQuerySign(entry->key);
    TSQuerySign sq = makeTSQuerySign(query);
    bool        retval;

    /* All cases served by this function are inexact */
    *recheck = true;

    switch (strategy)
    {
        case RTContainsStrategyNumber:
            if (GIST_LEAF(entry))
                retval = (key & sq) == sq;
            else
                retval = (key & sq) != 0;
            break;
        case RTContainedByStrategyNumber:
            if (GIST_LEAF(entry))
                retval = (key & sq) == key;
            else
                retval = (key & sq) != 0;
            break;
        default:
            retval = FALSE;
    }
    PG_RETURN_BOOL(retval);
}

Datum gtsquery_decompress ( PG_FUNCTION_ARGS   ) 

Definition at line 46 of file tsquery_gist.c.

References PG_GETARG_DATUM, and PG_RETURN_DATUM.

Datum gtsquery_penalty ( PG_FUNCTION_ARGS   ) 

Definition at line 138 of file tsquery_gist.c.

References DatumGetTSQuerySign, hemdist(), PG_GETARG_POINTER, and PG_RETURN_POINTER.

{
    TSQuerySign origval = DatumGetTSQuerySign(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
    TSQuerySign newval = DatumGetTSQuerySign(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
    float      *penalty = (float *) PG_GETARG_POINTER(2);

    *penalty = hemdist(origval, newval);

    PG_RETURN_POINTER(penalty);
}

Datum gtsquery_picksplit ( PG_FUNCTION_ARGS   ) 

Definition at line 168 of file tsquery_gist.c.

References comparecost(), SPLITCOST::cost, FirstOffsetNumber, GETENTRY, hemdist(), NODE::left, GistEntryVector::n, OffsetNumberNext, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, SPLITCOST::pos, qsort, NODE::right, GIST_SPLITVEC::spl_ldatum, GIST_SPLITVEC::spl_left, GIST_SPLITVEC::spl_nleft, GIST_SPLITVEC::spl_nright, GIST_SPLITVEC::spl_rdatum, GIST_SPLITVEC::spl_right, TSQuerySignGetDatum, and WISH_F.

{
    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
    GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
    OffsetNumber maxoff = entryvec->n - 2;
    OffsetNumber k,
                j;
    TSQuerySign datum_l,
                datum_r;
    int32       size_alpha,
                size_beta;
    int32       size_waste,
                waste = -1;
    int32       nbytes;
    OffsetNumber seed_1 = 0,
                seed_2 = 0;
    OffsetNumber *left,
               *right;

    SPLITCOST  *costvector;

    nbytes = (maxoff + 2) * sizeof(OffsetNumber);
    left = v->spl_left = (OffsetNumber *) palloc(nbytes);
    right = v->spl_right = (OffsetNumber *) palloc(nbytes);
    v->spl_nleft = v->spl_nright = 0;

    for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
        for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
        {
            size_waste = hemdist(GETENTRY(entryvec, j), GETENTRY(entryvec, k));
            if (size_waste > waste)
            {
                waste = size_waste;
                seed_1 = k;
                seed_2 = j;
            }
        }


    if (seed_1 == 0 || seed_2 == 0)
    {
        seed_1 = 1;
        seed_2 = 2;
    }

    datum_l = GETENTRY(entryvec, seed_1);
    datum_r = GETENTRY(entryvec, seed_2);

    maxoff = OffsetNumberNext(maxoff);
    costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
    for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
    {
        costvector[j - 1].pos = j;
        size_alpha = hemdist(GETENTRY(entryvec, seed_1), GETENTRY(entryvec, j));
        size_beta = hemdist(GETENTRY(entryvec, seed_2), GETENTRY(entryvec, j));
        costvector[j - 1].cost = abs(size_alpha - size_beta);
    }
    qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);

    for (k = 0; k < maxoff; k++)
    {
        j = costvector[k].pos;
        if (j == seed_1)
        {
            *left++ = j;
            v->spl_nleft++;
            continue;
        }
        else if (j == seed_2)
        {
            *right++ = j;
            v->spl_nright++;
            continue;
        }
        size_alpha = hemdist(datum_l, GETENTRY(entryvec, j));
        size_beta = hemdist(datum_r, GETENTRY(entryvec, j));

        if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.05))
        {
            datum_l |= GETENTRY(entryvec, j);
            *left++ = j;
            v->spl_nleft++;
        }
        else
        {
            datum_r |= GETENTRY(entryvec, j);
            *right++ = j;
            v->spl_nright++;
        }
    }

    *right = *left = FirstOffsetNumber;
    v->spl_ldatum = TSQuerySignGetDatum(datum_l);
    v->spl_rdatum = TSQuerySignGetDatum(datum_r);

    PG_RETURN_POINTER(v);
}

Datum gtsquery_same ( PG_FUNCTION_ARGS   ) 

Definition at line 106 of file tsquery_gist.c.

References PG_GETARG_POINTER, PG_GETARG_TSQUERYSIGN, and PG_RETURN_POINTER.

{
    TSQuerySign a = PG_GETARG_TSQUERYSIGN(0);
    TSQuerySign b = PG_GETARG_TSQUERYSIGN(1);
    bool       *result = (bool *) PG_GETARG_POINTER(2);

    *result = (a == b) ? true : false;

    PG_RETURN_POINTER(result);
}

Datum gtsquery_union ( PG_FUNCTION_ARGS   ) 

Definition at line 88 of file tsquery_gist.c.

References GETENTRY, i, GistEntryVector::n, PG_GETARG_POINTER, PG_RETURN_TSQUERYSIGN, and sign.

{
    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
    int        *size = (int *) PG_GETARG_POINTER(1);
    TSQuerySign sign;
    int         i;

    sign = 0;

    for (i = 0; i < entryvec->n; i++)
        sign |= GETENTRY(entryvec, i);

    *size = sizeof(TSQuerySign);

    PG_RETURN_TSQUERYSIGN(sign);
}

Datum gtsvector_compress ( PG_FUNCTION_ARGS   ) 

Definition at line 180 of file tsgistidx.c.

References ALLISTRUE, ARRKEY, ARRPTR, CALCGTSIZE, COMP_CRC32, DatumGetPointer, DatumGetTSVector, FALSE, FIN_CRC32, SignTSVector::flag, GETARR, GETSIGN, gistentryinit, i, INIT_CRC32, ISALLTRUE, ISSIGNKEY, GISTENTRY::key, GISTENTRY::leafkey, WordEntry::len, LOOPBYTE, makesign(), GISTENTRY::offset, GISTENTRY::page, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum, WordEntry::pos, GISTENTRY::rel, repalloc(), SET_VARSIZE, sign, SIGNKEY, TSVectorData::size, STRPTR, TOAST_INDEX_TARGET, uniqueint(), val, and VARSIZE.

{
    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    GISTENTRY  *retval = entry;

    if (entry->leafkey)
    {                           /* tsvector */
        SignTSVector *res;
        TSVector    val = DatumGetTSVector(entry->key);
        int32       len;
        int32      *arr;
        WordEntry  *ptr = ARRPTR(val);
        char       *words = STRPTR(val);

        len = CALCGTSIZE(ARRKEY, val->size);
        res = (SignTSVector *) palloc(len);
        SET_VARSIZE(res, len);
        res->flag = ARRKEY;
        arr = GETARR(res);
        len = val->size;
        while (len--)
        {
            pg_crc32    c;

            INIT_CRC32(c);
            COMP_CRC32(c, words + ptr->pos, ptr->len);
            FIN_CRC32(c);

            *arr = *(int32 *) &c;
            arr++;
            ptr++;
        }

        len = uniqueint(GETARR(res), val->size);
        if (len != val->size)
        {
            /*
             * there is a collision of hash-function; len is always less than
             * val->size
             */
            len = CALCGTSIZE(ARRKEY, len);
            res = (SignTSVector *) repalloc((void *) res, len);
            SET_VARSIZE(res, len);
        }

        /* make signature, if array is too long */
        if (VARSIZE(res) > TOAST_INDEX_TARGET)
        {
            SignTSVector *ressign;

            len = CALCGTSIZE(SIGNKEY, 0);
            ressign = (SignTSVector *) palloc(len);
            SET_VARSIZE(ressign, len);
            ressign->flag = SIGNKEY;
            makesign(GETSIGN(ressign), res);
            res = ressign;
        }

        retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
        gistentryinit(*retval, PointerGetDatum(res),
                      entry->rel, entry->page,
                      entry->offset, FALSE);
    }
    else if (ISSIGNKEY(DatumGetPointer(entry->key)) &&
             !ISALLTRUE(DatumGetPointer(entry->key)))
    {
        int32       i,
                    len;
        SignTSVector *res;
        BITVECP     sign = GETSIGN(DatumGetPointer(entry->key));

        LOOPBYTE
        {
            if ((sign[i] & 0xff) != 0xff)
                PG_RETURN_POINTER(retval);
        }

        len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0);
        res = (SignTSVector *) palloc(len);
        SET_VARSIZE(res, len);
        res->flag = SIGNKEY | ALLISTRUE;

        retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
        gistentryinit(*retval, PointerGetDatum(res),
                      entry->rel, entry->page,
                      entry->offset, FALSE);
    }
    PG_RETURN_POINTER(retval);
}

Datum gtsvector_consistent ( PG_FUNCTION_ARGS   ) 

Definition at line 340 of file tsgistidx.c.

References CHKVAL::arrb, CHKVAL::arre, ARRNELEM, checkcondition_arr(), checkcondition_bit(), DatumGetPointer, GETARR, GETQUERY, GETSIGN, ISALLTRUE, ISSIGNKEY, GISTENTRY::key, PG_GETARG_POINTER, PG_GETARG_TSQUERY, PG_RETURN_BOOL, TSQueryData::size, and TS_execute().

{
    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    TSQuery     query = PG_GETARG_TSQUERY(1);

    /* StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); */
    /* Oid      subtype = PG_GETARG_OID(3); */
    bool       *recheck = (bool *) PG_GETARG_POINTER(4);
    SignTSVector *key = (SignTSVector *) DatumGetPointer(entry->key);

    /* All cases served by this function are inexact */
    *recheck = true;

    if (!query->size)
        PG_RETURN_BOOL(false);

    if (ISSIGNKEY(key))
    {
        if (ISALLTRUE(key))
            PG_RETURN_BOOL(true);

        PG_RETURN_BOOL(TS_execute(
                                  GETQUERY(query),
                                  (void *) GETSIGN(key), false,
                                  checkcondition_bit
                                  ));
    }
    else
    {                           /* only leaf pages */
        CHKVAL      chkval;

        chkval.arrb = GETARR(key);
        chkval.arre = chkval.arrb + ARRNELEM(key);
        PG_RETURN_BOOL(TS_execute(
                                  GETQUERY(query),
                                  (void *) &chkval, true,
                                  checkcondition_arr
                                  ));
    }
}

Datum gtsvector_decompress ( PG_FUNCTION_ARGS   ) 
Datum gtsvector_penalty ( PG_FUNCTION_ARGS   ) 

Definition at line 541 of file tsgistidx.c.

References DatumGetPointer, GETSIGN, hemdist(), hemdistsign(), ISALLTRUE, ISARRKEY, GISTENTRY::key, makesign(), PG_GETARG_POINTER, PG_RETURN_POINTER, SIGLENBIT, sign, and sizebitvec().

{
    GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
    GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
    float      *penalty = (float *) PG_GETARG_POINTER(2);
    SignTSVector *origval = (SignTSVector *) DatumGetPointer(origentry->key);
    SignTSVector *newval = (SignTSVector *) DatumGetPointer(newentry->key);
    BITVECP     orig = GETSIGN(origval);

    *penalty = 0.0;

    if (ISARRKEY(newval))
    {
        BITVEC      sign;

        makesign(sign, newval);

        if (ISALLTRUE(origval))
            *penalty = ((float) (SIGLENBIT - sizebitvec(sign))) / (float) (SIGLENBIT + 1);
        else
            *penalty = hemdistsign(sign, orig);
    }
    else
        *penalty = hemdist(origval, newval);
    PG_RETURN_POINTER(penalty);
}

Datum gtsvector_picksplit ( PG_FUNCTION_ARGS   ) 

Definition at line 623 of file tsgistidx.c.

References Abs, ALLISTRUE, CALCGTSIZE, comparecost(), SPLITCOST::cost, fillcache(), FirstOffsetNumber, SignTSVector::flag, GETENTRY, GETSIGN, hemdistcache(), hemdistsign(), i, ISALLTRUE, LOOPBYTE, MemSet, GistEntryVector::n, OffsetNumberNext, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum, SPLITCOST::pos, qsort, SET_VARSIZE, SIGLENBIT, CACHESIGN::sign, sign, SIGNKEY, sizebitvec(), GIST_SPLITVEC::spl_ldatum, GIST_SPLITVEC::spl_left, GIST_SPLITVEC::spl_nleft, GIST_SPLITVEC::spl_nright, GIST_SPLITVEC::spl_rdatum, GIST_SPLITVEC::spl_right, and WISH_F.

{
    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
    GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
    OffsetNumber k,
                j;
    SignTSVector *datum_l,
               *datum_r;
    BITVECP     union_l,
                union_r;
    int32       size_alpha,
                size_beta;
    int32       size_waste,
                waste = -1;
    int32       nbytes;
    OffsetNumber seed_1 = 0,
                seed_2 = 0;
    OffsetNumber *left,
               *right;
    OffsetNumber maxoff;
    BITVECP     ptr;
    int         i;
    CACHESIGN  *cache;
    SPLITCOST  *costvector;

    maxoff = entryvec->n - 2;
    nbytes = (maxoff + 2) * sizeof(OffsetNumber);
    v->spl_left = (OffsetNumber *) palloc(nbytes);
    v->spl_right = (OffsetNumber *) palloc(nbytes);

    cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 2));
    fillcache(&cache[FirstOffsetNumber], GETENTRY(entryvec, FirstOffsetNumber));

    for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
    {
        for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
        {
            if (k == FirstOffsetNumber)
                fillcache(&cache[j], GETENTRY(entryvec, j));

            size_waste = hemdistcache(&(cache[j]), &(cache[k]));
            if (size_waste > waste)
            {
                waste = size_waste;
                seed_1 = k;
                seed_2 = j;
            }
        }
    }

    left = v->spl_left;
    v->spl_nleft = 0;
    right = v->spl_right;
    v->spl_nright = 0;

    if (seed_1 == 0 || seed_2 == 0)
    {
        seed_1 = 1;
        seed_2 = 2;
    }

    /* form initial .. */
    if (cache[seed_1].allistrue)
    {
        datum_l = (SignTSVector *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
        SET_VARSIZE(datum_l, CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
        datum_l->flag = SIGNKEY | ALLISTRUE;
    }
    else
    {
        datum_l = (SignTSVector *) palloc(CALCGTSIZE(SIGNKEY, 0));
        SET_VARSIZE(datum_l, CALCGTSIZE(SIGNKEY, 0));
        datum_l->flag = SIGNKEY;
        memcpy((void *) GETSIGN(datum_l), (void *) cache[seed_1].sign, sizeof(BITVEC));
    }
    if (cache[seed_2].allistrue)
    {
        datum_r = (SignTSVector *) palloc(CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
        SET_VARSIZE(datum_r, CALCGTSIZE(SIGNKEY | ALLISTRUE, 0));
        datum_r->flag = SIGNKEY | ALLISTRUE;
    }
    else
    {
        datum_r = (SignTSVector *) palloc(CALCGTSIZE(SIGNKEY, 0));
        SET_VARSIZE(datum_r, CALCGTSIZE(SIGNKEY, 0));
        datum_r->flag = SIGNKEY;
        memcpy((void *) GETSIGN(datum_r), (void *) cache[seed_2].sign, sizeof(BITVEC));
    }

    union_l = GETSIGN(datum_l);
    union_r = GETSIGN(datum_r);
    maxoff = OffsetNumberNext(maxoff);
    fillcache(&cache[maxoff], GETENTRY(entryvec, maxoff));
    /* sort before ... */
    costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
    for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
    {
        costvector[j - 1].pos = j;
        size_alpha = hemdistcache(&(cache[seed_1]), &(cache[j]));
        size_beta = hemdistcache(&(cache[seed_2]), &(cache[j]));
        costvector[j - 1].cost = Abs(size_alpha - size_beta);
    }
    qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);

    for (k = 0; k < maxoff; k++)
    {
        j = costvector[k].pos;
        if (j == seed_1)
        {
            *left++ = j;
            v->spl_nleft++;
            continue;
        }
        else if (j == seed_2)
        {
            *right++ = j;
            v->spl_nright++;
            continue;
        }

        if (ISALLTRUE(datum_l) || cache[j].allistrue)
        {
            if (ISALLTRUE(datum_l) && cache[j].allistrue)
                size_alpha = 0;
            else
                size_alpha = SIGLENBIT - sizebitvec(
                                                    (cache[j].allistrue) ? GETSIGN(datum_l) : GETSIGN(cache[j].sign)
                    );
        }
        else
            size_alpha = hemdistsign(cache[j].sign, GETSIGN(datum_l));

        if (ISALLTRUE(datum_r) || cache[j].allistrue)
        {
            if (ISALLTRUE(datum_r) && cache[j].allistrue)
                size_beta = 0;
            else
                size_beta = SIGLENBIT - sizebitvec(
                                                   (cache[j].allistrue) ? GETSIGN(datum_r) : GETSIGN(cache[j].sign)
                    );
        }
        else
            size_beta = hemdistsign(cache[j].sign, GETSIGN(datum_r));

        if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.1))
        {
            if (ISALLTRUE(datum_l) || cache[j].allistrue)
            {
                if (!ISALLTRUE(datum_l))
                    MemSet((void *) GETSIGN(datum_l), 0xff, sizeof(BITVEC));
            }
            else
            {
                ptr = cache[j].sign;
                LOOPBYTE
                    union_l[i] |= ptr[i];
            }
            *left++ = j;
            v->spl_nleft++;
        }
        else
        {
            if (ISALLTRUE(datum_r) || cache[j].allistrue)
            {
                if (!ISALLTRUE(datum_r))
                    MemSet((void *) GETSIGN(datum_r), 0xff, sizeof(BITVEC));
            }
            else
            {
                ptr = cache[j].sign;
                LOOPBYTE
                    union_r[i] |= ptr[i];
            }
            *right++ = j;
            v->spl_nright++;
        }
    }

    *right = *left = FirstOffsetNumber;
    v->spl_ldatum = PointerGetDatum(datum_l);
    v->spl_rdatum = PointerGetDatum(datum_r);

    PG_RETURN_POINTER(v);
}

Datum gtsvector_same ( PG_FUNCTION_ARGS   ) 

Definition at line 441 of file tsgistidx.c.

References ARRNELEM, GETARR, GETSIGN, i, ISALLTRUE, ISSIGNKEY, LOOPBYTE, PG_GETARG_POINTER, and PG_RETURN_POINTER.

{
    SignTSVector *a = (SignTSVector *) PG_GETARG_POINTER(0);
    SignTSVector *b = (SignTSVector *) PG_GETARG_POINTER(1);
    bool       *result = (bool *) PG_GETARG_POINTER(2);

    if (ISSIGNKEY(a))
    {                           /* then b also ISSIGNKEY */
        if (ISALLTRUE(a) && ISALLTRUE(b))
            *result = true;
        else if (ISALLTRUE(a))
            *result = false;
        else if (ISALLTRUE(b))
            *result = false;
        else
        {
            int32       i;
            BITVECP     sa = GETSIGN(a),
                        sb = GETSIGN(b);

            *result = true;
            LOOPBYTE
            {
                if (sa[i] != sb[i])
                {
                    *result = false;
                    break;
                }
            }
        }
    }
    else
    {                           /* a and b ISARRKEY */
        int32       lena = ARRNELEM(a),
                    lenb = ARRNELEM(b);

        if (lena != lenb)
            *result = false;
        else
        {
            int32      *ptra = GETARR(a),
                       *ptrb = GETARR(b);
            int32       i;

            *result = true;
            for (i = 0; i < lena; i++)
                if (ptra[i] != ptrb[i])
                {
                    *result = false;
                    break;
                }
        }
    }

    PG_RETURN_POINTER(result);
}

Datum gtsvector_union ( PG_FUNCTION_ARGS   ) 

Definition at line 408 of file tsgistidx.c.

References CALCGTSIZE, SignTSVector::flag, flag(), GETENTRY, GETSIGN, i, ISALLTRUE, MemSet, GistEntryVector::n, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, SET_VARSIZE, and unionkey().

{
    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
    int        *size = (int *) PG_GETARG_POINTER(1);
    BITVEC      base;
    int32       i,
                len;
    int32       flag = 0;
    SignTSVector *result;

    MemSet((void *) base, 0, sizeof(BITVEC));
    for (i = 0; i < entryvec->n; i++)
    {
        if (unionkey(base, GETENTRY(entryvec, i)))
        {
            flag = ALLISTRUE;
            break;
        }
    }

    flag |= SIGNKEY;
    len = CALCGTSIZE(flag, 0);
    result = (SignTSVector *) palloc(len);
    *size = len;
    SET_VARSIZE(result, len);
    result->flag = flag;
    if (!ISALLTRUE(result))
        memcpy((void *) GETSIGN(result), (void *) base, sizeof(BITVEC));

    PG_RETURN_POINTER(result);
}

Datum gtsvectorin ( PG_FUNCTION_ARGS   ) 

Definition at line 94 of file tsgistidx.c.

References ereport, errcode(), errmsg(), ERROR, and PG_RETURN_DATUM.

{
    ereport(ERROR,
            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
             errmsg("gtsvector_in not implemented")));
    PG_RETURN_DATUM(0);
}

Datum gtsvectorout ( PG_FUNCTION_ARGS   ) 

Definition at line 109 of file tsgistidx.c.

References ARRNELEM, ARROUTSTR, DatumGetPointer, EXTRALEN, GETSIGN, ISALLTRUE, ISARRKEY, Max, outbuf_maxlen, palloc(), PG_DETOAST_DATUM, PG_FREE_IF_COPY, PG_GETARG_POINTER, PG_RETURN_POINTER, SIGLENBIT, SINGOUTSTR, and sizebitvec().

{
    SignTSVector *key = (SignTSVector *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_POINTER(0)));
    char       *outbuf;

    if (outbuf_maxlen == 0)
        outbuf_maxlen = 2 * EXTRALEN + Max(strlen(SINGOUTSTR), strlen(ARROUTSTR)) + 1;
    outbuf = palloc(outbuf_maxlen);

    if (ISARRKEY(key))
        sprintf(outbuf, ARROUTSTR, (int) ARRNELEM(key));
    else
    {
        int         cnttrue = (ISALLTRUE(key)) ? SIGLENBIT : sizebitvec(GETSIGN(key));

        sprintf(outbuf, SINGOUTSTR, cnttrue, (int) SIGLENBIT - cnttrue);
    }

    PG_FREE_IF_COPY(key, 0);
    PG_RETURN_POINTER(outbuf);
}

void hlparsetext ( Oid  cfgId,
HeadlineParsedText prs,
TSQuery  query,
char *  buf,
int32  buflen 
)
TSVectorParseState init_tsvector_parser ( char *  input,
bool  oprisdelim,
bool  is_tsquery 
)
TSVector make_tsvector ( ParsedText prs  ) 

Definition at line 138 of file to_tsany.c.

References ParsedWord::alen, ARRPTR, CALCDATASIZE, ParsedText::curwords, elog, ereport, errcode(), errmsg(), ERROR, WordEntry::haspos, i, WordEntry::len, ParsedWord::len, MAXSTRPOS, palloc0(), pfree(), WordEntry::pos, ParsedWord::pos, POSDATAPTR, SET_VARSIZE, SHORTALIGN, TSVectorData::size, STRPTR, uniqueWORD(), WEP_SETPOS, WEP_SETWEIGHT, ParsedWord::word, and ParsedText::words.

Referenced by to_tsvector_byid(), and tsvector_update_trigger().

{
    int         i,
                j,
                lenstr = 0,
                totallen;
    TSVector    in;
    WordEntry  *ptr;
    char       *str;
    int         stroff;

    prs->curwords = uniqueWORD(prs->words, prs->curwords);
    for (i = 0; i < prs->curwords; i++)
    {
        lenstr += prs->words[i].len;
        if (prs->words[i].alen)
        {
            lenstr = SHORTALIGN(lenstr);
            lenstr += sizeof(uint16) + prs->words[i].pos.apos[0] * sizeof(WordEntryPos);
        }
    }

    if (lenstr > MAXSTRPOS)
        ereport(ERROR,
                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                 errmsg("string is too long for tsvector (%d bytes, max %d bytes)", lenstr, MAXSTRPOS)));

    totallen = CALCDATASIZE(prs->curwords, lenstr);
    in = (TSVector) palloc0(totallen);
    SET_VARSIZE(in, totallen);
    in->size = prs->curwords;

    ptr = ARRPTR(in);
    str = STRPTR(in);
    stroff = 0;
    for (i = 0; i < prs->curwords; i++)
    {
        ptr->len = prs->words[i].len;
        ptr->pos = stroff;
        memcpy(str + stroff, prs->words[i].word, prs->words[i].len);
        stroff += prs->words[i].len;
        pfree(prs->words[i].word);
        if (prs->words[i].alen)
        {
            int         k = prs->words[i].pos.apos[0];
            WordEntryPos *wptr;

            if (k > 0xFFFF)
                elog(ERROR, "positions array too long");

            ptr->haspos = 1;
            stroff = SHORTALIGN(stroff);
            *(uint16 *) (str + stroff) = (uint16) k;
            wptr = POSDATAPTR(in, ptr);
            for (j = 0; j < k; j++)
            {
                WEP_SETWEIGHT(wptr[j], 0);
                WEP_SETPOS(wptr[j], prs->words[i].pos.apos[j + 1]);
            }
            stroff += sizeof(uint16) + k * sizeof(WordEntryPos);
            pfree(prs->words[i].pos.apos);
        }
        else
            ptr->haspos = 0;
        ptr++;
    }
    pfree(prs->words);
    return in;
}

TSQuerySign makeTSQuerySign ( TSQuery  a  ) 

Definition at line 200 of file tsquery_op.c.

References GETQUERY, i, QI_VAL, QueryItem::qoperand, sign, TSQueryData::size, QueryItem::type, and QueryOperand::valcrc.

Referenced by gtsquery_compress(), gtsquery_consistent(), and tsq_mcontains().

{
    int         i;
    QueryItem  *ptr = GETQUERY(a);
    TSQuerySign sign = 0;

    for (i = 0; i < a->size; i++)
    {
        if (ptr->type == QI_VAL)
            sign |= ((TSQuerySign) 1) << (((unsigned int) ptr->qoperand.valcrc) % TSQS_SIGLEN);
        ptr++;
    }

    return sign;
}

TSQuery parse_tsquery ( char *  buf,
PushFunction  pushval,
Datum  opaque,
bool  isplain 
)

Definition at line 473 of file tsquery.c.

References TSQueryParserStateData::buf, TSQueryParserStateData::buffer, close_tsvector_parser(), COMPUTESIZE, TSQueryParserStateData::count, TSQueryParserStateData::curop, elog, ereport, errmsg(), ERROR, findoprnd(), GETOPERAND, GETQUERY, HDRSIZETQ, i, init_tsvector_parser(), TSQueryParserStateData::lenop, lfirst, list_length(), makepol(), NOTICE, TSQueryParserStateData::op, palloc(), palloc0(), pfree(), TSQueryParserStateData::polstr, QI_OPR, QI_VAL, QI_VALSTOP, SET_VARSIZE, TSQueryData::size, TSQueryParserStateData::state, TSQueryParserStateData::sumlen, QueryItem::type, TSQueryParserStateData::valstate, WAITFIRSTOPERAND, and WAITSINGLEOPERAND.

Referenced by plainto_tsquery_byid(), to_tsquery_byid(), and tsqueryin().

{
    struct TSQueryParserStateData state;
    int         i;
    TSQuery     query;
    int         commonlen;
    QueryItem  *ptr;
    ListCell   *cell;

    /* init state */
    state.buffer = buf;
    state.buf = buf;
    state.state = (isplain) ? WAITSINGLEOPERAND : WAITFIRSTOPERAND;
    state.count = 0;
    state.polstr = NIL;

    /* init value parser's state */
    state.valstate = init_tsvector_parser(state.buffer, true, true);

    /* init list of operand */
    state.sumlen = 0;
    state.lenop = 64;
    state.curop = state.op = (char *) palloc(state.lenop);
    *(state.curop) = '\0';

    /* parse query & make polish notation (postfix, but in reverse order) */
    makepol(&state, pushval, opaque);

    close_tsvector_parser(state.valstate);

    if (list_length(state.polstr) == 0)
    {
        ereport(NOTICE,
                (errmsg("text-search query doesn't contain lexemes: \"%s\"",
                        state.buffer)));
        query = (TSQuery) palloc(HDRSIZETQ);
        SET_VARSIZE(query, HDRSIZETQ);
        query->size = 0;
        return query;
    }

    /* Pack the QueryItems in the final TSQuery struct to return to caller */
    commonlen = COMPUTESIZE(list_length(state.polstr), state.sumlen);
    query = (TSQuery) palloc0(commonlen);
    SET_VARSIZE(query, commonlen);
    query->size = list_length(state.polstr);
    ptr = GETQUERY(query);

    /* Copy QueryItems to TSQuery */
    i = 0;
    foreach(cell, state.polstr)
    {
        QueryItem  *item = (QueryItem *) lfirst(cell);

        switch (item->type)
        {
            case QI_VAL:
                memcpy(&ptr[i], item, sizeof(QueryOperand));
                break;
            case QI_VALSTOP:
                ptr[i].type = QI_VALSTOP;
                break;
            case QI_OPR:
                memcpy(&ptr[i], item, sizeof(QueryOperator));
                break;
            default:
                elog(ERROR, "unrecognized QueryItem type: %d", item->type);
        }
        i++;
    }

    /* Copy all the operand strings to TSQuery */
    memcpy((void *) GETOPERAND(query), (void *) state.op, state.sumlen);
    pfree(state.op);

    /* Set left operand pointers for every operator. */
    findoprnd(ptr, query->size);

    return query;
}

void parsetext ( Oid  cfgId,
ParsedText prs,
char *  buf,
int32  buflen 
)
Datum plainto_tsquery ( PG_FUNCTION_ARGS   ) 
Datum plainto_tsquery_byid ( PG_FUNCTION_ARGS   ) 

Definition at line 386 of file to_tsany.c.

References Assert, clean_fakeval(), COMPUTESIZE, GETOPERAND, GETQUERY, HDRSIZETQ, ObjectIdGetDatum, parse_tsquery(), pfree(), PG_GETARG_OID, PG_GETARG_TEXT_P, PG_RETURN_POINTER, PG_RETURN_TSQUERY, pushval_morph(), SET_VARSIZE, TSQueryData::size, text_to_cstring(), and VARSIZE.

Referenced by plainto_tsquery(), and tsa_plainto_tsquery_name().

{
    Oid         cfgid = PG_GETARG_OID(0);
    text       *in = PG_GETARG_TEXT_P(1);
    TSQuery     query;
    QueryItem  *res;
    int32       len;

    query = parse_tsquery(text_to_cstring(in), pushval_morph, ObjectIdGetDatum(cfgid), true);

    if (query->size == 0)
        PG_RETURN_TSQUERY(query);

    res = clean_fakeval(GETQUERY(query), &len);
    if (!res)
    {
        SET_VARSIZE(query, HDRSIZETQ);
        query->size = 0;
        PG_RETURN_POINTER(query);
    }
    memcpy((void *) GETQUERY(query), (void *) res, len * sizeof(QueryItem));

    if (len != query->size)
    {
        char       *oldoperand = GETOPERAND(query);
        int32       lenoperand = VARSIZE(query) - (oldoperand - (char *) query);

        Assert(len < query->size);

        query->size = len;
        memcpy((void *) GETOPERAND(query), oldoperand, lenoperand);
        SET_VARSIZE(query, COMPUTESIZE(len, lenoperand));
    }

    pfree(res);
    PG_RETURN_POINTER(query);
}

Datum prsd_end ( PG_FUNCTION_ARGS   ) 

Definition at line 1998 of file wparser_def.c.

References PG_GETARG_POINTER, PG_RETURN_VOID, and TParserClose().

Datum prsd_headline ( PG_FUNCTION_ARGS   ) 

Definition at line 2505 of file wparser_def.c.

References defGetString(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, HeadlineParsedText::fragdelim, HeadlineParsedText::fragdelimlen, lfirst, mark_hl_fragments(), mark_hl_words(), pg_atoi(), PG_GETARG_POINTER, PG_GETARG_TSQUERY, PG_RETURN_POINTER, pg_strcasecmp(), pstrdup(), HeadlineParsedText::startsel, HeadlineParsedText::startsellen, HeadlineParsedText::stopsel, HeadlineParsedText::stopsellen, and val.

{
    HeadlineParsedText *prs = (HeadlineParsedText *) PG_GETARG_POINTER(0);
    List       *prsoptions = (List *) PG_GETARG_POINTER(1);
    TSQuery     query = PG_GETARG_TSQUERY(2);

    /* from opt + start and end tag */
    int         min_words = 15;
    int         max_words = 35;
    int         shortword = 3;
    int         max_fragments = 0;
    int         highlight = 0;
    ListCell   *l;

    /* config */
    prs->startsel = NULL;
    prs->stopsel = NULL;
    foreach(l, prsoptions)
    {
        DefElem    *defel = (DefElem *) lfirst(l);
        char       *val = defGetString(defel);

        if (pg_strcasecmp(defel->defname, "MaxWords") == 0)
            max_words = pg_atoi(val, sizeof(int32), 0);
        else if (pg_strcasecmp(defel->defname, "MinWords") == 0)
            min_words = pg_atoi(val, sizeof(int32), 0);
        else if (pg_strcasecmp(defel->defname, "ShortWord") == 0)
            shortword = pg_atoi(val, sizeof(int32), 0);
        else if (pg_strcasecmp(defel->defname, "MaxFragments") == 0)
            max_fragments = pg_atoi(val, sizeof(int32), 0);
        else if (pg_strcasecmp(defel->defname, "StartSel") == 0)
            prs->startsel = pstrdup(val);
        else if (pg_strcasecmp(defel->defname, "StopSel") == 0)
            prs->stopsel = pstrdup(val);
        else if (pg_strcasecmp(defel->defname, "FragmentDelimiter") == 0)
            prs->fragdelim = pstrdup(val);
        else if (pg_strcasecmp(defel->defname, "HighlightAll") == 0)
            highlight = (pg_strcasecmp(val, "1") == 0 ||
                         pg_strcasecmp(val, "on") == 0 ||
                         pg_strcasecmp(val, "true") == 0 ||
                         pg_strcasecmp(val, "t") == 0 ||
                         pg_strcasecmp(val, "y") == 0 ||
                         pg_strcasecmp(val, "yes") == 0);
        else
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("unrecognized headline parameter: \"%s\"",
                            defel->defname)));
    }

    if (highlight == 0)
    {
        if (min_words >= max_words)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("MinWords should be less than MaxWords")));
        if (min_words <= 0)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("MinWords should be positive")));
        if (shortword < 0)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("ShortWord should be >= 0")));
        if (max_fragments < 0)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("MaxFragments should be >= 0")));
    }

    if (max_fragments == 0)
        /* call the default headline generator */
        mark_hl_words(prs, query, highlight, shortword, min_words, max_words);
    else
        mark_hl_fragments(prs, query, highlight, shortword, min_words, max_words, max_fragments);

    if (!prs->startsel)
        prs->startsel = pstrdup("<b>");
    if (!prs->stopsel)
        prs->stopsel = pstrdup("</b>");
    if (!prs->fragdelim)
        prs->fragdelim = pstrdup(" ... ");
    prs->startsellen = strlen(prs->startsel);
    prs->stopsellen = strlen(prs->stopsel);
    prs->fragdelimlen = strlen(prs->fragdelim);

    PG_RETURN_POINTER(prs);
}

Datum prsd_lextype ( PG_FUNCTION_ARGS   ) 

Definition at line 1958 of file wparser_def.c.

References LexDescr::alias, LexDescr::descr, i, LASTNUM, lex_descr, LexDescr::lexid, palloc(), PG_RETURN_POINTER, pstrdup(), and tok_alias.

{
    LexDescr   *descr = (LexDescr *) palloc(sizeof(LexDescr) * (LASTNUM + 1));
    int         i;

    for (i = 1; i <= LASTNUM; i++)
    {
        descr[i - 1].lexid = i;
        descr[i - 1].alias = pstrdup(tok_alias[i]);
        descr[i - 1].descr = pstrdup(lex_descr[i]);
    }

    descr[LASTNUM].lexid = 0;

    PG_RETURN_POINTER(descr);
}

Datum prsd_nexttoken ( PG_FUNCTION_ARGS   ) 

Definition at line 1982 of file wparser_def.c.

References TParser::lenbytetoken, PG_GETARG_POINTER, PG_RETURN_INT32, TParser::token, TParserGet(), and TParser::type.

{
    TParser    *p = (TParser *) PG_GETARG_POINTER(0);
    char      **t = (char **) PG_GETARG_POINTER(1);
    int        *tlen = (int *) PG_GETARG_POINTER(2);

    if (!TParserGet(p))
        PG_RETURN_INT32(0);

    *t = p->token;
    *tlen = p->lenbytetoken;

    PG_RETURN_INT32(p->type);
}

Datum prsd_start ( PG_FUNCTION_ARGS   ) 
void pushOperator ( TSQueryParserState  state,
int8  oper 
)

Definition at line 225 of file tsquery.c.

References Assert, lcons(), OP_AND, OP_NOT, OP_OR, QueryOperator::oper, palloc0(), TSQueryParserStateData::polstr, and QueryOperator::type.

Referenced by makepol(), and pushval_morph().

{
    QueryOperator *tmp;

    Assert(oper == OP_NOT || oper == OP_AND || oper == OP_OR);

    tmp = (QueryOperator *) palloc0(sizeof(QueryOperator));
    tmp->type = QI_OPR;
    tmp->oper = oper;
    /* left is filled in later with findoprnd */

    state->polstr = lcons(tmp, state->polstr);
}

void pushStop ( TSQueryParserState  state  ) 

Definition at line 309 of file tsquery.c.

References lcons(), palloc0(), TSQueryParserStateData::polstr, and QueryOperand::type.

Referenced by pushval_morph().

{
    QueryOperand *tmp;

    tmp = (QueryOperand *) palloc0(sizeof(QueryOperand));
    tmp->type = QI_VALSTOP;

    state->polstr = lcons(tmp, state->polstr);
}

void pushValue ( TSQueryParserState  state,
char *  strval,
int  lenval,
int16  weight,
bool  prefix 
)

Definition at line 273 of file tsquery.c.

References TSQueryParserStateData::buffer, COMP_CRC32, TSQueryParserStateData::curop, ereport, errcode(), errmsg(), ERROR, FIN_CRC32, INIT_CRC32, TSQueryParserStateData::lenop, MAXSTRLEN, TSQueryParserStateData::op, pushValue_internal(), repalloc(), and TSQueryParserStateData::sumlen.

Referenced by pushval_asis(), and pushval_morph().

{
    pg_crc32    valcrc;

    if (lenval >= MAXSTRLEN)
        ereport(ERROR,
                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                 errmsg("word is too long in tsquery: \"%s\"",
                        state->buffer)));

    INIT_CRC32(valcrc);
    COMP_CRC32(valcrc, strval, lenval);
    FIN_CRC32(valcrc);
    pushValue_internal(state, valcrc, state->curop - state->op, lenval, weight, prefix);

    /* append the value string to state.op, enlarging buffer if needed first */
    while (state->curop - state->op + lenval + 1 >= state->lenop)
    {
        int         used = state->curop - state->op;

        state->lenop *= 2;
        state->op = (char *) repalloc((void *) state->op, state->lenop);
        state->curop = state->op + used;
    }
    memcpy((void *) state->curop, (void *) strval, lenval);
    state->curop += lenval;
    *(state->curop) = '\0';
    state->curop++;
    state->sumlen += lenval + 1 /* \0 */ ;
}

QTNode* QT2QTN ( QueryItem in,
char *  operand 
)

Definition at line 21 of file tsquery_util.c.

References check_stack_depth(), QTNode::child, QueryOperand::distance, QueryOperator::left, QTNode::nchild, OP_NOT, QueryOperator::oper, palloc0(), QI_OPR, QueryItem::qoperand, QueryItem::qoperator, QT2QTN(), QTNode::sign, QueryItem::type, QueryOperand::valcrc, QTNode::valnode, and QTNode::word.

Referenced by CompareTSQ(), join_tsqueries(), QT2QTN(), tsa_rewrite_accum(), tsquery_not(), tsquery_rewrite(), and tsquery_rewrite_query().

{
    QTNode     *node = (QTNode *) palloc0(sizeof(QTNode));

    /* since this function recurses, it could be driven to stack overflow. */
    check_stack_depth();

    node->valnode = in;

    if (in->type == QI_OPR)
    {
        node->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
        node->child[0] = QT2QTN(in + 1, operand);
        node->sign = node->child[0]->sign;
        if (in->qoperator.oper == OP_NOT)
            node->nchild = 1;
        else
        {
            node->nchild = 2;
            node->child[1] = QT2QTN(in + in->qoperator.left, operand);
            node->sign |= node->child[1]->sign;
        }
    }
    else if (operand)
    {
        node->word = operand + in->qoperand.distance;
        node->sign = ((uint32) 1) << (((unsigned int) in->qoperand.valcrc) % 32);
    }

    return node;
}

TSQuery QTN2QT ( QTNode in  ) 

Definition at line 327 of file tsquery_util.c.

References cntsize(), COMPUTESIZE, QTN2QTState::curitem, QTN2QTState::curoperand, fillQT(), GETOPERAND, GETQUERY, QTN2QTState::operand, palloc0(), SET_VARSIZE, and TSQueryData::size.

Referenced by tsa_rewrite_accum(), tsquery_and(), tsquery_not(), tsquery_or(), tsquery_rewrite(), and tsquery_rewrite_query().

{
    TSQuery     out;
    int         len;
    int         sumlen = 0,
                nnode = 0;
    QTN2QTState state;

    cntsize(in, &sumlen, &nnode);
    len = COMPUTESIZE(nnode, sumlen);

    out = (TSQuery) palloc0(len);
    SET_VARSIZE(out, len);
    out->size = nnode;

    state.curitem = GETQUERY(out);
    state.operand = state.curoperand = GETOPERAND(out);

    fillQT(&state, in);
    return out;
}

void QTNBinary ( QTNode in  ) 

Definition at line 219 of file tsquery_util.c.

References check_stack_depth(), QTNode::child, QTNode::flags, i, QTNode::nchild, QueryOperator::oper, palloc0(), QI_OPR, QueryItem::qoperator, QTNBinary(), QTNode::sign, QueryItem::type, and QTNode::valnode.

Referenced by QTNBinary(), tsa_rewrite_accum(), tsquery_rewrite(), and tsquery_rewrite_query().

{
    int         i;

    /* since this function recurses, it could be driven to stack overflow. */
    check_stack_depth();

    if (in->valnode->type != QI_OPR)
        return;

    for (i = 0; i < in->nchild; i++)
        QTNBinary(in->child[i]);

    if (in->nchild <= 2)
        return;

    while (in->nchild > 2)
    {
        QTNode     *nn = (QTNode *) palloc0(sizeof(QTNode));

        nn->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
        nn->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);

        nn->nchild = 2;
        nn->flags = QTN_NEEDFREE;

        nn->child[0] = in->child[0];
        nn->child[1] = in->child[1];
        nn->sign = nn->child[0]->sign | nn->child[1]->sign;

        nn->valnode->type = in->valnode->type;
        nn->valnode->qoperator.oper = in->valnode->qoperator.oper;

        in->child[0] = nn;
        in->child[1] = in->child[in->nchild - 1];
        in->nchild--;
    }
}

void QTNClearFlags ( QTNode in,
uint32  flags 
)

Definition at line 385 of file tsquery_util.c.

References check_stack_depth(), QTNode::child, QTNode::flags, i, QTNode::nchild, QI_VAL, QTNClearFlags(), QueryItem::type, and QTNode::valnode.

Referenced by QTNClearFlags(), and tsquery_rewrite_query().

{
    /* since this function recurses, it could be driven to stack overflow. */
    check_stack_depth();

    in->flags &= ~flags;

    if (in->valnode->type != QI_VAL)
    {
        int         i;

        for (i = 0; i < in->nchild; i++)
            QTNClearFlags(in->child[i], flags);
    }
}

QTNode* QTNCopy ( QTNode in  ) 

Definition at line 350 of file tsquery_util.c.

References check_stack_depth(), QTNode::child, QTNode::flags, i, QueryOperand::length, QTNode::nchild, palloc(), QI_VAL, QueryItem::qoperand, QTNCopy(), QueryItem::type, QTNode::valnode, and QTNode::word.

Referenced by findeq(), and QTNCopy().

{
    QTNode     *out;

    /* since this function recurses, it could be driven to stack overflow. */
    check_stack_depth();

    out = (QTNode *) palloc(sizeof(QTNode));

    *out = *in;
    out->valnode = (QueryItem *) palloc(sizeof(QueryItem));
    *(out->valnode) = *(in->valnode);
    out->flags |= QTN_NEEDFREE;

    if (in->valnode->type == QI_VAL)
    {
        out->word = palloc(in->valnode->qoperand.length + 1);
        memcpy(out->word, in->word, in->valnode->qoperand.length);
        out->word[in->valnode->qoperand.length] = '\0';
        out->flags |= QTN_WORDFREE;
    }
    else
    {
        int         i;

        out->child = (QTNode **) palloc(sizeof(QTNode *) * in->nchild);

        for (i = 0; i < in->nchild; i++)
            out->child[i] = QTNCopy(in->child[i]);
    }

    return out;
}

bool QTNEq ( QTNode a,
QTNode b 
)

Definition at line 158 of file tsquery_util.c.

References QTNodeCompare(), QTNode::sign, and sign.

Referenced by findeq().

{
    uint32      sign = a->sign & b->sign;

    if (!(sign == a->sign && sign == b->sign))
        return 0;

    return (QTNodeCompare(a, b) == 0) ? true : false;
}

void QTNFree ( QTNode in  ) 

Definition at line 54 of file tsquery_util.c.

References check_stack_depth(), QTNode::child, QTNode::flags, i, QTNode::nchild, pfree(), QI_OPR, QI_VAL, QTN_NEEDFREE, QTN_WORDFREE, QTNFree(), QueryItem::type, QTNode::valnode, and QTNode::word.

Referenced by CompareTSQ(), dropvoidsubtree(), findeq(), QTNFree(), tsa_rewrite_accum(), tsquery_and(), tsquery_not(), tsquery_or(), tsquery_rewrite(), and tsquery_rewrite_query().

{
    if (!in)
        return;

    /* since this function recurses, it could be driven to stack overflow. */
    check_stack_depth();

    if (in->valnode->type == QI_VAL && in->word && (in->flags & QTN_WORDFREE) != 0)
        pfree(in->word);

    if (in->child)
    {
        if (in->valnode)
        {
            if (in->valnode->type == QI_OPR && in->nchild > 0)
            {
                int         i;

                for (i = 0; i < in->nchild; i++)
                    QTNFree(in->child[i]);
            }
            if (in->flags & QTN_NEEDFREE)
                pfree(in->valnode);
        }
        pfree(in->child);
    }

    pfree(in);
}

int QTNodeCompare ( QTNode an,
QTNode bn 
)

Definition at line 86 of file tsquery_util.c.

References check_stack_depth(), QTNode::child, elog, ERROR, i, QueryOperand::length, QTNode::nchild, QueryOperator::oper, QI_OPR, QI_VAL, QueryItem::qoperand, QueryItem::qoperator, QTNodeCompare(), tsCompareString(), QueryItem::type, QueryOperand::valcrc, QTNode::valnode, and QTNode::word.

Referenced by cmpQTN(), CompareTSQ(), QTNEq(), and QTNodeCompare().

{
    /* since this function recurses, it could be driven to stack overflow. */
    check_stack_depth();

    if (an->valnode->type != bn->valnode->type)
        return (an->valnode->type > bn->valnode->type) ? -1 : 1;

    if (an->valnode->type == QI_OPR)
    {
        QueryOperator *ao = &an->valnode->qoperator;
        QueryOperator *bo = &bn->valnode->qoperator;

        if (ao->oper != bo->oper)
            return (ao->oper > bo->oper) ? -1 : 1;

        if (an->nchild != bn->nchild)
            return (an->nchild > bn->nchild) ? -1 : 1;

        {
            int         i,
                        res;

            for (i = 0; i < an->nchild; i++)
                if ((res = QTNodeCompare(an->child[i], bn->child[i])) != 0)
                    return res;
        }
        return 0;
    }
    else if (an->valnode->type == QI_VAL)
    {
        QueryOperand *ao = &an->valnode->qoperand;
        QueryOperand *bo = &bn->valnode->qoperand;

        if (ao->valcrc != bo->valcrc)
        {
            return (ao->valcrc > bo->valcrc) ? -1 : 1;
        }

        return tsCompareString(an->word, ao->length, bn->word, bo->length, false);
    }
    else
    {
        elog(ERROR, "unrecognized QueryItem type: %d", an->valnode->type);
        return 0;               /* keep compiler quiet */
    }
}

void QTNSort ( QTNode in  ) 

Definition at line 141 of file tsquery_util.c.

References check_stack_depth(), QTNode::child, cmpQTN(), i, QTNode::nchild, QI_OPR, qsort, QTNSort(), QueryItem::type, and QTNode::valnode.

Referenced by findeq(), QTNSort(), tsa_rewrite_accum(), tsquery_rewrite(), and tsquery_rewrite_query().

{
    int         i;

    /* since this function recurses, it could be driven to stack overflow. */
    check_stack_depth();

    if (in->valnode->type != QI_OPR)
        return;

    for (i = 0; i < in->nchild; i++)
        QTNSort(in->child[i]);
    if (in->nchild > 1)
        qsort((void *) in->child, in->nchild, sizeof(QTNode *), cmpQTN);
}

void QTNTernary ( QTNode in  ) 

Definition at line 176 of file tsquery_util.c.

References check_stack_depth(), QTNode::child, QTNode::flags, i, memmove, QTNode::nchild, QueryOperator::oper, pfree(), QI_OPR, QueryItem::qoperator, QTN_NEEDFREE, QTNTernary(), repalloc(), QueryItem::type, and QTNode::valnode.

Referenced by QTNTernary(), tsa_rewrite_accum(), tsquery_rewrite(), and tsquery_rewrite_query().

{
    int         i;

    /* since this function recurses, it could be driven to stack overflow. */
    check_stack_depth();

    if (in->valnode->type != QI_OPR)
        return;

    for (i = 0; i < in->nchild; i++)
        QTNTernary(in->child[i]);

    for (i = 0; i < in->nchild; i++)
    {
        QTNode     *cc = in->child[i];

        if (cc->valnode->type == QI_OPR && in->valnode->qoperator.oper == cc->valnode->qoperator.oper)
        {
            int         oldnchild = in->nchild;

            in->nchild += cc->nchild - 1;
            in->child = (QTNode **) repalloc(in->child, in->nchild * sizeof(QTNode *));

            if (i + 1 != oldnchild)
                memmove(in->child + i + cc->nchild, in->child + i + 1,
                        (oldnchild - i - 1) * sizeof(QTNode *));

            memcpy(in->child + i, cc->child, cc->nchild * sizeof(QTNode *));
            i += cc->nchild - 1;

            if (cc->flags & QTN_NEEDFREE)
                pfree(cc->valnode);
            pfree(cc);
        }
    }
}

void reset_tsvector_parser ( TSVectorParseState  state,
char *  input 
)

Definition at line 65 of file tsvector_parser.c.

References TSVectorParseStateData::prsbuf.

Referenced by gettoken_query().

{
    state->prsbuf = input;
}

Datum thesaurus_init ( PG_FUNCTION_ARGS   ) 

Definition at line 595 of file dict_thesaurus.c.

References compileTheLexeme(), compileTheSubstitute(), defGetString(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, get_ts_dict_oid(), lfirst, lookup_ts_dictionary_cache(), palloc0(), PG_GETARG_POINTER, PG_RETURN_POINTER, pg_strcasecmp(), pstrdup(), stringToQualifiedNameList(), DictThesaurus::subdict, DictThesaurus::subdictOid, and thesaurusRead().

{
    List       *dictoptions = (List *) PG_GETARG_POINTER(0);
    DictThesaurus *d;
    char       *subdictname = NULL;
    bool        fileloaded = false;
    ListCell   *l;

    d = (DictThesaurus *) palloc0(sizeof(DictThesaurus));

    foreach(l, dictoptions)
    {
        DefElem    *defel = (DefElem *) lfirst(l);

        if (pg_strcasecmp("DictFile", defel->defname) == 0)
        {
            if (fileloaded)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("multiple DictFile parameters")));
            thesaurusRead(defGetString(defel), d);
            fileloaded = true;
        }
        else if (pg_strcasecmp("Dictionary", defel->defname) == 0)
        {
            if (subdictname)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("multiple Dictionary parameters")));
            subdictname = pstrdup(defGetString(defel));
        }
        else
        {
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("unrecognized Thesaurus parameter: \"%s\"",
                            defel->defname)));
        }
    }

    if (!fileloaded)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("missing DictFile parameter")));
    if (!subdictname)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("missing Dictionary parameter")));

    d->subdictOid = get_ts_dict_oid(stringToQualifiedNameList(subdictname), false);
    d->subdict = lookup_ts_dictionary_cache(d->subdictOid);

    compileTheLexeme(d);
    compileTheSubstitute(d);

    PG_RETURN_POINTER(d);
}

Datum thesaurus_lexize ( PG_FUNCTION_ARGS   ) 

Definition at line 785 of file dict_thesaurus.c.

References checkMatch(), DatumGetPointer, TSDictionaryCacheEntry::dictData, elog, ERROR, findTheLexeme(), findVariant(), FunctionCall4, DictSubState::getnext, i, DictSubState::isend, TSDictionaryCacheEntry::isvalid, TSLexeme::lexeme, TSDictionaryCacheEntry::lexize, lookup_ts_dictionary_cache(), NULL, TSLexeme::nvariant, palloc(), pfree(), PG_GETARG_DATUM, PG_GETARG_POINTER, PG_NARGS, PG_RETURN_POINTER, PointerGetDatum, LexemeInfo::posinsubst, DictSubState::private_state, DictThesaurus::subdict, and DictThesaurus::subdictOid.

{
    DictThesaurus *d = (DictThesaurus *) PG_GETARG_POINTER(0);
    DictSubState *dstate = (DictSubState *) PG_GETARG_POINTER(3);
    TSLexeme   *res = NULL;
    LexemeInfo *stored,
               *info = NULL;
    uint16      curpos = 0;
    bool        moreres = false;

    if (PG_NARGS() != 4 || dstate == NULL)
        elog(ERROR, "forbidden call of thesaurus or nested call");

    if (dstate->isend)
        PG_RETURN_POINTER(NULL);
    stored = (LexemeInfo *) dstate->private_state;

    if (stored)
        curpos = stored->posinsubst + 1;

    if (!d->subdict->isvalid)
        d->subdict = lookup_ts_dictionary_cache(d->subdictOid);

    res = (TSLexeme *) DatumGetPointer(FunctionCall4(&(d->subdict->lexize),
                                       PointerGetDatum(d->subdict->dictData),
                                                     PG_GETARG_DATUM(1),
                                                     PG_GETARG_DATUM(2),
                                                     PointerGetDatum(NULL)));

    if (res && res->lexeme)
    {
        TSLexeme   *ptr = res,
                   *basevar;

        while (ptr->lexeme)
        {
            uint16      nv = ptr->nvariant;
            uint16      i,
                        nlex = 0;
            LexemeInfo **infos;

            basevar = ptr;
            while (ptr->lexeme && nv == ptr->nvariant)
            {
                nlex++;
                ptr++;
            }

            infos = (LexemeInfo **) palloc(sizeof(LexemeInfo *) * nlex);
            for (i = 0; i < nlex; i++)
                if ((infos[i] = findTheLexeme(d, basevar[i].lexeme)) == NULL)
                    break;

            if (i < nlex)
            {
                /* no chance to find */
                pfree(infos);
                continue;
            }

            info = findVariant(info, stored, curpos, infos, nlex);
        }
    }
    else if (res)
    {                           /* stop-word */
        LexemeInfo *infos = findTheLexeme(d, NULL);

        info = findVariant(NULL, stored, curpos, &infos, 1);
    }
    else
    {
        info = NULL;            /* word isn't recognized */
    }

    dstate->private_state = (void *) info;

    if (!info)
    {
        dstate->getnext = false;
        PG_RETURN_POINTER(NULL);
    }

    if ((res = checkMatch(d, info, curpos, &moreres)) != NULL)
    {
        dstate->getnext = moreres;
        PG_RETURN_POINTER(res);
    }

    dstate->getnext = true;

    PG_RETURN_POINTER(NULL);
}

Datum to_tsquery ( PG_FUNCTION_ARGS   ) 
Datum to_tsquery_byid ( PG_FUNCTION_ARGS   ) 

Definition at line 330 of file to_tsany.c.

References Assert, clean_fakeval(), COMPUTESIZE, GETOPERAND, GETQUERY, HDRSIZETQ, memmove, ObjectIdGetDatum, parse_tsquery(), pfree(), PG_GETARG_OID, PG_GETARG_TEXT_P, PG_RETURN_POINTER, PG_RETURN_TSQUERY, pushval_morph(), SET_VARSIZE, TSQueryData::size, text_to_cstring(), and VARSIZE.

Referenced by to_tsquery(), and tsa_to_tsquery_name().

{
    Oid         cfgid = PG_GETARG_OID(0);
    text       *in = PG_GETARG_TEXT_P(1);
    TSQuery     query;
    QueryItem  *res;
    int32       len;

    query = parse_tsquery(text_to_cstring(in), pushval_morph, ObjectIdGetDatum(cfgid), false);

    if (query->size == 0)
        PG_RETURN_TSQUERY(query);

    /* clean out any stopword placeholders from the tree */
    res = clean_fakeval(GETQUERY(query), &len);
    if (!res)
    {
        SET_VARSIZE(query, HDRSIZETQ);
        query->size = 0;
        PG_RETURN_POINTER(query);
    }
    memcpy((void *) GETQUERY(query), (void *) res, len * sizeof(QueryItem));

    /*
     * Removing the stopword placeholders might've resulted in fewer
     * QueryItems. If so, move the operands up accordingly.
     */
    if (len != query->size)
    {
        char       *oldoperand = GETOPERAND(query);
        int32       lenoperand = VARSIZE(query) - (oldoperand - (char *) query);

        Assert(len < query->size);

        query->size = len;
        memmove((void *) GETOPERAND(query), oldoperand, VARSIZE(query) - (oldoperand - (char *) query));
        SET_VARSIZE(query, COMPUTESIZE(len, lenoperand));
    }

    pfree(res);
    PG_RETURN_TSQUERY(query);
}

Datum to_tsvector ( PG_FUNCTION_ARGS   ) 
Datum to_tsvector_byid ( PG_FUNCTION_ARGS   ) 

Definition at line 209 of file to_tsany.c.

References CALCDATASIZE, ParsedText::curwords, ParsedText::lenwords, make_tsvector(), palloc(), parsetext(), pfree(), PG_FREE_IF_COPY, PG_GETARG_OID, PG_GETARG_TEXT_P, PG_RETURN_POINTER, ParsedText::pos, SET_VARSIZE, TSVectorData::size, VARDATA, VARHDRSZ, VARSIZE, and ParsedText::words.

Referenced by to_tsvector(), and tsa_to_tsvector_name().

{
    Oid         cfgId = PG_GETARG_OID(0);
    text       *in = PG_GETARG_TEXT_P(1);
    ParsedText  prs;
    TSVector    out;

    prs.lenwords = (VARSIZE(in) - VARHDRSZ) / 6;        /* just estimation of
                                                         * word's number */
    if (prs.lenwords == 0)
        prs.lenwords = 2;
    prs.curwords = 0;
    prs.pos = 0;
    prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);

    parsetext(cfgId, &prs, VARDATA(in), VARSIZE(in) - VARHDRSZ);
    PG_FREE_IF_COPY(in, 1);

    if (prs.curwords)
        out = make_tsvector(&prs);
    else
    {
        pfree(prs.words);
        out = palloc(CALCDATASIZE(0, 0));
        SET_VARSIZE(out, CALCDATASIZE(0, 0));
        out->size = 0;
    }

    PG_RETURN_POINTER(out);
}

bool TS_execute ( QueryItem curitem,
void *  checkval,
bool  calcnot,
bool(*)(void *checkval, QueryOperand *val chkcond 
)

Definition at line 681 of file tsvector_op.c.

References check_stack_depth(), elog, ERROR, OP_AND, OP_NOT, OP_OR, QI_VAL, TS_execute(), and QueryItem::type.

Referenced by Cover(), gin_tsquery_consistent(), gtsvector_consistent(), hlCover(), TS_execute(), and ts_match_vq().

{
    /* since this function recurses, it could be driven to stack overflow */
    check_stack_depth();

    if (curitem->type == QI_VAL)
        return chkcond(checkval, (QueryOperand *) curitem);

    switch (curitem->qoperator.oper)
    {
        case OP_NOT:
            if (calcnot)
                return !TS_execute(curitem + 1, checkval, calcnot, chkcond);
            else
                return true;

        case OP_AND:
            if (TS_execute(curitem + curitem->qoperator.left, checkval, calcnot, chkcond))
                return TS_execute(curitem + 1, checkval, calcnot, chkcond);
            else
                return false;

        case OP_OR:
            if (TS_execute(curitem + curitem->qoperator.left, checkval, calcnot, chkcond))
                return true;
            else
                return TS_execute(curitem + 1, checkval, calcnot, chkcond);

        default:
            elog(ERROR, "unrecognized operator: %d", curitem->qoperator.oper);
    }

    /* not reachable, but keep compiler quiet */
    return false;
}

Datum ts_headline ( PG_FUNCTION_ARGS   ) 
Datum ts_headline_byid ( PG_FUNCTION_ARGS   ) 
Datum ts_headline_byid_opt ( PG_FUNCTION_ARGS   ) 

Definition at line 289 of file wparser.c.

References TSConfigCacheEntry::cfgId, deserialize_deflist(), ereport, errcode(), errmsg(), ERROR, FunctionCall3, generateHeadline(), TSParserCacheEntry::headlineOid, hlparsetext(), HeadlineParsedText::lenwords, lookup_ts_config_cache(), lookup_ts_parser_cache(), OidIsValid, palloc(), pfree(), PG_FREE_IF_COPY, PG_GETARG_OID, PG_GETARG_POINTER, PG_GETARG_TEXT_P, PG_GETARG_TSQUERY, PG_NARGS, PG_RETURN_POINTER, PointerGetDatum, TSParserCacheEntry::prsheadline, TSConfigCacheEntry::prsId, HeadlineParsedText::startsel, HeadlineParsedText::stopsel, VARDATA, VARHDRSZ, VARSIZE, and HeadlineParsedText::words.

Referenced by ts_headline(), ts_headline_byid(), ts_headline_opt(), and tsa_headline_byname().

{
    text       *in = PG_GETARG_TEXT_P(1);
    TSQuery     query = PG_GETARG_TSQUERY(2);
    text       *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
    HeadlineParsedText prs;
    List       *prsoptions;
    text       *out;
    TSConfigCacheEntry *cfg;
    TSParserCacheEntry *prsobj;

    cfg = lookup_ts_config_cache(PG_GETARG_OID(0));
    prsobj = lookup_ts_parser_cache(cfg->prsId);

    if (!OidIsValid(prsobj->headlineOid))
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
           errmsg("text search parser does not support headline creation")));

    memset(&prs, 0, sizeof(HeadlineParsedText));
    prs.lenwords = 32;
    prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);

    hlparsetext(cfg->cfgId, &prs, query, VARDATA(in), VARSIZE(in) - VARHDRSZ);

    if (opt)
        prsoptions = deserialize_deflist(PointerGetDatum(opt));
    else
        prsoptions = NIL;

    FunctionCall3(&(prsobj->prsheadline),
                  PointerGetDatum(&prs),
                  PointerGetDatum(prsoptions),
                  PointerGetDatum(query));

    out = generateHeadline(&prs);

    PG_FREE_IF_COPY(in, 1);
    PG_FREE_IF_COPY(query, 2);
    if (opt)
        PG_FREE_IF_COPY(opt, 3);
    pfree(prs.words);
    pfree(prs.startsel);
    pfree(prs.stopsel);

    PG_RETURN_POINTER(out);
}

Datum ts_headline_opt ( PG_FUNCTION_ARGS   ) 
Datum ts_lexize ( PG_FUNCTION_ARGS   ) 

Definition at line 26 of file dict.c.

References construct_array(), CStringGetTextDatum, DatumGetPointer, TSDictionaryCacheEntry::dictData, FunctionCall4, DictSubState::getnext, Int32GetDatum, DictSubState::isend, TSLexeme::lexeme, TSDictionaryCacheEntry::lexize, lookup_ts_dictionary_cache(), NULL, palloc(), pfree(), PG_GETARG_OID, PG_GETARG_TEXT_P, PG_RETURN_NULL, PG_RETURN_POINTER, PointerGetDatum, TEXTOID, VARDATA, VARHDRSZ, and VARSIZE.

Referenced by tsa_lexize_bycurrent(), and tsa_lexize_byname().

{
    Oid         dictId = PG_GETARG_OID(0);
    text       *in = PG_GETARG_TEXT_P(1);
    ArrayType  *a;
    TSDictionaryCacheEntry *dict;
    TSLexeme   *res,
               *ptr;
    Datum      *da;
    DictSubState dstate = {false, false, NULL};

    dict = lookup_ts_dictionary_cache(dictId);

    res = (TSLexeme *) DatumGetPointer(FunctionCall4(&dict->lexize,
                                             PointerGetDatum(dict->dictData),
                                                PointerGetDatum(VARDATA(in)),
                                       Int32GetDatum(VARSIZE(in) - VARHDRSZ),
                                                  PointerGetDatum(&dstate)));

    if (dstate.getnext)
    {
        dstate.isend = true;
        ptr = (TSLexeme *) DatumGetPointer(FunctionCall4(&dict->lexize,
                                             PointerGetDatum(dict->dictData),
                                                PointerGetDatum(VARDATA(in)),
                                       Int32GetDatum(VARSIZE(in) - VARHDRSZ),
                                                  PointerGetDatum(&dstate)));
        if (ptr != NULL)
            res = ptr;
    }

    if (!res)
        PG_RETURN_NULL();

    ptr = res;
    while (ptr->lexeme)
        ptr++;
    da = (Datum *) palloc(sizeof(Datum) * (ptr - res));
    ptr = res;
    while (ptr->lexeme)
    {
        da[ptr - res] = CStringGetTextDatum(ptr->lexeme);
        ptr++;
    }

    a = construct_array(da,
                        ptr - res,
                        TEXTOID,
                        -1,
                        false,
                        'i');

    ptr = res;
    while (ptr->lexeme)
    {
        pfree(DatumGetPointer(da[ptr - res]));
        pfree(ptr->lexeme);
        ptr++;
    }
    pfree(res);
    pfree(da);

    PG_RETURN_POINTER(a);
}

Datum ts_parse_byid ( PG_FUNCTION_ARGS   ) 
Datum ts_parse_byname ( PG_FUNCTION_ARGS   ) 

Definition at line 265 of file wparser.c.

References get_ts_parser_oid(), PG_GETARG_TEXT_P, prs_process_call(), prs_setup_firstcall(), SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and textToQualifiedNameList().

{
    FuncCallContext *funcctx;
    Datum       result;

    if (SRF_IS_FIRSTCALL())
    {
        text       *prsname = PG_GETARG_TEXT_P(0);
        text       *txt = PG_GETARG_TEXT_P(1);
        Oid         prsId;

        funcctx = SRF_FIRSTCALL_INIT();
        prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
        prs_setup_firstcall(funcctx, prsId, txt);
    }

    funcctx = SRF_PERCALL_SETUP();

    if ((result = prs_process_call(funcctx)) != (Datum) 0)
        SRF_RETURN_NEXT(funcctx, result);
    SRF_RETURN_DONE(funcctx);
}

Datum ts_token_type_byid ( PG_FUNCTION_ARGS   ) 

Definition at line 99 of file wparser.c.

References PG_GETARG_OID, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, tt_process_call(), and tt_setup_firstcall().

Referenced by tsa_token_type_current().

{
    FuncCallContext *funcctx;
    Datum       result;

    if (SRF_IS_FIRSTCALL())
    {
        funcctx = SRF_FIRSTCALL_INIT();
        tt_setup_firstcall(funcctx, PG_GETARG_OID(0));
    }

    funcctx = SRF_PERCALL_SETUP();

    if ((result = tt_process_call(funcctx)) != (Datum) 0)
        SRF_RETURN_NEXT(funcctx, result);
    SRF_RETURN_DONE(funcctx);
}

Datum ts_token_type_byname ( PG_FUNCTION_ARGS   ) 

Definition at line 118 of file wparser.c.

References get_ts_parser_oid(), PG_GETARG_TEXT_P, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, textToQualifiedNameList(), tt_process_call(), and tt_setup_firstcall().

{
    FuncCallContext *funcctx;
    Datum       result;

    if (SRF_IS_FIRSTCALL())
    {
        text       *prsname = PG_GETARG_TEXT_P(0);
        Oid         prsId;

        funcctx = SRF_FIRSTCALL_INIT();
        prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
        tt_setup_firstcall(funcctx, prsId);
    }

    funcctx = SRF_PERCALL_SETUP();

    if ((result = tt_process_call(funcctx)) != (Datum) 0)
        SRF_RETURN_NEXT(funcctx, result);
    SRF_RETURN_DONE(funcctx);
}

int32 tsCompareString ( char *  a,
int  lena,
char *  b,
int  lenb,
bool  prefix 
)

Definition at line 556 of file tsvector_op.c.

References memcmp(), and Min.

Referenced by checkcondition_str(), compareentry(), compareQueryOperand(), compareWORD(), gin_cmp_prefix(), gin_cmp_tslexeme(), hlfinditem(), QTNodeCompare(), and silly_cmp_tsvector().

{
    int         cmp;

    if (lena == 0)
    {
        if (prefix)
            cmp = 0;            /* empty string is prefix of anything */
        else
            cmp = (lenb > 0) ? -1 : 0;
    }
    else if (lenb == 0)
    {
        cmp = (lena > 0) ? 1 : 0;
    }
    else
    {
        cmp = memcmp(a, b, Min(lena, lenb));

        if (prefix)
        {
            if (cmp == 0 && lena > lenb)
                cmp = 1;        /* a is longer, so not a prefix of b */
        }
        else if (cmp == 0 && lena != lenb)
        {
            cmp = (lena < lenb) ? -1 : 1;
        }
    }

    return cmp;
}

bool tsquery_requires_match ( QueryItem curitem  ) 

Definition at line 727 of file tsvector_op.c.

References check_stack_depth(), elog, ERROR, QueryOperator::left, OP_AND, OP_NOT, OP_OR, QueryOperator::oper, QI_VAL, QueryItem::qoperator, tsquery_requires_match(), and QueryItem::type.

Referenced by gin_extract_tsquery(), and tsquery_requires_match().

{
    /* since this function recurses, it could be driven to stack overflow */
    check_stack_depth();

    if (curitem->type == QI_VAL)
        return true;

    switch (curitem->qoperator.oper)
    {
        case OP_NOT:

            /*
             * Assume there are no required matches underneath a NOT.  For
             * some cases with nested NOTs, we could prove there's a required
             * match, but it seems unlikely to be worth the trouble.
             */
            return false;

        case OP_AND:
            /* If either side requires a match, we're good */
            if (tsquery_requires_match(curitem + curitem->qoperator.left))
                return true;
            else
                return tsquery_requires_match(curitem + 1);

        case OP_OR:
            /* Both sides must require a match */
            if (tsquery_requires_match(curitem + curitem->qoperator.left))
                return tsquery_requires_match(curitem + 1);
            else
                return false;

        default:
            elog(ERROR, "unrecognized operator: %d", curitem->qoperator.oper);
    }

    /* not reachable, but keep compiler quiet */
    return false;
}