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-2021, 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/builtins.h"
34 #include "utils/datum.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_opaque = (InclusionOpaque *)
112  MAXALIGN((char *) result + SizeofBrinOpcInfo(3));
113 
114  /* the union */
115  result->oi_typcache[INCLUSION_UNION] =
116  lookup_type_cache(typoid, 0);
117 
118  /* includes elements that are not mergeable */
119  result->oi_typcache[INCLUSION_UNMERGEABLE] = bool_typcache;
120 
121  /* includes the empty element */
122  result->oi_typcache[INCLUSION_CONTAINS_EMPTY] = bool_typcache;
123 
124  PG_RETURN_POINTER(result);
125 }
126 
127 /*
128  * BRIN inclusion add value function
129  *
130  * Examine the given index tuple (which contains partial status of a certain
131  * page range) by comparing it to the given value that comes from another heap
132  * tuple. If the new value is outside the union specified by the existing
133  * tuple values, update the index tuple and return true. Otherwise, return
134  * false and do not modify in this case.
135  */
136 Datum
138 {
139  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
140  BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
142  bool isnull = PG_GETARG_BOOL(3);
143  Oid colloid = PG_GET_COLLATION();
144  FmgrInfo *finfo;
145  Datum result;
146  bool new = false;
147  AttrNumber attno;
148  Form_pg_attribute attr;
149 
150  /*
151  * If the new value is null, we record that we saw it if it's the first
152  * one; otherwise, there's nothing to do.
153  */
154  if (isnull)
155  {
156  if (column->bv_hasnulls)
157  PG_RETURN_BOOL(false);
158 
159  column->bv_hasnulls = true;
160  PG_RETURN_BOOL(true);
161  }
162 
163  attno = column->bv_attno;
164  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
165 
166  /*
167  * If the recorded value is null, copy the new value (which we know to be
168  * not null), and we're almost done.
169  */
170  if (column->bv_allnulls)
171  {
172  column->bv_values[INCLUSION_UNION] =
173  datumCopy(newval, attr->attbyval, attr->attlen);
174  column->bv_values[INCLUSION_UNMERGEABLE] = BoolGetDatum(false);
176  column->bv_allnulls = false;
177  new = true;
178  }
179 
180  /*
181  * No need for further processing if the block range is marked as
182  * containing unmergeable values.
183  */
185  PG_RETURN_BOOL(false);
186 
187  /*
188  * If the opclass supports the concept of empty values, test the passed
189  * new value for emptiness; if it returns true, we need to set the
190  * "contains empty" flag in the element (unless already set).
191  */
192  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_EMPTY);
193  if (finfo != NULL && DatumGetBool(FunctionCall1Coll(finfo, colloid, newval)))
194  {
196  {
198  PG_RETURN_BOOL(true);
199  }
200 
201  PG_RETURN_BOOL(false);
202  }
203 
204  if (new)
205  PG_RETURN_BOOL(true);
206 
207  /* Check if the new value is already contained. */
208  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_CONTAINS);
209  if (finfo != NULL &&
210  DatumGetBool(FunctionCall2Coll(finfo, colloid,
211  column->bv_values[INCLUSION_UNION],
212  newval)))
213  PG_RETURN_BOOL(false);
214 
215  /*
216  * Check if the new value is mergeable to the existing union. If it is
217  * not, mark the value as containing unmergeable elements and get out.
218  *
219  * Note: at this point we could remove the value from the union, since
220  * it's not going to be used any longer. However, the BRIN framework
221  * doesn't allow for the value not being present. Improve someday.
222  */
223  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE);
224  if (finfo != NULL &&
225  !DatumGetBool(FunctionCall2Coll(finfo, colloid,
226  column->bv_values[INCLUSION_UNION],
227  newval)))
228  {
230  PG_RETURN_BOOL(true);
231  }
232 
233  /* Finally, merge the new value to the existing union. */
234  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE);
235  Assert(finfo != NULL);
236  result = FunctionCall2Coll(finfo, colloid,
237  column->bv_values[INCLUSION_UNION], newval);
238  if (!attr->attbyval &&
240  {
242 
243  if (result == newval)
244  result = datumCopy(result, attr->attbyval, attr->attlen);
245  }
246  column->bv_values[INCLUSION_UNION] = result;
247 
248  PG_RETURN_BOOL(true);
249 }
250 
251 /*
252  * BRIN inclusion consistent function
253  *
254  * All of the strategies are optional.
255  */
256 Datum
258 {
259  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
260  BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
262  Oid colloid = PG_GET_COLLATION(),
263  subtype;
264  Datum unionval;
265  AttrNumber attno;
266  Datum query;
267  FmgrInfo *finfo;
268  Datum result;
269 
270  Assert(key->sk_attno == column->bv_attno);
271 
272  /* Handle IS NULL/IS NOT NULL tests. */
273  if (key->sk_flags & SK_ISNULL)
274  {
275  if (key->sk_flags & SK_SEARCHNULL)
276  {
277  if (column->bv_allnulls || column->bv_hasnulls)
278  PG_RETURN_BOOL(true);
279  PG_RETURN_BOOL(false);
280  }
281 
282  /*
283  * For IS NOT NULL, we can only skip ranges that are known to have
284  * only nulls.
285  */
286  if (key->sk_flags & SK_SEARCHNOTNULL)
287  PG_RETURN_BOOL(!column->bv_allnulls);
288 
289  /*
290  * Neither IS NULL nor IS NOT NULL was used; assume all indexable
291  * operators are strict and return false.
292  */
293  PG_RETURN_BOOL(false);
294  }
295 
296  /* If it is all nulls, it cannot possibly be consistent. */
297  if (column->bv_allnulls)
298  PG_RETURN_BOOL(false);
299 
300  /* It has to be checked, if it contains elements that are not mergeable. */
302  PG_RETURN_BOOL(true);
303 
304  attno = key->sk_attno;
305  subtype = key->sk_subtype;
306  query = key->sk_argument;
307  unionval = column->bv_values[INCLUSION_UNION];
308  switch (key->sk_strategy)
309  {
310  /*
311  * Placement strategies
312  *
313  * These are implemented by logically negating the result of the
314  * converse placement operator; for this to work, the converse
315  * operator must be part of the opclass. An error will be thrown
316  * by inclusion_get_strategy_procinfo() if the required strategy
317  * is not part of the opclass.
318  *
319  * These all return false if either argument is empty, so there is
320  * no need to check for empty elements.
321  */
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 
342  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
344  result = FunctionCall2Coll(finfo, colloid, unionval, query);
345  PG_RETURN_BOOL(!DatumGetBool(result));
346 
348  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
350  result = FunctionCall2Coll(finfo, colloid, unionval, query);
351  PG_RETURN_BOOL(!DatumGetBool(result));
352 
354  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
356  result = FunctionCall2Coll(finfo, colloid, unionval, query);
357  PG_RETURN_BOOL(!DatumGetBool(result));
358 
360  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
362  result = FunctionCall2Coll(finfo, colloid, unionval, query);
363  PG_RETURN_BOOL(!DatumGetBool(result));
364 
366  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
368  result = FunctionCall2Coll(finfo, colloid, unionval, query);
369  PG_RETURN_BOOL(!DatumGetBool(result));
370 
371  /*
372  * Overlap and contains strategies
373  *
374  * These strategies are simple enough that we can simply call the
375  * operator and return its result. Empty elements don't change
376  * the result.
377  */
378 
382  case RTSubStrategyNumber:
384  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
385  key->sk_strategy);
386  result = FunctionCall2Coll(finfo, colloid, unionval, query);
387  PG_RETURN_DATUM(result);
388 
389  /*
390  * Contained by strategies
391  *
392  * We cannot just call the original operator for the contained by
393  * strategies because some elements can be contained even though
394  * the union is not; instead we use the overlap operator.
395  *
396  * We check for empty elements separately as they are not merged
397  * to the union but contained by everything.
398  */
399 
403  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
405  result = FunctionCall2Coll(finfo, colloid, unionval, query);
406  if (DatumGetBool(result))
407  PG_RETURN_BOOL(true);
408 
410 
411  /*
412  * Adjacent strategy
413  *
414  * We test for overlap first but to be safe we need to call the
415  * actual adjacent operator also.
416  *
417  * An empty element cannot be adjacent to any other, so there is
418  * no need to check for it.
419  */
420 
422  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
424  result = FunctionCall2Coll(finfo, colloid, unionval, query);
425  if (DatumGetBool(result))
426  PG_RETURN_BOOL(true);
427 
428  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
430  result = FunctionCall2Coll(finfo, colloid, unionval, query);
431  PG_RETURN_DATUM(result);
432 
433  /*
434  * Basic comparison strategies
435  *
436  * It is straightforward to support the equality strategies with
437  * the contains operator. Generally, inequality strategies do not
438  * make much sense for the types which will be used with the
439  * inclusion BRIN family of opclasses, but it is possible to
440  * implement them with logical negation of the left-of and
441  * right-of operators.
442  *
443  * NB: These strategies cannot be used with geometric datatypes
444  * that use comparison of areas! The only exception is the "same"
445  * strategy.
446  *
447  * Empty elements are considered to be less than the others. We
448  * cannot use the empty support function to check the query is an
449  * empty element, because the query can be another data type than
450  * the empty support function argument. So we will return true,
451  * if there is a possibility that empty elements will change the
452  * result.
453  */
454 
457  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
459  result = FunctionCall2Coll(finfo, colloid, unionval, query);
460  if (!DatumGetBool(result))
461  PG_RETURN_BOOL(true);
462 
464 
467  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
469  result = FunctionCall2Coll(finfo, colloid, unionval, query);
470  if (DatumGetBool(result))
471  PG_RETURN_BOOL(true);
472 
474 
476  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
478  result = FunctionCall2Coll(finfo, colloid, unionval, query);
479  if (!DatumGetBool(result))
480  PG_RETURN_BOOL(true);
481 
483 
485  /* no need to check for empty elements */
486  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
488  result = FunctionCall2Coll(finfo, colloid, unionval, query);
489  PG_RETURN_BOOL(!DatumGetBool(result));
490 
491  default:
492  /* shouldn't happen */
493  elog(ERROR, "invalid strategy number %d", key->sk_strategy);
494  PG_RETURN_BOOL(false);
495  }
496 }
497 
498 /*
499  * BRIN inclusion union function
500  *
501  * Given two BrinValues, update the first of them as a union of the summary
502  * values contained in both. The second one is untouched.
503  */
504 Datum
506 {
507  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
508  BrinValues *col_a = (BrinValues *) PG_GETARG_POINTER(1);
509  BrinValues *col_b = (BrinValues *) PG_GETARG_POINTER(2);
510  Oid colloid = PG_GET_COLLATION();
511  AttrNumber attno;
512  Form_pg_attribute attr;
513  FmgrInfo *finfo;
514  Datum result;
515 
516  Assert(col_a->bv_attno == col_b->bv_attno);
517 
518  /* Adjust "hasnulls". */
519  if (!col_a->bv_hasnulls && col_b->bv_hasnulls)
520  col_a->bv_hasnulls = true;
521 
522  /* If there are no values in B, there's nothing left to do. */
523  if (col_b->bv_allnulls)
524  PG_RETURN_VOID();
525 
526  attno = col_a->bv_attno;
527  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
528 
529  /*
530  * Adjust "allnulls". If A doesn't have values, just copy the values from
531  * B into A, and we're done. We cannot run the operators in this case,
532  * because values in A might contain garbage. Note we already established
533  * that B contains values.
534  */
535  if (col_a->bv_allnulls)
536  {
537  col_a->bv_allnulls = false;
538  col_a->bv_values[INCLUSION_UNION] =
540  attr->attbyval, attr->attlen);
545  PG_RETURN_VOID();
546  }
547 
548  /* If B includes empty elements, mark A similarly, if needed. */
552 
553  /* Check if A includes elements that are not mergeable. */
555  PG_RETURN_VOID();
556 
557  /* If B includes elements that are not mergeable, mark A similarly. */
559  {
561  PG_RETURN_VOID();
562  }
563 
564  /* Check if A and B are mergeable; if not, mark A unmergeable. */
565  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE);
566  if (finfo != NULL &&
567  !DatumGetBool(FunctionCall2Coll(finfo, colloid,
568  col_a->bv_values[INCLUSION_UNION],
569  col_b->bv_values[INCLUSION_UNION])))
570  {
572  PG_RETURN_VOID();
573  }
574 
575  /* Finally, merge B to A. */
576  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE);
577  Assert(finfo != NULL);
578  result = FunctionCall2Coll(finfo, colloid,
579  col_a->bv_values[INCLUSION_UNION],
580  col_b->bv_values[INCLUSION_UNION]);
581  if (!attr->attbyval &&
583  {
585 
586  if (result == col_b->bv_values[INCLUSION_UNION])
587  result = datumCopy(result, attr->attbyval, attr->attlen);
588  }
589  col_a->bv_values[INCLUSION_UNION] = result;
590 
591  PG_RETURN_VOID();
592 }
593 
594 /*
595  * Cache and return inclusion opclass support procedure
596  *
597  * Return the procedure corresponding to the given function support number
598  * or null if it is not exists.
599  */
600 static FmgrInfo *
602 {
603  InclusionOpaque *opaque;
604  uint16 basenum = procnum - PROCNUM_BASE;
605 
606  /*
607  * We cache these in the opaque struct, to avoid repetitive syscache
608  * lookups.
609  */
610  opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
611 
612  /*
613  * If we already searched for this proc and didn't find it, don't bother
614  * searching again.
615  */
616  if (opaque->extra_proc_missing[basenum])
617  return NULL;
618 
619  if (opaque->extra_procinfos[basenum].fn_oid == InvalidOid)
620  {
621  if (RegProcedureIsValid(index_getprocid(bdesc->bd_index, attno,
622  procnum)))
623  {
624  fmgr_info_copy(&opaque->extra_procinfos[basenum],
625  index_getprocinfo(bdesc->bd_index, attno, procnum),
626  bdesc->bd_context);
627  }
628  else
629  {
630  opaque->extra_proc_missing[basenum] = true;
631  return NULL;
632  }
633  }
634 
635  return &opaque->extra_procinfos[basenum];
636 }
637 
638 /*
639  * Cache and return the procedure of the given strategy
640  *
641  * Return the procedure corresponding to the given sub-type and strategy
642  * number. The data type of the index will be used as the left hand side of
643  * the operator and the given sub-type will be used as the right hand side.
644  * Throws an error if the pg_amop row does not exist, but that should not
645  * happen with a properly configured opclass.
646  *
647  * It always throws an error when the data type of the opclass is different
648  * from the data type of the column or the expression. That happens when the
649  * column data type has implicit cast to the opclass data type. We don't
650  * bother casting types, because this situation can easily be avoided by
651  * setting storage data type to that of the opclass. The same problem does not
652  * apply to the data type of the right hand side, because the type in the
653  * ScanKey always matches the opclass' one.
654  *
655  * Note: this function mirrors minmax_get_strategy_procinfo; if changes are
656  * made here, see that function too.
657  */
658 static FmgrInfo *
660  uint16 strategynum)
661 {
662  InclusionOpaque *opaque;
663 
664  Assert(strategynum >= 1 &&
665  strategynum <= RTMaxStrategyNumber);
666 
667  opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
668 
669  /*
670  * We cache the procedures for the last sub-type in the opaque struct, to
671  * avoid repetitive syscache lookups. If the sub-type is changed,
672  * invalidate all the cached entries.
673  */
674  if (opaque->cached_subtype != subtype)
675  {
676  uint16 i;
677 
678  for (i = 1; i <= RTMaxStrategyNumber; i++)
679  opaque->strategy_procinfos[i - 1].fn_oid = InvalidOid;
680  opaque->cached_subtype = subtype;
681  }
682 
683  if (opaque->strategy_procinfos[strategynum - 1].fn_oid == InvalidOid)
684  {
685  Form_pg_attribute attr;
686  HeapTuple tuple;
687  Oid opfamily,
688  oprid;
689  bool isNull;
690 
691  opfamily = bdesc->bd_index->rd_opfamily[attno - 1];
692  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
693  tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
694  ObjectIdGetDatum(attr->atttypid),
695  ObjectIdGetDatum(subtype),
696  Int16GetDatum(strategynum));
697 
698  if (!HeapTupleIsValid(tuple))
699  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
700  strategynum, attr->atttypid, subtype, opfamily);
701 
703  Anum_pg_amop_amopopr, &isNull));
704  ReleaseSysCache(tuple);
705  Assert(!isNull && RegProcedureIsValid(oprid));
706 
707  fmgr_info_cxt(get_opcode(oprid),
708  &opaque->strategy_procinfos[strategynum - 1],
709  bdesc->bd_context);
710  }
711 
712  return &opaque->strategy_procinfos[strategynum - 1];
713 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
Datum brin_inclusion_opcinfo(PG_FUNCTION_ARGS)
Oid sk_subtype
Definition: skey.h:69
Definition: fmgr.h:56
FmgrInfo extra_procinfos[INCLUSION_MAX_PROCNUMS]
Datum brin_inclusion_add_value(PG_FUNCTION_ARGS)
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:803
bool extra_proc_missing[INCLUSION_MAX_PROCNUMS]
#define RTSuperStrategyNumber
Definition: stratnum.h:76
#define RTLeftStrategyNumber
Definition: stratnum.h:51
struct InclusionOpaque InclusionOpaque
Oid oprid(Operator op)
Definition: parse_oper.c:250
#define INCLUSION_UNMERGEABLE
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define DatumGetObjectId(X)
Definition: postgres.h:500
#define SizeofBrinOpcInfo(ncols)
Definition: brin_internal.h:38
FmgrInfo strategy_procinfos[RTMaxStrategyNumber]
bool bv_allnulls
Definition: brin_tuple.h:28
#define Int16GetDatum(X)
Definition: postgres.h:451
#define RTOverBelowStrategyNumber
Definition: stratnum.h:59
#define RTContainedByStrategyNumber
Definition: stratnum.h:58
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define RTLessStrategyNumber
Definition: stratnum.h:70
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1151
unsigned int Oid
Definition: postgres_ext.h:31
Datum brin_inclusion_union(PG_FUNCTION_ARGS)
#define RTBelowStrategyNumber
Definition: stratnum.h:60
#define PROCNUM_CONTAINS
#define PG_GET_COLLATION()
Definition: fmgr.h:198
static FmgrInfo * inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum)
#define RTOverAboveStrategyNumber
Definition: stratnum.h:62
#define PROCNUM_BASE
unsigned short uint16
Definition: c.h:428
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
Relation bd_index
Definition: brin_internal.h:47
bool bv_hasnulls
Definition: brin_tuple.h:27
TypeCacheEntry * oi_typcache[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:34
static FmgrInfo * inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, uint16 strategynum)
StrategyNumber sk_strategy
Definition: skey.h:68
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition: fmgr.c:611
AttrNumber bv_attno
Definition: brin_tuple.h:26
uint16 oi_nstored
Definition: brin_internal.h:28
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
ScanKeyData * ScanKey
Definition: skey.h:75
#define RTGreaterStrategyNumber
Definition: stratnum.h:72
#define RTLessEqualStrategyNumber
Definition: stratnum.h:71
#define RegProcedureIsValid(p)
Definition: c.h:700
#define DatumGetBool(X)
Definition: postgres.h:393
#define RTSameStrategyNumber
Definition: stratnum.h:56
#define INCLUSION_UNION
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
Datum brin_inclusion_consistent(PG_FUNCTION_ARGS)
#define SK_SEARCHNOTNULL
Definition: skey.h:122
Oid * rd_opfamily
Definition: rel.h:190
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1160
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
#define RTOverRightStrategyNumber
Definition: stratnum.h:54
#define SK_ISNULL
Definition: skey.h:115
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
#define RTMaxStrategyNumber
Definition: stratnum.h:82
#define RTOverLeftStrategyNumber
Definition: stratnum.h:52
void * palloc0(Size size)
Definition: mcxt.c:981
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define RTSubStrategyNumber
Definition: stratnum.h:74
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
void * oi_opaque
Definition: brin_internal.h:31
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1131
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define INCLUSION_CONTAINS_EMPTY
BrinOpcInfo * bd_info[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:59
#define BoolGetDatum(X)
Definition: postgres.h:402
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1229
Oid fn_oid
Definition: fmgr.h:59
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define RTAboveStrategyNumber
Definition: stratnum.h:61
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int sk_flags
Definition: skey.h:66
#define Assert(condition)
Definition: c.h:792
#define INCLUSION_MAX_PROCNUMS
#define RTEqualStrategyNumber
Definition: stratnum.h:68
#define RTRightStrategyNumber
Definition: stratnum.h:55
#define newval
#define MAXALIGN(LEN)
Definition: c.h:745
#define RTContainsStrategyNumber
Definition: stratnum.h:57
#define DatumGetPointer(X)
Definition: postgres.h:549
#define RTSuperEqualStrategyNumber
Definition: stratnum.h:77
#define RTAdjacentStrategyNumber
Definition: stratnum.h:67
MemoryContext bd_context
Definition: brin_internal.h:44
#define RTContainsElemStrategyNumber
Definition: stratnum.h:66
#define PROCNUM_MERGE
#define elog(elevel,...)
Definition: elog.h:228
int i
#define RTSubEqualStrategyNumber
Definition: stratnum.h:75
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PROCNUM_MERGEABLE
#define RTGreaterEqualStrategyNumber
Definition: stratnum.h:73
#define PROCNUM_EMPTY
Datum * bv_values
Definition: brin_tuple.h:29
Datum sk_argument
Definition: skey.h:72
int16 AttrNumber
Definition: attnum.h:21
#define SK_SEARCHNULL
Definition: skey.h:121
AttrNumber sk_attno
Definition: skey.h:67
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:769