PostgreSQL Source Code  git master
brin_minmax.c File Reference
#include "postgres.h"
#include "access/brin_internal.h"
#include "access/brin_tuple.h"
#include "access/genam.h"
#include "access/stratnum.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_minmax.c:

Go to the source code of this file.

Data Structures

struct  MinmaxOpaque
 

Typedefs

typedef struct MinmaxOpaque MinmaxOpaque
 

Functions

static FmgrInfominmax_get_strategy_procinfo (BrinDesc *bdesc, uint16 attno, Oid subtype, uint16 strategynum)
 
Datum brin_minmax_opcinfo (PG_FUNCTION_ARGS)
 
Datum brin_minmax_add_value (PG_FUNCTION_ARGS)
 
Datum brin_minmax_consistent (PG_FUNCTION_ARGS)
 
Datum brin_minmax_union (PG_FUNCTION_ARGS)
 

Typedef Documentation

◆ MinmaxOpaque

typedef struct MinmaxOpaque MinmaxOpaque

Function Documentation

◆ brin_minmax_add_value()

Datum brin_minmax_add_value ( PG_FUNCTION_ARGS  )

Definition at line 65 of file brin_minmax.c.

References BrinDesc::bd_tupdesc, BTGreaterStrategyNumber, BTLessStrategyNumber, BrinValues::bv_allnulls, BrinValues::bv_attno, BrinValues::bv_hasnulls, BrinValues::bv_values, datumCopy(), DatumGetBool, DatumGetPointer, FunctionCall2Coll(), minmax_get_strategy_procinfo(), newval, pfree(), PG_GET_COLLATION, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_RETURN_BOOL, and TupleDescAttr.

66 {
67  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
68  BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
70  bool isnull = PG_GETARG_DATUM(3);
71  Oid colloid = PG_GET_COLLATION();
72  FmgrInfo *cmpFn;
73  Datum compar;
74  bool updated = false;
75  Form_pg_attribute attr;
76  AttrNumber attno;
77 
78  /*
79  * If the new value is null, we record that we saw it if it's the first
80  * one; otherwise, there's nothing to do.
81  */
82  if (isnull)
83  {
84  if (column->bv_hasnulls)
85  PG_RETURN_BOOL(false);
86 
87  column->bv_hasnulls = true;
88  PG_RETURN_BOOL(true);
89  }
90 
91  attno = column->bv_attno;
92  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
93 
94  /*
95  * If the recorded value is null, store the new value (which we know to be
96  * not null) as both minimum and maximum, and we're done.
97  */
98  if (column->bv_allnulls)
99  {
100  column->bv_values[0] = datumCopy(newval, attr->attbyval, attr->attlen);
101  column->bv_values[1] = datumCopy(newval, attr->attbyval, attr->attlen);
102  column->bv_allnulls = false;
103  PG_RETURN_BOOL(true);
104  }
105 
106  /*
107  * Otherwise, need to compare the new value with the existing boundaries
108  * and update them accordingly. First check if it's less than the
109  * existing minimum.
110  */
111  cmpFn = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid,
113  compar = FunctionCall2Coll(cmpFn, colloid, newval, column->bv_values[0]);
114  if (DatumGetBool(compar))
115  {
116  if (!attr->attbyval)
117  pfree(DatumGetPointer(column->bv_values[0]));
118  column->bv_values[0] = datumCopy(newval, attr->attbyval, attr->attlen);
119  updated = true;
120  }
121 
122  /*
123  * And now compare it to the existing maximum.
124  */
125  cmpFn = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid,
127  compar = FunctionCall2Coll(cmpFn, colloid, newval, column->bv_values[1]);
128  if (DatumGetBool(compar))
129  {
130  if (!attr->attbyval)
131  pfree(DatumGetPointer(column->bv_values[1]));
132  column->bv_values[1] = datumCopy(newval, attr->attbyval, attr->attlen);
133  updated = true;
134  }
135 
136  PG_RETURN_BOOL(updated);
137 }
Definition: fmgr.h:56
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#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
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
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
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:130
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
uintptr_t Datum
Definition: postgres.h:367
#define newval
#define DatumGetPointer(X)
Definition: postgres.h:549
static FmgrInfo * minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, uint16 strategynum)
Definition: brin_minmax.c:316
#define BTLessStrategyNumber
Definition: stratnum.h:29
Datum * bv_values
Definition: brin_tuple.h:29
int16 AttrNumber
Definition: attnum.h:21

