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-2018, 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  column->bv_values[INCLUSION_UNION] = result;
241 
242  PG_RETURN_BOOL(true);
243 }
244 
245 /*
246  * BRIN inclusion consistent function
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);
255  ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
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  Assert(key->sk_attno == column->bv_attno);
265 
266  /* Handle IS NULL/IS NOT NULL tests. */
267  if (key->sk_flags & SK_ISNULL)
268  {
269  if (key->sk_flags & SK_SEARCHNULL)
270  {
271  if (column->bv_allnulls || column->bv_hasnulls)
272  PG_RETURN_BOOL(true);
273  PG_RETURN_BOOL(false);
274  }
275 
276  /*
277  * For IS NOT NULL, we can only skip ranges that are known to have
278  * only nulls.
279  */
280  if (key->sk_flags & SK_SEARCHNOTNULL)
281  PG_RETURN_BOOL(!column->bv_allnulls);
282 
283  /*
284  * Neither IS NULL nor IS NOT NULL was used; assume all indexable
285  * operators are strict and return false.
286  */
287  PG_RETURN_BOOL(false);
288  }
289 
290  /* If it is all nulls, it cannot possibly be consistent. */
291  if (column->bv_allnulls)
292  PG_RETURN_BOOL(false);
293 
294  /* It has to be checked, if it contains elements that are not mergeable. */
296  PG_RETURN_BOOL(true);
297 
298  attno = key->sk_attno;
299  subtype = key->sk_subtype;
300  query = key->sk_argument;
301  unionval = column->bv_values[INCLUSION_UNION];
302  switch (key->sk_strategy)
303  {
304  /*
305  * Placement strategies
306  *
307  * These are implemented by logically negating the result of the
308  * converse placement operator; for this to work, the converse
309  * operator must be part of the opclass. An error will be thrown
310  * by inclusion_get_strategy_procinfo() if the required strategy
311  * is not part of the opclass.
312  *
313  * These all return false if either argument is empty, so there is
314  * no need to check for empty elements.
315  */
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 
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 
365  /*
366  * Overlap and contains strategies
367  *
368  * These strategies are simple enough that we can simply call the
369  * operator and return its result. Empty elements don't change
370  * the result.
371  */
372 
377  case RTSubStrategyNumber:
379  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
380  key->sk_strategy);
381  result = FunctionCall2Coll(finfo, colloid, unionval, query);
382  PG_RETURN_DATUM(result);
383 
384  /*
385  * Contained by strategies
386  *
387  * We cannot just call the original operator for the contained by
388  * strategies because some elements can be contained even though
389  * the union is not; instead we use the overlap operator.
390  *
391  * We check for empty elements separately as they are not merged
392  * to the union but contained by everything.
393  */
394 
399  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
401  result = FunctionCall2Coll(finfo, colloid, unionval, query);
402  if (DatumGetBool(result))
403  PG_RETURN_BOOL(true);
404 
406 
407  /*
408  * Adjacent strategy
409  *
410  * We test for overlap first but to be safe we need to call the
411  * actual adjacent operator also.
412  *
413  * An empty element cannot be adjacent to any other, so there is
414  * no need to check for it.
415  */
416 
418  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
420  result = FunctionCall2Coll(finfo, colloid, unionval, query);
421  if (DatumGetBool(result))
422  PG_RETURN_BOOL(true);
423 
424  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
426  result = FunctionCall2Coll(finfo, colloid, unionval, query);
427  PG_RETURN_DATUM(result);
428 
429  /*
430  * Basic comparison strategies
431  *
432  * It is straightforward to support the equality strategies with
433  * the contains operator. Generally, inequality strategies do not
434  * make much sense for the types which will be used with the
435  * inclusion BRIN family of opclasses, but is possible to
436  * implement them with logical negation of the left-of and
437  * right-of operators.
438  *
439  * NB: These strategies cannot be used with geometric datatypes
440  * that use comparison of areas! The only exception is the "same"
441  * strategy.
442  *
443  * Empty elements are considered to be less than the others. We
444  * cannot use the empty support function to check the query is an
445  * empty element, because the query can be another data type than
446  * the empty support function argument. So we will return true,
447  * if there is a possibility that empty elements will change the
448  * result.
449  */
450 
453  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
455  result = FunctionCall2Coll(finfo, colloid, unionval, query);
456  if (!DatumGetBool(result))
457  PG_RETURN_BOOL(true);
458 
460 
463  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
465  result = FunctionCall2Coll(finfo, colloid, unionval, query);
466  if (DatumGetBool(result))
467  PG_RETURN_BOOL(true);
468 
470 
472  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
474  result = FunctionCall2Coll(finfo, colloid, unionval, query);
475  if (!DatumGetBool(result))
476  PG_RETURN_BOOL(true);
477 
479 
481  /* no need to check for empty elements */
482  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
484  result = FunctionCall2Coll(finfo, colloid, unionval, query);
485  PG_RETURN_BOOL(!DatumGetBool(result));
486 
487  default:
488  /* shouldn't happen */
489  elog(ERROR, "invalid strategy number %d", key->sk_strategy);
490  PG_RETURN_BOOL(false);
491  }
492 }
493 
494 /*
495  * BRIN inclusion union function
496  *
497  * Given two BrinValues, update the first of them as a union of the summary
498  * values contained in both. The second one is untouched.
499  */
500 Datum
502 {
503  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
504  BrinValues *col_a = (BrinValues *) PG_GETARG_POINTER(1);
505  BrinValues *col_b = (BrinValues *) PG_GETARG_POINTER(2);
506  Oid colloid = PG_GET_COLLATION();
507  AttrNumber attno;
508  Form_pg_attribute attr;
509  FmgrInfo *finfo;
510  Datum result;
511 
512  Assert(col_a->bv_attno == col_b->bv_attno);
513 
514  /* Adjust "hasnulls". */
515  if (!col_a->bv_hasnulls && col_b->bv_hasnulls)
516  col_a->bv_hasnulls = true;
517 
518  /* If there are no values in B, there's nothing left to do. */
519  if (col_b->bv_allnulls)
520  PG_RETURN_VOID();
521 
522  attno = col_a->bv_attno;
523  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
524 
525  /*
526  * Adjust "allnulls". If A doesn't have values, just copy the values from
527  * B into A, and we're done. We cannot run the operators in this case,
528  * because values in A might contain garbage. Note we already established
529  * that B contains values.
530  */
531  if (col_a->bv_allnulls)
532  {
533  col_a->bv_allnulls = false;
534  col_a->bv_values[INCLUSION_UNION] =
536  attr->attbyval, attr->attlen);
541  PG_RETURN_VOID();
542  }
543 
544  /* If B includes empty elements, mark A similarly, if needed. */
548 
549  /* Check if A includes elements that are not mergeable. */
551  PG_RETURN_VOID();
552 
553  /* If B includes elements that are not mergeable, mark A similarly. */
555  {
557  PG_RETURN_VOID();
558  }
559 
560  /* Check if A and B are mergeable; if not, mark A unmergeable. */
561  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE);
562  if (finfo != NULL &&
563  !DatumGetBool(FunctionCall2Coll(finfo, colloid,
564  col_a->bv_values[INCLUSION_UNION],
565  col_b->bv_values[INCLUSION_UNION])))
566  {
568  PG_RETURN_VOID();
569  }
570 
571  /* Finally, merge B to A. */
572  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE);
573  Assert(finfo != NULL);
574  result = FunctionCall2Coll(finfo, colloid,
575  col_a->bv_values[INCLUSION_UNION],
576  col_b->bv_values[INCLUSION_UNION]);
577  if (!attr->attbyval)
579  col_a->bv_values[INCLUSION_UNION] = result;
580 
581  PG_RETURN_VOID();
582 }
583 
584 /*
585  * Cache and return inclusion opclass support procedure
586  *
587  * Return the procedure corresponding to the given function support number
588  * or null if it is not exists.
589  */
590 static FmgrInfo *
592 {
593  InclusionOpaque *opaque;
594  uint16 basenum = procnum - PROCNUM_BASE;
595 
596  /*
597  * We cache these in the opaque struct, to avoid repetitive syscache
598  * lookups.
599  */
600  opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
601 
602  /*
603  * If we already searched for this proc and didn't find it, don't bother
604  * searching again.
605  */
606  if (opaque->extra_proc_missing[basenum])
607  return NULL;
608 
609  if (opaque->extra_procinfos[basenum].fn_oid == InvalidOid)
610  {
611  if (RegProcedureIsValid(index_getprocid(bdesc->bd_index, attno,
612  procnum)))
613  {
614  fmgr_info_copy(&opaque->extra_procinfos[basenum],
615  index_getprocinfo(bdesc->bd_index, attno, procnum),
616  bdesc->bd_context);
617  }
618  else
619  {
620  opaque->extra_proc_missing[basenum] = true;
621  return NULL;
622  }
623  }
624 
625  return &opaque->extra_procinfos[basenum];
626 }
627 
628 /*
629  * Cache and return the procedure of the given strategy
630  *
631  * Return the procedure corresponding to the given sub-type and strategy
632  * number. The data type of the index will be used as the left hand side of
633  * the operator and the given sub-type will be used as the right hand side.
634  * Throws an error if the pg_amop row does not exist, but that should not
635  * happen with a properly configured opclass.
636  *
637  * It always throws an error when the data type of the opclass is different
638  * from the data type of the column or the expression. That happens when the
639  * column data type has implicit cast to the opclass data type. We don't
640  * bother casting types, because this situation can easily be avoided by
641  * setting storage data type to that of the opclass. The same problem does not
642  * apply to the data type of the right hand side, because the type in the
643  * ScanKey always matches the opclass' one.
644  *
645  * Note: this function mirrors minmax_get_strategy_procinfo; if changes are
646  * made here, see that function too.
647  */
648 static FmgrInfo *
650  uint16 strategynum)
651 {
652  InclusionOpaque *opaque;
653 
654  Assert(strategynum >= 1 &&
655  strategynum <= RTMaxStrategyNumber);
656 
657  opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
658 
659  /*
660  * We cache the procedures for the last sub-type in the opaque struct, to
661  * avoid repetitive syscache lookups. If the sub-type is changed,
662  * invalidate all the cached entries.
663  */
664  if (opaque->cached_subtype != subtype)
665  {
666  uint16 i;
667 
668  for (i = 1; i <= RTMaxStrategyNumber; i++)
669  opaque->strategy_procinfos[i - 1].fn_oid = InvalidOid;
670  opaque->cached_subtype = subtype;
671  }
672 
673  if (opaque->strategy_procinfos[strategynum - 1].fn_oid == InvalidOid)
674  {
675  Form_pg_attribute attr;
676  HeapTuple tuple;
677  Oid opfamily,
678  oprid;
679  bool isNull;
680 
681  opfamily = bdesc->bd_index->rd_opfamily[attno - 1];
682  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
683  tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
684  ObjectIdGetDatum(attr->atttypid),
685  ObjectIdGetDatum(subtype),
686  Int16GetDatum(strategynum));
687 
688  if (!HeapTupleIsValid(tuple))
689  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
690  strategynum, attr->atttypid, subtype, opfamily);
691 
693  Anum_pg_amop_amopopr, &isNull));
694  ReleaseSysCache(tuple);
695  Assert(!isNull && RegProcedureIsValid(oprid));
696 
697  fmgr_info_cxt(get_opcode(oprid),
698  &opaque->strategy_procinfos[strategynum - 1],
699  bdesc->bd_context);
700  }
701 
702  return &opaque->strategy_procinfos[strategynum - 1];
703 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
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:855
bool extra_proc_missing[INCLUSION_MAX_PROCNUMS]
#define RTOldContainsStrategyNumber
Definition: stratnum.h:56
#define RTSuperStrategyNumber
Definition: stratnum.h:69
#define RTOldContainedByStrategyNumber
Definition: stratnum.h:57
#define RTLeftStrategyNumber
Definition: stratnum.h:44
struct InclusionOpaque InclusionOpaque
Oid oprid(Operator op)
Definition: parse_oper.c:245
#define INCLUSION_UNMERGEABLE
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
#define DatumGetObjectId(X)
Definition: postgres.h:483
#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:434
#define RTOverBelowStrategyNumber
Definition: stratnum.h:52
#define RTContainedByStrategyNumber
Definition: stratnum.h:51
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define RTLessStrategyNumber
Definition: stratnum.h:63
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:244
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1132
unsigned int Oid
Definition: postgres_ext.h:31
Datum brin_inclusion_union(PG_FUNCTION_ARGS)
#define RTBelowStrategyNumber
Definition: stratnum.h:53
#define PROCNUM_CONTAINS
#define PG_GET_COLLATION()
Definition: fmgr.h:168
static FmgrInfo * inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum)
#define RTOverAboveStrategyNumber
Definition: stratnum.h:55
#define PROCNUM_BASE
unsigned short uint16
Definition: c.h:324
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
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:609
AttrNumber bv_attno
Definition: brin_tuple.h:26
uint16 oi_nstored
Definition: brin_internal.h:28
#define PG_GETARG_OID(n)
Definition: fmgr.h:245
ScanKeyData * ScanKey
Definition: skey.h:75
#define RTGreaterStrategyNumber
Definition: stratnum.h:65
#define RTLessEqualStrategyNumber
Definition: stratnum.h:64
#define RegProcedureIsValid(p)
Definition: c.h:607
#define DatumGetBool(X)
Definition: postgres.h:376
#define RTSameStrategyNumber
Definition: stratnum.h:49
#define INCLUSION_UNION
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
Datum brin_inclusion_consistent(PG_FUNCTION_ARGS)
#define SK_SEARCHNOTNULL
Definition: skey.h:122
Oid * rd_opfamily
Definition: rel.h:154
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1145
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:133
#define RTOverRightStrategyNumber
Definition: stratnum.h:47
#define SK_ISNULL
Definition: skey.h:115
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
#define RTMaxStrategyNumber
Definition: stratnum.h:73
#define RTOverLeftStrategyNumber
Definition: stratnum.h:45
void * palloc0(Size size)
Definition: mcxt.c:955
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:324
uintptr_t Datum
Definition: postgres.h:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define RTSubStrategyNumber
Definition: stratnum.h:67
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:318
void * oi_opaque
Definition: brin_internal.h:31
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1112
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
#define INCLUSION_CONTAINS_EMPTY
BrinOpcInfo * bd_info[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:59
#define BoolGetDatum(X)
Definition: postgres.h:385
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:321
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1079
Oid fn_oid
Definition: fmgr.h:59
#define PG_RETURN_VOID()
Definition: fmgr.h:314
#define RTAboveStrategyNumber
Definition: stratnum.h:54
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
int sk_flags
Definition: skey.h:66
#define Assert(condition)
Definition: c.h:699
#define INCLUSION_MAX_PROCNUMS
#define RTEqualStrategyNumber
Definition: stratnum.h:61
#define RTRightStrategyNumber
Definition: stratnum.h:48
#define newval
#define MAXALIGN(LEN)
Definition: c.h:652
#define RTContainsStrategyNumber
Definition: stratnum.h:50
#define DatumGetPointer(X)
Definition: postgres.h:532
#define RTSuperEqualStrategyNumber
Definition: stratnum.h:70
#define RTAdjacentStrategyNumber
Definition: stratnum.h:60
MemoryContext bd_context
Definition: brin_internal.h:44
#define RTContainsElemStrategyNumber
Definition: stratnum.h:59
#define PROCNUM_MERGE
int i
#define RTSubEqualStrategyNumber
Definition: stratnum.h:68
#define RTOverlapStrategyNumber
Definition: stratnum.h:46
#define PG_FUNCTION_ARGS
Definition: fmgr.h:163
#define elog
Definition: elog.h:219
#define PROCNUM_MERGEABLE
#define RTGreaterEqualStrategyNumber
Definition: stratnum.h:66
#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:821