PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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

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

Definition at line 46 of file brin_inclusion.c.

#define INCLUSION_UNION   0
#define INCLUSION_UNMERGEABLE   1
#define PROCNUM_BASE   11

Definition at line 57 of file brin_inclusion.c.

Referenced by inclusion_get_procinfo().

#define PROCNUM_CONTAINS   13 /* optional */

Definition at line 49 of file brin_inclusion.c.

Referenced by brin_inclusion_add_value().

#define PROCNUM_EMPTY   14 /* optional */

Definition at line 50 of file brin_inclusion.c.

Referenced by brin_inclusion_add_value().

#define PROCNUM_MERGE   11 /* required */

Definition at line 47 of file brin_inclusion.c.

Referenced by brin_inclusion_add_value(), and brin_inclusion_union().

#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

Function Documentation

Datum brin_inclusion_add_value ( PG_FUNCTION_ARGS  )

Definition at line 133 of file brin_inclusion.c.

References Assert, tupleDesc::attrs, 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, NULL, 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 result.

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 }
Definition: fmgr.h:56
#define INCLUSION_UNMERGEABLE
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
Form_pg_attribute * attrs
Definition: tupdesc.h:74
bool bv_allnulls
Definition: brin_tuple.h:28
return result
Definition: formatting.c:1633
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:239
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1047
unsigned int Oid
Definition: postgres_ext.h:31
#define PROCNUM_CONTAINS
#define PG_GET_COLLATION()
Definition: fmgr.h:163
static FmgrInfo * inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum)
void pfree(void *pointer)
Definition: mcxt.c:950
bool bv_hasnulls
Definition: brin_tuple.h:27
AttrNumber bv_attno
Definition: brin_tuple.h:26
#define DatumGetBool(X)
Definition: postgres.h:399
#define INCLUSION_UNION
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
uintptr_t Datum
Definition: postgres.h:372
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1027
#define INCLUSION_CONTAINS_EMPTY
#define BoolGetDatum(X)
Definition: postgres.h:408
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#define newval
#define DatumGetPointer(X)
Definition: postgres.h:555
#define PROCNUM_MERGE
#define PROCNUM_MERGEABLE
#define PROCNUM_EMPTY
Datum * bv_values
Definition: brin_tuple.h:29
int16 AttrNumber
Definition: attnum.h:21
Datum brin_inclusion_consistent ( PG_FUNCTION_ARGS  )

Definition at line 247 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, result, 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.

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 }
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
return result
Definition: formatting.c:1633
#define RTContainedByStrategyNumber
Definition: stratnum.h:51
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define RTLessStrategyNumber
Definition: stratnum.h:63
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1047
unsigned int Oid
Definition: postgres_ext.h:31
#define RTBelowStrategyNumber
Definition: stratnum.h:53
#define PG_GET_COLLATION()
Definition: fmgr.h:163
#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:399
#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:319
uintptr_t Datum
Definition: postgres.h:372
#define RTSubStrategyNumber
Definition: stratnum.h:67
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define INCLUSION_CONTAINS_EMPTY
#define RTAboveStrategyNumber
Definition: stratnum.h:54
int sk_flags
Definition: skey.h:66
#define Assert(condition)
Definition: c.h:676
#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
Datum brin_inclusion_opcinfo ( PG_FUNCTION_ARGS  )

Definition at line 90 of file brin_inclusion.c.

References BOOLOID, 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, result, and SizeofBrinOpcInfo.

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 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define INCLUSION_UNMERGEABLE
#define SizeofBrinOpcInfo(ncols)
Definition: brin_internal.h:38
return result
Definition: formatting.c:1633
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:240
#define INCLUSION_UNION
void * palloc0(Size size)
Definition: mcxt.c:878
void * oi_opaque
Definition: brin_internal.h:31
#define INCLUSION_CONTAINS_EMPTY
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define MAXALIGN(LEN)
Definition: c.h:588
#define BOOLOID
Definition: pg_type.h:288
Datum brin_inclusion_union ( PG_FUNCTION_ARGS  )

Definition at line 497 of file brin_inclusion.c.

References Assert, tupleDesc::attrs, 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, NULL, pfree(), PG_GET_COLLATION, PG_GETARG_POINTER, PG_RETURN_VOID, PROCNUM_MERGE, PROCNUM_MERGEABLE, and result.

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 }
Definition: fmgr.h:56
#define INCLUSION_UNMERGEABLE
Form_pg_attribute * attrs
Definition: tupdesc.h:74
bool bv_allnulls
Definition: brin_tuple.h:28
return result
Definition: formatting.c:1633
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1047
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GET_COLLATION()
Definition: fmgr.h:163
static FmgrInfo * inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum)
void pfree(void *pointer)
Definition: mcxt.c:950
bool bv_hasnulls
Definition: brin_tuple.h:27
AttrNumber bv_attno
Definition: brin_tuple.h:26
#define DatumGetBool(X)
Definition: postgres.h:399
#define INCLUSION_UNION
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:372
#define INCLUSION_CONTAINS_EMPTY
#define BoolGetDatum(X)
Definition: postgres.h:408
#define PG_RETURN_VOID()
Definition: fmgr.h:309
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#define DatumGetPointer(X)
Definition: postgres.h:555
#define PROCNUM_MERGE
#define PROCNUM_MERGEABLE
Datum * bv_values
Definition: brin_tuple.h:29
int16 AttrNumber
Definition: attnum.h:21
static FmgrInfo * inclusion_get_procinfo ( BrinDesc bdesc,
uint16  attno,
uint16  procnum 
)
static

Definition at line 587 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, NULL, BrinOpcInfo::oi_opaque, PROCNUM_BASE, and RegProcedureIsValid.

Referenced by brin_inclusion_add_value(), and brin_inclusion_union().

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 }
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:267
Relation bd_index
Definition: brin_internal.h:47
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition: fmgr.c:524
#define RegProcedureIsValid(p)
Definition: c.h:540
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
#define NULL
Definition: c.h:229
MemoryContext bd_context
Definition: brin_internal.h:44
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:821
static FmgrInfo * inclusion_get_strategy_procinfo ( BrinDesc bdesc,
uint16  attno,
Oid  subtype,
uint16  strategynum 
)
static

Definition at line 645 of file brin_inclusion.c.

References AMOPSTRATEGY, Anum_pg_amop_amopopr, Assert, tupleDesc::attrs, 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, and SysCacheGetAttr().

Referenced by brin_inclusion_consistent().

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 }
Oid oprid(Operator op)
Definition: parse_oper.c:245
#define SearchSysCache4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:162
#define DatumGetObjectId(X)
Definition: postgres.h:506
FmgrInfo strategy_procinfos[RTMaxStrategyNumber]
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define Int16GetDatum(X)
Definition: postgres.h:457
unsigned int Oid
Definition: postgres_ext.h:31
unsigned short uint16
Definition: c.h:267
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Relation bd_index
Definition: brin_internal.h:47
#define RegProcedureIsValid(p)
Definition: c.h:540
TupleDesc bd_tupdesc
Definition: brin_internal.h:50
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Oid * rd_opfamily
Definition: rel.h:182
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
#define RTMaxStrategyNumber
Definition: stratnum.h:72
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
void * oi_opaque
Definition: brin_internal.h:31
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
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:1094
Oid fn_oid
Definition: fmgr.h:59
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:676
MemoryContext bd_context
Definition: brin_internal.h:44
#define Anum_pg_amop_amopopr
Definition: pg_amop.h:89
int i
#define elog
Definition: elog.h:219