◆ brin_minmax_consistent()

Datum brin_minmax_consistent ( PG_FUNCTION_ARGS  )

Definition at line 145 of file brin_minmax.c.

References Assert, BTEqualStrategyNumber, BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, BTLessEqualStrategyNumber, BTLessStrategyNumber, BrinValues::bv_allnulls, BrinValues::bv_attno, BrinValues::bv_hasnulls, BrinValues::bv_values, DatumGetBool, elog, ERROR, FunctionCall2Coll(), sort-test::key, minmax_get_strategy_procinfo(), PG_GET_COLLATION, PG_GETARG_POINTER, PG_RETURN_BOOL, PG_RETURN_DATUM, ScanKeyData::sk_argument, ScanKeyData::sk_attno, ScanKeyData::sk_flags, SK_ISNULL, SK_SEARCHNOTNULL, SK_SEARCHNULL, ScanKeyData::sk_strategy, ScanKeyData::sk_subtype, and value.

146 {
147  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
148  BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
150  Oid colloid = PG_GET_COLLATION(),
151  subtype;
152  AttrNumber attno;
153  Datum value;
154  Datum matches;
155  FmgrInfo *finfo;
156 
157  Assert(key->sk_attno == column->bv_attno);
158 
159  /* handle IS NULL/IS NOT NULL tests */
160  if (key->sk_flags & SK_ISNULL)
161  {
162  if (key->sk_flags & SK_SEARCHNULL)
163  {
164  if (column->bv_allnulls || column->bv_hasnulls)
165  PG_RETURN_BOOL(true);
166  PG_RETURN_BOOL(false);
167  }
168 
169  /*
170  * For IS NOT NULL, we can only skip ranges that are known to have
171  * only nulls.
172  */
173  if (key->sk_flags & SK_SEARCHNOTNULL)
174  PG_RETURN_BOOL(!column->bv_allnulls);
175 
176  /*
177  * Neither IS NULL nor IS NOT NULL was used; assume all indexable
178  * operators are strict and return false.
179  */
180  PG_RETURN_BOOL(false);
181  }
182 
183  /* if the range is all empty, it cannot possibly be consistent */
184  if (column->bv_allnulls)
185  PG_RETURN_BOOL(false);
186 
187  attno = key->sk_attno;
188  subtype = key->sk_subtype;
189  value = key->sk_argument;
190  switch (key->sk_strategy)
191  {
194  finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
195  key->sk_strategy);
196  matches = FunctionCall2Coll(finfo, colloid, column->bv_values[0],
197  value);
198  break;
200 
201  /*
202  * In the equality case (WHERE col = someval), we want to return
203  * the current page range if the minimum value in the range <=
204  * scan key, and the maximum value >= scan key.
205  */
206  finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
208  matches = FunctionCall2Coll(finfo, colloid, column->bv_values[0],
209  value);
210  if (!DatumGetBool(matches))
211  break;
212  /* max() >= scankey */
213  finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
215  matches = FunctionCall2Coll(finfo, colloid, column->bv_values[1],
216  value);
217  break;
220  finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
221  key->sk_strategy);
222  matches = FunctionCall2Coll(finfo, colloid, column->bv_values[1],
223  value);
224  break;
225  default:
226  /* shouldn't happen */
227  elog(ERROR, "invalid strategy number %d", key->sk_strategy);
228  matches = 0;
229  break;
230  }
231 
232  PG_RETURN_DATUM(matches);
233 }
Oid sk_subtype
Definition: skey.h:69
Definition: fmgr.h:56
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
bool bv_allnulls
Definition: brin_tuple.h:28
static struct @145 value
#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
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
#define ERROR
Definition: elog.h:43
bool bv_hasnulls
Definition: brin_tuple.h:27
StrategyNumber sk_strategy
Definition: skey.h:68
AttrNumber bv_attno
Definition: brin_tuple.h:26
ScanKeyData * ScanKey
Definition: skey.h:75
#define DatumGetBool(X)
Definition: postgres.h:393
#define SK_SEARCHNOTNULL
Definition: skey.h:122
#define SK_ISNULL
Definition: skey.h:115
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
int sk_flags
Definition: skey.h:66
#define Assert(condition)
Definition: c.h:739
static FmgrInfo * minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, uint16 strategynum)
Definition: brin_minmax.c:316
#define elog(elevel,...)
Definition: elog.h:228
#define BTLessStrategyNumber
Definition: stratnum.h:29
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
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32
AttrNumber sk_attno
Definition: skey.h:67

