PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2017, 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  * 0 - the union of the values in the block range
63  * 1 - whether an empty value is present in any tuple in the block range
64  * 2 - whether the values in the block range cannot be merged (e.g. an IPv6
65  * address amidst IPv4 addresses).
66  */
67 #define INCLUSION_UNION 0
68 #define INCLUSION_UNMERGEABLE 1
69 #define INCLUSION_CONTAINS_EMPTY 2
70 
71 
72 typedef struct InclusionOpaque
73 {
79 
80 static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
81  uint16 procnum);
83  Oid subtype, uint16 strategynum);
84 
85 
86 /*
87  * BRIN inclusion OpcInfo function
88  */
89 Datum
91 {
92  Oid typoid = PG_GETARG_OID(0);
94  TypeCacheEntry *bool_typcache = lookup_type_cache(BOOLOID, 0);
95 
96  /*
97  * All members of opaque are initialized lazily; both procinfo arrays
98  * start out as non-initialized by having fn_oid be InvalidOid, and
99  * "missing" to false, by zeroing here. strategy_procinfos elements can
100  * be invalidated when cached_subtype changes by zeroing fn_oid.
101  * extra_procinfo entries are never invalidated, but if a lookup fails
102  * (which is expected), extra_proc_missing is set to true, indicating not
103  * to look it up again.
104  */
105  result = palloc0(MAXALIGN(SizeofBrinOpcInfo(3)) + sizeof(InclusionOpaque));
106  result->oi_nstored = 3;
107  result->oi_opaque = (InclusionOpaque *)
108  MAXALIGN((char *) result + SizeofBrinOpcInfo(3));
109 
110  /* the union */
111  result->oi_typcache[INCLUSION_UNION] =
112  lookup_type_cache(typoid, 0);
113 
114  /* includes elements that are not mergeable */
115  result->oi_typcache[INCLUSION_UNMERGEABLE] = bool_typcache;
116 
117  /* includes the empty element */
118  result->oi_typcache[INCLUSION_CONTAINS_EMPTY] = bool_typcache;
119 
120  PG_RETURN_POINTER(result);
121 }
122 
123 /*
124  * BRIN inclusion add value function
125  *
126  * Examine the given index tuple (which contains partial status of a certain
127  * page range) by comparing it to the given value that comes from another heap
128  * tuple. If the new value is outside the union specified by the existing
129  * tuple values, update the index tuple and return true. Otherwise, return
130  * false and do not modify in this case.
131  */
132 Datum
134 {
135  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
136  BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
138  bool isnull = PG_GETARG_BOOL(3);
139  Oid colloid = PG_GET_COLLATION();
140  FmgrInfo *finfo;
141  Datum result;
142  bool new = false;
143  AttrNumber attno;
144  Form_pg_attribute attr;
145 
146  /*
147  * If the new value is null, we record that we saw it if it's the first
148  * one; otherwise, there's nothing to do.
149  */
150  if (isnull)
151  {
152  if (column->bv_hasnulls)
153  PG_RETURN_BOOL(false);
154 
155  column->bv_hasnulls = true;
156  PG_RETURN_BOOL(true);
157  }
158 
159  attno = column->bv_attno;
160  attr = bdesc->bd_tupdesc->attrs[attno - 1];
161 
162  /*
163  * If the recorded value is null, copy the new value (which we know to be
164  * not null), and we're almost done.
165  */
166  if (column->bv_allnulls)
167  {
168  column->bv_values[INCLUSION_UNION] =
169  datumCopy(newval, attr->attbyval, attr->attlen);
170  column->bv_values[INCLUSION_UNMERGEABLE] = BoolGetDatum(false);
172  column->bv_allnulls = false;
173  new = true;
174  }
175 
176  /*
177  * No need for further processing if the block range is marked as
178  * containing unmergeable values.
179  */
181  PG_RETURN_BOOL(false);
182 
183  /*
184  * If the opclass supports the concept of empty values, test the passed
185  * new value for emptiness; if it returns true, we need to set the
186  * "contains empty" flag in the element (unless already set).
187  */
188  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_EMPTY);
189  if (finfo != NULL && DatumGetBool(FunctionCall1Coll(finfo, colloid, newval)))
190  {
192  {
194  PG_RETURN_BOOL(true);
195  }
196 
197  PG_RETURN_BOOL(false);
198  }
199 
200  if (new)
201  PG_RETURN_BOOL(true);
202 
203  /* Check if the new value is already contained. */
204  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_CONTAINS);
205  if (finfo != NULL &&
206  DatumGetBool(FunctionCall2Coll(finfo, colloid,
207  column->bv_values[INCLUSION_UNION],
208  newval)))
209  PG_RETURN_BOOL(false);
210 
211  /*
212  * Check if the new value is mergeable to the existing union. If it is
213  * not, mark the value as containing unmergeable elements and get out.
214  *
215  * Note: at this point we could remove the value from the union, since
216  * it's not going to be used any longer. However, the BRIN framework
217  * doesn't allow for the value not being present. Improve someday.
218  */
219  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE);
220  if (finfo != NULL &&
221  !DatumGetBool(FunctionCall2Coll(finfo, colloid,
222  column->bv_values[INCLUSION_UNION],
223  newval)))
224  {
226  PG_RETURN_BOOL(true);
227  }
228 
229  /* Finally, merge the new value to the existing union. */
230  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE);
231  Assert(finfo != NULL);
232  result = FunctionCall2Coll(finfo, colloid,
233  column->bv_values[INCLUSION_UNION], newval);
234  if (!attr->attbyval)
236  column->bv_values[INCLUSION_UNION] = result;
237 
238  PG_RETURN_BOOL(true);
239 }
240 
241 /*
242  * BRIN inclusion consistent function
243  *
244  * All of the strategies are optional.
245  */
246 Datum
248 {
249  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
250  BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
251  ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
252  Oid colloid = PG_GET_COLLATION(),
253  subtype;
254  Datum unionval;
255  AttrNumber attno;
256  Datum query;
257  FmgrInfo *finfo;
258  Datum result;
259 
260  Assert(key->sk_attno == column->bv_attno);
261 
262  /* Handle IS NULL/IS NOT NULL tests. */
263  if (key->sk_flags & SK_ISNULL)
264  {
265  if (key->sk_flags & SK_SEARCHNULL)
266  {
267  if (column->bv_allnulls || column->bv_hasnulls)
268  PG_RETURN_BOOL(true);
269  PG_RETURN_BOOL(false);
270  }
271 
272  /*
273  * For IS NOT NULL, we can only skip ranges that are known to have
274  * only nulls.
275  */
276  if (key->sk_flags & SK_SEARCHNOTNULL)
277  PG_RETURN_BOOL(!column->bv_allnulls);
278 
279  /*
280  * Neither IS NULL nor IS NOT NULL was used; assume all indexable
281  * operators are strict and return false.
282  */
283  PG_RETURN_BOOL(false);
284  }
285 
286  /* If it is all nulls, it cannot possibly be consistent. */
287  if (column->bv_allnulls)
288  PG_RETURN_BOOL(false);
289 
290  /* It has to be checked, if it contains elements that are not mergeable. */
292  PG_RETURN_BOOL(true);
293 
294  attno = key->sk_attno;
295  subtype = key->sk_subtype;
296  query = key->sk_argument;
297  unionval = column->bv_values[INCLUSION_UNION];
298  switch (key->sk_strategy)
299  {
300  /*
301  * Placement strategies
302  *
303  * These are implemented by logically negating the result of the
304  * converse placement operator; for this to work, the converse
305  * operator must be part of the opclass. An error will be thrown
306  * by inclusion_get_strategy_procinfo() if the required strategy
307  * is not part of the opclass.
308  *
309  * These all return false if either argument is empty, so there is
310  * no need to check for empty elements.
311  */
312 
314  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
316  result = FunctionCall2Coll(finfo, colloid, unionval, query);
317  PG_RETURN_BOOL(!DatumGetBool(result));
318 
320  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
322  result = FunctionCall2Coll(finfo, colloid, unionval, query);
323  PG_RETURN_BOOL(!DatumGetBool(result));
324 
326  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
328  result = FunctionCall2Coll(finfo, colloid, unionval, query);
329  PG_RETURN_BOOL(!DatumGetBool(result));
330 
332  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
334  result = FunctionCall2Coll(finfo, colloid, unionval, query);
335  PG_RETURN_BOOL(!DatumGetBool(result));
336 
338  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
340  result = FunctionCall2Coll(finfo, colloid, unionval, query);
341  PG_RETURN_BOOL(!DatumGetBool(result));
342 
344  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
346  result = FunctionCall2Coll(finfo, colloid, unionval, query);
347  PG_RETURN_BOOL(!DatumGetBool(result));
348 
350  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
352  result = FunctionCall2Coll(finfo, colloid, unionval, query);
353  PG_RETURN_BOOL(!DatumGetBool(result));
354 
356  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
358  result = FunctionCall2Coll(finfo, colloid, unionval, query);
359  PG_RETURN_BOOL(!DatumGetBool(result));
360 
361  /*
362  * Overlap and contains strategies
363  *
364  * These strategies are simple enough that we can simply call the
365  * operator and return its result. Empty elements don't change
366  * the result.
367  */
368 
373  case RTSubStrategyNumber:
375  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
376  key->sk_strategy);
377  result = FunctionCall2Coll(finfo, colloid, unionval, query);
378  PG_RETURN_DATUM(result);
379 
380  /*
381  * Contained by strategies
382  *
383  * We cannot just call the original operator for the contained by
384  * strategies because some elements can be contained even though
385  * the union is not; instead we use the overlap operator.
386  *
387  * We check for empty elements separately as they are not merged
388  * to the union but contained by everything.
389  */
390 
395  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
397  result = FunctionCall2Coll(finfo, colloid, unionval, query);
398  if (DatumGetBool(result))
399  PG_RETURN_BOOL(true);
400 
402 
403  /*
404  * Adjacent strategy
405  *
406  * We test for overlap first but to be safe we need to call the
407  * actual adjacent operator also.
408  *
409  * An empty element cannot be adjacent to any other, so there is
410  * no need to check for it.
411  */
412 
414  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
416  result = FunctionCall2Coll(finfo, colloid, unionval, query);
417  if (DatumGetBool(result))
418  PG_RETURN_BOOL(true);
419 
420  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
422  result = FunctionCall2Coll(finfo, colloid, unionval, query);
423  PG_RETURN_DATUM(result);
424 
425  /*
426  * Basic comparison strategies
427  *
428  * It is straightforward to support the equality strategies with
429  * the contains operator. Generally, inequality strategies do not
430  * make much sense for the types which will be used with the
431  * inclusion BRIN family of opclasses, but is possible to
432  * implement them with logical negation of the left-of and
433  * right-of operators.
434  *
435  * NB: These strategies cannot be used with geometric datatypes
436  * that use comparison of areas! The only exception is the "same"
437  * strategy.
438  *
439  * Empty elements are considered to be less than the others. We
440  * cannot use the empty support function to check the query is an
441  * empty element, because the query can be another data type than
442  * the empty support function argument. So we will return true,
443  * if there is a possibility that empty elements will change the
444  * result.
445  */
446 
449  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
451  result = FunctionCall2Coll(finfo, colloid, unionval, query);
452  if (!DatumGetBool(result))
453  PG_RETURN_BOOL(true);
454 
456 
459  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
461  result = FunctionCall2Coll(finfo, colloid, unionval, query);
462  if (DatumGetBool(result))
463  PG_RETURN_BOOL(true);
464 
466 
468  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
470  result = FunctionCall2Coll(finfo, colloid, unionval, query);
471  if (!DatumGetBool(result))
472  PG_RETURN_BOOL(true);
473 
475 
477  /* no need to check for empty elements */
478  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
480  result = FunctionCall2Coll(finfo, colloid, unionval, query);
481  PG_RETURN_BOOL(!DatumGetBool(result));
482 
483  default:
484  /* shouldn't happen */
485  elog(ERROR, "invalid strategy number %d", key->sk_strategy);
486  PG_RETURN_BOOL(false);
487  }
488 }
489 
490 /*
491  * BRIN inclusion union function
492  *
493  * Given two BrinValues, update the first of them as a union of the summary
494  * values contained in both. The second one is untouched.
495  */
496 Datum
498 {
499  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
500  BrinValues *col_a = (BrinValues *) PG_GETARG_POINTER(1);
501  BrinValues *col_b = (BrinValues *) PG_GETARG_POINTER(2);
502  Oid colloid = PG_GET_COLLATION();
503  AttrNumber attno;
504  Form_pg_attribute attr;
505  FmgrInfo *finfo;
506  Datum result;
507 
508  Assert(col_a->bv_attno == col_b->bv_attno);
509 
510  /* Adjust "hasnulls". */
511  if (!col_a->bv_hasnulls && col_b->bv_hasnulls)
512  col_a->bv_hasnulls = true;
513 
514  /* If there are no values in B, there's nothing left to do. */
515  if (col_b->bv_allnulls)
516  PG_RETURN_VOID();
517 
518  attno = col_a->bv_attno;
519  attr = bdesc->bd_tupdesc->attrs[attno - 1];
520 
521  /*
522  * Adjust "allnulls". If A doesn't have values, just copy the values from
523  * B into A, and we're done. We cannot run the operators in this case,
524  * because values in A might contain garbage. Note we already established
525  * that B contains values.
526  */
527  if (col_a->bv_allnulls)
528  {
529  col_a->bv_allnulls = false;
530  col_a->bv_values[INCLUSION_UNION] =
532  attr->attbyval, attr->attlen);
537  PG_RETURN_VOID();
538  }
539 
540  /* If B includes empty elements, mark A similarly, if needed. */
544 
545  /* Check if A includes elements that are not mergeable. */
547  PG_RETURN_VOID();
548 
549  /* If B includes elements that are not mergeable, mark A similarly. */
551  {
553  PG_RETURN_VOID();
554  }
555 
556  /* Check if A and B are mergeable; if not, mark A unmergeable. */
557  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE);
558  if (finfo != NULL &&
559  !DatumGetBool(FunctionCall2Coll(finfo, colloid,
560  col_a->bv_values[INCLUSION_UNION],
561  col_b->bv_values[INCLUSION_UNION])))
562  {
564  PG_RETURN_VOID();
565  }
566 
567  /* Finally, merge B to A. */
568  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE);
569  Assert(finfo != NULL);
570  result = FunctionCall2Coll(finfo, colloid,
571  col_a->bv_values[INCLUSION_UNION],
572  col_b->bv_values[INCLUSION_UNION]);
573  if (!attr->attbyval)
575  col_a->bv_values[INCLUSION_UNION] = result;
576 
577  PG_RETURN_VOID();
578 }
579 
580 /*
581  * Cache and return inclusion opclass support procedure
582  *
583  * Return the procedure corresponding to the given function support number
584  * or null if it is not exists.
585  */
586 static FmgrInfo *
588 {
589  InclusionOpaque *opaque;
590  uint16 basenum = procnum - PROCNUM_BASE;
591 
592  /*
593  * We cache these in the opaque struct, to avoid repetitive syscache
594  * lookups.
595  */
596  opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
597 
598  /*
599  * If we already searched for this proc and didn't find it, don't bother
600  * searching again.
601  */
602  if (opaque->extra_proc_missing[basenum])
603  return NULL;
604 
605  if (opaque->extra_procinfos[basenum].fn_oid == InvalidOid)
606  {
607  if (RegProcedureIsValid(index_getprocid(bdesc->bd_index, attno,
608  procnum)))
609  {
610  fmgr_info_copy(&opaque->extra_procinfos[basenum],
611  index_getprocinfo(bdesc->bd_index, attno, procnum),
612  bdesc->bd_context);
613  }
614  else
615  {
616  opaque->extra_proc_missing[basenum] = true;
617  return NULL;
618  }
619  }
620 
621  return &opaque->extra_procinfos[basenum];
622 }
623 
624 /*
625  * Cache and return the procedure of the given strategy
626  *
627  * Return the procedure corresponding to the given sub-type and strategy
628  * number. The data type of the index will be used as the left hand side of
629  * the operator and the given sub-type will be used as the right hand side.
630  * Throws an error if the pg_amop row does not exist, but that should not
631  * happen with a properly configured opclass.
632  *
633  * It always throws an error when the data type of the opclass is different
634  * from the data type of the column or the expression. That happens when the
635  * column data type has implicit cast to the opclass data type. We don't
636  * bother casting types, because this situation can easily be avoided by
637  * setting storage data type to that of the opclass. The same problem does not
638  * apply to the data type of the right hand side, because the type in the
639  * ScanKey always matches the opclass' one.
640  *
641  * Note: this function mirrors minmax_get_strategy_procinfo; if changes are
642  * made here, see that function too.
643  */
644 static FmgrInfo *
646  uint16 strategynum)
647 {
648  InclusionOpaque *opaque;
649 
650  Assert(strategynum >= 1 &&
651  strategynum <= RTMaxStrategyNumber);
652 
653  opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
654 
655  /*
656  * We cache the procedures for the last sub-type in the opaque struct, to
657  * avoid repetitive syscache lookups. If the sub-type is changed,
658  * invalidate all the cached entries.
659  */
660  if (opaque->cached_subtype != subtype)
661  {
662  uint16 i;
663 
664  for (i = 1; i <= RTMaxStrategyNumber; i++)
665  opaque->strategy_procinfos[i - 1].fn_oid = InvalidOid;
666  opaque->cached_subtype = subtype;
667  }
668 
669  if (opaque->strategy_procinfos[strategynum - 1].fn_oid == InvalidOid)
670  {
671  Form_pg_attribute attr;
672  HeapTuple tuple;
673  Oid opfamily,
674  oprid;
675  bool isNull;
676 
677  opfamily = bdesc->bd_index->rd_opfamily[attno - 1];
678  attr = bdesc->bd_tupdesc->attrs[attno - 1];
679  tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
680  ObjectIdGetDatum(attr->atttypid),
681  ObjectIdGetDatum(subtype),
682  Int16GetDatum(strategynum));
683 
684  if (!HeapTupleIsValid(tuple))
685  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
686  strategynum, attr->atttypid, subtype, opfamily);
687 
689  Anum_pg_amop_amopopr, &isNull));
690  ReleaseSysCache(tuple);
691  Assert(!isNull && RegProcedureIsValid(oprid));
692 
693  fmgr_info_cxt(get_opcode(oprid),
694  &opaque->strategy_procinfos[strategynum - 1],
695  bdesc->bd_context);
696  }
697 
698  return &opaque->strategy_procinfos[strategynum - 1];
699 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
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:233
#define SearchSysCache4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:158
#define DatumGetObjectId(X)
Definition: postgres.h:506
#define SizeofBrinOpcInfo(ncols)
Definition: brin_internal.h:38
FmgrInfo strategy_procinfos[RTMaxStrategyNumber]
Form_pg_attribute * attrs
Definition: tupdesc.h:74
bool bv_allnulls
Definition: brin_tuple.h:28
#define Int16GetDatum(X)
Definition: postgres.h:457
#define RTOverBelowStrategyNumber
Definition: stratnum.h:52
return result
Definition: formatting.c:1618
#define RTContainedByStrategyNumber
Definition: stratnum.h:51
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define RTLessStrategyNumber
Definition: stratnum.h:63
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:239
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1356
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:163
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:267
void pfree(void *pointer)
Definition: mcxt.c:950
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:583
AttrNumber bv_attno
Definition: brin_tuple.h:26
uint16 oi_nstored
Definition: brin_internal.h:28
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
ScanKeyData * ScanKey
Definition: skey.h:75
#define RTGreaterStrategyNumber
Definition: stratnum.h:65
#define RTLessEqualStrategyNumber
Definition: stratnum.h:64
#define RegProcedureIsValid(p)
Definition: c.h:540
#define DatumGetBool(X)
Definition: postgres.h:399
#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:184
Datum brin_inclusion_consistent(PG_FUNCTION_ARGS)
#define SK_SEARCHNOTNULL
Definition: skey.h:122
Oid * rd_opfamily
Definition: rel.h:182
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:169
#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:72
#define RTOverLeftStrategyNumber
Definition: stratnum.h:45
void * palloc0(Size size)
Definition: mcxt.c:878
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
#define RTSubStrategyNumber
Definition: stratnum.h:67
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
void * oi_opaque
Definition: brin_internal.h:31
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1336
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
#define INCLUSION_CONTAINS_EMPTY
BrinOpcInfo * bd_info[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:59
#define BoolGetDatum(X)
Definition: postgres.h:408
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1062
Oid fn_oid
Definition: fmgr.h:59
#define PG_RETURN_VOID()
Definition: fmgr.h:309
#define RTAboveStrategyNumber
Definition: stratnum.h:54
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
int sk_flags
Definition: skey.h:66
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define INCLUSION_MAX_PROCNUMS
#define RTEqualStrategyNumber
Definition: stratnum.h:61
#define RTRightStrategyNumber
Definition: stratnum.h:48
#define newval
#define MAXALIGN(LEN)
Definition: c.h:588
#define RTContainsStrategyNumber
Definition: stratnum.h:50
#define BOOLOID
Definition: pg_type.h:288
#define DatumGetPointer(X)
Definition: postgres.h:555
#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 Anum_pg_amop_amopopr
Definition: pg_amop.h:89
#define PROCNUM_MERGE
int i
#define RTSubEqualStrategyNumber
Definition: stratnum.h:68
#define RTOverlapStrategyNumber
Definition: stratnum.h:46
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
#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