PostgreSQL Source Code  git master
brin_inclusion.c
Go to the documentation of this file.
1 /*
2  * brin_inclusion.c
3  * Implementation of inclusion opclasses for BRIN
4  *
5  * This module provides framework BRIN support functions for the "inclusion"
6  * operator classes. A few SQL-level support functions are also required for
7  * each opclass.
8  *
9  * The "inclusion" BRIN strategy is useful for types that support R-Tree
10  * operations. This implementation is a straight mapping of those operations
11  * to the block-range nature of BRIN, with two exceptions: (a) we explicitly
12  * support "empty" elements: at least with range types, we need to consider
13  * emptiness separately from regular R-Tree strategies; and (b) we need to
14  * consider "unmergeable" elements, that is, a set of elements for whose union
15  * no representation exists. The only case where that happens as of this
16  * writing is the INET type, where IPv6 values cannot be merged with IPv4
17  * values.
18  *
19  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
20  * Portions Copyright (c) 1994, Regents of the University of California
21  *
22  * IDENTIFICATION
23  * src/backend/access/brin/brin_inclusion.c
24  */
25 #include "postgres.h"
26 
27 #include "access/brin_internal.h"
28 #include "access/brin_tuple.h"
29 #include "access/genam.h"
30 #include "access/skey.h"
31 #include "catalog/pg_amop.h"
32 #include "catalog/pg_type.h"
33 #include "utils/datum.h"
34 #include "utils/fmgrprotos.h"
35 #include "utils/lsyscache.h"
36 #include "utils/rel.h"
37 #include "utils/syscache.h"
38 
39 
40 /*
41  * Additional SQL level support functions
42  *
43  * Procedure numbers must not use values reserved for BRIN itself; see
44  * brin_internal.h.
45  */
46 #define INCLUSION_MAX_PROCNUMS 4 /* maximum support procs we need */
47 #define PROCNUM_MERGE 11 /* required */
48 #define PROCNUM_MERGEABLE 12 /* optional */
49 #define PROCNUM_CONTAINS 13 /* optional */
50 #define PROCNUM_EMPTY 14 /* optional */
51 
52 
53 /*
54  * Subtract this from procnum to obtain index in InclusionOpaque arrays
55  * (Must be equal to minimum of private procnums).
56  */
57 #define PROCNUM_BASE 11
58 
59 /*-
60  * The values stored in the bv_values arrays correspond to:
61  *
62  * INCLUSION_UNION
63  * the union of the values in the block range
64  * INCLUSION_UNMERGEABLE
65  * whether the values in the block range cannot be merged
66  * (e.g. an IPv6 address amidst IPv4 addresses)
67  * INCLUSION_CONTAINS_EMPTY
68  * whether an empty value is present in any tuple
69  * in the block range
70  */
71 #define INCLUSION_UNION 0
72 #define INCLUSION_UNMERGEABLE 1
73 #define INCLUSION_CONTAINS_EMPTY 2
74 
75 
76 typedef struct InclusionOpaque
77 {
83 
84 static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
85  uint16 procnum);
87  Oid subtype, uint16 strategynum);
88 
89 
90 /*
91  * BRIN inclusion OpcInfo function
92  */
93 Datum
95 {
96  Oid typoid = PG_GETARG_OID(0);
97  BrinOpcInfo *result;
98  TypeCacheEntry *bool_typcache = lookup_type_cache(BOOLOID, 0);
99 
100  /*
101  * All members of opaque are initialized lazily; both procinfo arrays
102  * start out as non-initialized by having fn_oid be InvalidOid, and
103  * "missing" to false, by zeroing here. strategy_procinfos elements can
104  * be invalidated when cached_subtype changes by zeroing fn_oid.
105  * extra_procinfo entries are never invalidated, but if a lookup fails
106  * (which is expected), extra_proc_missing is set to true, indicating not
107  * to look it up again.
108  */
109  result = palloc0(MAXALIGN(SizeofBrinOpcInfo(3)) + sizeof(InclusionOpaque));
110  result->oi_nstored = 3;
111  result->oi_regular_nulls = true;
112  result->oi_opaque = (InclusionOpaque *)
113  MAXALIGN((char *) result + SizeofBrinOpcInfo(3));
114 
115  /* the union */
116  result->oi_typcache[INCLUSION_UNION] =
117  lookup_type_cache(typoid, 0);
118 
119  /* includes elements that are not mergeable */
120  result->oi_typcache[INCLUSION_UNMERGEABLE] = bool_typcache;
121 
122  /* includes the empty element */
123  result->oi_typcache[INCLUSION_CONTAINS_EMPTY] = bool_typcache;
124 
125  PG_RETURN_POINTER(result);
126 }
127 
128 /*
129  * BRIN inclusion add value function
130  *
131  * Examine the given index tuple (which contains partial status of a certain
132  * page range) by comparing it to the given value that comes from another heap
133  * tuple. If the new value is outside the union specified by the existing
134  * tuple values, update the index tuple and return true. Otherwise, return
135  * false and do not modify in this case.
136  */
137 Datum
139 {
140  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
141  BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
143  bool isnull PG_USED_FOR_ASSERTS_ONLY = PG_GETARG_BOOL(3);
144  Oid colloid = PG_GET_COLLATION();
145  FmgrInfo *finfo;
146  Datum result;
147  bool new = false;
148  AttrNumber attno;
149  Form_pg_attribute attr;
150 
151  Assert(!isnull);
152 
153  attno = column->bv_attno;
154  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
155 
156  /*
157  * If the recorded value is null, copy the new value (which we know to be
158  * not null), and we're almost done.
159  */
160  if (column->bv_allnulls)
161  {
162  column->bv_values[INCLUSION_UNION] =
163  datumCopy(newval, attr->attbyval, attr->attlen);
164  column->bv_values[INCLUSION_UNMERGEABLE] = BoolGetDatum(false);
166  column->bv_allnulls = false;
167  new = true;
168  }
169 
170  /*
171  * No need for further processing if the block range is marked as
172  * containing unmergeable values.
173  */
175  PG_RETURN_BOOL(false);
176 
177  /*
178  * If the opclass supports the concept of empty values, test the passed
179  * new value for emptiness; if it returns true, we need to set the
180  * "contains empty" flag in the element (unless already set).
181  */
182  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_EMPTY);
183  if (finfo != NULL && DatumGetBool(FunctionCall1Coll(finfo, colloid, newval)))
184  {
186  {
188  PG_RETURN_BOOL(true);
189  }
190 
191  PG_RETURN_BOOL(false);
192  }
193 
194  if (new)
195  PG_RETURN_BOOL(true);
196 
197  /* Check if the new value is already contained. */
198  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_CONTAINS);
199  if (finfo != NULL &&
200  DatumGetBool(FunctionCall2Coll(finfo, colloid,
201  column->bv_values[INCLUSION_UNION],
202  newval)))
203  PG_RETURN_BOOL(false);
204 
205  /*
206  * Check if the new value is mergeable to the existing union. If it is
207  * not, mark the value as containing unmergeable elements and get out.
208  *
209  * Note: at this point we could remove the value from the union, since
210  * it's not going to be used any longer. However, the BRIN framework
211  * doesn't allow for the value not being present. Improve someday.
212  */
213  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE);
214  if (finfo != NULL &&
215  !DatumGetBool(FunctionCall2Coll(finfo, colloid,
216  column->bv_values[INCLUSION_UNION],
217  newval)))
218  {
220  PG_RETURN_BOOL(true);
221  }
222 
223  /* Finally, merge the new value to the existing union. */
224  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE);
225  Assert(finfo != NULL);
226  result = FunctionCall2Coll(finfo, colloid,
227  column->bv_values[INCLUSION_UNION], newval);
228  if (!attr->attbyval &&
230  {
232 
233  if (result == newval)
234  result = datumCopy(result, attr->attbyval, attr->attlen);
235  }
236  column->bv_values[INCLUSION_UNION] = result;
237 
238  PG_RETURN_BOOL(true);
239 }
240 
241 /*
242  * BRIN inclusion consistent function
243  *
244  * We're no longer dealing with NULL keys in the consistent function, that is
245  * now handled by the AM code. That means we should not get any all-NULL ranges
246  * either, because those can't be consistent with regular (not [IS] NULL) keys.
247  *
248  * All of the strategies are optional.
249  */
250 Datum
252 {
253  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
254  BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
256  Oid colloid = PG_GET_COLLATION(),
257  subtype;
258  Datum unionval;
259  AttrNumber attno;
260  Datum query;
261  FmgrInfo *finfo;
262  Datum result;
263 
264  /* This opclass uses the old signature with only three arguments. */
265  Assert(PG_NARGS() == 3);
266 
267  /* Should not be dealing with all-NULL ranges. */
268  Assert(!column->bv_allnulls);
269 
270  /* It has to be checked, if it contains elements that are not mergeable. */
272  PG_RETURN_BOOL(true);
273 
274  attno = key->sk_attno;
275  subtype = key->sk_subtype;
276  query = key->sk_argument;
277  unionval = column->bv_values[INCLUSION_UNION];
278  switch (key->sk_strategy)
279  {
280  /*
281  * Placement strategies
282  *
283  * These are implemented by logically negating the result of the
284  * converse placement operator; for this to work, the converse
285  * operator must be part of the opclass. An error will be thrown
286  * by inclusion_get_strategy_procinfo() if the required strategy
287  * is not part of the opclass.
288  *
289  * These all return false if either argument is empty, so there is
290  * no need to check for empty elements.
291  */
292 
294  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
296  result = FunctionCall2Coll(finfo, colloid, unionval, query);
297  PG_RETURN_BOOL(!DatumGetBool(result));
298 
300  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
302  result = FunctionCall2Coll(finfo, colloid, unionval, query);
303  PG_RETURN_BOOL(!DatumGetBool(result));
304 
306  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
308  result = FunctionCall2Coll(finfo, colloid, unionval, query);
309  PG_RETURN_BOOL(!DatumGetBool(result));
310 
312  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
314  result = FunctionCall2Coll(finfo, colloid, unionval, query);
315  PG_RETURN_BOOL(!DatumGetBool(result));
316 
318  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
320  result = FunctionCall2Coll(finfo, colloid, unionval, query);
321  PG_RETURN_BOOL(!DatumGetBool(result));
322 
324  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
326  result = FunctionCall2Coll(finfo, colloid, unionval, query);
327  PG_RETURN_BOOL(!DatumGetBool(result));
328 
330  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
332  result = FunctionCall2Coll(finfo, colloid, unionval, query);
333  PG_RETURN_BOOL(!DatumGetBool(result));
334 
336  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
338  result = FunctionCall2Coll(finfo, colloid, unionval, query);
339  PG_RETURN_BOOL(!DatumGetBool(result));
340 
341  /*
342  * Overlap and contains strategies
343  *
344  * These strategies are simple enough that we can simply call the
345  * operator and return its result. Empty elements don't change
346  * the result.
347  */
348 
352  case RTSubStrategyNumber:
354  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
355  key->sk_strategy);
356  result = FunctionCall2Coll(finfo, colloid, unionval, query);
357  PG_RETURN_DATUM(result);
358 
359  /*
360  * Contained by strategies
361  *
362  * We cannot just call the original operator for the contained by
363  * strategies because some elements can be contained even though
364  * the union is not; instead we use the overlap operator.
365  *
366  * We check for empty elements separately as they are not merged
367  * to the union but contained by everything.
368  */
369 
373  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
375  result = FunctionCall2Coll(finfo, colloid, unionval, query);
376  if (DatumGetBool(result))
377  PG_RETURN_BOOL(true);
378 
380 
381  /*
382  * Adjacent strategy
383  *
384  * We test for overlap first but to be safe we need to call the
385  * actual adjacent operator also.
386  *
387  * An empty element cannot be adjacent to any other, so there is
388  * no need to check for it.
389  */
390 
392  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
394  result = FunctionCall2Coll(finfo, colloid, unionval, query);
395  if (DatumGetBool(result))
396  PG_RETURN_BOOL(true);
397 
398  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
400  result = FunctionCall2Coll(finfo, colloid, unionval, query);
401  PG_RETURN_DATUM(result);
402 
403  /*
404  * Basic comparison strategies
405  *
406  * It is straightforward to support the equality strategies with
407  * the contains operator. Generally, inequality strategies do not
408  * make much sense for the types which will be used with the
409  * inclusion BRIN family of opclasses, but it is possible to
410  * implement them with logical negation of the left-of and
411  * right-of operators.
412  *
413  * NB: These strategies cannot be used with geometric datatypes
414  * that use comparison of areas! The only exception is the "same"
415  * strategy.
416  *
417  * Empty elements are considered to be less than the others. We
418  * cannot use the empty support function to check the query is an
419  * empty element, because the query can be another data type than
420  * the empty support function argument. So we will return true,
421  * if there is a possibility that empty elements will change the
422  * result.
423  */
424 
427  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
429  result = FunctionCall2Coll(finfo, colloid, unionval, query);
430  if (!DatumGetBool(result))
431  PG_RETURN_BOOL(true);
432 
434 
437  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
439  result = FunctionCall2Coll(finfo, colloid, unionval, query);
440  if (DatumGetBool(result))
441  PG_RETURN_BOOL(true);
442 
444 
446  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
448  result = FunctionCall2Coll(finfo, colloid, unionval, query);
449  if (!DatumGetBool(result))
450  PG_RETURN_BOOL(true);
451 
453 
455  /* no need to check for empty elements */
456  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
458  result = FunctionCall2Coll(finfo, colloid, unionval, query);
459  PG_RETURN_BOOL(!DatumGetBool(result));
460 
461  default:
462  /* shouldn't happen */
463  elog(ERROR, "invalid strategy number %d", key->sk_strategy);
464  PG_RETURN_BOOL(false);
465  }
466 }
467 
468 /*
469  * BRIN inclusion union function
470  *
471  * Given two BrinValues, update the first of them as a union of the summary
472  * values contained in both. The second one is untouched.
473  */
474 Datum
476 {
477  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
478  BrinValues *col_a = (BrinValues *) PG_GETARG_POINTER(1);
479  BrinValues *col_b = (BrinValues *) PG_GETARG_POINTER(2);
480  Oid colloid = PG_GET_COLLATION();
481  AttrNumber attno;
482  Form_pg_attribute attr;
483  FmgrInfo *finfo;
484  Datum result;
485 
486  Assert(col_a->bv_attno == col_b->bv_attno);
487  Assert(!col_a->bv_allnulls && !col_b->bv_allnulls);
488 
489  attno = col_a->bv_attno;
490  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
491 
492  /* If B includes empty elements, mark A similarly, if needed. */
496 
497  /* Check if A includes elements that are not mergeable. */
499  PG_RETURN_VOID();
500 
501  /* If B includes elements that are not mergeable, mark A similarly. */
503  {
505  PG_RETURN_VOID();
506  }
507 
508  /* Check if A and B are mergeable; if not, mark A unmergeable. */
509  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE);
510  if (finfo != NULL &&
511  !DatumGetBool(FunctionCall2Coll(finfo, colloid,
512  col_a->bv_values[INCLUSION_UNION],
513  col_b->bv_values[INCLUSION_UNION])))
514  {
516  PG_RETURN_VOID();
517  }
518 
519  /* Finally, merge B to A. */
520  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE);
521  Assert(finfo != NULL);
522  result = FunctionCall2Coll(finfo, colloid,
523  col_a->bv_values[INCLUSION_UNION],
524  col_b->bv_values[INCLUSION_UNION]);
525  if (!attr->attbyval &&
527  {
529 
530  if (result == col_b->bv_values[INCLUSION_UNION])
531  result = datumCopy(result, attr->attbyval, attr->attlen);
532  }
533  col_a->bv_values[INCLUSION_UNION] = result;
534 
535  PG_RETURN_VOID();
536 }
537 
538 /*
539  * Cache and return inclusion opclass support procedure
540  *
541  * Return the procedure corresponding to the given function support number
542  * or null if it is not exists.
543  */
544 static FmgrInfo *
546 {
547  InclusionOpaque *opaque;
548  uint16 basenum = procnum - PROCNUM_BASE;
549 
550  /*
551  * We cache these in the opaque struct, to avoid repetitive syscache
552  * lookups.
553  */
554  opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
555 
556  /*
557  * If we already searched for this proc and didn't find it, don't bother
558  * searching again.
559  */
560  if (opaque->extra_proc_missing[basenum])
561  return NULL;
562 
563  if (opaque->extra_procinfos[basenum].fn_oid == InvalidOid)
564  {
565  if (RegProcedureIsValid(index_getprocid(bdesc->bd_index, attno,
566  procnum)))
567  {
568  fmgr_info_copy(&opaque->extra_procinfos[basenum],
569  index_getprocinfo(bdesc->bd_index, attno, procnum),
570  bdesc->bd_context);
571  }
572  else
573  {
574  opaque->extra_proc_missing[basenum] = true;
575  return NULL;
576  }
577  }
578 
579  return &opaque->extra_procinfos[basenum];
580 }
581 
582 /*
583  * Cache and return the procedure of the given strategy
584  *
585  * Return the procedure corresponding to the given sub-type and strategy
586  * number. The data type of the index will be used as the left hand side of
587  * the operator and the given sub-type will be used as the right hand side.
588  * Throws an error if the pg_amop row does not exist, but that should not
589  * happen with a properly configured opclass.
590  *
591  * It always throws an error when the data type of the opclass is different
592  * from the data type of the column or the expression. That happens when the
593  * column data type has implicit cast to the opclass data type. We don't
594  * bother casting types, because this situation can easily be avoided by
595  * setting storage data type to that of the opclass. The same problem does not
596  * apply to the data type of the right hand side, because the type in the
597  * ScanKey always matches the opclass' one.
598  *
599  * Note: this function mirrors minmax_get_strategy_procinfo; if changes are
600  * made here, see that function too.
601  */
602 static FmgrInfo *
604  uint16 strategynum)
605 {
606  InclusionOpaque *opaque;
607 
608  Assert(strategynum >= 1 &&
609  strategynum <= RTMaxStrategyNumber);
610 
611  opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
612 
613  /*
614  * We cache the procedures for the last sub-type in the opaque struct, to
615  * avoid repetitive syscache lookups. If the sub-type is changed,
616  * invalidate all the cached entries.
617  */
618  if (opaque->cached_subtype != subtype)
619  {
620  uint16 i;
621 
622  for (i = 1; i <= RTMaxStrategyNumber; i++)
623  opaque->strategy_procinfos[i - 1].fn_oid = InvalidOid;
624  opaque->cached_subtype = subtype;
625  }
626 
627  if (opaque->strategy_procinfos[strategynum - 1].fn_oid == InvalidOid)
628  {
629  Form_pg_attribute attr;
630  HeapTuple tuple;
631  Oid opfamily,
632  oprid;
633 
634  opfamily = bdesc->bd_index->rd_opfamily[attno - 1];
635  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
636  tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
637  ObjectIdGetDatum(attr->atttypid),
638  ObjectIdGetDatum(subtype),
639  Int16GetDatum(strategynum));
640 
641  if (!HeapTupleIsValid(tuple))
642  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
643  strategynum, attr->atttypid, subtype, opfamily);
644 
645  oprid = DatumGetObjectId(SysCacheGetAttrNotNull(AMOPSTRATEGY, tuple,
646  Anum_pg_amop_amopopr));
647  ReleaseSysCache(tuple);
649 
651  &opaque->strategy_procinfos[strategynum - 1],
652  bdesc->bd_context);
653  }
654 
655  return &opaque->strategy_procinfos[strategynum - 1];
656 }
int16 AttrNumber
Definition: attnum.h:21
#define PROCNUM_MERGEABLE
#define PROCNUM_EMPTY
Datum brin_inclusion_union(PG_FUNCTION_ARGS)
#define INCLUSION_UNMERGEABLE
Datum brin_inclusion_opcinfo(PG_FUNCTION_ARGS)
static FmgrInfo * inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, uint16 strategynum)
Datum brin_inclusion_consistent(PG_FUNCTION_ARGS)
Datum brin_inclusion_add_value(PG_FUNCTION_ARGS)
#define INCLUSION_UNION
#define INCLUSION_MAX_PROCNUMS
#define PROCNUM_BASE
struct InclusionOpaque InclusionOpaque
#define PROCNUM_CONTAINS
#define INCLUSION_CONTAINS_EMPTY
static FmgrInfo * inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum)
#define PROCNUM_MERGE
#define SizeofBrinOpcInfo(ncols)
Definition: brin_internal.h:41
#define RegProcedureIsValid(p)
Definition: c.h:731
#define MAXALIGN(LEN)
Definition: c.h:765
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:201
#define Assert(condition)
Definition: c.h:812
uint16_t uint16
Definition: c.h:484
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1149
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1129
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition: fmgr.c:580
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_NARGS()
Definition: fmgr.h:203
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_GET_COLLATION()
Definition: fmgr.h:198
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define newval
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:862
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:828
int i
Definition: isn.c:72
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1285
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc0(Size size)
Definition: mcxt.c:1347
Oid oprid(Operator op)
Definition: parse_oper.c:238
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
uintptr_t Datum
Definition: postgres.h:64
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
ScanKeyData * ScanKey
Definition: skey.h:75
#define RTSubStrategyNumber
Definition: stratnum.h:74
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
#define RTLeftStrategyNumber
Definition: stratnum.h:51
#define RTSubEqualStrategyNumber
Definition: stratnum.h:75
#define RTSuperEqualStrategyNumber
Definition: stratnum.h:77
#define RTOverRightStrategyNumber
Definition: stratnum.h:54
#define RTRightStrategyNumber
Definition: stratnum.h:55
#define RTSameStrategyNumber
Definition: stratnum.h:56
#define RTEqualStrategyNumber
Definition: stratnum.h:68
#define RTOverAboveStrategyNumber
Definition: stratnum.h:62
#define RTMaxStrategyNumber
Definition: stratnum.h:82
#define RTLessEqualStrategyNumber
Definition: stratnum.h:71
#define RTGreaterEqualStrategyNumber
Definition: stratnum.h:73
#define RTContainsStrategyNumber
Definition: stratnum.h:57
#define RTOverBelowStrategyNumber
Definition: stratnum.h:59
#define RTBelowStrategyNumber
Definition: stratnum.h:60
#define RTGreaterStrategyNumber
Definition: stratnum.h:72
#define RTSuperStrategyNumber
Definition: stratnum.h:76
#define RTAboveStrategyNumber
Definition: stratnum.h:61
#define RTOverLeftStrategyNumber
Definition: stratnum.h:52
#define RTContainedByStrategyNumber
Definition: stratnum.h:58
#define RTLessStrategyNumber
Definition: stratnum.h:70
#define RTContainsElemStrategyNumber
Definition: stratnum.h:66
#define RTAdjacentStrategyNumber
Definition: stratnum.h:67
TupleDesc bd_tupdesc
Definition: brin_internal.h:53
BrinOpcInfo * bd_info[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:62
Relation bd_index
Definition: brin_internal.h:50
MemoryContext bd_context
Definition: brin_internal.h:47
TypeCacheEntry * oi_typcache[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:37
uint16 oi_nstored
Definition: brin_internal.h:28
bool oi_regular_nulls
Definition: brin_internal.h:31
void * oi_opaque
Definition: brin_internal.h:34
Datum * bv_values
Definition: brin_tuple.h:34
AttrNumber bv_attno
Definition: brin_tuple.h:31
bool bv_allnulls
Definition: brin_tuple.h:33
Definition: fmgr.h:57
Oid fn_oid
Definition: fmgr.h:59
FmgrInfo extra_procinfos[INCLUSION_MAX_PROCNUMS]
FmgrInfo strategy_procinfos[RTMaxStrategyNumber]
bool extra_proc_missing[INCLUSION_MAX_PROCNUMS]
Oid * rd_opfamily
Definition: rel.h:207
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:254
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:631
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386