PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
brin_minmax.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/brin_internal.h"
#include "access/brin_tuple.h"
#include "access/stratnum.h"
#include "catalog/pg_type.h"
#include "catalog/pg_amop.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

Function Documentation

Datum brin_minmax_add_value ( PG_FUNCTION_ARGS  )

Definition at line 66 of file brin_minmax.c.

References tupleDesc::attrs, 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, and PG_RETURN_BOOL.

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

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

147 {
148  BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
149  BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
150  ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
151  Oid colloid = PG_GET_COLLATION(),
152  subtype;
153  AttrNumber attno;
154  Datum value;
155  Datum matches;
156  FmgrInfo *finfo;
157 
158  Assert(key->sk_attno == column->bv_attno);
159 
160  /* handle IS NULL/IS NOT NULL tests */
161  if (key->sk_flags & SK_ISNULL)
162  {
163  if (key->sk_flags & SK_SEARCHNULL)
164  {
165  if (column->bv_allnulls || column->bv_hasnulls)
166  PG_RETURN_BOOL(true);
167  PG_RETURN_BOOL(false);
168  }
169 
170  /*
171  * For IS NOT NULL, we can only skip ranges that are known to have
172  * only nulls.
173  */
174  if (key->sk_flags & SK_SEARCHNOTNULL)
175  PG_RETURN_BOOL(!column->bv_allnulls);
176 
177  /*
178  * Neither IS NULL nor IS NOT NULL was used; assume all indexable
179  * operators are strict and return false.
180  */
181  PG_RETURN_BOOL(false);
182  }
183 
184  /* if the range is all empty, it cannot possibly be consistent */
185  if (column->bv_allnulls)
186  PG_RETURN_BOOL(false);
187 
188  attno = key->sk_attno;
189  subtype = key->sk_subtype;
190  value = key->sk_argument;
191  switch (key->sk_strategy)
192  {
195  finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
196  key->sk_strategy);
197  matches = FunctionCall2Coll(finfo, colloid, column->bv_values[0],
198  value);
199  break;
201 
202  /*
203  * In the equality case (WHERE col = someval), we want to return
204  * the current page range if the minimum value in the range <=
205  * scan key, and the maximum value >= scan key.
206  */
207  finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
209  matches = FunctionCall2Coll(finfo, colloid, column->bv_values[0],
210  value);
211  if (!DatumGetBool(matches))
212  break;
213  /* max() >= scankey */
214  finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
216  matches = FunctionCall2Coll(finfo, colloid, column->bv_values[1],
217  value);
218  break;
221  finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
222  key->sk_strategy);
223  matches = FunctionCall2Coll(finfo, colloid, column->bv_values[1],
224  value);
225  break;
226  default:
227  /* shouldn't happen */
228  elog(ERROR, "invalid strategy number %d", key->sk_strategy);
229  matches = 0;
230  break;
231  }
232 
233  PG_RETURN_DATUM(matches);
234 }
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
#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
#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:399
#define SK_SEARCHNOTNULL
Definition: skey.h:122
#define SK_ISNULL
Definition: skey.h:115
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
int sk_flags
Definition: skey.h:66
#define Assert(condition)
Definition: c.h:675
static FmgrInfo * minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, uint16 strategynum)
Definition: brin_minmax.c:317
#define elog
Definition: elog.h:219
static struct @121 value
#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
Datum brin_minmax_opcinfo ( PG_FUNCTION_ARGS  )

Definition at line 37 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, result, and SizeofBrinOpcInfo.

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

Definition at line 241 of file brin_minmax.c.

References Assert, tupleDesc::attrs, 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, and PG_RETURN_VOID.

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

Definition at line 317 of file brin_minmax.c.

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

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

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