1
/*-------------------------------------------------------------------------
4
* Extended synonym dictionary
6
* Copyright (c) 2007-2009, PostgreSQL Global Development Group
11
*-------------------------------------------------------------------------
17
#include "commands/defrem.h"
19
#include "tsearch/ts_locale.h"
20
#include "tsearch/ts_utils.h"
27
char *value; /* Unparsed list of synonyms, including the
40
PG_FUNCTION_INFO_V1(dxsyn_init);
41
Datum dxsyn_init(PG_FUNCTION_ARGS);
43
PG_FUNCTION_INFO_V1(dxsyn_lexize);
44
Datum dxsyn_lexize(PG_FUNCTION_ARGS);
47
find_word(char *in, char **end)
52
while (*in && t_isspace(in))
55
if (!*in || *in == '#')
59
while (*in && !t_isspace(in))
68
compare_syn(const void *a, const void *b)
70
return strcmp(((Syn *) a)->key, ((Syn *) b)->key);
74
read_dictionary(DictSyn *d, char *filename)
76
char *real_filename = get_tsearch_config_filename(filename, "rules");
77
tsearch_readline_state trst;
81
if (!tsearch_readline_begin(&trst, real_filename))
83
(errcode(ERRCODE_CONFIG_FILE_ERROR),
84
errmsg("could not open synonym file \"%s\": %m",
87
while ((line = tsearch_readline(&trst)) != NULL)
96
value = lowerstr(line);
99
key = find_word(value, &end);
108
d->len = (d->len > 0) ? 2 * d->len : 16;
110
d->syn = (Syn *) repalloc(d->syn, sizeof(Syn) * d->len);
112
d->syn = (Syn *) palloc(sizeof(Syn) * d->len);
115
d->syn[cur].key = pnstrdup(key, end - key);
116
d->syn[cur].value = value;
121
tsearch_readline_end(&trst);
125
qsort(d->syn, d->len, sizeof(Syn), compare_syn);
127
pfree(real_filename);
131
dxsyn_init(PG_FUNCTION_ARGS)
133
List *dictoptions = (List *) PG_GETARG_POINTER(0);
137
d = (DictSyn *) palloc0(sizeof(DictSyn));
142
foreach(l, dictoptions)
144
DefElem *defel = (DefElem *) lfirst(l);
146
if (pg_strcasecmp(defel->defname, "KEEPORIG") == 0)
148
d->keeporig = defGetBoolean(defel);
150
else if (pg_strcasecmp(defel->defname, "RULES") == 0)
152
read_dictionary(d, defGetString(defel));
157
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
158
errmsg("unrecognized xsyn parameter: \"%s\"",
163
PG_RETURN_POINTER(d);
167
dxsyn_lexize(PG_FUNCTION_ARGS)
169
DictSyn *d = (DictSyn *) PG_GETARG_POINTER(0);
170
char *in = (char *) PG_GETARG_POINTER(1);
171
int length = PG_GETARG_INT32(2);
174
TSLexeme *res = NULL;
176
if (!length || d->len == 0)
177
PG_RETURN_POINTER(NULL);
179
/* Create search pattern */
181
char *temp = pnstrdup(in, length);
183
word.key = lowerstr(temp);
188
/* Look for matching syn */
189
found = (Syn *) bsearch(&word, d->syn, d->len, sizeof(Syn), compare_syn);
193
PG_RETURN_POINTER(NULL);
195
/* Parse string of synonyms and return array of words */
197
char *value = pstrdup(found->value);
198
int value_length = strlen(value);
201
bool is_first = true;
205
while (pos < value + value_length)
208
char *syn = find_word(pos, &end);
214
res = repalloc(res, sizeof(TSLexeme) * (nsyns + 2));
215
res[nsyns].lexeme = NULL;
217
/* first word is added to result only if KEEPORIG flag is set */
218
if (d->keeporig || !is_first)
220
res[nsyns].lexeme = pstrdup(syn);
221
res[nsyns + 1].lexeme = NULL;
234
PG_RETURN_POINTER(res);