PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2017, 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 "tsearch/ts_utils.h"
18 #include "utils/builtins.h"
19 
20 Datum
22 {
23  TSQuery query = PG_GETARG_TSQUERY(0);
24  int nnode = query->size;
25 
26  PG_FREE_IF_COPY(query, 0);
27  PG_RETURN_INT32(nnode);
28 }
29 
30 static QTNode *
32 {
33  QTNode *res = (QTNode *) palloc0(sizeof(QTNode));
34 
35  res->flags |= QTN_NEEDFREE;
36 
37  res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
38  res->valnode->type = QI_OPR;
39  res->valnode->qoperator.oper = operator;
40  if (operator == OP_PHRASE)
42 
43  res->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
44  res->child[0] = QT2QTN(GETQUERY(b), GETOPERAND(b));
45  res->child[1] = QT2QTN(GETQUERY(a), GETOPERAND(a));
46  res->nchild = 2;
47 
48  return res;
49 }
50 
51 Datum
53 {
56  QTNode *res;
57  TSQuery query;
58 
59  if (a->size == 0)
60  {
61  PG_FREE_IF_COPY(a, 1);
63  }
64  else if (b->size == 0)
65  {
66  PG_FREE_IF_COPY(b, 1);
68  }
69 
70  res = join_tsqueries(a, b, OP_AND, 0);
71 
72  query = QTN2QT(res);
73 
74  QTNFree(res);
75  PG_FREE_IF_COPY(a, 0);
76  PG_FREE_IF_COPY(b, 1);
77 
78  PG_RETURN_TSQUERY(query);
79 }
80 
81 Datum
83 {
86  QTNode *res;
87  TSQuery query;
88 
89  if (a->size == 0)
90  {
91  PG_FREE_IF_COPY(a, 1);
93  }
94  else if (b->size == 0)
95  {
96  PG_FREE_IF_COPY(b, 1);
98  }
99 
100  res = join_tsqueries(a, b, OP_OR, 0);
101 
102  query = QTN2QT(res);
103 
104  QTNFree(res);
105  PG_FREE_IF_COPY(a, 0);
106  PG_FREE_IF_COPY(b, 1);
107 
108  PG_RETURN_TSQUERY(query);
109 }
110 
111 Datum
113 {
116  QTNode *res;
117  TSQuery query;
119 
120  if (distance < 0 || distance > MAXENTRYPOS)
121  ereport(ERROR,
122  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
123  errmsg("distance in phrase operator should be non-negative and less than %d",
124  MAXENTRYPOS)));
125  if (a->size == 0)
126  {
127  PG_FREE_IF_COPY(a, 1);
129  }
130  else if (b->size == 0)
131  {
132  PG_FREE_IF_COPY(b, 1);
134  }
135 
136  res = join_tsqueries(a, b, OP_PHRASE, (uint16) distance);
137 
138  query = QTN2QT(res);
139 
140  QTNFree(res);
141  PG_FREE_IF_COPY(a, 0);
142  PG_FREE_IF_COPY(b, 1);
143 
144  PG_RETURN_TSQUERY(query);
145 }
146 
147 Datum
149 {
152  PG_GETARG_DATUM(0),
153  PG_GETARG_DATUM(1),
154  Int32GetDatum(1)));
155 }
156 
157 Datum
159 {
161  QTNode *res;
162  TSQuery query;
163 
164  if (a->size == 0)
166 
167  res = (QTNode *) palloc0(sizeof(QTNode));
168 
169  res->flags |= QTN_NEEDFREE;
170 
171  res->valnode = (QueryItem *) palloc0(sizeof(QueryItem));
172  res->valnode->type = QI_OPR;
173  res->valnode->qoperator.oper = OP_NOT;
174 
175  res->child = (QTNode **) palloc0(sizeof(QTNode *));
176  res->child[0] = QT2QTN(GETQUERY(a), GETOPERAND(a));
177  res->nchild = 1;
178 
179  query = QTN2QT(res);
180 
181  QTNFree(res);
182  PG_FREE_IF_COPY(a, 0);
183 
184  PG_RETURN_POINTER(query);
185 }
186 
187 static int
189 {
190  if (a->size != b->size)
191  {
192  return (a->size < b->size) ? -1 : 1;
193  }
194  else if (VARSIZE(a) != VARSIZE(b))
195  {
196  return (VARSIZE(a) < VARSIZE(b)) ? -1 : 1;
197  }
198  else if (a->size != 0)
199  {
200  QTNode *an = QT2QTN(GETQUERY(a), GETOPERAND(a));
201  QTNode *bn = QT2QTN(GETQUERY(b), GETOPERAND(b));
202  int res = QTNodeCompare(an, bn);
203 
204  QTNFree(an);
205  QTNFree(bn);
206 
207  return res;
208  }
209 
210  return 0;
211 }
212 
213 Datum
215 {
218  int res = CompareTSQ(a, b);
219 
220  PG_FREE_IF_COPY(a, 0);
221  PG_FREE_IF_COPY(b, 1);
222 
223  PG_RETURN_INT32(res);
224 }
225 
226 #define CMPFUNC( NAME, CONDITION ) \
227 Datum \
228 NAME(PG_FUNCTION_ARGS) { \
229  TSQuery a = PG_GETARG_TSQUERY_COPY(0); \
230  TSQuery b = PG_GETARG_TSQUERY_COPY(1); \
231  int res = CompareTSQ(a,b); \
232  \
233  PG_FREE_IF_COPY(a,0); \
234  PG_FREE_IF_COPY(b,1); \
235  \
236  PG_RETURN_BOOL( CONDITION ); \
237 } \
238 /* keep compiler quiet - no extra ; */ \
239 extern int no_such_variable
240 
241 CMPFUNC(tsquery_lt, res < 0);
242 CMPFUNC(tsquery_le, res <= 0);
243 CMPFUNC(tsquery_eq, res == 0);
244 CMPFUNC(tsquery_ge, res >= 0);
245 CMPFUNC(tsquery_gt, res > 0);
246 CMPFUNC(tsquery_ne, res != 0);
247 
250 {
251  int i;
252  QueryItem *ptr = GETQUERY(a);
253  TSQuerySign sign = 0;
254 
255  for (i = 0; i < a->size; i++)
256  {
257  if (ptr->type == QI_VAL)
258  sign |= ((TSQuerySign) 1) << (((unsigned int) ptr->qoperand.valcrc) % TSQS_SIGLEN);
259  ptr++;
260  }
261 
262  return sign;
263 }
264 
265 static char **
266 collectTSQueryValues(TSQuery a, int *nvalues_p)
267 {
268  QueryItem *ptr = GETQUERY(a);
269  char *operand = GETOPERAND(a);
270  char **values;
271  int nvalues = 0;
272  int i;
273 
274  values = (char **) palloc(sizeof(char *) * a->size);
275 
276  for (i = 0; i < a->size; i++)
277  {
278  if (ptr->type == QI_VAL)
279  {
280  int len = ptr->qoperand.length;
281  char *val;
282 
283  val = palloc(len + 1);
284  memcpy(val, operand + ptr->qoperand.distance, len);
285  val[len] = '\0';
286 
287  values[nvalues++] = val;
288  }
289  ptr++;
290  }
291 
292  *nvalues_p = nvalues;
293  return values;
294 }
295 
296 static int
297 cmp_string(const void *a, const void *b)
298 {
299  const char *sa = *((const char **) a);
300  const char *sb = *((const char **) b);
301 
302  return strcmp(sa, sb);
303 }
304 
305 static int
306 remove_duplicates(char **strings, int n)
307 {
308  if (n <= 1)
309  return n;
310  else
311  {
312  int i;
313  char *prev = strings[0];
314  int new_n = 1;
315 
316  for (i = 1; i < n; i++)
317  {
318  if (strcmp(strings[i], prev) != 0)
319  {
320  strings[new_n++] = strings[i];
321  prev = strings[i];
322  }
323  }
324  return new_n;
325  }
326 }
327 
328 Datum
330 {
331  TSQuery query = PG_GETARG_TSQUERY(0);
332  TSQuery ex = PG_GETARG_TSQUERY(1);
333  char **query_values;
334  int query_nvalues;
335  char **ex_values;
336  int ex_nvalues;
337  bool result = true;
338 
339  /* Extract the query terms into arrays */
340  query_values = collectTSQueryValues(query, &query_nvalues);
341  ex_values = collectTSQueryValues(ex, &ex_nvalues);
342 
343  /* Sort and remove duplicates from both arrays */
344  qsort(query_values, query_nvalues, sizeof(char *), cmp_string);
345  query_nvalues = remove_duplicates(query_values, query_nvalues);
346  qsort(ex_values, ex_nvalues, sizeof(char *), cmp_string);
347  ex_nvalues = remove_duplicates(ex_values, ex_nvalues);
348 
349  if (ex_nvalues > query_nvalues)
350  result = false;
351  else
352  {
353  int i;
354  int j = 0;
355 
356  for (i = 0; i < ex_nvalues; i++)
357  {
358  for (; j < query_nvalues; j++)
359  {
360  if (strcmp(ex_values[i], query_values[j]) == 0)
361  break;
362  }
363  if (j == query_nvalues)
364  {
365  result = false;
366  break;
367  }
368  }
369  }
370 
371  PG_RETURN_BOOL(result);
372 }
373 
374 Datum
376 {
380  PG_GETARG_DATUM(1),
381  PG_GETARG_DATUM(0)
382  )
383  );
384 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
QueryOperator qoperator
Definition: ts_type.h:205
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define TSQS_SIGLEN
Definition: ts_utils.h:218
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:304
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_TSQUERY(n)
Definition: ts_type.h:247
Datum tsquery_cmp(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:214
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
Datum tsq_mcontains(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:329
Datum tsquery_phrase(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:148
int errcode(int sqlerrcode)
Definition: elog.c:575
#define QI_VAL
Definition: ts_type.h:143
return result
Definition: formatting.c:1632
uint32 distance
Definition: ts_type.h:167
int16 distance
Definition: ts_type.h:192
#define OP_OR
Definition: ts_type.h:177
Datum tsquery_phrase_distance(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:112
#define GETQUERY(x)
Definition: _int.h:142
signed int int32
Definition: c.h:256
#define GETOPERAND(x)
Definition: ltree.h:118
static QTNode * join_tsqueries(TSQuery a, TSQuery b, int8 operator, uint16 distance)
Definition: tsquery_op.c:31
#define PG_RETURN_TSQUERY(x)
Definition: ts_type.h:249
#define OP_AND
Definition: ts_type.h:176
#define PG_GETARG_TSQUERY_COPY(n)
Definition: ts_type.h:248
unsigned short uint16
Definition: c.h:267
#define ERROR
Definition: elog.h:43
TSQuerySign makeTSQuerySign(TSQuery a)
Definition: tsquery_op.c:249
static char ** collectTSQueryValues(TSQuery a, int *nvalues_p)
Definition: tsquery_op.c:266
char sign
Definition: informix.c:693
uint64 TSQuerySign
Definition: ts_utils.h:216
int32 valcrc
Definition: ts_type.h:160
TSQuery QTN2QT(QTNode *in)
Definition: tsquery_util.c:362
#define ereport(elevel, rest)
Definition: elog.h:122
static int cmp_string(const void *a, const void *b)
Definition: tsquery_op.c:297
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:588
signed char int8
Definition: c.h:254
#define QI_OPR
Definition: ts_type.h:144
QueryItemType type
Definition: ts_type.h:204
void * palloc0(Size size)
Definition: mcxt.c:878
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
Datum tsq_mcontained(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:375
static int CompareTSQ(TSQuery a, TSQuery b)
Definition: tsquery_op.c:188
Datum tsquery_not(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:158
#define CMPFUNC(NAME, CONDITION)
Definition: tsquery_op.c:226
#define OP_PHRASE
Definition: ts_type.h:178
Datum tsquery_and(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:52
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:225
struct QTNode ** child
Definition: ts_utils.h:208
#define QTN_NEEDFREE
Definition: ts_utils.h:212
uint32 length
Definition: ts_type.h:167
static int remove_duplicates(char **strings, int n)
Definition: tsquery_op.c:306
int16 distance
Definition: ltxtquery_io.c:31
Datum tsquery_numnode(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:21
static Datum values[MAXATTR]
Definition: bootstrap.c:163
QueryItem * valnode
Definition: ts_utils.h:203
#define Int32GetDatum(X)
Definition: postgres.h:485
int32 nchild
Definition: ts_utils.h:205
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
int32 size
Definition: ts_type.h:217
int i
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
int QTNodeCompare(QTNode *an, QTNode *bn)
Definition: tsquery_util.c:96
QueryOperand qoperand
Definition: ts_type.h:206
#define qsort(a, b, c, d)
Definition: port.h:440
#define MAXENTRYPOS
Definition: ts_type.h:85
long val
Definition: informix.c:689
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:586
uint32 flags
Definition: ts_utils.h:204
Datum tsquery_or(PG_FUNCTION_ARGS)
Definition: tsquery_op.c:82
#define OP_NOT
Definition: ts_type.h:175