#include "postgres.h"
#include "commands/defrem.h"
#include "tsearch/ts_locale.h"
#include "tsearch/ts_utils.h"
Go to the source code of this file.
Data Structures | |
struct | Syn |
struct | DictSyn |
Functions | |
static char * | findwrd (char *in, char **end, uint16 *flags) |
static int | compareSyn (const void *a, const void *b) |
Datum | dsynonym_init (PG_FUNCTION_ARGS) |
Datum | dsynonym_lexize (PG_FUNCTION_ARGS) |
static int compareSyn | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 84 of file dict_synonym.c.
Referenced by dsynonym_init().
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); }
static char* findwrd | ( | char * | in, | |
char ** | end, | |||
uint16 * | flags | |||
) | [static] |
Definition at line 43 of file dict_synonym.c.
References pg_mblen(), t_iseq, and t_isspace.
Referenced by dsynonym_init().
{ char *start; char *lastchar; /* Skip leading spaces */ while (*in && t_isspace(in)) in += pg_mblen(in); /* Return NULL on empty lines */ if (*in == '\0') { *end = NULL; return NULL; } lastchar = start = in; /* Find end of word */ while (*in && !t_isspace(in)) { lastchar = in; in += pg_mblen(in); } if (in - lastchar == 1 && t_iseq(lastchar, '*') && flags) { *flags = TSL_PREFIX; *end = lastchar; } else { if (flags) *flags = 0; *end = in; } return start; }