◆ brin_minmax_opcinfo()

Datum brin_minmax_opcinfo ( PG_FUNCTION_ARGS  )

Definition at line 36 of file brin_minmax.c.

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

37 {
38  Oid typoid = PG_GETARG_OID(0);
39  BrinOpcInfo *result;
40 
41  /*
42  * opaque->strategy_procinfos is initialized lazily; here it is set to
43  * all-uninitialized by palloc0 which sets fn_oid to InvalidOid.
44  */
45 
46  result = palloc0(MAXALIGN(SizeofBrinOpcInfo(2)) +
47  sizeof(MinmaxOpaque));
48  result->oi_nstored = 2;
49  result->oi_opaque = (MinmaxOpaque *)
50  MAXALIGN((char *) result + SizeofBrinOpcInfo(2));
51  result->oi_typcache[0] = result->oi_typcache[1] =
52  lookup_type_cache(typoid, 0);
53 
54  PG_RETURN_POINTER(result);
55 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#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
void * palloc0(Size size)
Definition: mcxt.c:980
void * oi_opaque
Definition: brin_internal.h:31
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define MAXALIGN(LEN)
Definition: c.h:692

◆ brin_minmax_union()

Datum brin_minmax_union ( PG_FUNCTION_ARGS  )

Definition at line 240 of file brin_minmax.c.

References Assert, BrinDesc::bd_tupdesc, BTGreaterStrategyNumber, BTLessStrategyNumber, BrinValues::bv_allnulls, BrinValues::bv_attno, BrinValues::bv_hasnulls, BrinValues::bv_values, datumCopy(), DatumGetPointer, FunctionCall2Coll(), minmax_get_strategy_procinfo(), pfree(), PG_GET_COLLATION, PG_GETARG_POINTER, PG_RETURN_VOID, and TupleDescAttr.

241 {
242  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
243  BrinValues *col_a = (BrinValues *) PG_GETARG_POINTER(1);
244  BrinValues *col_b = (BrinValues *) PG_GETARG_POINTER(2);
245  Oid colloid = PG_GET_COLLATION();
246  AttrNumber attno;
247  Form_pg_attribute attr;
248  FmgrInfo *finfo;
249  bool needsadj;
250 
251  Assert(col_a->bv_attno == col_b->bv_attno);
252 
253  /* Adjust "hasnulls" */
254  if (!col_a->bv_hasnulls && col_b->bv_hasnulls)
255  col_a->bv_hasnulls = true;
256 
257  /* If there are no values in B, there's nothing left to do */
258  if (col_b->bv_allnulls)
259  PG_RETURN_VOID();
260 
261  attno = col_a->bv_attno;
262  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
263 
264  /*
265  * Adjust "allnulls". If A doesn't have values, just copy the values from
266  * B into A, and we're done. We cannot run the operators in this case,
267  * because values in A might contain garbage. Note we already established
268  * that B contains values.
269  */
270  if (col_a->bv_allnulls)
271  {
272  col_a->bv_allnulls = false;
273  col_a->bv_values[0] = datumCopy(col_b->bv_values[0],
274  attr->attbyval, attr->attlen);
275  col_a->bv_values[1] = datumCopy(col_b->bv_values[1],
276  attr->attbyval, attr->attlen);
277  PG_RETURN_VOID();
278  }
279 
280  /* Adjust minimum, if B's min is less than A's min */
281  finfo = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid,
283  needsadj = FunctionCall2Coll(finfo, colloid, col_b->bv_values[0],
284  col_a->bv_values[0]);
285  if (needsadj)
286  {
287  if (!attr->attbyval)
288  pfree(DatumGetPointer(col_a->bv_values[0]));
289  col_a->bv_values[0] = datumCopy(col_b->bv_values[0],
290  attr->attbyval, attr->attlen);
291  }
292 
293  /* Adjust maximum, if B's max is greater than A's max */
294  finfo = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid,
296  needsadj = FunctionCall2Coll(finfo, colloid, col_b->bv_values[1],
297  col_a->bv_values[1]);
298  if (needsadj)
299  {
300  if (!attr->attbyval)
301  pfree(DatumGetPointer(col_a->bv_values[1]));
302  col_a->bv_values[1] = datumCopy(col_b->bv_values[1],
303  attr->attbyval, attr->attlen);
304  }
305 
306  PG_RETURN_VOID();
307 }
Definition: fmgr.h:56
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#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
void pfree(void *pointer)
Definition: mcxt.c:1056
bool bv_hasnulls
Definition: brin_tuple.h:27
AttrNumber bv_attno
Definition: brin_tuple.h:26
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:130
#define PG_RETURN_VOID()
Definition: fmgr.h:339
#define Assert(condition)
Definition: c.h:739
#define DatumGetPointer(X)
Definition: postgres.h:549
static FmgrInfo * minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, uint16 strategynum)
Definition: brin_minmax.c:316
#define BTLessStrategyNumber
Definition: stratnum.h:29
Datum * bv_values
Definition: brin_tuple.h:29
int16 AttrNumber
Definition: attnum.h:21

