Header And Logo

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

Data Structures | Functions | Variables

dict_xsyn.c File Reference

#include "postgres.h"
#include <ctype.h>
#include "commands/defrem.h"
#include "tsearch/ts_locale.h"
#include "tsearch/ts_utils.h"
Include dependency graph for dict_xsyn.c:

Go to the source code of this file.

Data Structures

struct  Syn
struct  DictSyn

Functions

 PG_FUNCTION_INFO_V1 (dxsyn_init)
Datum dxsyn_init (PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1 (dxsyn_lexize)
Datum dxsyn_lexize (PG_FUNCTION_ARGS)
static char * find_word (char *in, char **end)
static int compare_syn (const void *a, const void *b)
static void read_dictionary (DictSyn *d, char *filename)

Variables

 PG_MODULE_MAGIC

Function Documentation

static int compare_syn ( const void *  a,
const void *  b 
) [static]

Definition at line 70 of file dict_xsyn.c.

Referenced by read_dictionary().

{
    return strcmp(((const Syn *) a)->key, ((const Syn *) b)->key);
}

Datum dxsyn_init ( PG_FUNCTION_ARGS   ) 

Definition at line 144 of file dict_xsyn.c.

References defGetBoolean(), defGetString(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, filename, DictSyn::keeporig, DictSyn::keepsynonyms, DictSyn::len, lfirst, DictSyn::matchorig, DictSyn::matchsynonyms, palloc0(), PG_GETARG_POINTER, PG_RETURN_POINTER, pg_strcasecmp(), read_dictionary(), and DictSyn::syn.

{
    List       *dictoptions = (List *) PG_GETARG_POINTER(0);
    DictSyn    *d;
    ListCell   *l;
    char       *filename = NULL;

    d = (DictSyn *) palloc0(sizeof(DictSyn));
    d->len = 0;
    d->syn = NULL;
    d->matchorig = true;
    d->keeporig = true;
    d->matchsynonyms = false;
    d->keepsynonyms = true;

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

        if (pg_strcasecmp(defel->defname, "MATCHORIG") == 0)
        {
            d->matchorig = defGetBoolean(defel);
        }
        else if (pg_strcasecmp(defel->defname, "KEEPORIG") == 0)
        {
            d->keeporig = defGetBoolean(defel);
        }
        else if (pg_strcasecmp(defel->defname, "MATCHSYNONYMS") == 0)
        {
            d->matchsynonyms = defGetBoolean(defel);
        }
        else if (pg_strcasecmp(defel->defname, "KEEPSYNONYMS") == 0)
        {
            d->keepsynonyms = defGetBoolean(defel);
        }
        else if (pg_strcasecmp(defel->defname, "RULES") == 0)
        {
            /* we can't read the rules before parsing all options! */
            filename = defGetString(defel);
        }
        else
        {
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("unrecognized xsyn parameter: \"%s\"",
                            defel->defname)));
        }
    }

    if (filename)
        read_dictionary(d, filename);

    PG_RETURN_POINTER(d);
}

Datum dxsyn_lexize ( PG_FUNCTION_ARGS   ) 

Definition at line 200 of file dict_xsyn.c.

References find_word(), TSLexeme::flags, DictSyn::keeporig, DictSyn::keepsynonyms, Syn::key, DictSyn::len, length(), TSLexeme::lexeme, lowerstr(), NULL, TSLexeme::nvariant, palloc(), pfree(), PG_GETARG_INT32, PG_GETARG_POINTER, PG_RETURN_POINTER, pnstrdup(), repalloc(), DictSyn::syn, value, and Syn::value.

