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  column->bv_values[INCLUSION_UNION] = result;
241 
242  PG_RETURN_BOOL(true);
243 }
Definition: fmgr.h:56
#define INCLUSION_UNMERGEABLE
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
bool bv_allnulls
Definition: brin_tuple.h:28
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:244
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1133
unsigned int Oid
Definition: postgres_ext.h:31
#define PROCNUM_CONTAINS
#define PG_GET_COLLATION()
Definition: fmgr.h:168
static FmgrInfo * inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum)
void pfree(void *pointer)
Definition: mcxt.c:1031
bool bv_hasnulls
Definition: brin_tuple.h:27
AttrNumber bv_attno
Definition: brin_tuple.h:26
#define DatumGetBool(X)
Definition: postgres.h:378
#define INCLUSION_UNION
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:324
uintptr_t Datum
Definition: postgres.h:367
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1113
#define INCLUSION_CONTAINS_EMPTY
#define BoolGetDatum(X)
Definition: postgres.h:387
#define Assert(condition)
Definition: c.h:699
#define newval
#define DatumGetPointer(X)
Definition: postgres.h:534
#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 251 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, 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.

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 }
Oid sk_subtype
Definition: skey.h:69
Definition: fmgr.h:56
#define RTOldContainsStrategyNumber
Definition: stratnum.h:56
#define RTSuperStrategyNumber
Definition: stratnum.h:69
#define RTOldContainedByStrategyNumber
Definition: stratnum.h:57
#define RTLeftStrategyNumber
Definition: stratnum.h:44
#define INCLUSION_UNMERGEABLE
bool bv_allnulls
Definition: brin_tuple.h:28
#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
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1133
unsigned int Oid
Definition: postgres_ext.h:31
#define RTBelowStrategyNumber
Definition: stratnum.h:53
#define PG_GET_COLLATION()
Definition: fmgr.h:168
#define RTOverAboveStrategyNumber
Definition: stratnum.h:55
#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:65
#define RTLessEqualStrategyNumber
Definition: stratnum.h:64
#define DatumGetBool(X)
Definition: postgres.h:378
#define RTSameStrategyNumber
Definition: stratnum.h:49
#define INCLUSION_UNION
#define SK_SEARCHNOTNULL
Definition: skey.h:122
#define RTOverRightStrategyNumber
Definition: stratnum.h:47
#define SK_ISNULL
Definition: skey.h:115
#define RTOverLeftStrategyNumber
Definition: stratnum.h:45
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:324
uintptr_t Datum
Definition: postgres.h:367
#define RTSubStrategyNumber
Definition: stratnum.h:67
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:318
#define INCLUSION_CONTAINS_EMPTY
#define RTAboveStrategyNumber
Definition: stratnum.h:54
int sk_flags
Definition: skey.h:66
#define Assert(condition)
Definition: c.h:699
#define RTEqualStrategyNumber
Definition: stratnum.h:61
#define RTRightStrategyNumber
Definition: stratnum.h:48
#define RTContainsStrategyNumber
Definition: stratnum.h:50
#define RTSuperEqualStrategyNumber
Definition: stratnum.h:70
#define RTAdjacentStrategyNumber
Definition: stratnum.h:60
#define RTContainsElemStrategyNumber
Definition: stratnum.h:59
#define RTSubEqualStrategyNumber
Definition: stratnum.h:68
#define RTOverlapStrategyNumber
Definition: stratnum.h:46
#define elog
Definition: elog.h:219
#define RTGreaterEqualStrategyNumber
Definition: stratnum.h:66
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:326
#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:245
#define INCLUSION_UNION
void * palloc0(Size size)
Definition: mcxt.c:955
void * oi_opaque
Definition: brin_internal.h:31
#define INCLUSION_CONTAINS_EMPTY
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:321
#define MAXALIGN(LEN)
Definition: c.h:652

◆ brin_inclusion_union()

Datum brin_inclusion_union ( PG_FUNCTION_ARGS  )

Definition at line 501 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.

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 }
Definition: fmgr.h:56
#define INCLUSION_UNMERGEABLE
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
bool bv_allnulls
Definition: brin_tuple.h:28
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1133
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GET_COLLATION()
Definition: fmgr.h:168
static FmgrInfo * inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum)
void pfree(void *pointer)
Definition: mcxt.c:1031
bool bv_hasnulls
Definition: brin_tuple.h:27
AttrNumber bv_attno
Definition: brin_tuple.h:26
#define DatumGetBool(X)
Definition: postgres.h:378
#define INCLUSION_UNION
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:367
#define INCLUSION_CONTAINS_EMPTY
#define BoolGetDatum(X)
Definition: postgres.h:387
#define PG_RETURN_VOID()
Definition: fmgr.h:314
#define Assert(condition)
Definition: c.h:699
#define DatumGetPointer(X)
Definition: postgres.h:534
#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 591 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().

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 }
FmgrInfo extra_procinfos[INCLUSION_MAX_PROCNUMS]
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:855
bool extra_proc_missing[INCLUSION_MAX_PROCNUMS]
#define PROCNUM_BASE
unsigned short uint16
Definition: c.h:324
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:607
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:821

◆ inclusion_get_strategy_procinfo()

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

Definition at line 649 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().

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 }
Oid oprid(Operator op)
Definition: parse_oper.c:245
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
#define DatumGetObjectId(X)
Definition: postgres.h:485
FmgrInfo strategy_procinfos[RTMaxStrategyNumber]
#define Int16GetDatum(X)
Definition: postgres.h:436
unsigned int Oid
Definition: postgres_ext.h:31
unsigned short uint16
Definition: c.h:324
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
Relation bd_index
Definition: brin_internal.h:47
#define RegProcedureIsValid(p)
Definition: c.h:607
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
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:134
#define RTMaxStrategyNumber
Definition: stratnum.h:73
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
void * oi_opaque
Definition: brin_internal.h:31
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
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:1079
Oid fn_oid
Definition: fmgr.h:59
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
MemoryContext bd_context
Definition: brin_internal.h:44
int i
#define elog
Definition: elog.h:219