PostgreSQL Source Code  git master
brin_inclusion.c File Reference
#include "postgres.h"
#include "access/brin_internal.h"
#include "access/brin_tuple.h"
#include "access/genam.h"
#include "access/skey.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for brin_inclusion.c:

Go to the source code of this file.

Data Structures

struct  InclusionOpaque
 

Macros

#define INCLUSION_MAX_PROCNUMS   4 /* maximum support procs we need */
 
#define PROCNUM_MERGE   11 /* required */
 
#define PROCNUM_MERGEABLE   12 /* optional */
 
#define PROCNUM_CONTAINS   13 /* optional */
 
#define PROCNUM_EMPTY   14 /* optional */
 
#define PROCNUM_BASE   11
 
#define INCLUSION_UNION   0
 
#define INCLUSION_UNMERGEABLE   1
 
#define INCLUSION_CONTAINS_EMPTY   2
 

Typedefs

typedef struct InclusionOpaque InclusionOpaque
 

Functions

static FmgrInfoinclusion_get_procinfo (BrinDesc *bdesc, uint16 attno, uint16 procnum)
 
static FmgrInfoinclusion_get_strategy_procinfo (BrinDesc *bdesc, uint16 attno, Oid subtype, uint16 strategynum)
 
Datum brin_inclusion_opcinfo (PG_FUNCTION_ARGS)
 
Datum brin_inclusion_add_value (PG_FUNCTION_ARGS)
 
Datum brin_inclusion_consistent (PG_FUNCTION_ARGS)
 
Datum brin_inclusion_union (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ INCLUSION_CONTAINS_EMPTY

#define INCLUSION_CONTAINS_EMPTY   2

◆ INCLUSION_MAX_PROCNUMS

#define INCLUSION_MAX_PROCNUMS   4 /* maximum support procs we need */

Definition at line 46 of file brin_inclusion.c.

◆ INCLUSION_UNION

#define INCLUSION_UNION   0

◆ INCLUSION_UNMERGEABLE

#define INCLUSION_UNMERGEABLE   1

◆ PROCNUM_BASE

#define PROCNUM_BASE   11

Definition at line 57 of file brin_inclusion.c.

Referenced by inclusion_get_procinfo().

◆ PROCNUM_CONTAINS

#define PROCNUM_CONTAINS   13 /* optional */

Definition at line 49 of file brin_inclusion.c.

Referenced by brin_inclusion_add_value().

◆ PROCNUM_EMPTY

#define PROCNUM_EMPTY   14 /* optional */

Definition at line 50 of file brin_inclusion.c.

Referenced by brin_inclusion_add_value().

◆ PROCNUM_MERGE

#define PROCNUM_MERGE   11 /* required */

Definition at line 47 of file brin_inclusion.c.

Referenced by brin_inclusion_add_value(), and brin_inclusion_union().

◆ PROCNUM_MERGEABLE

#define PROCNUM_MERGEABLE   12 /* optional */

Definition at line 48 of file brin_inclusion.c.

Referenced by brin_inclusion_add_value(), and brin_inclusion_union().

Typedef Documentation

◆ InclusionOpaque

Function Documentation

◆ brin_inclusion_add_value()

Datum brin_inclusion_add_value ( PG_FUNCTION_ARGS  )

Definition at line 137 of file brin_inclusion.c.

References Assert, BrinDesc::bd_tupdesc, BoolGetDatum, BrinValues::bv_allnulls, BrinValues::bv_attno, BrinValues::bv_hasnulls, BrinValues::bv_values, datumCopy(), DatumGetBool, DatumGetPointer, FunctionCall1Coll(), FunctionCall2Coll(), INCLUSION_CONTAINS_EMPTY, inclusion_get_procinfo(), INCLUSION_UNION, INCLUSION_UNMERGEABLE, newval, pfree(), PG_GET_COLLATION, PG_GETARG_BOOL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_RETURN_BOOL, PROCNUM_CONTAINS, PROCNUM_EMPTY, PROCNUM_MERGE, PROCNUM_MERGEABLE, and TupleDescAttr.

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 }
Definition: fmgr.h:56
#define INCLUSION_UNMERGEABLE
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
bool bv_allnulls
Definition: brin_tuple.h:28
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1150
unsigned int Oid
Definition: postgres_ext.h:31
#define PROCNUM_CONTAINS
#define PG_GET_COLLATION()
Definition: fmgr.h:193
static FmgrInfo * inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum)
void pfree(void *pointer)
Definition: mcxt.c:1056
bool bv_hasnulls
Definition: brin_tuple.h:27
AttrNumber bv_attno
Definition: brin_tuple.h:26
#define DatumGetBool(X)
Definition: postgres.h:393
#define INCLUSION_UNION
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
uintptr_t Datum
Definition: postgres.h:367
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1130
#define INCLUSION_CONTAINS_EMPTY
#define BoolGetDatum(X)
Definition: postgres.h:402
#define Assert(condition)
Definition: c.h:738
#define newval
#define DatumGetPointer(X)
Definition: postgres.h:549
#define PROCNUM_MERGE
#define PROCNUM_MERGEABLE
#define PROCNUM_EMPTY
Datum * bv_values
Definition: brin_tuple.h:29
int16 AttrNumber
Definition: attnum.h:21