◆ minmax_get_strategy_procinfo()

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

Definition at line 316 of file brin_minmax.c.

References AMOPSTRATEGY, Assert, BrinDesc::bd_context, BrinDesc::bd_index, BrinDesc::bd_info, BrinDesc::bd_tupdesc, BTMaxStrategyNumber, MinmaxOpaque::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(), SearchSysCache4(), MinmaxOpaque::strategy_procinfos, SysCacheGetAttr(), and TupleDescAttr.

Referenced by brin_minmax_add_value(), brin_minmax_consistent(), and brin_minmax_union().

318 {
319  MinmaxOpaque *opaque;
320 
321  Assert(strategynum >= 1 &&
322  strategynum <= BTMaxStrategyNumber);
323 
324  opaque = (MinmaxOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
325 
326  /*
327  * We cache the procedures for the previous subtype in the opaque struct,
328  * to avoid repetitive syscache lookups. If the subtype changed,
329  * invalidate all the cached entries.
330  */
331  if (opaque->cached_subtype != subtype)
332  {
333  uint16 i;
334 
335  for (i = 1; i <= BTMaxStrategyNumber; i++)
336  opaque->strategy_procinfos[i - 1].fn_oid = InvalidOid;
337  opaque->cached_subtype = subtype;
338  }
339 
340  if (opaque->strategy_procinfos[strategynum - 1].fn_oid == InvalidOid)
341  {
342  Form_pg_attribute attr;
343  HeapTuple tuple;
344  Oid opfamily,
345  oprid;
346  bool isNull;
347 
348  opfamily = bdesc->bd_index->rd_opfamily[attno - 1];
349  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
350  tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
351  ObjectIdGetDatum(attr->atttypid),
352  ObjectIdGetDatum(subtype),
353  Int16GetDatum(strategynum));
354 
355  if (!HeapTupleIsValid(tuple))
356  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
357  strategynum, attr->atttypid, subtype, opfamily);
358 
360  Anum_pg_amop_amopopr, &isNull));
361  ReleaseSysCache(tuple);
362  Assert(!isNull && RegProcedureIsValid(oprid));
363 
364  fmgr_info_cxt(get_opcode(oprid),
365  &opaque->strategy_procinfos[strategynum - 1],
366  bdesc->bd_context);
367  }
368 
369  return &opaque->strategy_procinfos[strategynum - 1];
370 }
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[BTMaxStrategyNumber]
Definition: brin_minmax.c:28
#define Int16GetDatum(X)
Definition: postgres.h:451
unsigned int Oid
Definition: postgres_ext.h:31
unsigned short uint16
Definition: c.h:358
#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:647
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:158
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
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
Oid cached_subtype
Definition: brin_minmax.c:27
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:739
MemoryContext bd_context
Definition: brin_internal.h:44
#define elog(elevel,...)
Definition: elog.h:228
int i
#define BTMaxStrategyNumber
Definition: stratnum.h:35