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-2019, 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/builtins.h"
20 
21 Datum
23 {
24  TSQuery query = PG_GETARG_TSQUERY(0);
25  int nnode = query->size;
26 
27  PG_FREE_IF_COPY(query, 0);
28  PG_RETURN_INT32(nnode);
29 }
30 
31 static QTNode *
33 {
34  QTNode *res = (QTNode *) palloc0(sizeof(QTNode));
35 
36  res->flags |= QTN_NEEDFREE;
37 
38  res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
39  res->valnode->type = QI_OPR;
40  res->valnode->qoperator.oper = operator;
41  if (operator == OP_PHRASE)
43 
44  res->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
45  res->child[0] = QT2QTN(GETQUERY(b), GETOPERAND(b));
46  res->child[1] = QT2QTN(GETQUERY(a), GETOPERAND(a));
47  res->nchild = 2;
48 
49  return res;
50 }
51 
52 Datum
54 {
57  QTNode *res;
58  TSQuery query;
59 
60  if (a->size == 0)
61  {
62  PG_FREE_IF_COPY(a, 1);
64  }
65  else if (b->size == 0)
66  {
67  PG_FREE_IF_COPY(b, 1);
69  }
70 
71  res = join_tsqueries(a, b, OP_AND, 0);
72 
73  query = QTN2QT(res);
74 
75  QTNFree(res);
76  PG_FREE_IF_COPY(a, 0);
77  PG_FREE_IF_COPY(b, 1);
78 
79  PG_RETURN_TSQUERY(query);
80 }
81 
82 Datum
84 {
87  QTNode *res;
88  TSQuery query;
89 
90  if (a->size == 0)
91  {
92  PG_FREE_IF_COPY(a, 1);
94  }
95  else if (b->size == 0)
96  {
97  PG_FREE_IF_COPY(b, 1);
99  }
100 
101  res = join_tsqueries(a, b, OP_OR, 0);
102 
103  query = QTN2QT(res);
104 
105  QTNFree(res);
106  PG_FREE_IF_COPY(a, 0);
107  PG_FREE_IF_COPY(b, 1);
108 
109  PG_RETURN_TSQUERY(query);
110 }
111 
112 Datum
114 {
117  QTNode *res;
118  TSQuery query;
120 
121  if (distance < 0 || distance > MAXENTRYPOS)
122  ereport(ERROR,
123  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
124  errmsg("distance in phrase operator should be non-negative and less than %d",
125  MAXENTRYPOS)));
126  if (a->size == 0)
127  {
128  PG_FREE_IF_COPY(a, 1);
130  }
131  else if (b->size == 0)
132  {
133  PG_FREE_IF_COPY(b, 1);
135  }
136 
137  res = join_tsqueries(a, b, OP_PHRASE, (uint16) distance);
138 
139  query = QTN2QT(res);
140 
141  QTNFree(res);
142  PG_FREE_IF_COPY(a, 0);
143  PG_FREE_IF_COPY(b, 1);
144 
145  PG_RETURN_TSQUERY(query);
146 }
147 
148 Datum
150 {
153  PG_GETARG_DATUM(0),
154  PG_GETARG_DATUM(1),
155  Int32GetDatum(1)));
156 }
157 
158 Datum
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;
174  res->valnode->qoperator.oper = OP_NOT;
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 
188 static 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  {
201  QTNode *an = QT2QTN(GETQUERY(a), GETOPERAND(a));
202  QTNode *bn = QT2QTN(GETQUERY(b), GETOPERAND(b));
203  int res = QTNodeCompare(an, bn);
204 
205  QTNFree(an);
206  QTNFree(bn);
207 
208  return res;
209  }
210 
211  return 0;
212 }
213 
214 Datum
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 ) \
228 Datum \
229 NAME(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 ; */ \
240 extern int no_such_variable
241 
242 CMPFUNC(tsquery_lt, res < 0);
243 CMPFUNC(tsquery_le, res <= 0);
244 CMPFUNC(tsquery_eq, res == 0);
245 CMPFUNC(tsquery_ge, res >= 0);
246 CMPFUNC(tsquery_gt, res > 0);
247 CMPFUNC(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 
266 static char **
267 collectTSQueryValues(TSQuery a, int *nvalues_p)
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 
297 static int
298 cmp_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 
306 Datum
308 {
309  TSQuery query = PG_GETARG_TSQUERY(0);
310  TSQuery ex = PG_GETARG_TSQUERY(1);
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 
353 Datum
355 {
359  PG_GETARG_DATUM(1),
360  PG_GETARG_DATUM(0)
361  )
362  );
363 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
QueryOperator qoperator
Definition: ts_type.h:196
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define TSQS_SIGLEN
Definition: ts_utils.h:233
void QTNFree(QTNode *in)
Definition: tsquery_util.c:63
QTNode * QT2QTN(QueryItem *in, char *operand)
Definition: tsquery_util.c:24
#define VARSIZE(PTR)
Definition: postgres.h:303
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_TSQUERY(n)
Definition: ts_type.h:238
Datum tsquery_cmp(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:215
#define PG_RETURN_INT32(x)
Definition: fmgr.h:344
Datum tsq_mcontains(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:307
Datum tsquery_phrase(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:149
int errcode(int sqlerrcode)
Definition: elog.c:608
#define QI_VAL
Definition: ts_type.h:134
uint32 distance
Definition: ts_type.h:158
int16 distance
Definition: ts_type.h:183
#define OP_OR
Definition: ts_type.h:168
Datum tsquery_phrase_distance(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:113
#define GETQUERY(x)
Definition: _int.h:136
signed int int32
Definition: c.h:347
#define GETOPERAND(x)
Definition: ltree.h:118
static QTNode * join_tsqueries(TSQuery a, TSQuery b, int8 operator, uint16 distance)
Definition: tsquery_op.c:32
#define PG_RETURN_TSQUERY(x)
Definition: ts_type.h:240
#define OP_AND
Definition: ts_type.h:167
#define PG_GETARG_TSQUERY_COPY(n)
Definition: ts_type.h:239
unsigned short uint16
Definition: c.h:358
#define ERROR
Definition: elog.h:43
TSQuerySign makeTSQuerySign(TSQuery a)
Definition: tsquery_op.c:250
static char ** collectTSQueryValues(TSQuery a, int *nvalues_p)
Definition: tsquery_op.c:267
char sign
Definition: informix.c:688
uint64 TSQuerySign
Definition: ts_utils.h:231
int32 valcrc
Definition: ts_type.h:151
TSQuery QTN2QT(QTNode *in)
Definition: tsquery_util.c:362
#define ereport(elevel, rest)
Definition: elog.h:141
static int cmp_string(const void *a, const void *b)
Definition: tsquery_op.c:298
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:619
signed char int8
Definition: c.h:345
#define QI_OPR
Definition: ts_type.h:135
QueryItemType type
Definition: ts_type.h:195
void * palloc0(Size size)
Definition: mcxt.c:980
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
Datum tsq_mcontained(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:354
static int CompareTSQ(TSQuery a, TSQuery b)
Definition: tsquery_op.c:189
Datum tsquery_not(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:159
#define CMPFUNC(NAME, CONDITION)
Definition: tsquery_op.c:227
#define OP_PHRASE
Definition: ts_type.h:169
Datum tsquery_and(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:53
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
Definition: qunique.h:21
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:255
struct QTNode ** child
Definition: ts_utils.h:223
#define QTN_NEEDFREE
Definition: ts_utils.h:227
uint32 length
Definition: ts_type.h:158
int16 distance
Definition: ltxtquery_io.c:31
Datum tsquery_numnode(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:22
static Datum values[MAXATTR]
Definition: bootstrap.c:167
QueryItem * valnode
Definition: ts_utils.h:218
#define Int32GetDatum(X)
Definition: postgres.h:479
int32 nchild
Definition: ts_utils.h:220
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
int32 size
Definition: ts_type.h:208
int i
#define PG_FUNCTION_ARGS
Definition: fmgr.h:188
int QTNodeCompare(QTNode *an, QTNode *bn)
Definition: tsquery_util.c:96
QueryOperand qoperand
Definition: ts_type.h:197
#define qsort(a, b, c, d)
Definition: port.h:492
#define MAXENTRYPOS
Definition: ts_type.h:85
long val
Definition: informix.c:684
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:617
uint32 flags
Definition: ts_utils.h:219
Datum tsquery_or(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:83
#define OP_NOT
Definition: ts_type.h:166