◆ brin_inclusion_consistent()

Datum brin_inclusion_consistent ( PG_FUNCTION_ARGS  )

Definition at line 257 of file brin_inclusion.c.

References Assert, BrinValues::bv_allnulls, BrinValues::bv_attno, BrinValues::bv_hasnulls, BrinValues::bv_values, DatumGetBool, elog, ERROR, FunctionCall2Coll(), INCLUSION_CONTAINS_EMPTY, inclusion_get_strategy_procinfo(), INCLUSION_UNION, INCLUSION_UNMERGEABLE, sort-test::key, PG_GET_COLLATION, PG_GETARG_POINTER, PG_RETURN_BOOL, PG_RETURN_DATUM, RTAboveStrategyNumber, RTAdjacentStrategyNumber, RTBelowStrategyNumber, RTContainedByStrategyNumber, RTContainsElemStrategyNumber, RTContainsStrategyNumber, RTEqualStrategyNumber, RTGreaterEqualStrategyNumber, RTGreaterStrategyNumber, RTLeftStrategyNumber, RTLessEqualStrategyNumber, RTLessStrategyNumber, RTOldContainedByStrategyNumber, RTOldContainsStrategyNumber, RTOverAboveStrategyNumber, RTOverBelowStrategyNumber, RTOverlapStrategyNumber, RTOverLeftStrategyNumber, RTOverRightStrategyNumber, RTRightStrategyNumber, RTSameStrategyNumber, RTSubEqualStrategyNumber, RTSubStrategyNumber, RTSuperEqualStrategyNumber, RTSuperStrategyNumber, ScanKeyData::sk_argument, ScanKeyData::sk_attno, ScanKeyData::sk_flags, SK_ISNULL, SK_SEARCHNOTNULL, SK_SEARCHNULL, ScanKeyData::sk_strategy, and ScanKeyData::sk_subtype.

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 
383  case RTSubStrategyNumber:
385  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
386  key->sk_strategy);
387  result = FunctionCall2Coll(finfo, colloid, unionval, query);
388  PG_RETURN_DATUM(result);
389 
390  /*
391  * Contained by strategies
392  *
393  * We cannot just call the original operator for the contained by
394  * strategies because some elements can be contained even though
395  * the union is not; instead we use the overlap operator.
396  *
397  * We check for empty elements separately as they are not merged
398  * to the union but contained by everything.
399  */
400 
405  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
407  result = FunctionCall2Coll(finfo, colloid, unionval, query);
408  if (DatumGetBool(result))
409  PG_RETURN_BOOL(true);
410 
412 
413  /*
414  * Adjacent strategy
415  *
416  * We test for overlap first but to be safe we need to call the
417  * actual adjacent operator also.
418  *
419  * An empty element cannot be adjacent to any other, so there is
420  * no need to check for it.
421  */
422 
424  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
426  result = FunctionCall2Coll(finfo, colloid, unionval, query);
427  if (DatumGetBool(result))
428  PG_RETURN_BOOL(true);
429 
430  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
432  result = FunctionCall2Coll(finfo, colloid, unionval, query);
433  PG_RETURN_DATUM(result);
434 
435  /*
436  * Basic comparison strategies
437  *
438  * It is straightforward to support the equality strategies with
439  * the contains operator. Generally, inequality strategies do not
440  * make much sense for the types which will be used with the
441  * inclusion BRIN family of opclasses, but it is possible to
442  * implement them with logical negation of the left-of and
443  * right-of operators.
444  *
445  * NB: These strategies cannot be used with geometric datatypes
446  * that use comparison of areas! The only exception is the "same"
447  * strategy.
448  *
449  * Empty elements are considered to be less than the others. We
450  * cannot use the empty support function to check the query is an
451  * empty element, because the query can be another data type than
452  * the empty support function argument. So we will return true,
453  * if there is a possibility that empty elements will change the
454  * result.
455  */
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 
469  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
471  result = FunctionCall2Coll(finfo, colloid, unionval, query);
472  if (DatumGetBool(result))
473  PG_RETURN_BOOL(true);
474 
476 
478  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
480  result = FunctionCall2Coll(finfo, colloid, unionval, query);
481  if (!DatumGetBool(result))
482  PG_RETURN_BOOL(true);
483 
485 
487  /* no need to check for empty elements */
488  finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
490  result = FunctionCall2Coll(finfo, colloid, unionval, query);
491  PG_RETURN_BOOL(!DatumGetBool(result));
492 
493  default:
494  /* shouldn't happen */
495  elog(ERROR, "invalid strategy number %d", key->sk_strategy);
496  PG_RETURN_BOOL(false);
497  }
498 }
Oid sk_subtype
Definition: skey.h:69
Definition: fmgr.h:56
#define RTOldContainsStrategyNumber
Definition: stratnum.h:63
#define RTSuperStrategyNumber
Definition: stratnum.h:76
#define RTOldContainedByStrategyNumber
Definition: stratnum.h:64
#define RTLeftStrategyNumber
Definition: stratnum.h:51
#define INCLUSION_UNMERGEABLE
bool bv_allnulls
Definition: brin_tuple.h:28
#define RTOverBelowStrategyNumber
Definition: stratnum.h:59
#define RTContainedByStrategyNumber
Definition: stratnum.h:58
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define RTLessStrategyNumber
Definition: stratnum.h:70
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1150
unsigned int Oid
Definition: postgres_ext.h:31
#define RTBelowStrategyNumber
Definition: stratnum.h:60
#define PG_GET_COLLATION()
Definition: fmgr.h:193
#define RTOverAboveStrategyNumber
Definition: stratnum.h:62
#define ERROR
Definition: elog.h:43
bool bv_hasnulls
Definition: brin_tuple.h:27
static FmgrInfo * inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, uint16 strategynum)
StrategyNumber sk_strategy
Definition: skey.h:68
AttrNumber bv_attno
Definition: brin_tuple.h:26
ScanKeyData * ScanKey
Definition: skey.h:75
#define RTGreaterStrategyNumber
Definition: stratnum.h:72
#define RTLessEqualStrategyNumber
Definition: stratnum.h:71
#define DatumGetBool(X)
Definition: postgres.h:393
#define RTSameStrategyNumber
Definition: stratnum.h:56
#define INCLUSION_UNION
#define SK_SEARCHNOTNULL
Definition: skey.h:122
#define RTOverRightStrategyNumber
Definition: stratnum.h:54
#define SK_ISNULL
Definition: skey.h:115
#define RTOverLeftStrategyNumber
Definition: stratnum.h:52
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
uintptr_t Datum
Definition: postgres.h:367
#define RTSubStrategyNumber
Definition: stratnum.h:74
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
#define INCLUSION_CONTAINS_EMPTY
#define RTAboveStrategyNumber
Definition: stratnum.h:61
int sk_flags
Definition: skey.h:66
#define Assert(condition)
Definition: c.h:738
#define RTEqualStrategyNumber
Definition: stratnum.h:68
#define RTRightStrategyNumber
Definition: stratnum.h:55
#define RTContainsStrategyNumber
Definition: stratnum.h:57
#define RTSuperEqualStrategyNumber
Definition: stratnum.h:77
#define RTAdjacentStrategyNumber
Definition: stratnum.h:67
#define RTContainsElemStrategyNumber
Definition: stratnum.h:66
#define elog(elevel,...)
Definition: elog.h:228
#define RTSubEqualStrategyNumber
Definition: stratnum.h:75
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
#define RTGreaterEqualStrategyNumber
Definition: stratnum.h:73
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

