PostgreSQL Source Code  git master
btree_gin.c
Go to the documentation of this file.
1 /*
2  * contrib/btree_gin/btree_gin.c
3  */
4 #include "postgres.h"
5 
6 #include <limits.h>
7 
8 #include "access/stratnum.h"
9 #include "utils/builtins.h"
10 #include "utils/bytea.h"
11 #include "utils/cash.h"
12 #include "utils/date.h"
13 #include "utils/inet.h"
14 #include "utils/numeric.h"
15 #include "utils/timestamp.h"
16 #include "utils/varbit.h"
17 #include "utils/uuid.h"
18 
20 
21 typedef struct QueryInfo
22 {
25  bool is_varlena;
27 } QueryInfo;
28 
29 /*** GIN support functions shared by all datatypes ***/
30 
31 static Datum
33 {
35  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
36  Datum *entries = (Datum *) palloc(sizeof(Datum));
37 
38  if (is_varlena)
39  datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
40  entries[0] = datum;
41  *nentries = 1;
42 
43  PG_RETURN_POINTER(entries);
44 }
45 
46 /*
47  * For BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, and
48  * BTEqualStrategyNumber we want to start the index scan at the
49  * supplied query datum, and work forward. For BTLessStrategyNumber
50  * and BTLessEqualStrategyNumber, we need to start at the leftmost
51  * key, and work forward until the supplied query datum (which must be
52  * sent along inside the QueryInfo structure).
53  */
54 static Datum
56  bool is_varlena,
57  Datum (*leftmostvalue) (void),
59 {
61  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
63  bool **partialmatch = (bool **) PG_GETARG_POINTER(3);
64  Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
65  Datum *entries = (Datum *) palloc(sizeof(Datum));
66  QueryInfo *data = (QueryInfo *) palloc(sizeof(QueryInfo));
67  bool *ptr_partialmatch;
68 
69  *nentries = 1;
70  ptr_partialmatch = *partialmatch = (bool *) palloc(sizeof(bool));
71  *ptr_partialmatch = false;
72  if (is_varlena)
73  datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
74  data->strategy = strategy;
75  data->datum = datum;
76  data->is_varlena = is_varlena;
77  data->typecmp = typecmp;
78  *extra_data = (Pointer *) palloc(sizeof(Pointer));
79  **extra_data = (Pointer) data;
80 
81  switch (strategy)
82  {
85  entries[0] = leftmostvalue();
86  *ptr_partialmatch = true;
87  break;
90  *ptr_partialmatch = true;
92  entries[0] = datum;
93  break;
94  default:
95  elog(ERROR, "unrecognized strategy number: %d", strategy);
96  }
97 
98  PG_RETURN_POINTER(entries);
99 }
100 
101 /*
102  * Datum a is a value from extract_query method and for BTLess*
103  * strategy it is a left-most value. So, use original datum from QueryInfo
104  * to decide to stop scanning or not. Datum b is always from index.
105  */
106 static Datum
108 {
109  Datum a = PG_GETARG_DATUM(0);
110  Datum b = PG_GETARG_DATUM(1);
111  QueryInfo *data = (QueryInfo *) PG_GETARG_POINTER(3);
112  int32 res,
113  cmp;
114 
116  data->typecmp,
117  fcinfo->flinfo,
119  (data->strategy == BTLessStrategyNumber ||
121  ? data->datum : a,
122  b));
123 
124  switch (data->strategy)
125  {
127  /* If original datum > indexed one then return match */
128  if (cmp > 0)
129  res = 0;
130  else
131  res = 1;
132  break;
134  /* The same except equality */
135  if (cmp >= 0)
136  res = 0;
137  else
138  res = 1;
139  break;
141  if (cmp != 0)
142  res = 1;
143  else
144  res = 0;
145  break;
147  /* If original datum <= indexed one then return match */
148  if (cmp <= 0)
149  res = 0;
150  else
151  res = 1;
152  break;
154  /* If original datum <= indexed one then return match */
155  /* If original datum == indexed one then continue scan */
156  if (cmp < 0)
157  res = 0;
158  else if (cmp == 0)
159  res = -1;
160  else
161  res = 1;
162  break;
163  default:
164  elog(ERROR, "unrecognized strategy number: %d",
165  data->strategy);
166  res = 0;
167  }
168 
169  PG_RETURN_INT32(res);
170 }
171 
173 Datum
175 {
176  bool *recheck = (bool *) PG_GETARG_POINTER(5);
177 
178  *recheck = false;
179  PG_RETURN_BOOL(true);
180 }
181 
182 /*** GIN_SUPPORT macro defines the datatype specific functions ***/
183 
184 #define GIN_SUPPORT(type, is_varlena, leftmostvalue, typecmp) \
185 PG_FUNCTION_INFO_V1(gin_extract_value_##type); \
186 Datum \
187 gin_extract_value_##type(PG_FUNCTION_ARGS) \
188 { \
189  return gin_btree_extract_value(fcinfo, is_varlena); \
190 } \
191 PG_FUNCTION_INFO_V1(gin_extract_query_##type); \
192 Datum \
193 gin_extract_query_##type(PG_FUNCTION_ARGS) \
194 { \
195  return gin_btree_extract_query(fcinfo, \
196  is_varlena, leftmostvalue, typecmp); \
197 } \
198 PG_FUNCTION_INFO_V1(gin_compare_prefix_##type); \
199 Datum \
200 gin_compare_prefix_##type(PG_FUNCTION_ARGS) \
201 { \
202  return gin_btree_compare_prefix(fcinfo); \
203 }
204 
205 
206 /*** Datatype specifications ***/
207 
208 static Datum
210 {
211  return Int16GetDatum(SHRT_MIN);
212 }
213 
215 
216 static Datum
218 {
219  return Int32GetDatum(INT_MIN);
220 }
221 
223 
224 static Datum
226 {
227  return Int64GetDatum(PG_INT64_MIN);
228 }
229 
231 
232 static Datum
234 {
236 }
237 
239 
240 static Datum
242 {
244 }
245 
247 
248 static Datum
250 {
251  return Int64GetDatum(PG_INT64_MIN);
252 }
253 
255 
256 static Datum
258 {
259  return ObjectIdGetDatum(0);
260 }
261 
263 
264 static Datum
266 {
268 }
269 
271 
273 
274 static Datum
276 {
277  return TimeADTGetDatum(0);
278 }
279 
281 
282 static Datum
284 {
285  TimeTzADT *v = palloc(sizeof(TimeTzADT));
286 
287  v->time = 0;
288  v->zone = -24 * 3600; /* XXX is that true? */
289 
290  return TimeTzADTPGetDatum(v);
291 }
292 
294 
295 static Datum
297 {
299 }
300 
302 
303 static Datum
305 {
306  Interval *v = palloc(sizeof(Interval));
307 
308  v->time = DT_NOBEGIN;
309  v->day = 0;
310  v->month = 0;
311  return IntervalPGetDatum(v);
312 }
313 
315 
316 static Datum
318 {
319  macaddr *v = palloc0(sizeof(macaddr));
320 
321  return MacaddrPGetDatum(v);
322 }
323 
325 
326 static Datum
328 {
329  macaddr8 *v = palloc0(sizeof(macaddr8));
330 
331  return Macaddr8PGetDatum(v);
332 }
333 
335 
336 static Datum
338 {
339  return DirectFunctionCall1(inet_in, CStringGetDatum("0.0.0.0/0"));
340 }
341 
343 
345 
346 static Datum
348 {
350 }
351 
353 
355 
356 static Datum
358 {
359  return CharGetDatum(SCHAR_MIN);
360 }
361 
363 
365 
366 static Datum
368 {
370  CStringGetDatum(""),
371  ObjectIdGetDatum(0),
372  Int32GetDatum(-1));
373 }
374 
376 
377 static Datum
379 {
381  CStringGetDatum(""),
382  ObjectIdGetDatum(0),
383  Int32GetDatum(-1));
384 }
385 
387 
388 /*
389  * Numeric type hasn't a real left-most value, so we use PointerGetDatum(NULL)
390  * (*not* a SQL NULL) to represent that. We can get away with that because
391  * the value returned by our leftmostvalue function will never be stored in
392  * the index nor passed to anything except our compare and prefix-comparison
393  * functions. The same trick could be used for other pass-by-reference types.
394  */
395 
396 #define NUMERIC_IS_LEFTMOST(x) ((x) == NULL)
397 
399 
400 Datum
402 {
405  int res = 0;
406 
407  if (NUMERIC_IS_LEFTMOST(a))
408  {
409  res = (NUMERIC_IS_LEFTMOST(b)) ? 0 : -1;
410  }
411  else if (NUMERIC_IS_LEFTMOST(b))
412  {
413  res = 1;
414  }
415  else
416  {
418  NumericGetDatum(a),
419  NumericGetDatum(b)));
420  }
421 
422  PG_RETURN_INT32(res);
423 }
424 
425 static Datum
427 {
428  return PointerGetDatum(NULL);
429 }
430 
432 
433 /*
434  * Use a similar trick to that used for numeric for enums, since we don't
435  * actually know the leftmost value of any enum without knowing the concrete
436  * type, so we use a dummy leftmost value of InvalidOid.
437  *
438  * Note that we use CallerFInfoFunctionCall2 here so that enum_cmp
439  * gets a valid fn_extra to work with. Unlike most other type comparison
440  * routines it needs it, so we can't use DirectFunctionCall2.
441  */
442 
443 #define ENUM_IS_LEFTMOST(x) ((x) == InvalidOid)
444 
446 
447 Datum
449 {
450  Oid a = PG_GETARG_OID(0);
451  Oid b = PG_GETARG_OID(1);
452  int res = 0;
453 
454  if (ENUM_IS_LEFTMOST(a))
455  {
456  res = (ENUM_IS_LEFTMOST(b)) ? 0 : -1;
457  }
458  else if (ENUM_IS_LEFTMOST(b))
459  {
460  res = 1;
461  }
462  else
463  {
465  enum_cmp,
466  fcinfo->flinfo,
468  ObjectIdGetDatum(a),
469  ObjectIdGetDatum(b)));
470  }
471 
472  PG_RETURN_INT32(res);
473 }
474 
475 static Datum
477 {
479 }
480 
482 
483 static Datum
485 {
486  /* palloc0 will create the UUID with all zeroes: "00000000-0000-0000-0000-000000000000" */
487  pg_uuid_t *retval = (pg_uuid_t *) palloc0(sizeof(pg_uuid_t));
488  return UUIDPGetDatum(retval);
489 }
490 
492 
493 static Datum
495 {
496  NameData* result = (NameData *) palloc0(NAMEDATALEN);
497  return NameGetDatum(result);
498 }
499 
501 
502 static Datum
504 {
505  return BoolGetDatum(false);
506 }
507 
static Datum leftmostvalue_date(void)
Definition: btree_gin.c:296
Datum timetz_cmp(PG_FUNCTION_ARGS)
Definition: date.c:2263
Datum gin_numeric_cmp(PG_FUNCTION_ARGS)
Definition: btree_gin.c:401
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Datum macaddr8_cmp(PG_FUNCTION_ARGS)
Definition: mac8.c:333
#define NameGetDatum(X)
Definition: postgres.h:578
Datum varbit_in(PG_FUNCTION_ARGS)
Definition: varbit.c:430
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
bool is_varlena
Definition: btree_gin.c:25
TimeADT time
Definition: date.h:29
static Datum leftmostvalue_bit(void)
Definition: btree_gin.c:367
#define DatumGetInt32(X)
Definition: postgres.h:455
Datum timestamp_cmp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2083
Datum btfloat8cmp(PG_FUNCTION_ARGS)
Definition: float.c:1133
static Datum leftmostvalue_int8(void)
Definition: btree_gin.c:225
int64 timestamp
Datum CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1085
#define PointerGetDatum(X)
Definition: postgres.h:539
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
#define MacaddrPGetDatum(X)
Definition: inet.h:132
static Datum leftmostvalue_inet(void)
Definition: btree_gin.c:337
Datum bitcmp(PG_FUNCTION_ARGS)
Definition: varbit.c:929
#define NumericGetDatum(X)
Definition: numeric.h:51
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2031
#define TimeTzADTPGetDatum(X)
Definition: date.h:59
#define Int16GetDatum(X)
Definition: postgres.h:434
#define PG_RETURN_INT32(x)
Definition: fmgr.h:319
uint16 StrategyNumber
Definition: stratnum.h:22
Datum btfloat4cmp(PG_FUNCTION_ARGS)
Definition: float.c:1019
#define DateADTGetDatum(X)
Definition: date.h:57
static Datum leftmostvalue_text(void)
Definition: btree_gin.c:347
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
long date
Definition: pgtypes_date.h:8
static Datum gin_btree_extract_query(FunctionCallInfo fcinfo, bool is_varlena, Datum(*leftmostvalue)(void), Datum(*typecmp)(FunctionCallInfo))
Definition: btree_gin.c:55
static Datum leftmostvalue_macaddr(void)
Definition: btree_gin.c:317
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
unsigned int Oid
Definition: postgres_ext.h:31
static Datum leftmostvalue_char(void)
Definition: btree_gin.c:357
struct NumericData * Numeric
Definition: numeric.h:43
Datum interval_cmp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2394
#define PG_GET_COLLATION()
Definition: fmgr.h:168
Datum btboolcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:56
signed int int32
Definition: c.h:313
static Datum leftmostvalue_numeric(void)
Definition: btree_gin.c:426
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1900
Datum datum
Definition: btree_gin.c:24
static Datum leftmostvalue_time(void)
Definition: btree_gin.c:275
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
int32 day
Definition: timestamp.h:47
StrategyNumber strategy
Definition: btree_gin.c:23
float get_float4_infinity(void)
Definition: float.c:143
Datum gin_enum_cmp(PG_FUNCTION_ARGS)
Definition: btree_gin.c:448
Datum btoidcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:250
#define NAMEDATALEN
FmgrInfo * flinfo
Definition: fmgr.h:79
static Datum leftmostvalue_interval(void)
Definition: btree_gin.c:304
char * Pointer
Definition: c.h:302
static Datum leftmostvalue_macaddr8(void)
Definition: btree_gin.c:327
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
Datum btcharcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:311
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:458
Definition: inet.h:107
#define IntervalPGetDatum(X)
Definition: timestamp.h:33
Datum time_cmp(PG_FUNCTION_ARGS)
Definition: date.c:1519
static Datum leftmostvalue_timetz(void)
Definition: btree_gin.c:283
Datum bit_in(PG_FUNCTION_ARGS)
Definition: varbit.c:114
#define UUIDPGetDatum(X)
Definition: uuid.h:26
int32 zone
Definition: date.h:30
struct FunctionCallInfoData * FunctionCallInfo
Definition: fmgr.h:38
Datum varbit(PG_FUNCTION_ARGS)
Definition: varbit.c:715
Datum Float4GetDatum(float4 X)
Definition: fmgr.c:1888
Definition: c.h:570
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
#define PG_INT64_MIN
Definition: c.h:410
#define PG_GETARG_OID(n)
Definition: fmgr.h:245
#define DATEVAL_NOBEGIN
Definition: date.h:36
#define CStringGetDatum(X)
Definition: postgres.h:561
Definition: inet.h:52
TimeOffset time
Definition: timestamp.h:45
#define ENUM_IS_LEFTMOST(x)
Definition: btree_gin.c:443
static Datum leftmostvalue_money(void)
Definition: btree_gin.c:249
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1876
Datum(* typecmp)(FunctionCallInfo)
Definition: btree_gin.c:26
Datum btint4cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:92
#define TimestampGetDatum(X)
Definition: timestamp.h:31
static Datum leftmostvalue_uuid(void)
Definition: btree_gin.c:484
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:594
double get_float8_infinity(void)
Definition: float.c:118
int32 month
Definition: timestamp.h:48
signed char int8
Definition: c.h:311
float float4
Definition: c.h:457
static Datum leftmostvalue_oid(void)
Definition: btree_gin.c:257
void * palloc0(Size size)
Definition: mcxt.c:955
#define NUMERIC_IS_LEFTMOST(x)
Definition: btree_gin.c:396
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:324
uintptr_t Datum
Definition: postgres.h:365
#define Macaddr8PGetDatum(X)
Definition: inet.h:138
#define TimeADTGetDatum(X)
Definition: date.h:58
static Datum leftmostvalue_int4(void)
Definition: btree_gin.c:217
#define BoolGetDatum(X)
Definition: postgres.h:385
static Datum leftmostvalue_bool(void)
Definition: btree_gin.c:503
static Datum leftmostvalue_varbit(void)
Definition: btree_gin.c:378
Datum byteacmp(PG_FUNCTION_ARGS)
Definition: varlena.c:3659
#define InvalidOid
Definition: postgres_ext.h:36
Datum bit(PG_FUNCTION_ARGS)
Definition: varbit.c:362
static Datum leftmostvalue_name(void)
Definition: btree_gin.c:494
struct QueryInfo QueryInfo
static Datum leftmostvalue_timestamp(void)
Definition: btree_gin.c:265
Datum enum_cmp(PG_FUNCTION_ARGS)
Definition: enum.c:294
Datum inet_in(PG_FUNCTION_ARGS)
Definition: network.c:80
static Datum leftmostvalue_float4(void)
Definition: btree_gin.c:233
static Datum leftmostvalue_enum(void)
Definition: btree_gin.c:476
static Datum leftmostvalue_float8(void)
Definition: btree_gin.c:241
Definition: inet.h:94
#define GIN_SUPPORT(type, is_varlena, leftmostvalue, typecmp)
Definition: btree_gin.c:184
Datum date_cmp(PG_FUNCTION_ARGS)
Definition: date.c:441
PG_FUNCTION_INFO_V1(gin_btree_consistent)
Datum macaddr_cmp(PG_FUNCTION_ARGS)
Definition: mac.c:197
const char * name
Definition: encode.c:521
#define CharGetDatum(X)
Definition: postgres.h:399
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:242
Datum btint8cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:129
Datum bttextcmp(PG_FUNCTION_ARGS)
Definition: varlena.c:1793
#define Int32GetDatum(X)
Definition: postgres.h:462
static Datum gin_btree_extract_value(FunctionCallInfo fcinfo, bool is_varlena)
Definition: btree_gin.c:32
Definition: uuid.h:20
void * palloc(Size size)
Definition: mcxt.c:924
Datum gin_btree_consistent(PG_FUNCTION_ARGS)
Definition: btree_gin.c:174
Datum btint2cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:65
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:210
Definition: c.h:516
#define PG_FUNCTION_ARGS
Definition: fmgr.h:163
Datum bpcharcmp(PG_FUNCTION_ARGS)
Definition: varchar.c:849
Datum network_cmp(PG_FUNCTION_ARGS)
Definition: network.c:384
Datum uuid_cmp(PG_FUNCTION_ARGS)
Definition: uuid.c:225
#define elog
Definition: elog.h:219
#define DT_NOBEGIN
Definition: timestamp.h:109
Datum cash_cmp(PG_FUNCTION_ARGS)
Definition: cash.c:593
Datum bpchar(PG_FUNCTION_ARGS)
Definition: varchar.c:267
PG_MODULE_MAGIC
Definition: btree_gin.c:19
static Datum leftmostvalue_int2(void)
Definition: btree_gin.c:209
#define BTLessStrategyNumber
Definition: stratnum.h:29
Definition: date.h:27
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:592
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32
static Datum gin_btree_compare_prefix(FunctionCallInfo fcinfo)
Definition: btree_gin.c:107
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:742
Datum btnamecmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:321