PostgreSQL Source Code git master
tsquery_op.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * tsquery_op.c
4 * Various operations with tsquery
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 *
8 *
9 * IDENTIFICATION
10 * src/backend/utils/adt/tsquery_op.c
11 *
12 *-------------------------------------------------------------------------
13 */
14
15#include "postgres.h"
16
17#include "lib/qunique.h"
18#include "tsearch/ts_utils.h"
19#include "utils/fmgrprotos.h"
20#include "varatt.h"
21
24{
25 TSQuery query = PG_GETARG_TSQUERY(0);
26 int nnode = query->size;
27
28 PG_FREE_IF_COPY(query, 0);
29 PG_RETURN_INT32(nnode);
30}
31
32static QTNode *
34{
35 QTNode *res = (QTNode *) palloc0(sizeof(QTNode));
36
37 res->flags |= QTN_NEEDFREE;
38
39 res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
40 res->valnode->type = QI_OPR;
41 res->valnode->qoperator.oper = operator;
42 if (operator == OP_PHRASE)
43 res->valnode->qoperator.distance = distance;
44
45 res->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
46 res->child[0] = QT2QTN(GETQUERY(b), GETOPERAND(b));
47 res->child[1] = QT2QTN(GETQUERY(a), GETOPERAND(a));
48 res->nchild = 2;
49
50 return res;
51}
52
55{
58 QTNode *res;
59 TSQuery query;
60
61 if (a->size == 0)
62 {
65 }
66 else if (b->size == 0)
67 {
70 }
71
72 res = join_tsqueries(a, b, OP_AND, 0);
73
74 query = QTN2QT(res);
75
76 QTNFree(res);
79
80 PG_RETURN_TSQUERY(query);
81}
82
85{
88 QTNode *res;
89 TSQuery query;
90
91 if (a->size == 0)
92 {
95 }
96 else if (b->size == 0)
97 {
100 }
101
102 res = join_tsqueries(a, b, OP_OR, 0);
103
104 query = QTN2QT(res);
105
106 QTNFree(res);
107 PG_FREE_IF_COPY(a, 0);
108 PG_FREE_IF_COPY(b, 1);
109
110 PG_RETURN_TSQUERY(query);
111}
112
113Datum
115{
118 QTNode *res;
119 TSQuery query;
120 int32 distance = PG_GETARG_INT32(2);
121
122 if (distance < 0 || distance > MAXENTRYPOS)
124 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
125 errmsg("distance in phrase operator must be an integer value between zero and %d inclusive",
126 MAXENTRYPOS)));
127 if (a->size == 0)
128 {
129 PG_FREE_IF_COPY(a, 1);
131 }
132 else if (b->size == 0)
133 {
134 PG_FREE_IF_COPY(b, 1);
136 }
137
138 res = join_tsqueries(a, b, OP_PHRASE, (uint16) distance);
139
140 query = QTN2QT(res);
141
142 QTNFree(res);
143 PG_FREE_IF_COPY(a, 0);
144 PG_FREE_IF_COPY(b, 1);
145
146 PG_RETURN_TSQUERY(query);
147}
148
149Datum
151{
155 Int32GetDatum(1)));
156}
157
158Datum
160{
162 QTNode *res;
163 TSQuery query;
164
165 if (a->size == 0)
167
168 res = (QTNode *) palloc0(sizeof(QTNode));
169
170 res->flags |= QTN_NEEDFREE;
171
172 res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
173 res->valnode->type = QI_OPR;
175
176 res->child = (QTNode **) palloc0(sizeof(QTNode *));
177 res->child[0] = QT2QTN(GETQUERY(a), GETOPERAND(a));
178 res->nchild = 1;
179
180 query = QTN2QT(res);
181
182 QTNFree(res);
183 PG_FREE_IF_COPY(a, 0);
184
185 PG_RETURN_POINTER(query);
186}
187
188static int
190{
191 if (a->size != b->size)
192 {
193 return (a->size < b->size) ? -1 : 1;
194 }
195 else if (VARSIZE(a) != VARSIZE(b))
196 {
197 return (VARSIZE(a) < VARSIZE(b)) ? -1 : 1;
198 }
199 else if (a->size != 0)
200 {
203 int res = QTNodeCompare(an, bn);
204
205 QTNFree(an);
206 QTNFree(bn);
207
208 return res;
209 }
210
211 return 0;
212}
213
214Datum
216{
219 int res = CompareTSQ(a, b);
220
221 PG_FREE_IF_COPY(a, 0);
222 PG_FREE_IF_COPY(b, 1);
223
224 PG_RETURN_INT32(res);
225}
226
227#define CMPFUNC( NAME, CONDITION ) \
228Datum \
229NAME(PG_FUNCTION_ARGS) { \
230 TSQuery a = PG_GETARG_TSQUERY_COPY(0); \
231 TSQuery b = PG_GETARG_TSQUERY_COPY(1); \
232 int res = CompareTSQ(a,b); \
233 \
234 PG_FREE_IF_COPY(a,0); \
235 PG_FREE_IF_COPY(b,1); \
236 \
237 PG_RETURN_BOOL( CONDITION ); \
238} \
239/* keep compiler quiet - no extra ; */ \
240extern int no_such_variable
241
242CMPFUNC(tsquery_lt, res < 0);
243CMPFUNC(tsquery_le, res <= 0);
244CMPFUNC(tsquery_eq, res == 0);
245CMPFUNC(tsquery_ge, res >= 0);
246CMPFUNC(tsquery_gt, res > 0);
247CMPFUNC(tsquery_ne, res != 0);
248
251{
252 int i;
253 QueryItem *ptr = GETQUERY(a);
254 TSQuerySign sign = 0;
255
256 for (i = 0; i < a->size; i++)
257 {
258 if (ptr->type == QI_VAL)
259 sign |= ((TSQuerySign) 1) << (((unsigned int) ptr->qoperand.valcrc) % TSQS_SIGLEN);
260 ptr++;
261 }
262
263 return sign;
264}
265
266static char **
268{
269 QueryItem *ptr = GETQUERY(a);
270 char *operand = GETOPERAND(a);
271 char **values;
272 int nvalues = 0;
273 int i;
274
275 values = (char **) palloc(sizeof(char *) * a->size);
276
277 for (i = 0; i < a->size; i++)
278 {
279 if (ptr->type == QI_VAL)
280 {
281 int len = ptr->qoperand.length;
282 char *val;
283
284 val = palloc(len + 1);
285 memcpy(val, operand + ptr->qoperand.distance, len);
286 val[len] = '\0';
287
288 values[nvalues++] = val;
289 }
290 ptr++;
291 }
292
293 *nvalues_p = nvalues;
294 return values;
295}
296
297static int
298cmp_string(const void *a, const void *b)
299{
300 const char *sa = *((char *const *) a);
301 const char *sb = *((char *const *) b);
302
303 return strcmp(sa, sb);
304}
305
306Datum
308{
309 TSQuery query = PG_GETARG_TSQUERY(0);
311 char **query_values;
312 int query_nvalues;
313 char **ex_values;
314 int ex_nvalues;
315 bool result = true;
316
317 /* Extract the query terms into arrays */
318 query_values = collectTSQueryValues(query, &query_nvalues);
319 ex_values = collectTSQueryValues(ex, &ex_nvalues);
320
321 /* Sort and remove duplicates from both arrays */
322 qsort(query_values, query_nvalues, sizeof(char *), cmp_string);
323 query_nvalues = qunique(query_values, query_nvalues, sizeof(char *),
324 cmp_string);
325 qsort(ex_values, ex_nvalues, sizeof(char *), cmp_string);
326 ex_nvalues = qunique(ex_values, ex_nvalues, sizeof(char *), cmp_string);
327
328 if (ex_nvalues > query_nvalues)
329 result = false;
330 else
331 {
332 int i;
333 int j = 0;
334
335 for (i = 0; i < ex_nvalues; i++)
336 {
337 for (; j < query_nvalues; j++)
338 {
339 if (strcmp(ex_values[i], query_values[j]) == 0)
340 break;
341 }
342 if (j == query_nvalues)
343 {
344 result = false;
345 break;
346 }
347 }
348 }
349
350 PG_RETURN_BOOL(result);
351}
352
353Datum
355{
358 PG_GETARG_DATUM(0)));
359}
#define GETQUERY(x)
Definition: _int.h:157
static Datum values[MAXATTR]
Definition: bootstrap.c:151
int8_t int8
Definition: c.h:496
int32_t int32
Definition: c.h:498
uint16_t uint16
Definition: c.h:501
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:645
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
long val
Definition: informix.c:689
char sign
Definition: informix.c:693
int b
Definition: isn.c:71
int a
Definition: isn.c:70
int j
Definition: isn.c:75
int i
Definition: isn.c:74
#define GETOPERAND(x)
Definition: ltree.h:165
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
const void size_t len
#define qsort(a, b, c, d)
Definition: port.h:475
uintptr_t Datum
Definition: postgres.h:69
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
Definition: qunique.h:21
int32 nchild
Definition: ts_utils.h:238
QueryItem * valnode
Definition: ts_utils.h:236
uint32 flags
Definition: ts_utils.h:237
struct QTNode ** child
Definition: ts_utils.h:241
uint32 distance
Definition: ts_type.h:172
uint32 length
Definition: ts_type.h:171
int32 valcrc
Definition: ts_type.h:164
int16 distance
Definition: ts_type.h:196
int32 size
Definition: ts_type.h:221
#define MAXENTRYPOS
Definition: ts_type.h:85
#define PG_GETARG_TSQUERY(n)
Definition: ts_type.h:266
#define PG_RETURN_TSQUERY(x)
Definition: ts_type.h:268
#define QI_OPR
Definition: ts_type.h:150
#define PG_GETARG_TSQUERY_COPY(n)
Definition: ts_type.h:267
#define QI_VAL
Definition: ts_type.h:149
#define OP_AND
Definition: ts_type.h:180
#define OP_PHRASE
Definition: ts_type.h:182
#define OP_OR
Definition: ts_type.h:181
#define OP_NOT
Definition: ts_type.h:179
#define TSQS_SIGLEN
Definition: ts_utils.h:251
#define QTN_NEEDFREE
Definition: ts_utils.h:245
uint64 TSQuerySign
Definition: ts_utils.h:249
Datum tsq_mcontains(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:307
Datum tsquery_numnode(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:23
Datum tsquery_and(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:54
static char ** collectTSQueryValues(TSQuery a, int *nvalues_p)
Definition: tsquery_op.c:267
static QTNode * join_tsqueries(TSQuery a, TSQuery b, int8 operator, uint16 distance)
Definition: tsquery_op.c:33
Datum tsq_mcontained(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:354
TSQuerySign makeTSQuerySign(TSQuery a)
Definition: tsquery_op.c:250
static int cmp_string(const void *a, const void *b)
Definition: tsquery_op.c:298
Datum tsquery_not(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:159
Datum tsquery_or(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:84
static int CompareTSQ(TSQuery a, TSQuery b)
Definition: tsquery_op.c:189
Datum tsquery_phrase(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:150
Datum tsquery_phrase_distance(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:114
Datum tsquery_cmp(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:215
#define CMPFUNC(NAME, CONDITION)
Definition: tsquery_op.c:227
int QTNodeCompare(QTNode *an, QTNode *bn)
Definition: tsquery_util.c:97
void QTNFree(QTNode *in)
Definition: tsquery_util.c:64
QTNode * QT2QTN(QueryItem *in, char *operand)
Definition: tsquery_util.c:25
TSQuery QTN2QT(QTNode *in)
Definition: tsquery_util.c:363
QueryOperator qoperator
Definition: ts_type.h:209
QueryOperand qoperand
Definition: ts_type.h:210
QueryItemType type
Definition: ts_type.h:208
#define VARSIZE(PTR)
Definition: varatt.h:279