◆ brin_inclusion_opcinfo()

Datum brin_inclusion_opcinfo ( PG_FUNCTION_ARGS  )

Definition at line 94 of file brin_inclusion.c.

References INCLUSION_CONTAINS_EMPTY, INCLUSION_UNION, INCLUSION_UNMERGEABLE, lookup_type_cache(), MAXALIGN, BrinOpcInfo::oi_nstored, BrinOpcInfo::oi_opaque, BrinOpcInfo::oi_typcache, palloc0(), PG_GETARG_OID, PG_RETURN_POINTER, and SizeofBrinOpcInfo.

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 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define INCLUSION_UNMERGEABLE
#define SizeofBrinOpcInfo(ncols)
Definition: brin_internal.h:38
unsigned int Oid
Definition: postgres_ext.h:31
TypeCacheEntry * oi_typcache[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:34
uint16 oi_nstored
Definition: brin_internal.h:28
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
#define INCLUSION_UNION
void * palloc0(Size size)
Definition: mcxt.c:980
void * oi_opaque
Definition: brin_internal.h:31
#define INCLUSION_CONTAINS_EMPTY
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define MAXALIGN(LEN)
Definition: c.h:691

◆ brin_inclusion_union()

Datum brin_inclusion_union ( PG_FUNCTION_ARGS  )

Definition at line 507 of file brin_inclusion.c.

References Assert, BrinDesc::bd_tupdesc, BoolGetDatum, BrinValues::bv_allnulls, BrinValues::bv_attno, BrinValues::bv_hasnulls, BrinValues::bv_values, datumCopy(), DatumGetBool, DatumGetPointer, FunctionCall2Coll(), INCLUSION_CONTAINS_EMPTY, inclusion_get_procinfo(), INCLUSION_UNION, INCLUSION_UNMERGEABLE, pfree(), PG_GET_COLLATION, PG_GETARG_POINTER, PG_RETURN_VOID, PROCNUM_MERGE, PROCNUM_MERGEABLE, and TupleDescAttr.

508 {
509  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
510  BrinValues *col_a = (BrinValues *) PG_GETARG_POINTER(1);
511  BrinValues *col_b = (BrinValues *) PG_GETARG_POINTER(2);
512  Oid colloid = PG_GET_COLLATION();
513  AttrNumber attno;
514  Form_pg_attribute attr;
515  FmgrInfo *finfo;
516  Datum result;
517 
518  Assert(col_a->bv_attno == col_b->bv_attno);
519 
520  /* Adjust "hasnulls". */
521  if (!col_a->bv_hasnulls && col_b->bv_hasnulls)
522  col_a->bv_hasnulls = true;
523 
524  /* If there are no values in B, there's nothing left to do. */
525  if (col_b->bv_allnulls)
526  PG_RETURN_VOID();
527 
528  attno = col_a->bv_attno;
529  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
530 
531  /*
532  * Adjust "allnulls". If A doesn't have values, just copy the values from
533  * B into A, and we're done. We cannot run the operators in this case,
534  * because values in A might contain garbage. Note we already established
535  * that B contains values.
536  */
537  if (col_a->bv_allnulls)
538  {
539  col_a->bv_allnulls = false;
540  col_a->bv_values[INCLUSION_UNION] =
542  attr->attbyval, attr->attlen);
547  PG_RETURN_VOID();
548  }
549 
550  /* If B includes empty elements, mark A similarly, if needed. */
554 
555  /* Check if A includes elements that are not mergeable. */
557  PG_RETURN_VOID();
558 
559  /* If B includes elements that are not mergeable, mark A similarly. */
561  {
563  PG_RETURN_VOID();
564  }
565 
566  /* Check if A and B are mergeable; if not, mark A unmergeable. */
567  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE);
568  if (finfo != NULL &&
569  !DatumGetBool(FunctionCall2Coll(finfo, colloid,
570  col_a->bv_values[INCLUSION_UNION],
571  col_b->bv_values[INCLUSION_UNION])))
572  {
574  PG_RETURN_VOID();
575  }
576 
577  /* Finally, merge B to A. */
578  finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE);
579  Assert(finfo != NULL);
580  result = FunctionCall2Coll(finfo, colloid,
581  col_a->bv_values[INCLUSION_UNION],
582  col_b->bv_values[INCLUSION_UNION]);
583  if (!attr->attbyval &&
585  {
587 
588  if (result == col_b->bv_values[INCLUSION_UNION])
589  result = datumCopy(result, attr->attbyval, attr->attlen);
590  }
591  col_a->bv_values[INCLUSION_UNION] = result;
592 
593  PG_RETURN_VOID();
594 }
Definition: fmgr.h:56
#define INCLUSION_UNMERGEABLE
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
bool bv_allnulls
Definition: brin_tuple.h:28
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1150
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GET_COLLATION()
Definition: fmgr.h:193
static FmgrInfo * inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum)
void pfree(void *pointer)
Definition: mcxt.c:1056
bool bv_hasnulls
Definition: brin_tuple.h:27
AttrNumber bv_attno
Definition: brin_tuple.h:26
#define DatumGetBool(X)
Definition: postgres.h:393
#define INCLUSION_UNION
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
uintptr_t Datum
Definition: postgres.h:367
#define INCLUSION_CONTAINS_EMPTY
#define BoolGetDatum(X)
Definition: postgres.h:402
#define PG_RETURN_VOID()
Definition: fmgr.h:339
#define Assert(condition)
Definition: c.h:738
#define DatumGetPointer(X)
Definition: postgres.h:549
#define PROCNUM_MERGE
#define PROCNUM_MERGEABLE
Datum * bv_values
Definition: brin_tuple.h:29
int16 AttrNumber
Definition: attnum.h:21

