PostgreSQL Source Code  git master
tsginidx.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * tsginidx.c
4  * GIN support functions for tsvector_ops
5  *
6  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  * src/backend/utils/adt/tsginidx.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "access/gin.h"
17 #include "access/stratnum.h"
18 #include "miscadmin.h"
19 #include "tsearch/ts_type.h"
20 #include "tsearch/ts_utils.h"
21 #include "utils/builtins.h"
22 
23 
24 Datum
26 {
27  text *a = PG_GETARG_TEXT_PP(0);
28  text *b = PG_GETARG_TEXT_PP(1);
29  int cmp;
30 
33  false);
34 
35  PG_FREE_IF_COPY(a, 0);
36  PG_FREE_IF_COPY(b, 1);
37  PG_RETURN_INT32(cmp);
38 }
39 
40 Datum
42 {
43  text *a = PG_GETARG_TEXT_PP(0);
44  text *b = PG_GETARG_TEXT_PP(1);
45 
46 #ifdef NOT_USED
47  StrategyNumber strategy = PG_GETARG_UINT16(2);
48  Pointer extra_data = PG_GETARG_POINTER(3);
49 #endif
50  int cmp;
51 
54  true);
55 
56  if (cmp < 0)
57  cmp = 1; /* prevent continue scan */
58 
59  PG_FREE_IF_COPY(a, 0);
60  PG_FREE_IF_COPY(b, 1);
61  PG_RETURN_INT32(cmp);
62 }
63 
64 Datum
66 {
67  TSVector vector = PG_GETARG_TSVECTOR(0);
68  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
69  Datum *entries = NULL;
70 
71  *nentries = vector->size;
72  if (vector->size > 0)
73  {
74  int i;
75  WordEntry *we = ARRPTR(vector);
76 
77  entries = (Datum *) palloc(sizeof(Datum) * vector->size);
78 
79  for (i = 0; i < vector->size; i++)
80  {
81  text *txt;
82 
83  txt = cstring_to_text_with_len(STRPTR(vector) + we->pos, we->len);
84  entries[i] = PointerGetDatum(txt);
85 
86  we++;
87  }
88  }
89 
90  PG_FREE_IF_COPY(vector, 0);
91  PG_RETURN_POINTER(entries);
92 }
93 
94 Datum
96 {
97  TSQuery query = PG_GETARG_TSQUERY(0);
98  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
99 
100  /* StrategyNumber strategy = PG_GETARG_UINT16(2); */
101  bool **ptr_partialmatch = (bool **) PG_GETARG_POINTER(3);
102  Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
103 
104  /* bool **nullFlags = (bool **) PG_GETARG_POINTER(5); */
105  int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
106  Datum *entries = NULL;
107 
108  *nentries = 0;
109 
110  if (query->size > 0)
111  {
112  QueryItem *item = GETQUERY(query);
113  int32 i,
114  j;
115  bool *partialmatch;
116  int *map_item_operand;
117 
118  /*
119  * If the query doesn't have any required positive matches (for
120  * instance, it's something like '! foo'), we have to do a full index
121  * scan.
122  */
123  if (tsquery_requires_match(item))
124  *searchMode = GIN_SEARCH_MODE_DEFAULT;
125  else
126  *searchMode = GIN_SEARCH_MODE_ALL;
127 
128  /* count number of VAL items */
129  j = 0;
130  for (i = 0; i < query->size; i++)
131  {
132  if (item[i].type == QI_VAL)
133  j++;
134  }
135  *nentries = j;
136 
137  entries = (Datum *) palloc(sizeof(Datum) * j);
138  partialmatch = *ptr_partialmatch = (bool *) palloc(sizeof(bool) * j);
139 
140  /*
141  * Make map to convert item's number to corresponding operand's (the
142  * same, entry's) number. Entry's number is used in check array in
143  * consistent method. We use the same map for each entry.
144  */
145  *extra_data = (Pointer *) palloc(sizeof(Pointer) * j);
146  map_item_operand = (int *) palloc0(sizeof(int) * query->size);
147 
148  /* Now rescan the VAL items and fill in the arrays */
149  j = 0;
150  for (i = 0; i < query->size; i++)
151  {
152  if (item[i].type == QI_VAL)
153  {
154  QueryOperand *val = &item[i].qoperand;
155  text *txt;
156 
157  txt = cstring_to_text_with_len(GETOPERAND(query) + val->distance,
158  val->length);
159  entries[j] = PointerGetDatum(txt);
160  partialmatch[j] = val->prefix;
161  (*extra_data)[j] = (Pointer) map_item_operand;
162  map_item_operand[i] = j;
163  j++;
164  }
165  }
166  }
167 
168  PG_FREE_IF_COPY(query, 0);
169 
170  PG_RETURN_POINTER(entries);
171 }
172 
173 typedef struct
174 {
179 } GinChkVal;
180 
181 /*
182  * TS_execute callback for matching a tsquery operand to GIN index data
183  */
184 static TSTernaryValue
186 {
187  GinChkVal *gcv = (GinChkVal *) checkval;
188  int j;
189 
190  /*
191  * if any val requiring a weight is used or caller needs position
192  * information then set recheck flag
193  */
194  if (val->weight != 0 || data != NULL)
195  *(gcv->need_recheck) = true;
196 
197  /* convert item's number to corresponding entry's (operand's) number */
198  j = gcv->map_item_operand[((QueryItem *) val) - gcv->first_item];
199 
200  /*
201  * return presence of current entry in indexed value; but TRUE becomes
202  * MAYBE in the presence of a query requiring recheck
203  */
204  if (gcv->check[j] == GIN_TRUE)
205  {
206  if (val->weight != 0 || data != NULL)
207  return TS_MAYBE;
208  }
209 
210  /*
211  * We rely on GinTernaryValue and TSTernaryValue using equivalent value
212  * assignments. We could use a switch statement to map the values if that
213  * ever stops being true, but it seems unlikely to happen.
214  */
215  return (TSTernaryValue) gcv->check[j];
216 }
217 
218 Datum
220 {
221  bool *check = (bool *) PG_GETARG_POINTER(0);
222 
223  /* StrategyNumber strategy = PG_GETARG_UINT16(1); */
224  TSQuery query = PG_GETARG_TSQUERY(2);
225 
226  /* int32 nkeys = PG_GETARG_INT32(3); */
227  Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4);
228  bool *recheck = (bool *) PG_GETARG_POINTER(5);
229  bool res = false;
230 
231  /* Initially assume query doesn't require recheck */
232  *recheck = false;
233 
234  if (query->size > 0)
235  {
236  GinChkVal gcv;
237 
238  /*
239  * check-parameter array has one entry for each value (operand) in the
240  * query.
241  */
242  gcv.first_item = GETQUERY(query);
243  StaticAssertStmt(sizeof(GinTernaryValue) == sizeof(bool),
244  "sizes of GinTernaryValue and bool are not equal");
245  gcv.check = (GinTernaryValue *) check;
246  gcv.map_item_operand = (int *) (extra_data[0]);
247  gcv.need_recheck = recheck;
248 
249  res = TS_execute(GETQUERY(query),
250  &gcv,
253  }
254 
255  PG_RETURN_BOOL(res);
256 }
257 
258 Datum
260 {
262 
263  /* StrategyNumber strategy = PG_GETARG_UINT16(1); */
264  TSQuery query = PG_GETARG_TSQUERY(2);
265 
266  /* int32 nkeys = PG_GETARG_INT32(3); */
267  Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4);
269  bool recheck;
270 
271  /* Initially assume query doesn't require recheck */
272  recheck = false;
273 
274  if (query->size > 0)
275  {
276  GinChkVal gcv;
277 
278  /*
279  * check-parameter array has one entry for each value (operand) in the
280  * query.
281  */
282  gcv.first_item = GETQUERY(query);
283  gcv.check = check;
284  gcv.map_item_operand = (int *) (extra_data[0]);
285  gcv.need_recheck = &recheck;
286 
287  if (TS_execute(GETQUERY(query),
288  &gcv,
291  res = recheck ? GIN_MAYBE : GIN_TRUE;
292  }
293 
295 }
296 
297 /*
298  * Formerly, gin_extract_tsvector had only two arguments. Now it has three,
299  * but we still need a pg_proc entry with two args to support reloading
300  * pre-9.1 contrib/tsearch2 opclass declarations. This compatibility
301  * function should go away eventually. (Note: you might say "hey, but the
302  * code above is only *using* two args, so let's just declare it that way".
303  * If you try that you'll find the opr_sanity regression test complains.)
304  */
305 Datum
307 {
308  if (PG_NARGS() < 3) /* should not happen */
309  elog(ERROR, "gin_extract_tsvector requires three arguments");
310  return gin_extract_tsvector(fcinfo);
311 }
312 
313 /*
314  * Likewise, we need a stub version of gin_extract_tsquery declared with
315  * only five arguments.
316  */
317 Datum
319 {
320  if (PG_NARGS() < 7) /* should not happen */
321  elog(ERROR, "gin_extract_tsquery requires seven arguments");
322  return gin_extract_tsquery(fcinfo);
323 }
324 
325 /*
326  * Likewise, we need a stub version of gin_tsquery_consistent declared with
327  * only six arguments.
328  */
329 Datum
331 {
332  if (PG_NARGS() < 8) /* should not happen */
333  elog(ERROR, "gin_tsquery_consistent requires eight arguments");
334  return gin_tsquery_consistent(fcinfo);
335 }
336 
337 /*
338  * Likewise, a stub version of gin_extract_tsquery declared with argument
339  * types that are no longer considered appropriate.
340  */
341 Datum
343 {
344  return gin_extract_tsquery(fcinfo);
345 }
346 
347 /*
348  * Likewise, a stub version of gin_tsquery_consistent declared with argument
349  * types that are no longer considered appropriate.
350  */
351 Datum
353 {
354  return gin_tsquery_consistent(fcinfo);
355 }
#define GIN_TRUE
Definition: gin.h:61
bool TS_execute(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)
Definition: tsvector_op.c:1846
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
Datum gin_tsquery_consistent(PG_FUNCTION_ARGS)
Definition: tsginidx.c:219
Datum gin_extract_tsvector(PG_FUNCTION_ARGS)
Definition: tsginidx.c:65
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
Datum gin_tsquery_consistent_6args(PG_FUNCTION_ARGS)
Definition: tsginidx.c:330
Datum gin_extract_tsvector_2args(PG_FUNCTION_ARGS)
Definition: tsginidx.c:306
#define GIN_MAYBE
Definition: gin.h:62
Datum gin_tsquery_consistent_oldsig(PG_FUNCTION_ARGS)
Definition: tsginidx.c:352
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PG_GETARG_TSQUERY(n)
Definition: ts_type.h:238
bool tsquery_requires_match(QueryItem *curitem)
Definition: tsvector_op.c:1965
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
uint32 len
Definition: ts_type.h:44
uint16 StrategyNumber
Definition: stratnum.h:22
#define QI_VAL
Definition: ts_type.h:134
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
Datum gin_tsquery_triconsistent(PG_FUNCTION_ARGS)
Definition: tsginidx.c:259
uint32 distance
Definition: ts_type.h:158
#define GETQUERY(x)
Definition: _int.h:157
signed int int32
Definition: c.h:417
#define GETOPERAND(x)
Definition: ltree.h:151
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:914
#define PG_RETURN_GIN_TERNARY_VALUE(x)
Definition: gin.h:67
#define GIN_SEARCH_MODE_ALL
Definition: gin.h:36
char * Pointer
Definition: c.h:406
#define ERROR
Definition: elog.h:43
uint8 weight
Definition: ts_type.h:146
QueryItem * first_item
Definition: tsginidx.c:175
char GinTernaryValue
Definition: gin.h:58
Datum gin_extract_tsquery_5args(PG_FUNCTION_ARGS)
Definition: tsginidx.c:318
static TSTernaryValue checkcondition_gin(void *checkval, QueryOperand *val, ExecPhraseData *data)
Definition: tsginidx.c:185
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:200
int32 size
Definition: ts_type.h:93
void * palloc0(Size size)
Definition: mcxt.c:981
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
uintptr_t Datum
Definition: postgres.h:367
bool * need_recheck
Definition: tsginidx.c:178
#define GIN_SEARCH_MODE_DEFAULT
Definition: gin.h:34
#define TS_EXEC_PHRASE_NO_POS
Definition: ts_utils.h:198
#define GIN_FALSE
Definition: gin.h:60
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
int32 tsCompareString(char *a, int lena, char *b, int lenb, bool prefix)
Definition: tsvector_op.c:1147
#define PG_NARGS()
Definition: fmgr.h:203
Datum gin_extract_tsquery(PG_FUNCTION_ARGS)
Definition: tsginidx.c:95
uint32 pos
Definition: ts_type.h:44
Datum gin_cmp_tslexeme(PG_FUNCTION_ARGS)
Definition: tsginidx.c:25
uint32 length
Definition: ts_type.h:158
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:272
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
void * palloc(Size size)
Definition: mcxt.c:950
#define STRPTR(x)
Definition: hstore.h:76
int32 size
Definition: ts_type.h:208
#define elog(elevel,...)
Definition: elog.h:228
int i
Datum gin_extract_tsquery_oldsig(PG_FUNCTION_ARGS)
Definition: tsginidx.c:342
GinTernaryValue * check
Definition: tsginidx.c:176
TSTernaryValue
Definition: ts_utils.h:128
#define PG_GETARG_TSVECTOR(n)
Definition: ts_type.h:120
Definition: c.h:617
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
bool prefix
Definition: ts_type.h:150
#define ARRPTR(x)
Definition: cube.c:24
QueryOperand qoperand
Definition: ts_type.h:197
Datum gin_cmp_prefix(PG_FUNCTION_ARGS)
Definition: tsginidx.c:41
long val
Definition: informix.c:664
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:742
int * map_item_operand
Definition: tsginidx.c:177