{
    DictSyn    *d = (DictSyn *) PG_GETARG_POINTER(0);
    char       *in = (char *) PG_GETARG_POINTER(1);
    int         length = PG_GETARG_INT32(2);
    Syn         word;
    Syn        *found;
    TSLexeme   *res = NULL;

    if (!length || d->len == 0)
        PG_RETURN_POINTER(NULL);

    /* Create search pattern */
    {
        char       *temp = pnstrdup(in, length);

        word.key = lowerstr(temp);
        pfree(temp);
        word.value = NULL;
    }

    /* Look for matching syn */
    found = (Syn *) bsearch(&word, d->syn, d->len, sizeof(Syn), compare_syn);
    pfree(word.key);

    if (!found)
        PG_RETURN_POINTER(NULL);

    /* Parse string of synonyms and return array of words */
    {
        char       *value = found->value;
        char       *syn;
        char       *pos;
        char       *end;
        int         nsyns = 0;

        res = palloc(sizeof(TSLexeme));

        pos = value;
        while ((syn = find_word(pos, &end)) != NULL)
        {
            res = repalloc(res, sizeof(TSLexeme) * (nsyns + 2));

            /* The first word is output only if keeporig=true */
            if (pos != value || d->keeporig)
            {
                res[nsyns].lexeme = pnstrdup(syn, end - syn);
                res[nsyns].nvariant = 0;
                res[nsyns].flags = 0;
                nsyns++;
            }

            pos = end;

            /* Stop if we are not to output the synonyms */
            if (!d->keepsynonyms)
                break;
        }
        res[nsyns].lexeme = NULL;
    }

    PG_RETURN_POINTER(res);
}

static char* find_word ( char *  in,
char **  end 
) [static]

Definition at line 49 of file dict_xsyn.c.

References pg_mblen(), and t_isspace.

Referenced by dxsyn_lexize(), and read_dictionary().

{
    char       *start;

    *end = NULL;
    while (*in && t_isspace(in))
        in += pg_mblen(in);

    if (!*in || *in == '#')
        return NULL;
    start = in;

    while (*in && !t_isspace(in))
        in += pg_mblen(in);

    *end = in;

    return start;
}

PG_FUNCTION_INFO_V1 ( dxsyn_init   ) 
PG_FUNCTION_INFO_V1 ( dxsyn_lexize   ) 
static void read_dictionary ( DictSyn d,
char *  filename 
) [static]

Definition at line 76 of file dict_xsyn.c.

References compare_syn(), cur, ereport, errcode(), errmsg(), ERROR, find_word(), get_tsearch_config_filename(), Syn::key, DictSyn::len, lowerstr(), DictSyn::matchorig, DictSyn::matchsynonyms, NULL, palloc(), pfree(), pnstrdup(), pstrdup(), qsort, repalloc(), DictSyn::syn, tsearch_readline(), tsearch_readline_begin(), tsearch_readline_end(), Syn::value, and value.

Referenced by dxsyn_init().

{
    char       *real_filename = get_tsearch_config_filename(filename, "rules");
    tsearch_readline_state trst;
    char       *line;
    int         cur = 0;

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

    while ((line = tsearch_readline(&trst)) != NULL)
    {
        char       *value;
        char       *key;
        char       *pos;
        char       *end;

        if (*line == '\0')
            continue;

        value = lowerstr(line);
        pfree(line);

        pos = value;
        while ((key = find_word(pos, &end)) != NULL)
        {
            /* Enlarge syn structure if full */
            if (cur == d->len)
            {
                d->len = (d->len > 0) ? 2 * d->len : 16;
                if (d->syn)
                    d->syn = (Syn *) repalloc(d->syn, sizeof(Syn) * d->len);
                else
                    d->syn = (Syn *) palloc(sizeof(Syn) * d->len);
            }

            /* Save first word only if we will match it */
            if (pos != value || d->matchorig)
            {
                d->syn[cur].key = pnstrdup(key, end - key);
                d->syn[cur].value = pstrdup(value);

                cur++;
            }

            pos = end;

            /* Don't bother scanning synonyms if we will not match them */
            if (!d->matchsynonyms)
                break;
        }

        pfree(value);
    }

    tsearch_readline_end(&trst);

    d->len = cur;
    if (cur > 1)
        qsort(d->syn, d->len, sizeof(Syn), compare_syn);

    pfree(real_filename);
}


Variable Documentation

Definition at line 21 of file dict_xsyn.c.