◆ inclusion_get_procinfo()

static FmgrInfo * inclusion_get_procinfo ( BrinDesc bdesc,
uint16  attno,
uint16  procnum 
)
static

Definition at line 603 of file brin_inclusion.c.

References BrinDesc::bd_context, BrinDesc::bd_index, BrinDesc::bd_info, InclusionOpaque::extra_proc_missing, InclusionOpaque::extra_procinfos, fmgr_info_copy(), FmgrInfo::fn_oid, index_getprocid(), index_getprocinfo(), InvalidOid, BrinOpcInfo::oi_opaque, PROCNUM_BASE, and RegProcedureIsValid.

Referenced by brin_inclusion_add_value(), and brin_inclusion_union().

604 {
605  InclusionOpaque *opaque;
606  uint16 basenum = procnum - PROCNUM_BASE;
607 
608  /*
609  * We cache these in the opaque struct, to avoid repetitive syscache
610  * lookups.
611  */
612  opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
613 
614  /*
615  * If we already searched for this proc and didn't find it, don't bother
616  * searching again.
617  */
618  if (opaque->extra_proc_missing[basenum])
619  return NULL;
620 
621  if (opaque->extra_procinfos[basenum].fn_oid == InvalidOid)
622  {
623  if (RegProcedureIsValid(index_getprocid(bdesc->bd_index, attno,
624  procnum)))
625  {
626  fmgr_info_copy(&opaque->extra_procinfos[basenum],
627  index_getprocinfo(bdesc->bd_index, attno, procnum),
628  bdesc->bd_context);
629  }
630  else
631  {
632  opaque->extra_proc_missing[basenum] = true;
633  return NULL;
634  }
635  }
636 
637  return &opaque->extra_procinfos[basenum];
638 }
FmgrInfo extra_procinfos[INCLUSION_MAX_PROCNUMS]
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:794
bool extra_proc_missing[INCLUSION_MAX_PROCNUMS]
#define PROCNUM_BASE
unsigned short uint16
Definition: c.h:366
Relation bd_index
Definition: brin_internal.h:47
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition: fmgr.c:610
#define RegProcedureIsValid(p)
Definition: c.h:646
void * oi_opaque
Definition: brin_internal.h:31
BrinOpcInfo * bd_info[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:59
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
MemoryContext bd_context
Definition: brin_internal.h:44
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:760

◆ inclusion_get_strategy_procinfo()

static FmgrInfo * inclusion_get_strategy_procinfo ( BrinDesc bdesc,
uint16  attno,
Oid  subtype,
uint16  strategynum 
)
static

Definition at line 661 of file brin_inclusion.c.

References AMOPSTRATEGY, Assert, BrinDesc::bd_context, BrinDesc::bd_index, BrinDesc::bd_info, BrinDesc::bd_tupdesc, InclusionOpaque::cached_subtype, DatumGetObjectId, elog, ERROR, fmgr_info_cxt(), FmgrInfo::fn_oid, get_opcode(), HeapTupleIsValid, i, Int16GetDatum, InvalidOid, ObjectIdGetDatum, BrinOpcInfo::oi_opaque, oprid(), RelationData::rd_opfamily, RegProcedureIsValid, ReleaseSysCache(), RTMaxStrategyNumber, SearchSysCache4(), InclusionOpaque::strategy_procinfos, SysCacheGetAttr(), and TupleDescAttr.

Referenced by brin_inclusion_consistent().

663 {
664  InclusionOpaque *opaque;
665 
666  Assert(strategynum >= 1 &&
667  strategynum <= RTMaxStrategyNumber);
668 
669  opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
670 
671  /*
672  * We cache the procedures for the last sub-type in the opaque struct, to
673  * avoid repetitive syscache lookups. If the sub-type is changed,
674  * invalidate all the cached entries.
675  */
676  if (opaque->cached_subtype != subtype)
677  {
678  uint16 i;
679 
680  for (i = 1; i <= RTMaxStrategyNumber; i++)
681  opaque->strategy_procinfos[i - 1].fn_oid = InvalidOid;
682  opaque->cached_subtype = subtype;
683  }
684 
685  if (opaque->strategy_procinfos[strategynum - 1].fn_oid == InvalidOid)
686  {
687  Form_pg_attribute attr;
688  HeapTuple tuple;
689  Oid opfamily,
690  oprid;
691  bool isNull;
692 
693  opfamily = bdesc->bd_index->rd_opfamily[attno - 1];
694  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
695  tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
696  ObjectIdGetDatum(attr->atttypid),
697  ObjectIdGetDatum(subtype),
698  Int16GetDatum(strategynum));
699 
700  if (!HeapTupleIsValid(tuple))
701  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
702  strategynum, attr->atttypid, subtype, opfamily);
703 
705  Anum_pg_amop_amopopr, &isNull));
706  ReleaseSysCache(tuple);
707  Assert(!isNull && RegProcedureIsValid(oprid));
708 
709  fmgr_info_cxt(get_opcode(oprid),
710  &opaque->strategy_procinfos[strategynum - 1],
711  bdesc->bd_context);
712  }
713 
714  return &opaque->strategy_procinfos[strategynum - 1];
715 }
Oid oprid(Operator op)
Definition: parse_oper.c:245
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define DatumGetObjectId(X)
Definition: postgres.h:500
FmgrInfo strategy_procinfos[RTMaxStrategyNumber]
#define Int16GetDatum(X)
Definition: postgres.h:451
unsigned int Oid
Definition: postgres_ext.h:31
unsigned short uint16
Definition: c.h:366
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation bd_index
Definition: brin_internal.h:47
#define RegProcedureIsValid(p)
Definition: c.h:646
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
Oid * rd_opfamily
Definition: rel.h:164
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1149
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
#define RTMaxStrategyNumber
Definition: stratnum.h:80
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
void * oi_opaque
Definition: brin_internal.h:31
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
BrinOpcInfo * bd_info[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:59
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1092
Oid fn_oid
Definition: fmgr.h:59
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
MemoryContext bd_context
Definition: brin_internal.h:44
#define elog(elevel,...)
Definition: elog.h:228
int i