PostgreSQL Source Code git master
Data Structures | Macros | Typedefs | Functions
brin_internal.h File Reference
#include "access/amapi.h"
#include "storage/bufpage.h"
#include "utils/typcache.h"
Include dependency graph for brin_internal.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct   BrinOpcInfo
 
struct   BrinDesc
 

Macros

#define  SizeofBrinOpcInfo(ncols)    (offsetof(BrinOpcInfo, oi_typcache) + sizeof(TypeCacheEntry *) * ncols)
 
#define  BRIN_PROCNUM_OPCINFO   1
 
#define  BRIN_PROCNUM_ADDVALUE   2
 
#define  BRIN_PROCNUM_CONSISTENT   3
 
#define  BRIN_PROCNUM_UNION   4
 
#define  BRIN_MANDATORY_NPROCS   4
 
#define  BRIN_PROCNUM_OPTIONS   5 /* optional */
 
#define  BRIN_FIRST_OPTIONAL_PROCNUM   11
 
#define  BRIN_LAST_OPTIONAL_PROCNUM   15
 
#define  BRIN_elog(args)   ((void) 0)
 

Typedefs

typedef struct BrinOpcInfo  BrinOpcInfo
 
typedef struct BrinDesc  BrinDesc
 

Functions

 
void  brin_free_desc (BrinDesc *bdesc)
 
 
 
