PostgreSQL Source Code git master
Loading...
Searching...
No Matches
dict_synonym.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * dict_synonym.c
4 * Synonym dictionary: replace word by its synonym
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 *
8 *
9 * IDENTIFICATION
10 * src/backend/tsearch/dict_synonym.c
11 *
12 *-------------------------------------------------------------------------
13 */
14#include "postgres.h"
15
16#include "catalog/pg_collation_d.h"
17#include "commands/defrem.h"
18#include "tsearch/ts_locale.h"
19#include "tsearch/ts_public.h"
20#include "utils/fmgrprotos.h"
21#include "utils/formatting.h"
22
23typedef struct
24{
25 char *in;
26 char *out;
28} Syn;
29
30typedef struct
31{
32 int len; /* length of syn array */
33 Syn *syn;
35} DictSyn;
36
37/*
38 * Finds the next whitespace-delimited word within the 'in' string.
39 * Returns a pointer to the first character of the word, and a pointer
40 * to the next byte after the last character in the word (in *end).
41 * Character '*' at the end of word will not be treated as word
42 * character if flags is not null.
43 */
44static char *
45findwrd(char *in, char **end, uint16 *flags)
46{
47 char *start;
48 char *lastchar;
49
50 /* Skip leading spaces */
51 while (*in && isspace((unsigned char) *in))
52 in += pg_mblen_cstr(in);
53
54 /* Return NULL on empty lines */
55 if (*in == '\0')
56 {
57 *end = NULL;
58 return NULL;
59 }
60
61 lastchar = start = in;
62
63 /* Find end of word */
64 while (*in && !isspace((unsigned char) *in))
65 {
66 lastchar = in;
67 in += pg_mblen_cstr(in);
68 }
69
70 if (in - lastchar == 1 && t_iseq(lastchar, '*') && flags)
71 {
72 *flags = TSL_PREFIX;
73 *end = lastchar;
74 }
75 else
76 {
77 if (flags)
78 *flags = 0;
79 *end = in;
80 }
81
82 return start;
83}
84
85static int
86compareSyn(const void *a, const void *b)
87{
88 return strcmp(((const Syn *) a)->in, ((const Syn *) b)->in);
89}
90
91
94{
96 DictSyn *d;
97 ListCell *l;
98 char *filename = NULL;
99 bool case_sensitive = false;
101 char *starti,
102 *starto,
103 *end = NULL;
104 int cur = 0;
105 char *line = NULL;
106 uint16 flags = 0;
107
108 foreach(l, dictoptions)
109 {
110 DefElem *defel = (DefElem *) lfirst(l);
111
112 if (strcmp(defel->defname, "synonyms") == 0)
114 else if (strcmp(defel->defname, "casesensitive") == 0)
115 case_sensitive = defGetBoolean(defel);
116 else
119 errmsg("unrecognized synonym parameter: \"%s\"",
120 defel->defname)));
121 }
122
123 if (!filename)
126 errmsg("missing Synonyms parameter")));
127
129
133 errmsg("could not open synonym file \"%s\": %m",
134 filename)));
135
137
138 while ((line = tsearch_readline(&trst)) != NULL)
139 {
140 starti = findwrd(line, &end, NULL);
141 if (!starti)
142 {
143 /* Empty line */
144 goto skipline;
145 }
146 if (*end == '\0')
147 {
148 /* A line with only one word. Ignore silently. */
149 goto skipline;
150 }
151 *end = '\0';
152
153 starto = findwrd(end + 1, &end, &flags);
154 if (!starto)
155 {
156 /* A line with only one word (+whitespace). Ignore silently. */
157 goto skipline;
158 }
159 *end = '\0';
160
161 /*
162 * starti now points to the first word, and starto to the second word
163 * on the line, with a \0 terminator at the end of both words.
164 */
165
166 if (cur >= d->len)
167 {
168 if (d->len == 0)
169 {
170 d->len = 64;
171 d->syn = palloc_array(Syn, d->len);
172 }
173 else
174 {
175 d->len *= 2;
176 d->syn = repalloc_array(d->syn, Syn, d->len);
177 }
178 }
179
180 if (case_sensitive)
181 {
182 d->syn[cur].in = pstrdup(starti);
183 d->syn[cur].out = pstrdup(starto);
184 }
185 else
186 {
189 }
190
191 d->syn[cur].flags = flags;
192
193 cur++;
194
196 pfree(line);
197 }
198
201
202 d->len = cur;
203 qsort(d->syn, d->len, sizeof(Syn), compareSyn);
204
205 d->case_sensitive = case_sensitive;
206
208}
209
210Datum
212{
214 char *in = (char *) PG_GETARG_POINTER(1);
216 Syn key,
217 *found;
218 TSLexeme *res;
219
220 /* note: d->len test protects against Solaris bsearch-of-no-items bug */
221 if (len <= 0 || d->len <= 0)
223
224 if (d->case_sensitive)
225 key.in = pnstrdup(in, len);
226 else
228
229 key.out = NULL;
230
231 found = (Syn *) bsearch(&key, d->syn, d->len, sizeof(Syn), compareSyn);
232 pfree(key.in);
233
234 if (!found)
236
237 res = palloc0_array(TSLexeme, 2);
238 res[0].lexeme = pstrdup(found->out);
239 res[0].flags = found->flags;
240
242}
int32_t int32
Definition c.h:620
uint16_t uint16
Definition c.h:623
char * defGetString(DefElem *def)
Definition define.c:34
bool defGetBoolean(DefElem *def)
Definition define.c:93
static int compareSyn(const void *a, const void *b)
static char * findwrd(char *in, char **end, uint16 *flags)
Datum dsynonym_lexize(PG_FUNCTION_ARGS)
Datum dsynonym_init(PG_FUNCTION_ARGS)
struct cursor * cur
Definition ecpg.c:29
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
#define repalloc_array(pointer, type, count)
Definition fe_memutils.h:94
#define palloc_array(type, count)
Definition fe_memutils.h:91
#define palloc0_array(type, count)
Definition fe_memutils.h:92
#define palloc0_object(type)
Definition fe_memutils.h:90
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_GETARG_INT32(n)
Definition fmgr.h:269
#define PG_RETURN_POINTER(x)
Definition fmgr.h:363
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
char * str_tolower(const char *buff, size_t nbytes, Oid collid)
return str start
int b
Definition isn.c:74
int a
Definition isn.c:73
int pg_mblen_cstr(const char *mbstr)
Definition mbutils.c:1045
char * pstrdup(const char *in)
Definition mcxt.c:1910
void pfree(void *pointer)
Definition mcxt.c:1619
char * pnstrdup(const char *in, Size len)
Definition mcxt.c:1921
static char * errmsg
const void size_t len
static char * filename
Definition pg_dumpall.c:120
#define lfirst(lc)
Definition pg_list.h:172
#define qsort(a, b, c, d)
Definition port.h:496
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
bool case_sensitive
Syn * syn
Definition dict_xsyn.c:38
int len
Definition dict_xsyn.c:37
Definition pg_list.h:54
uint16 flags
char * in
char * out
char * lexeme
Definition ts_public.h:138
uint16 flags
Definition ts_public.h:136
bool tsearch_readline_begin(tsearch_readline_state *stp, const char *filename)
Definition ts_locale.c:85
char * tsearch_readline(tsearch_readline_state *stp)
Definition ts_locale.c:108
void tsearch_readline_end(tsearch_readline_state *stp)
Definition ts_locale.c:153
#define t_iseq(x, c)
Definition ts_locale.h:38
#define TSL_PREFIX
Definition ts_public.h:143
char * get_tsearch_config_filename(const char *basename, const char *extension)
Definition ts_utils.c:34