bool  brininsert (Relation idxRel, Datum *values, bool *nulls, ItemPointer heaptid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
 
 
IndexScanDesc  brinbeginscan (Relation r, int nkeys, int norderbys)
 
 
void  brinrescan (IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
 
void  brinendscan (IndexScanDesc scan)
 
 
 
byteabrinoptions (Datum reloptions, bool validate)
 
bool  brinvalidate (Oid opclassoid)
 

Macro Definition Documentation

BRIN_elog

#define BRIN_elog (   args )    ((void) 0)

Definition at line 85 of file brin_internal.h.

BRIN_FIRST_OPTIONAL_PROCNUM

#define BRIN_FIRST_OPTIONAL_PROCNUM   11

Definition at line 77 of file brin_internal.h.

BRIN_LAST_OPTIONAL_PROCNUM

#define BRIN_LAST_OPTIONAL_PROCNUM   15

Definition at line 78 of file brin_internal.h.

BRIN_MANDATORY_NPROCS

#define BRIN_MANDATORY_NPROCS   4

Definition at line 74 of file brin_internal.h.

BRIN_PROCNUM_ADDVALUE

#define BRIN_PROCNUM_ADDVALUE   2

Definition at line 71 of file brin_internal.h.

BRIN_PROCNUM_CONSISTENT

#define BRIN_PROCNUM_CONSISTENT   3

Definition at line 72 of file brin_internal.h.

BRIN_PROCNUM_OPCINFO

#define BRIN_PROCNUM_OPCINFO   1

Definition at line 70 of file brin_internal.h.

BRIN_PROCNUM_OPTIONS

#define BRIN_PROCNUM_OPTIONS   5 /* optional */

Definition at line 75 of file brin_internal.h.

BRIN_PROCNUM_UNION

#define BRIN_PROCNUM_UNION   4

Definition at line 73 of file brin_internal.h.

SizeofBrinOpcInfo

#define SizeofBrinOpcInfo (   ncols )     (offsetof(BrinOpcInfo, oi_typcache) + sizeof(TypeCacheEntry *) * ncols)

Definition at line 41 of file brin_internal.h.

Typedef Documentation

BrinDesc

typedef struct BrinDesc BrinDesc

BrinOpcInfo

typedef struct BrinOpcInfo BrinOpcInfo

Function Documentation

brin_build_desc()

BrinDesc * brin_build_desc ( Relation  rel )

Definition at line 1581 of file brin.c.

1582{
1583 BrinOpcInfo **opcinfo;
1584 BrinDesc *bdesc;
1585 TupleDesc tupdesc;
1586 int totalstored = 0;
1587 int keyno;
1588 long totalsize;
1589 MemoryContext cxt;
1590 MemoryContext oldcxt;
1591
1593 "brin desc cxt",
1595 oldcxt = MemoryContextSwitchTo(cxt);
1596 tupdesc = RelationGetDescr(rel);
1597
1598 /*
1599 * Obtain BrinOpcInfo for each indexed column. While at it, accumulate
1600 * the number of columns stored, since the number is opclass-defined.
1601 */
1602 opcinfo = palloc_array(BrinOpcInfo *, tupdesc->natts);
1603 for (keyno = 0; keyno < tupdesc->natts; keyno++)
1604 {
1605 FmgrInfo *opcInfoFn;
1606 Form_pg_attribute attr = TupleDescAttr(tupdesc, keyno);
1607
1608 opcInfoFn = index_getprocinfo(rel, keyno + 1, BRIN_PROCNUM_OPCINFO);
1609
1610 opcinfo[keyno] = (BrinOpcInfo *)
1611 DatumGetPointer(FunctionCall1(opcInfoFn, ObjectIdGetDatum(attr->atttypid)));
1612 totalstored += opcinfo[keyno]->oi_nstored;
1613 }
1614
1615 /* Allocate our result struct and fill it in */
1616 totalsize = offsetof(BrinDesc, bd_info) +
1617 sizeof(BrinOpcInfo *) * tupdesc->natts;
1618
1619 bdesc = palloc(totalsize);
1620 bdesc->bd_context = cxt;
1621 bdesc->bd_index = rel;
1622 bdesc->bd_tupdesc = tupdesc;
1623 bdesc->bd_disktdesc = NULL; /* generated lazily */
1624 bdesc->bd_totalstored = totalstored;
1625
1626 for (keyno = 0; keyno < tupdesc->natts; keyno++)
1627 bdesc->bd_info[keyno] = opcinfo[keyno];
1628 pfree(opcinfo);
1629
1630 MemoryContextSwitchTo(oldcxt);
1631
1632 return bdesc;
1633}
#define BRIN_PROCNUM_OPCINFO
Definition: brin_internal.h:70
#define palloc_array(type, count)
Definition: fe_memutils.h:76
#define FunctionCall1(flinfo, arg1)
Definition: fmgr.h:700
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:917
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc(Size size)
Definition: mcxt.c:1365
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:170
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
#define RelationGetDescr(relation)
Definition: rel.h:540
int bd_totalstored
Definition: brin_internal.h:59
TupleDesc bd_tupdesc
Definition: brin_internal.h:53
BrinOpcInfo * bd_info[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:62
Relation bd_index
Definition: brin_internal.h:50
MemoryContext bd_context
Definition: brin_internal.h:47
TupleDesc bd_disktdesc
Definition: brin_internal.h:56
uint16 oi_nstored
Definition: brin_internal.h:28
Definition: fmgr.h:57
int natts
Definition: tupdesc.h:137
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, BrinDesc::bd_context, BrinDesc::bd_disktdesc, BrinDesc::bd_index, BrinDesc::bd_info, BrinDesc::bd_totalstored, BrinDesc::bd_tupdesc, BRIN_PROCNUM_OPCINFO, CurrentMemoryContext, DatumGetPointer(), FunctionCall1, index_getprocinfo(), MemoryContextSwitchTo(), TupleDescData::natts, ObjectIdGetDatum(), BrinOpcInfo::oi_nstored, palloc(), palloc_array, pfree(), RelationGetDescr, and TupleDescAttr().

Referenced by brin_page_items(), brinbeginscan(), initialize_brin_buildstate(), and initialize_brin_insertstate().

brin_free_desc()

void brin_free_desc ( BrinDescbdesc )

Definition at line 1636 of file brin.c.

1637{
1638 /* make sure the tupdesc is still valid */
1639 Assert(bdesc->bd_tupdesc->tdrefcount >= 1);
1640 /* no need for retail pfree */
1642}
Assert(PointerIsAligned(start, uint64))
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:469
int tdrefcount
Definition: tupdesc.h:140

References Assert(), BrinDesc::bd_context, BrinDesc::bd_tupdesc, MemoryContextDelete(), and TupleDescData::tdrefcount.

Referenced by brin_page_items(), brinendscan(), and terminate_brin_buildstate().

brinbeginscan()

IndexScanDesc brinbeginscan ( Relation  r,
int  nkeys,
int  norderbys 
)

Definition at line 539 of file brin.c.

540{
541 IndexScanDesc scan;
542 BrinOpaque *opaque;
543
544 scan = RelationGetIndexScan(r, nkeys, norderbys);
545
546 opaque = palloc_object(BrinOpaque);
548 opaque->bo_bdesc = brin_build_desc(r);
549 scan->opaque = opaque;
550
551 return scan;
552}
BrinDesc * brin_build_desc(Relation rel)
Definition: brin.c:1581
BrinRevmap * brinRevmapInitialize(Relation idxrel, BlockNumber *pagesPerRange)
Definition: brin_revmap.c:70
#define palloc_object(type)
Definition: fe_memutils.h:74
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition: genam.c:80
Definition: brin.c:203
BlockNumber bo_pagesPerRange
Definition: brin.c:204
BrinDesc * bo_bdesc
Definition: brin.c:206
BrinRevmap * bo_rmAccess
Definition: brin.c:205
void * opaque
Definition: relscan.h:153

References BrinOpaque::bo_bdesc, BrinOpaque::bo_pagesPerRange, BrinOpaque::bo_rmAccess, brin_build_desc(), brinRevmapInitialize(), IndexScanDescData::opaque, palloc_object, and RelationGetIndexScan().

Referenced by brinhandler().

brinbuild()

IndexBuildResult * brinbuild ( Relation  heap,
Relation  index,
IndexInfoindexInfo 
)

Definition at line 1105 of file brin.c.

1106{
1107 IndexBuildResult *result;
1108 double reltuples;
1109 double idxtuples;
1110 BrinRevmap *revmap;
1112 Buffer meta;
1113 BlockNumber pagesPerRange;
1114
1115 /*
1116 * We expect to be called exactly once for any index relation.
1117 */
1119 elog(ERROR, "index \"%s\" already contains data",
1121
1122 /*
1123 * Critical section not required, because on error the creation of the
1124 * whole relation will be rolled back.
1125 */
1126
1130
1133 MarkBufferDirty(meta);
1134
1136 {
1137 xl_brin_createidx xlrec;
1138 XLogRecPtr recptr;
1139 Page page;
1140
1143
1147
1148 recptr = XLogInsert(RM_BRIN_ID, XLOG_BRIN_CREATE_INDEX);
1149
1150 page = BufferGetPage(meta);
1151 PageSetLSN(page, recptr);
1152 }
1153
1154 UnlockReleaseBuffer(meta);
1155
1156 /*
1157 * Initialize our state, including the deformed tuple state.
1158 */
1159 revmap = brinRevmapInitialize(index, &pagesPerRange);
1160 state = initialize_brin_buildstate(index, revmap, pagesPerRange,
1162
1163 /*
1164 * Attempt to launch parallel worker scan when required
1165 *
1166 * XXX plan_create_index_workers makes the number of workers dependent on
1167 * maintenance_work_mem, requiring 32MB for each worker. That makes sense
1168 * for btree, but not for BRIN, which can do with much less memory. So
1169 * maybe make that somehow less strict, optionally?
1170 */
1171 if (indexInfo->ii_ParallelWorkers > 0)
1172 _brin_begin_parallel(state, heap, index, indexInfo->ii_Concurrent,
1173 indexInfo->ii_ParallelWorkers);
1174
1175 /*
1176 * If parallel build requested and at least one worker process was
1177 * successfully launched, set up coordination state, wait for workers to
1178 * complete. Then read all tuples from the shared tuplesort and insert
1179 * them into the index.
1180 *
1181 * In serial mode, simply scan the table and build the index one index
1182 * tuple at a time.
1183 */
1184 if (state->bs_leader)
1185 {
1186 SortCoordinate coordinate;
1187
1188 coordinate = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
1189 coordinate->isWorker = false;
1190 coordinate->nParticipants =
1191 state->bs_leader->nparticipanttuplesorts;
1192 coordinate->sharedsort = state->bs_leader->sharedsort;
1193
1194 /*
1195 * Begin leader tuplesort.
1196 *
1197 * In cases where parallelism is involved, the leader receives the
1198 * same share of maintenance_work_mem as a serial sort (it is
1199 * generally treated in the same way as a serial sort once we return).
1200 * Parallel worker Tuplesortstates will have received only a fraction
1201 * of maintenance_work_mem, though.
1202 *
1203 * We rely on the lifetime of the Leader Tuplesortstate almost not
1204 * overlapping with any worker Tuplesortstate's lifetime. There may
1205 * be some small overlap, but that's okay because we rely on leader
1206 * Tuplesortstate only allocating a small, fixed amount of memory
1207 * here. When its tuplesort_performsort() is called (by our caller),
1208 * and significant amounts of memory are likely to be used, all
1209 * workers must have already freed almost all memory held by their
1210 * Tuplesortstates (they are about to go away completely, too). The
1211 * overall effect is that maintenance_work_mem always represents an
1212 * absolute high watermark on the amount of memory used by a CREATE
1213 * INDEX operation, regardless of the use of parallelism or any other
1214 * factor.
1215 */
1216 state->bs_sortstate =
1219
1220 /* scan the relation and merge per-worker results */
1221 reltuples = _brin_parallel_merge(state);
1222
1223 _brin_end_parallel(state->bs_leader, state);
1224 }
1225 else /* no parallel index build */
1226 {
1227 /*
1228 * Now scan the relation. No syncscan allowed here because we want
1229 * the heap blocks in physical order (we want to produce the ranges
1230 * starting from block 0, and the callback also relies on this to not
1231 * generate summary for the same range twice).
1232 */
1233 reltuples = table_index_build_scan(heap, index, indexInfo, false, true,
1234 brinbuildCallback, state, NULL);
1235
1236 /*
1237 * process the final batch
1238 *
1239 * XXX Note this does not update state->bs_currRangeStart, i.e. it
1240 * stays set to the last range added to the index. This is OK, because
1241 * that's what brin_fill_empty_ranges expects.
1242 */
1244
1245 /*
1246 * Backfill the final ranges with empty data.
1247 *
1248 * This saves us from doing what amounts to full table scans when the
1249 * index with a predicate like WHERE (nonnull_column IS NULL), or
1250 * other very selective predicates.
1251 */
1253 state->bs_currRangeStart,
1254 state->bs_maxRangeStart);
1255 }
1256
1257 /* release resources */
1258 idxtuples = state->bs_numtuples;
1259 brinRevmapTerminate(state->bs_rmAccess);
1261
1262 /*
1263 * Return statistics
1264 */
1266
1267 result->heap_tuples = reltuples;
1268 result->index_tuples = idxtuples;
1269
1270 return result;
1271}
uint32 BlockNumber
Definition: block.h:31
static double _brin_parallel_merge(BrinBuildState *state)
Definition: brin.c:2620
static void terminate_brin_buildstate(BrinBuildState *state)
Definition: brin.c:1716
static void form_and_insert_tuple(BrinBuildState *state)
Definition: brin.c:1985
static BrinBuildState * initialize_brin_buildstate(Relation idxRel, BrinRevmap *revmap, BlockNumber pagesPerRange, BlockNumber tablePages)
Definition: brin.c:1669
static void _brin_begin_parallel(BrinBuildState *buildstate, Relation heap, Relation index, bool isconcurrent, int request)
Definition: brin.c:2363
static void _brin_end_parallel(BrinLeader *brinleader, BrinBuildState *state)
Definition: brin.c:2548
static void brin_fill_empty_ranges(BrinBuildState *state, BlockNumber prevRange, BlockNumber nextRange)
Definition: brin.c:2993
static void brinbuildCallback(Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *brstate)
Definition: brin.c:995
#define BrinGetPagesPerRange(relation)
Definition: brin.h:40
#define BRIN_CURRENT_VERSION
Definition: brin_page.h:72
#define BRIN_METAPAGE_BLKNO
Definition: brin_page.h:75
void brin_metapage_init(Page page, BlockNumber pagesPerRange, uint16 version)
Definition: brin_pageops.c:486
void brinRevmapTerminate(BrinRevmap *revmap)
Definition: brin_revmap.c:100
#define SizeOfBrinCreateIdx
Definition: brin_xlog.h:55
#define XLOG_BRIN_CREATE_INDEX
Definition: brin_xlog.h:31
int Buffer
Definition: buf.h:23
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:4198
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
Definition: bufmgr.c:858
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5355
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2921
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:283
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:417
@ EB_SKIP_EXTENSION_LOCK
Definition: bufmgr.h:75
@ EB_LOCK_FIRST
Definition: bufmgr.h:87
#define BMR_REL(p_rel)
Definition: bufmgr.h:111
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:391
PageData * Page
Definition: bufpage.h:82
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
int maintenance_work_mem
Definition: globals.c:133
void * palloc0(Size size)
Definition: mcxt.c:1395
#define RelationGetRelationName(relation)
Definition: rel.h:548
#define RelationNeedsWAL(relation)
Definition: rel.h:637
@ MAIN_FORKNUM
Definition: relpath.h:58
double heap_tuples
Definition: genam.h:59
double index_tuples
Definition: genam.h:60
int ii_ParallelWorkers
Definition: execnodes.h:218
bool ii_Concurrent
Definition: execnodes.h:210
Sharedsort * sharedsort
Definition: tuplesort.h:59
Definition: type.h:96
Definition: regguts.h:323
uint16 version
Definition: brin_xlog.h:53
BlockNumber pagesPerRange
Definition: brin_xlog.h:52
static double table_index_build_scan(Relation table_rel, Relation index_rel, IndexInfo *index_info, bool allow_sync, bool progress, IndexBuildCallback callback, void *callback_state, TableScanDesc scan)
Definition: tableam.h:1744
struct SortCoordinateData * SortCoordinate
Definition: tuplesort.h:62
#define TUPLESORT_NONE
Definition: tuplesort.h:94
Tuplesortstate * tuplesort_begin_index_brin(int workMem, SortCoordinate coordinate, int sortopt)
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterData(const void *data, uint32 len)
Definition: xloginsert.c:364
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:242
void XLogBeginInsert(void)
Definition: xloginsert.c:149
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define REGBUF_WILL_INIT
Definition: xloginsert.h:34

References _brin_begin_parallel(), _brin_end_parallel(), _brin_parallel_merge(), Assert(), BMR_REL, BRIN_CURRENT_VERSION, brin_fill_empty_ranges(), BRIN_METAPAGE_BLKNO, brin_metapage_init(), brinbuildCallback(), BrinGetPagesPerRange, brinRevmapInitialize(), brinRevmapTerminate(), BufferGetBlockNumber(), BufferGetPage(), EB_LOCK_FIRST, EB_SKIP_EXTENSION_LOCK, elog, ERROR, ExtendBufferedRel(), form_and_insert_tuple(), IndexBuildResult::heap_tuples, IndexInfo::ii_Concurrent, IndexInfo::ii_ParallelWorkers, IndexBuildResult::index_tuples, initialize_brin_buildstate(), SortCoordinateData::isWorker, MAIN_FORKNUM, maintenance_work_mem, MarkBufferDirty(), SortCoordinateData::nParticipants, PageSetLSN(), xl_brin_createidx::pagesPerRange, palloc0(), palloc_object, REGBUF_STANDARD, REGBUF_WILL_INIT, RelationGetNumberOfBlocks, RelationGetRelationName, RelationNeedsWAL, SortCoordinateData::sharedsort, SizeOfBrinCreateIdx, table_index_build_scan(), terminate_brin_buildstate(), tuplesort_begin_index_brin(), TUPLESORT_NONE, UnlockReleaseBuffer(), xl_brin_createidx::version, XLOG_BRIN_CREATE_INDEX, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by brinhandler().

brinbuildempty()

void brinbuildempty ( Relation  index )

Definition at line 1274 of file brin.c.

1275{
1276 Buffer metabuf;
1277
1278 /* An empty BRIN index has a metapage only. */
1279 metabuf = ExtendBufferedRel(BMR_REL(index), INIT_FORKNUM, NULL,
1281
1282 /* Initialize and xlog metabuffer. */
1286 MarkBufferDirty(metabuf);
1287 log_newpage_buffer(metabuf, true);
1289
1290 UnlockReleaseBuffer(metabuf);
1291}
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
@ INIT_FORKNUM
Definition: relpath.h:61
XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std)
Definition: xloginsert.c:1249

References BMR_REL, BRIN_CURRENT_VERSION, brin_metapage_init(), BrinGetPagesPerRange, BufferGetPage(), EB_LOCK_FIRST, EB_SKIP_EXTENSION_LOCK, END_CRIT_SECTION, ExtendBufferedRel(), INIT_FORKNUM, log_newpage_buffer(), MarkBufferDirty(), START_CRIT_SECTION, and UnlockReleaseBuffer().

Referenced by brinhandler().

brinbulkdelete()

IndexBulkDeleteResult * brinbulkdelete ( IndexVacuumInfoinfo,
void *  callback_state 
)

Definition at line 1303 of file brin.c.

1305{
1306 /* allocate stats if first time through, else re-use existing struct */
1307 if (stats == NULL)
1309
1310 return stats;
1311}
#define palloc0_object(type)
Definition: fe_memutils.h:75

References palloc0_object.

Referenced by brinhandler().

brinendscan()

void brinendscan ( IndexScanDesc  scan )

Definition at line 978 of file brin.c.

979{
980 BrinOpaque *opaque = (BrinOpaque *) scan->opaque;
981
983 brin_free_desc(opaque->bo_bdesc);
984 pfree(opaque);
985}
void brin_free_desc(BrinDesc *bdesc)
Definition: brin.c:1636

References BrinOpaque::bo_bdesc, BrinOpaque::bo_rmAccess, brin_free_desc(), brinRevmapTerminate(), IndexScanDescData::opaque, and pfree().

Referenced by brinhandler().

bringetbitmap()

int64 bringetbitmap ( IndexScanDesc  scan,
TIDBitmaptbm 
)

Definition at line 567 of file brin.c.

568{
569 Relation idxRel = scan->indexRelation;
571 BrinDesc *bdesc;
572 Oid heapOid;
573 Relation heapRel;
574 BrinOpaque *opaque;
575 BlockNumber nblocks;
576 BlockNumber heapBlk;
577 int64 totalpages = 0;
578 FmgrInfo *consistentFn;
579 MemoryContext oldcxt;
580 MemoryContext perRangeCxt;
581 BrinMemTuple *dtup;
582 BrinTuple *btup = NULL;
583 Size btupsz = 0;
584 ScanKey **keys,
585 **nullkeys;
586 int *nkeys,
587 *nnullkeys;
588 char *ptr;
589 Size len;
590 char *tmp PG_USED_FOR_ASSERTS_ONLY;
591
592 opaque = (BrinOpaque *) scan->opaque;
593 bdesc = opaque->bo_bdesc;
595 if (scan->instrument)
596 scan->instrument->nsearches++;
597
598 /*
599 * We need to know the size of the table so that we know how long to
600 * iterate on the revmap.
601 */
602 heapOid = IndexGetRelation(RelationGetRelid(idxRel), false);
603 heapRel = table_open(heapOid, AccessShareLock);
604 nblocks = RelationGetNumberOfBlocks(heapRel);
606
607 /*
608 * Make room for the consistent support procedures of indexed columns. We
609 * don't look them up here; we do that lazily the first time we see a scan
610 * key reference each of them. We rely on zeroing fn_oid to InvalidOid.
611 */
612 consistentFn = palloc0_array(FmgrInfo, bdesc->bd_tupdesc->natts);
613
614 /*
615 * Make room for per-attribute lists of scan keys that we'll pass to the
616 * consistent support procedure. We don't know which attributes have scan
617 * keys, so we allocate space for all attributes. That may use more memory
618 * but it's probably cheaper than determining which attributes are used.
619 *
620 * We keep null and regular keys separate, so that we can pass just the
621 * regular keys to the consistent function easily.
622 *
623 * To reduce the allocation overhead, we allocate one big chunk and then
624 * carve it into smaller arrays ourselves. All the pieces have exactly the
625 * same lifetime, so that's OK.
626 *
627 * XXX The widest index can have 32 attributes, so the amount of wasted
628 * memory is negligible. We could invent a more compact approach (with
629 * just space for used attributes) but that would make the matching more
630 * complex so it's not a good trade-off.
631 */
632 len =
633 MAXALIGN(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts) + /* regular keys */
634 MAXALIGN(sizeof(ScanKey) * scan->numberOfKeys) * bdesc->bd_tupdesc->natts +
635 MAXALIGN(sizeof(int) * bdesc->bd_tupdesc->natts) +
636 MAXALIGN(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts) + /* NULL keys */
637 MAXALIGN(sizeof(ScanKey) * scan->numberOfKeys) * bdesc->bd_tupdesc->natts +
638 MAXALIGN(sizeof(int) * bdesc->bd_tupdesc->natts);
639
640 ptr = palloc(len);
641 tmp = ptr;
642
643 keys = (ScanKey **) ptr;
644 ptr += MAXALIGN(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
645
646 nullkeys = (ScanKey **) ptr;
647 ptr += MAXALIGN(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
648
649 nkeys = (int *) ptr;
650 ptr += MAXALIGN(sizeof(int) * bdesc->bd_tupdesc->natts);
651
652 nnullkeys = (int *) ptr;
653 ptr += MAXALIGN(sizeof(int) * bdesc->bd_tupdesc->natts);
654
655 for (int i = 0; i < bdesc->bd_tupdesc->natts; i++)
656 {
657 keys[i] = (ScanKey *) ptr;
658 ptr += MAXALIGN(sizeof(ScanKey) * scan->numberOfKeys);
659
660 nullkeys[i] = (ScanKey *) ptr;
661 ptr += MAXALIGN(sizeof(ScanKey) * scan->numberOfKeys);
662 }
663
664 Assert(tmp + len == ptr);
665
666 /* zero the number of keys */
667 memset(nkeys, 0, sizeof(int) * bdesc->bd_tupdesc->natts);
668 memset(nnullkeys, 0, sizeof(int) * bdesc->bd_tupdesc->natts);
669
670 /* Preprocess the scan keys - split them into per-attribute arrays. */
671 for (int keyno = 0; keyno < scan->numberOfKeys; keyno++)
672 {
673 ScanKey key = &scan->keyData[keyno];
674 AttrNumber keyattno = key->sk_attno;
675
676 /*
677 * The collation of the scan key must match the collation used in the
678 * index column (but only if the search is not IS NULL/ IS NOT NULL).
679 * Otherwise we shouldn't be using this index ...
680 */
681 Assert((key->sk_flags & SK_ISNULL) ||
682 (key->sk_collation ==
684 keyattno - 1)->attcollation));
685
686 /*
687 * First time we see this index attribute, so init as needed.
688 *
689 * This is a bit of an overkill - we don't know how many scan keys are
690 * there for this attribute, so we simply allocate the largest number
691 * possible (as if all keys were for this attribute). This may waste a
692 * bit of memory, but we only expect small number of scan keys in
693 * general, so this should be negligible, and repeated repalloc calls
694 * are not free either.
695 */
696 if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
697 {
698 FmgrInfo *tmp;
699
700 /* First time we see this attribute, so no key/null keys. */
701 Assert(nkeys[keyattno - 1] == 0);
702 Assert(nnullkeys[keyattno - 1] == 0);
703
704 tmp = index_getprocinfo(idxRel, keyattno,
706 fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
708 }
709
710 /* Add key to the proper per-attribute array. */
711 if (key->sk_flags & SK_ISNULL)
712 {
713 nullkeys[keyattno - 1][nnullkeys[keyattno - 1]] = key;
714 nnullkeys[keyattno - 1]++;
715 }
716 else
717 {
718 keys[keyattno - 1][nkeys[keyattno - 1]] = key;
719 nkeys[keyattno - 1]++;
720 }
721 }
722
723 /* allocate an initial in-memory tuple, out of the per-range memcxt */
724 dtup = brin_new_memtuple(bdesc);
725
726 /*
727 * Setup and use a per-range memory context, which is reset every time we
728 * loop below. This avoids having to free the tuples within the loop.
729 */
731 "bringetbitmap cxt",
733 oldcxt = MemoryContextSwitchTo(perRangeCxt);
734
735 /*
736 * Now scan the revmap. We start by querying for heap page 0,
737 * incrementing by the number of pages per range; this gives us a full
738 * view of the table.
739 */
740 for (heapBlk = 0; heapBlk < nblocks; heapBlk += opaque->bo_pagesPerRange)
741 {
742 bool addrange;
743 bool gottuple = false;
744 BrinTuple *tup;
745 OffsetNumber off;
746 Size size;
747
749
750 MemoryContextReset(perRangeCxt);
751
752 tup = brinGetTupleForHeapBlock(opaque->bo_rmAccess, heapBlk, &buf,
753 &off, &size, BUFFER_LOCK_SHARE);
754 if (tup)
755 {
756 gottuple = true;
757 btup = brin_copy_tuple(tup, size, btup, &btupsz);
759 }
760
761 /*
762 * For page ranges with no indexed tuple, we must return the whole
763 * range; otherwise, compare it to the scan keys.
764 */
765 if (!gottuple)
766 {
767 addrange = true;
768 }
769 else
770 {
771 dtup = brin_deform_tuple(bdesc, btup, dtup);
772 if (dtup->bt_placeholder)
773 {
774 /*
775 * Placeholder tuples are always returned, regardless of the
776 * values stored in them.
777 */
778 addrange = true;
779 }
780 else
781 {
782 int attno;
783
784 /*
785 * Compare scan keys with summary values stored for the range.
786 * If scan keys are matched, the page range must be added to
787 * the bitmap. We initially assume the range needs to be
788 * added; in particular this serves the case where there are
789 * no keys.
790 */
791 addrange = true;
792 for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
793 {
794 BrinValues *bval;
795 Datum add;
796 Oid collation;
797
798 /*
799 * skip attributes without any scan keys (both regular and
800 * IS [NOT] NULL)
801 */
802 if (nkeys[attno - 1] == 0 && nnullkeys[attno - 1] == 0)
803 continue;
804
805 bval = &dtup->bt_columns[attno - 1];
806
807 /*
808 * If the BRIN tuple indicates that this range is empty,
809 * we can skip it: there's nothing to match. We don't
810 * need to examine the next columns.
811 */
812 if (dtup->bt_empty_range)
813 {
814 addrange = false;
815 break;
816 }
817
818 /*
819 * First check if there are any IS [NOT] NULL scan keys,
820 * and if we're violating them. In that case we can
821 * terminate early, without invoking the support function.
822 *
823 * As there may be more keys, we can only determine
824 * mismatch within this loop.
825 */
826 if (bdesc->bd_info[attno - 1]->oi_regular_nulls &&
827 !check_null_keys(bval, nullkeys[attno - 1],
828 nnullkeys[attno - 1]))
829 {
830 /*
831 * If any of the IS [NOT] NULL keys failed, the page
832 * range as a whole can't pass. So terminate the loop.
833 */
834 addrange = false;
835 break;
836 }
837
838 /*
839 * So either there are no IS [NOT] NULL keys, or all
840 * passed. If there are no regular scan keys, we're done -
841 * the page range matches. If there are regular keys, but
842 * the page range is marked as 'all nulls' it can't
843 * possibly pass (we're assuming the operators are
844 * strict).
845 */
846
847 /* No regular scan keys - page range as a whole passes. */
848 if (!nkeys[attno - 1])
849 continue;
850
851 Assert((nkeys[attno - 1] > 0) &&
852 (nkeys[attno - 1] <= scan->numberOfKeys));
853
854 /* If it is all nulls, it cannot possibly be consistent. */
855 if (bval->bv_allnulls)
856 {
857 addrange = false;
858 break;
859 }
860
861 /*
862 * Collation from the first key (has to be the same for
863 * all keys for the same attribute).
864 */
865 collation = keys[attno - 1][0]->sk_collation;
866
867 /*
868 * Check whether the scan key is consistent with the page
869 * range values; if so, have the pages in the range added
870 * to the output bitmap.
871 *
872 * The opclass may or may not support processing of
873 * multiple scan keys. We can determine that based on the
874 * number of arguments - functions with extra parameter
875 * (number of scan keys) do support this, otherwise we
876 * have to simply pass the scan keys one by one.
877 */
878 if (consistentFn[attno - 1].fn_nargs >= 4)
879 {
880 /* Check all keys at once */
881 add = FunctionCall4Coll(&consistentFn[attno - 1],
882 collation,
883 PointerGetDatum(bdesc),
884 PointerGetDatum(bval),
885 PointerGetDatum(keys[attno - 1]),
886 Int32GetDatum(nkeys[attno - 1]));
887 addrange = DatumGetBool(add);
888 }
889 else
890 {
891 /*
892 * Check keys one by one
893 *
894 * When there are multiple scan keys, failure to meet
895 * the criteria for a single one of them is enough to
896 * discard the range as a whole, so break out of the
897 * loop as soon as a false return value is obtained.
898 */
899 int keyno;
900
901 for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
902 {
903 add = FunctionCall3Coll(&consistentFn[attno - 1],
904 keys[attno - 1][keyno]->sk_collation,
905 PointerGetDatum(bdesc),
906 PointerGetDatum(bval),
907 PointerGetDatum(keys[attno - 1][keyno]));
908 addrange = DatumGetBool(add);
909 if (!addrange)
910 break;
911 }
912 }
913
914 /*
915 * If we found a scan key eliminating the range, no need
916 * to check additional ones.
917 */
918 if (!addrange)
919 break;
920 }
921 }
922 }
923
924 /* add the pages in the range to the output bitmap, if needed */
925 if (addrange)
926 {
927 BlockNumber pageno;
928
929 for (pageno = heapBlk;
930 pageno <= Min(nblocks, heapBlk + opaque->bo_pagesPerRange) - 1;
931 pageno++)
932 {
933 MemoryContextSwitchTo(oldcxt);
934 tbm_add_page(tbm, pageno);
935 totalpages++;
936 MemoryContextSwitchTo(perRangeCxt);
937 }
938 }
939 }
940
941 MemoryContextSwitchTo(oldcxt);
942 MemoryContextDelete(perRangeCxt);
943
944 if (buf != InvalidBuffer)
946
947 /*
948 * XXX We have an approximation of the number of *pages* that our scan
949 * returns, but we don't have a precise idea of the number of heap tuples
950 * involved.
951 */
952 return totalpages * 10;
953}
int16 AttrNumber
Definition: attnum.h:21
static bool check_null_keys(BrinValues *bval, ScanKey *nullkeys, int nnullkeys)
Definition: brin.c:2299
#define BRIN_PROCNUM_CONSISTENT
Definition: brin_internal.h:72
BrinTuple * brinGetTupleForHeapBlock(BrinRevmap *revmap, BlockNumber heapBlk, Buffer *buf, OffsetNumber *off, Size *size, int mode)
Definition: brin_revmap.c:194
BrinTuple * brin_copy_tuple(BrinTuple *tuple, Size len, BrinTuple *dest, Size *destsz)
Definition: brin_tuple.c:446
BrinMemTuple * brin_new_memtuple(BrinDesc *brdesc)
Definition: brin_tuple.c:482
BrinMemTuple * brin_deform_tuple(BrinDesc *brdesc, BrinTuple *tuple, BrinMemTuple *dMemtuple)
Definition: brin_tuple.c:553
#define InvalidBuffer
Definition: buf.h:25
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5338
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5572
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:196
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:197
#define Min(x, y)
Definition: c.h:1003
#define MAXALIGN(LEN)
Definition: c.h:810
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:223
int64_t int64
Definition: c.h:535
size_t Size
Definition: c.h:610
#define palloc0_array(type, count)
Definition: fe_memutils.h:77
Datum FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4)
Definition: fmgr.c:1196
Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition: fmgr.c:1171
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition: fmgr.c:580
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3583
i
int i
Definition: isn.c:77
#define AccessShareLock
Definition: lockdefs.h:36
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:400
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
uint16 OffsetNumber
Definition: off.h:24
const void size_t len
static char * buf
Definition: pg_test_fsync.c:72
#define pgstat_count_index_scan(rel)
Definition: pgstat.h:695
static bool DatumGetBool(Datum X)
Definition: postgres.h:100
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
uint64_t Datum
Definition: postgres.h:70
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:222
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
static void addrange(struct cvec *cv, chr from, chr to)
Definition: regc_cvec.c:90
#define RelationGetRelid(relation)
Definition: rel.h:514
#define SK_ISNULL
Definition: skey.h:115
BrinValues bt_columns[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_tuple.h:55
bool bt_placeholder
Definition: brin_tuple.h:46
bool bt_empty_range
Definition: brin_tuple.h:47
bool oi_regular_nulls
Definition: brin_internal.h:31
bool bv_allnulls
Definition: brin_tuple.h:33
struct ScanKeyData * keyData
Definition: relscan.h:141
int numberOfKeys
Definition: relscan.h:139
struct IndexScanInstrumentation * instrument
Definition: relscan.h:159
Relation indexRelation
Definition: relscan.h:137
uint64 nsearches
Definition: genam.h:42
Definition: rel.h:56
Definition: skey.h:65
Oid sk_collation
Definition: skey.h:70
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
void tbm_add_page(TIDBitmap *tbm, BlockNumber pageno)
Definition: tidbitmap.c:433

References AccessShareLock, addrange(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), BrinDesc::bd_info, BrinDesc::bd_tupdesc, BrinOpaque::bo_bdesc, BrinOpaque::bo_pagesPerRange, BrinOpaque::bo_rmAccess, brin_copy_tuple(), brin_deform_tuple(), brin_new_memtuple(), BRIN_PROCNUM_CONSISTENT, brinGetTupleForHeapBlock(), BrinMemTuple::bt_columns, BrinMemTuple::bt_empty_range, BrinMemTuple::bt_placeholder, buf, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BrinValues::bv_allnulls, CHECK_FOR_INTERRUPTS, check_null_keys(), CurrentMemoryContext, DatumGetBool(), fmgr_info_copy(), FunctionCall3Coll(), FunctionCall4Coll(), i, index_getprocinfo(), IndexGetRelation(), IndexScanDescData::indexRelation, IndexScanDescData::instrument, Int32GetDatum(), InvalidBuffer, InvalidOid, sort-test::key, IndexScanDescData::keyData, len, LockBuffer(), MAXALIGN, MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), Min, TupleDescData::natts, IndexScanInstrumentation::nsearches, IndexScanDescData::numberOfKeys, BrinOpcInfo::oi_regular_nulls, IndexScanDescData::opaque, palloc(), palloc0_array, PG_USED_FOR_ASSERTS_ONLY, pgstat_count_index_scan, PointerGetDatum(), RelationGetNumberOfBlocks, RelationGetRelid, ReleaseBuffer(), ScanKeyData::sk_collation, SK_ISNULL, table_close(), table_open(), tbm_add_page(), and TupleDescAttr().

Referenced by brinhandler().

brininsert()

bool brininsert ( Relation  idxRel,
Datumvalues,
bool *  nulls,
ItemPointer  heaptid,
Relation  heapRel,
IndexUniqueCheck  checkUnique,
bool  indexUnchanged,
IndexInfoindexInfo 
)

Definition at line 344 of file brin.c.

349{
350 BlockNumber pagesPerRange;
351 BlockNumber origHeapBlk;
352 BlockNumber heapBlk;
353 BrinInsertState *bistate = (BrinInsertState *) indexInfo->ii_AmCache;
354 BrinRevmap *revmap;
355 BrinDesc *bdesc;
357 MemoryContext tupcxt = NULL;
359 bool autosummarize = BrinGetAutoSummarize(idxRel);
360
361 /*
362 * If first time through in this statement, initialize the insert state
363 * that we keep for all the inserts in the command.
364 */
365 if (!bistate)
366 bistate = initialize_brin_insertstate(idxRel, indexInfo);
367
368 revmap = bistate->bis_rmAccess;
369 bdesc = bistate->bis_desc;
370 pagesPerRange = bistate->bis_pages_per_range;
371
372 /*
373 * origHeapBlk is the block number where the insertion occurred. heapBlk
374 * is the first block in the corresponding page range.
375 */
376 origHeapBlk = ItemPointerGetBlockNumber(heaptid);
377 heapBlk = (origHeapBlk / pagesPerRange) * pagesPerRange;
378
379 for (;;)
380 {
381 bool need_insert = false;
382 OffsetNumber off;
383 BrinTuple *brtup;
384 BrinMemTuple *dtup;
385
387
388 /*
389 * If auto-summarization is enabled and we just inserted the first
390 * tuple into the first block of a new non-first page range, request a
391 * summarization run of the previous range.
392 */
393 if (autosummarize &&
394 heapBlk > 0 &&
395 heapBlk == origHeapBlk &&
397 {
398 BlockNumber lastPageRange = heapBlk - 1;
399 BrinTuple *lastPageTuple;
400
401 lastPageTuple =
402 brinGetTupleForHeapBlock(revmap, lastPageRange, &buf, &off,
403 NULL, BUFFER_LOCK_SHARE);
404 if (!lastPageTuple)
405 {
406 bool recorded;
407
409 RelationGetRelid(idxRel),
410 lastPageRange);
411 if (!recorded)
412 ereport(LOG,
413 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
414 errmsg("request for BRIN range summarization for index \"%s\" page %u was not recorded",
416 lastPageRange)));
417 }
418 else
420 }
421
422 brtup = brinGetTupleForHeapBlock(revmap, heapBlk, &buf, &off,
423 NULL, BUFFER_LOCK_SHARE);
424
425 /* if range is unsummarized, there's nothing to do */
426 if (!brtup)
427 break;
428
429 /* First time through in this brininsert call? */
430 if (tupcxt == NULL)
431 {
433 "brininsert cxt",
435 MemoryContextSwitchTo(tupcxt);
436 }
437
438 dtup = brin_deform_tuple(bdesc, brtup, NULL);
439
440 need_insert = add_values_to_range(idxRel, bdesc, dtup, values, nulls);
441
442 if (!need_insert)
443 {
444 /*
445 * The tuple is consistent with the new values, so there's nothing
446 * to do.
447 */
449 }
450 else
451 {
452 Page page = BufferGetPage(buf);
453 ItemId lp = PageGetItemId(page, off);
454 Size origsz;
455 BrinTuple *origtup;
456 Size newsz;
457 BrinTuple *newtup;
458 bool samepage;
459
460 /*
461 * Make a copy of the old tuple, so that we can compare it after
462 * re-acquiring the lock.
463 */
464 origsz = ItemIdGetLength(lp);
465 origtup = brin_copy_tuple(brtup, origsz, NULL, NULL);
466
467 /*
468 * Before releasing the lock, check if we can attempt a same-page
469 * update. Another process could insert a tuple concurrently in
470 * the same page though, so downstream we must be prepared to cope
471 * if this turns out to not be possible after all.
472 */
473 newtup = brin_form_tuple(bdesc, heapBlk, dtup, &newsz);
474 samepage = brin_can_do_samepage_update(buf, origsz, newsz);
476
477 /*
478 * Try to update the tuple. If this doesn't work for whatever
479 * reason, we need to restart from the top; the revmap might be
480 * pointing at a different tuple for this block now, so we need to
481 * recompute to ensure both our new heap tuple and the other
482 * inserter's are covered by the combined tuple. It might be that
483 * we don't need to update at all.
484 */
485 if (!brin_doupdate(idxRel, pagesPerRange, revmap, heapBlk,
486 buf, off, origtup, origsz, newtup, newsz,
487 samepage))
488 {
489 /* no luck; start over */
490 MemoryContextReset(tupcxt);
491 continue;
492 }
493 }
494
495 /* success! */
496 break;
497 }
498
499 if (BufferIsValid(buf))
501 MemoryContextSwitchTo(oldcxt);
502 if (tupcxt != NULL)
503 MemoryContextDelete(tupcxt);
504
505 return false;
506}
bool AutoVacuumRequestWork(AutoVacuumWorkItemType type, Oid relationId, BlockNumber blkno)
Definition: autovacuum.c:3320
@ AVW_BRINSummarizeRange
Definition: autovacuum.h:25
static Datum values[MAXATTR]
Definition: bootstrap.c:153
static bool add_values_to_range(Relation idxRel, BrinDesc *bdesc, BrinMemTuple *dtup, const Datum *values, const bool *nulls)
Definition: brin.c:2205
static BrinInsertState * initialize_brin_insertstate(Relation idxRel, IndexInfo *indexInfo)
Definition: brin.c:315
#define BrinGetAutoSummarize(relation)
Definition: brin.h:46
bool brin_doupdate(Relation idxrel, BlockNumber pagesPerRange, BrinRevmap *revmap, BlockNumber heapBlk, Buffer oldbuf, OffsetNumber oldoff, const BrinTuple *origtup, Size origsz, const BrinTuple *newtup, Size newsz, bool samepage)
Definition: brin_pageops.c:53
bool brin_can_do_samepage_update(Buffer buffer, Size origsz, Size newsz)
Definition: brin_pageops.c:323
BrinTuple * brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno, BrinMemTuple *tuple, Size *size)
Definition: brin_tuple.c:99
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:368
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:244
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define LOG
Definition: elog.h:31
#define ereport(elevel,...)
Definition: elog.h:150
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition: itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
#define FirstOffsetNumber
Definition: off.h:27
BrinDesc * bis_desc
Definition: brin.c:195
BrinRevmap * bis_rmAccess
Definition: brin.c:194
BlockNumber bis_pages_per_range
Definition: brin.c:196
void * ii_AmCache
Definition: execnodes.h:223
Definition: itemid.h:26

References add_values_to_range(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, AutoVacuumRequestWork(), AVW_BRINSummarizeRange, BrinInsertState::bis_desc, BrinInsertState::bis_pages_per_range, BrinInsertState::bis_rmAccess, brin_can_do_samepage_update(), brin_copy_tuple(), brin_deform_tuple(), brin_doupdate(), brin_form_tuple(), BrinGetAutoSummarize, brinGetTupleForHeapBlock(), buf, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage(), BufferIsValid(), CHECK_FOR_INTERRUPTS, CurrentMemoryContext, ereport, errcode(), errmsg(), FirstOffsetNumber, IndexInfo::ii_AmCache, initialize_brin_insertstate(), InvalidBuffer, ItemIdGetLength, ItemPointerGetBlockNumber(), ItemPointerGetOffsetNumber(), LockBuffer(), LOG, MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), PageGetItemId(), RelationGetRelationName, RelationGetRelid, ReleaseBuffer(), and values.

Referenced by brinhandler().

brininsertcleanup()

void brininsertcleanup ( Relation  index,
IndexInfoindexInfo 
)

Definition at line 512 of file brin.c.

513{
514 BrinInsertState *bistate = (BrinInsertState *) indexInfo->ii_AmCache;
515
516 /* bail out if cache not initialized */
517 if (bistate == NULL)
518 return;
519
520 /* do this first to avoid dangling pointer if we fail partway through */
521 indexInfo->ii_AmCache = NULL;
522
523 /*
524 * Clean up the revmap. Note that the brinDesc has already been cleaned up
525 * as part of its own memory context.
526 */
528 pfree(bistate);
529}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81

References BrinInsertState::bis_rmAccess, brinRevmapTerminate(), if(), IndexInfo::ii_AmCache, and pfree().

Referenced by brinhandler().

brinoptions()

bytea * brinoptions ( Datum  reloptions,
bool  validate 
)

Definition at line 1348 of file brin.c.

1349{
1350 static const relopt_parse_elt tab[] = {
1351 {"pages_per_range", RELOPT_TYPE_INT, offsetof(BrinOptions, pagesPerRange)},
1352 {"autosummarize", RELOPT_TYPE_BOOL, offsetof(BrinOptions, autosummarize)}
1353 };
1354
1355 return (bytea *) build_reloptions(reloptions, validate,
1357 sizeof(BrinOptions),
1358 tab, lengthof(tab));
1359}
static bool validate(Port *port, const char *auth)
Definition: auth-oauth.c:638
#define lengthof(array)
Definition: c.h:787
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
Definition: reloptions.c:1943
@ RELOPT_KIND_BRIN
Definition: reloptions.h:52
@ RELOPT_TYPE_INT
Definition: reloptions.h:32
@ RELOPT_TYPE_BOOL
Definition: reloptions.h:31
Definition: brin.h:22
Definition: c.h:692

References build_reloptions(), lengthof, RELOPT_KIND_BRIN, RELOPT_TYPE_BOOL, RELOPT_TYPE_INT, and validate().

Referenced by brinhandler().

brinrescan()

void brinrescan ( IndexScanDesc  scan,
ScanKey  scankey,
int  nscankeys,
ScanKey  orderbys,
int  norderbys 
)

Definition at line 959 of file brin.c.

961{
962 /*
963 * Other index AMs preprocess the scan keys at this point, or sometime
964 * early during the scan; this lets them optimize by removing redundant
965 * keys, or doing early returns when they are impossible to satisfy; see
966 * _bt_preprocess_keys for an example. Something like that could be added
967 * here someday, too.
968 */
969
970 if (scankey && scan->numberOfKeys > 0)
971 memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData));
972}

References IndexScanDescData::keyData, and IndexScanDescData::numberOfKeys.

Referenced by brinhandler().

brinvacuumcleanup()

IndexBulkDeleteResult * brinvacuumcleanup ( IndexVacuumInfoinfo,
IndexBulkDeleteResultstats 
)

Definition at line 1318 of file brin.c.

1319{
1320 Relation heapRel;
1321
1322 /* No-op in ANALYZE ONLY mode */
1323 if (info->analyze_only)
1324 return stats;
1325
1326 if (!stats)
1329 /* rest of stats is initialized by zeroing */
1330
1331 heapRel = table_open(IndexGetRelation(RelationGetRelid(info->index), false),
1333
1334 brin_vacuum_scan(info->index, info->strategy);
1335
1336 brinsummarize(info->index, heapRel, BRIN_ALL_BLOCKRANGES, false,
1337 &stats->num_index_tuples, &stats->num_index_tuples);
1338
1339 table_close(heapRel, AccessShareLock);
1340
1341 return stats;
1342}
static void brin_vacuum_scan(Relation idxrel, BufferAccessStrategy strategy)
Definition: brin.c:2172
#define BRIN_ALL_BLOCKRANGES
Definition: brin.c:209
static void brinsummarize(Relation index, Relation heapRel, BlockNumber pageRange, bool include_partial, double *numSummarized, double *numExisting)
Definition: brin.c:1887
BlockNumber num_pages
Definition: genam.h:104
double num_index_tuples
Definition: genam.h:106
Relation index
Definition: genam.h:73
bool analyze_only
Definition: genam.h:75
BufferAccessStrategy strategy
Definition: genam.h:80

References AccessShareLock, IndexVacuumInfo::analyze_only, BRIN_ALL_BLOCKRANGES, brin_vacuum_scan(), brinsummarize(), IndexVacuumInfo::index, IndexGetRelation(), IndexBulkDeleteResult::num_index_tuples, IndexBulkDeleteResult::num_pages, palloc0_object, RelationGetNumberOfBlocks, RelationGetRelid, IndexVacuumInfo::strategy, table_close(), and table_open().

Referenced by brinhandler().

brinvalidate()

bool brinvalidate ( Oid  opclassoid )

Definition at line 37 of file brin_validate.c.

38{
39 bool result = true;
40 HeapTuple classtup;
41 Form_pg_opclass classform;
42 Oid opfamilyoid;
43 Oid opcintype;
44 char *opclassname;
45 char *opfamilyname;
46 CatCList *proclist,
47 *oprlist;
48 uint64 allfuncs = 0;
49 uint64 allops = 0;
50 List *grouplist;
51 OpFamilyOpFuncGroup *opclassgroup;
52 int i;
53 ListCell *lc;
54
55 /* Fetch opclass information */
56 classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid));
57 if (!HeapTupleIsValid(classtup))
58 elog(ERROR, "cache lookup failed for operator class %u", opclassoid);
59 classform = (Form_pg_opclass) GETSTRUCT(classtup);
60
61 opfamilyoid = classform->opcfamily;
62 opcintype = classform->opcintype;
63 opclassname = NameStr(classform->opcname);
64
65 /* Fetch opfamily information */
66 opfamilyname = get_opfamily_name(opfamilyoid, false);
67
68 /* Fetch all operators and support functions of the opfamily */
69 oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid));
70 proclist = SearchSysCacheList1(AMPROCNUM, ObjectIdGetDatum(opfamilyoid));
71
72 /* Check individual support functions */
73 for (i = 0; i < proclist->n_members; i++)
74 {
75 HeapTuple proctup = &proclist->members[i]->tuple;
76 Form_pg_amproc procform = (Form_pg_amproc) GETSTRUCT(proctup);
77 bool ok;
78
79 /* Check procedure numbers and function signatures */
80 switch (procform->amprocnum)
81 {
83 ok = check_amproc_signature(procform->amproc, INTERNALOID, true,
84 1, 1, INTERNALOID);
85 break;
87 ok = check_amproc_signature(procform->amproc, BOOLOID, true,
88 4, 4, INTERNALOID, INTERNALOID,
89 INTERNALOID, INTERNALOID);
90 break;
92 ok = check_amproc_signature(procform->amproc, BOOLOID, true,
93 3, 4, INTERNALOID, INTERNALOID,
94 INTERNALOID, INT4OID);
95 break;
97 ok = check_amproc_signature(procform->amproc, BOOLOID, true,
98 3, 3, INTERNALOID, INTERNALOID,
99 INTERNALOID);
100 break;
102 ok = check_amoptsproc_signature(procform->amproc);
103 break;
104 default:
105 /* Complain if it's not a valid optional proc number */
106 if (procform->amprocnum < BRIN_FIRST_OPTIONAL_PROCNUM ||
107 procform->amprocnum > BRIN_LAST_OPTIONAL_PROCNUM)
108 {
110 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
111 errmsg("operator family \"%s\" of access method %s contains function %s with invalid support number %d",
112 opfamilyname, "brin",
113 format_procedure(procform->amproc),
114 procform->amprocnum)));
115 result = false;
116 continue; /* omit bad proc numbers from allfuncs */
117 }
118 /* Can't check signatures of optional procs, so assume OK */
119 ok = true;
120 break;
121 }
122
123 if (!ok)
124 {
126 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
127 errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d",
128 opfamilyname, "brin",
129 format_procedure(procform->amproc),
130 procform->amprocnum)));
131 result = false;
132 }
133
134 /* Track all valid procedure numbers seen in opfamily */
135 allfuncs |= ((uint64) 1) << procform->amprocnum;
136 }
137
138 /* Check individual operators */
139 for (i = 0; i < oprlist->n_members; i++)
140 {
141 HeapTuple oprtup = &oprlist->members[i]->tuple;
142 Form_pg_amop oprform = (Form_pg_amop) GETSTRUCT(oprtup);
143
144 /* Check that only allowed strategy numbers exist */
145 if (oprform->amopstrategy < 1 || oprform->amopstrategy > 63)
146 {
148 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
149 errmsg("operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d",
150 opfamilyname, "brin",
151 format_operator(oprform->amopopr),
152 oprform->amopstrategy)));
153 result = false;
154 }
155 else
156 {
157 /*
158 * The set of operators supplied varies across BRIN opfamilies.
159 * Our plan is to identify all operator strategy numbers used in
160 * the opfamily and then complain about datatype combinations that
161 * are missing any operator(s). However, consider only numbers
162 * that appear in some non-cross-type case, since cross-type
163 * operators may have unique strategies. (This is not a great
164 * heuristic, in particular an erroneous number used in a
165 * cross-type operator will not get noticed; but the core BRIN
166 * opfamilies are messy enough to make it necessary.)
167 */
168 if (oprform->amoplefttype == oprform->amoprighttype)
169 allops |= ((uint64) 1) << oprform->amopstrategy;
170 }
171
172 /* brin doesn't support ORDER BY operators */
173 if (oprform->amoppurpose != AMOP_SEARCH ||
174 OidIsValid(oprform->amopsortfamily))
175 {
177 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
178 errmsg("operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s",
179 opfamilyname, "brin",
180 format_operator(oprform->amopopr))));
181 result = false;
182 }
183
184 /* Check operator signature --- same for all brin strategies */
185 if (!check_amop_signature(oprform->amopopr, BOOLOID,
186 oprform->amoplefttype,
187 oprform->amoprighttype))
188 {
190 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
191 errmsg("operator family \"%s\" of access method %s contains operator %s with wrong signature",
192 opfamilyname, "brin",
193 format_operator(oprform->amopopr))));
194 result = false;
195 }
196 }
197
198 /* Now check for inconsistent groups of operators/functions */
199 grouplist = identify_opfamily_groups(oprlist, proclist);
200 opclassgroup = NULL;
201 foreach(lc, grouplist)
202 {
204
205 /* Remember the group exactly matching the test opclass */
206 if (thisgroup->lefttype == opcintype &&
207 thisgroup->righttype == opcintype)
208 opclassgroup = thisgroup;
209
210 /*
211 * Some BRIN opfamilies expect cross-type support functions to exist,
212 * and some don't. We don't know exactly which are which, so if we
213 * find a cross-type operator for which there are no support functions
214 * at all, let it pass. (Don't expect that all operators exist for
215 * such cross-type cases, either.)
216 */
217 if (thisgroup->functionset == 0 &&
218 thisgroup->lefttype != thisgroup->righttype)
219 continue;
220
221 /*
222 * Else complain if there seems to be an incomplete set of either
223 * operators or support functions for this datatype pair.
224 */
225 if (thisgroup->operatorset != allops)
226 {
228 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
229 errmsg("operator family \"%s\" of access method %s is missing operator(s) for types %s and %s",
230 opfamilyname, "brin",
231 format_type_be(thisgroup->lefttype),
232 format_type_be(thisgroup->righttype))));
233 result = false;
234 }
235 if (thisgroup->functionset != allfuncs)
236 {
238 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
239 errmsg("operator family \"%s\" of access method %s is missing support function(s) for types %s and %s",
240 opfamilyname, "brin",
241 format_type_be(thisgroup->lefttype),
242 format_type_be(thisgroup->righttype))));
243 result = false;
244 }
245 }
246
247 /* Check that the originally-named opclass is complete */
248 if (!opclassgroup || opclassgroup->operatorset != allops)
249 {
251 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
252 errmsg("operator class \"%s\" of access method %s is missing operator(s)",
253 opclassname, "brin")));
254 result = false;
255 }
256 for (i = 1; i <= BRIN_MANDATORY_NPROCS; i++)
257 {
258 if (opclassgroup &&
259 (opclassgroup->functionset & (((int64) 1) << i)) != 0)
260 continue; /* got it */
262 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
263 errmsg("operator class \"%s\" of access method %s is missing support function %d",
264 opclassname, "brin", i)));
265 result = false;
266 }
267
268 ReleaseCatCacheList(proclist);
269 ReleaseCatCacheList(oprlist);
270 ReleaseSysCache(classtup);
271
272 return result;
273}
bool check_amproc_signature(Oid funcid, Oid restype, bool exact, int minargs, int maxargs,...)
Definition: amvalidate.c:152
bool check_amop_signature(Oid opno, Oid restype, Oid lefttype, Oid righttype)
Definition: amvalidate.c:206
List * identify_opfamily_groups(CatCList *oprlist, CatCList *proclist)
Definition: amvalidate.c:43
bool check_amoptsproc_signature(Oid funcid)
Definition: amvalidate.c:192
#define BRIN_LAST_OPTIONAL_PROCNUM
Definition: brin_internal.h:78
#define BRIN_PROCNUM_UNION
Definition: brin_internal.h:73
#define BRIN_MANDATORY_NPROCS
Definition: brin_internal.h:74
#define BRIN_PROCNUM_OPTIONS
Definition: brin_internal.h:75
#define BRIN_FIRST_OPTIONAL_PROCNUM
Definition: brin_internal.h:77
#define BRIN_PROCNUM_ADDVALUE
Definition: brin_internal.h:71
#define NameStr(name)
Definition: c.h:751
uint64_t uint64
Definition: c.h:539
#define OidIsValid(objectId)
Definition: c.h:774
void ReleaseCatCacheList(CatCList *list)
Definition: catcache.c:2094
#define INFO
Definition: elog.h:34
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
char * get_opfamily_name(Oid opfid, bool missing_ok)
Definition: lsyscache.c:1420
FormData_pg_amop * Form_pg_amop
Definition: pg_amop.h:88
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:68
#define lfirst(lc)
Definition: pg_list.h:172
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:305
char * format_operator(Oid operator_oid)
Definition: regproc.c:801
Definition: pg_list.h:54
uint64 operatorset
Definition: amvalidate.h:24
uint64 functionset
Definition: amvalidate.h:25
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:185
int n_members
Definition: catcache.h:183
HeapTupleData tuple
Definition: catcache.h:124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:127
Definition: pg_list.h:46

References BRIN_FIRST_OPTIONAL_PROCNUM, BRIN_LAST_OPTIONAL_PROCNUM, BRIN_MANDATORY_NPROCS, BRIN_PROCNUM_ADDVALUE, BRIN_PROCNUM_CONSISTENT, BRIN_PROCNUM_OPCINFO, BRIN_PROCNUM_OPTIONS, BRIN_PROCNUM_UNION, check_amop_signature(), check_amoptsproc_signature(), check_amproc_signature(), elog, ereport, errcode(), errmsg(), ERROR, format_operator(), format_procedure(), format_type_be(), OpFamilyOpFuncGroup::functionset, get_opfamily_name(), GETSTRUCT(), HeapTupleIsValid, i, identify_opfamily_groups(), INFO, OpFamilyOpFuncGroup::lefttype, lfirst, catclist::members, catclist::n_members, NameStr, ObjectIdGetDatum(), OidIsValid, OpFamilyOpFuncGroup::operatorset, ReleaseCatCacheList(), ReleaseSysCache(), OpFamilyOpFuncGroup::righttype, SearchSysCache1(), SearchSysCacheList1, and catctup::tuple.

Referenced by brinhandler().

AltStyle によって変換されたページ (->オリジナル) /