From 58b1bcd28991a1be04d13783e1c46a1ebf5de51c Mon Sep 17 00:00:00 2001 From: Kommi Date: Fri, 24 Aug 2018 11:21:34 +1000 Subject: [PATCH 2/2] check-world fixes --- contrib/amcheck/verify_nbtree.c | 1 + contrib/pg_visibility/pg_visibility.c | 5 +++-- contrib/pgstattuple/pgstatapprox.c | 10 +++++++++- contrib/pgstattuple/pgstattuple.c | 9 ++++++++- src/backend/executor/execMain.c | 11 +---------- src/backend/executor/execTuples.c | 22 ++++++++++++++++++++++ src/backend/executor/nodeModifyTable.c | 12 ++++++++++-- src/include/executor/tuptable.h | 1 + 8 files changed, 55 insertions(+), 16 deletions(-) diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c index 04102dd3df..cb4294af7d 100644 --- a/contrib/amcheck/verify_nbtree.c +++ b/contrib/amcheck/verify_nbtree.c @@ -25,6 +25,7 @@ #include "access/htup_details.h" #include "access/nbtree.h" +#include "access/tableam.h" #include "access/transam.h" #include "access/xact.h" #include "catalog/index.h" diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c index dce5262e34..88ca4fd2af 100644 --- a/contrib/pg_visibility/pg_visibility.c +++ b/contrib/pg_visibility/pg_visibility.c @@ -563,12 +563,13 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen) rel = relation_open(relid, AccessShareLock); + /* Only some relkinds have a visibility map */ + check_relation_relkind(rel); + if (rel->rd_rel->relam != HEAP_TABLE_AM_OID) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("only heap AM is supported"))); - /* Only some relkinds have a visibility map */ - check_relation_relkind(rel); nblocks = RelationGetNumberOfBlocks(rel); diff --git a/contrib/pgstattuple/pgstatapprox.c b/contrib/pgstattuple/pgstatapprox.c index e805981bb9..6aee2ce8ac 100644 --- a/contrib/pgstattuple/pgstatapprox.c +++ b/contrib/pgstattuple/pgstatapprox.c @@ -12,6 +12,7 @@ */ #include "postgres.h" +#include "access/tableam.h" #include "access/transam.h" #include "access/visibilitymap.h" #include "access/xact.h" @@ -69,6 +70,7 @@ statapprox_heap(Relation rel, output_type *stat) Buffer vmbuffer = InvalidBuffer; BufferAccessStrategy bstrategy; TransactionId OldestXmin; + TupleTableSlot *slot; OldestXmin = GetOldestXmin(rel, PROCARRAY_FLAGS_VACUUM); bstrategy = GetAccessStrategy(BAS_BULKREAD); @@ -76,6 +78,8 @@ statapprox_heap(Relation rel, output_type *stat) nblocks = RelationGetNumberOfBlocks(rel); scanned = 0; + slot = MakeSingleTupleTableSlot(RelationGetDescr(rel), TTS_TYPE_BUFFER); + for (blkno = 0; blkno < nblocks; blkno++) { Buffer buf; @@ -153,13 +157,15 @@ statapprox_heap(Relation rel, output_type *stat) tuple.t_len = ItemIdGetLength(itemid); tuple.t_tableOid = RelationGetRelid(rel); + ExecStoreTuple(&tuple,slot,buf,false); + /* * We follow VACUUM's lead in counting INSERT_IN_PROGRESS tuples * as "dead" while DELETE_IN_PROGRESS tuples are "live". We don't * bother distinguishing tuples inserted/deleted by our own * transaction. */ - switch (rel->rd_tableamroutine->snapshot_satisfiesVacuum(&tuple, OldestXmin, buf)) + switch (rel->rd_tableamroutine->snapshot_satisfiesVacuum(slot, OldestXmin)) { case HEAPTUPLE_LIVE: case HEAPTUPLE_DELETE_IN_PROGRESS: @@ -210,6 +216,8 @@ statapprox_heap(Relation rel, output_type *stat) ReleaseBuffer(vmbuffer); vmbuffer = InvalidBuffer; } + + ExecDropSingleTupleTableSlot(slot); } /* diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c index 53fdff6c2c..5965ecbcf8 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -28,6 +28,7 @@ #include "access/hash.h" #include "access/nbtree.h" #include "access/relscan.h" +#include "access/tableam.h" #include "catalog/namespace.h" #include "catalog/pg_am.h" #include "funcapi.h" @@ -326,12 +327,14 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo) Buffer buffer; pgstattuple_type stat = {0}; SnapshotData SnapshotDirty; + TupleTableSlot *slot; TableAmRoutine *method = rel->rd_tableamroutine; /* Disable syncscan because we assume we scan from block zero upwards */ scan = table_beginscan_strat(rel, SnapshotAny, 0, NULL, true, false); InitDirtySnapshot(SnapshotDirty); + slot = MakeSingleTupleTableSlot(RelationGetDescr(rel), TTS_TYPE_BUFFER); pagescan = tableam_get_heappagescandesc(scan); nblocks = pagescan->rs_nblocks; /* # blocks to be scanned */ @@ -343,7 +346,10 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo) /* must hold a buffer lock to call HeapTupleSatisfiesVisibility */ LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE); - if (HeapTupleSatisfiesVisibility(method, tuple, &SnapshotDirty, scan->rs_cbuf)) + /* FIXME: change to get the slot directly, instead of tuple */ + ExecStoreTuple(tuple, slot, scan->rs_cbuf, false); + + if (HeapTupleSatisfiesVisibility(method, slot, &SnapshotDirty)) { stat.tuple_len += tuple->t_len; stat.tuple_count++; @@ -393,6 +399,7 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo) relation_close(rel, AccessShareLock); stat.table_len = (uint64) nblocks * BLCKSZ; + ExecDropSingleTupleTableSlot(slot); return build_pgstattuple_type(&stat, fcinfo); } diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 1237e809f3..e349a22e94 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -2765,16 +2765,7 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate) if (isNull) continue; - elog(ERROR, "frak, need to implement ROW_MARK_COPY"); -#ifdef FIXME - // FIXME: this should just deform the tuple and store it as a - // virtual one. - tuple = table_tuple_by_datum(erm->relation, datum, erm->relid); - - /* store tuple */ - EvalPlanQualSetTuple(epqstate, erm->rti, tuple); -#endif - + ExecForceStoreHeapTupleDatum(datum, slot); } } } diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 59ccc1a626..046f7b23dc 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -1385,6 +1385,28 @@ ExecForceStoreHeapTuple(HeapTuple tuple, } +void +ExecForceStoreHeapTupleDatum(Datum data, TupleTableSlot *slot) +{ + HeapTuple tuple; + HeapTupleHeader td; + MemoryContext oldContext; + + td = DatumGetHeapTupleHeader(data); + + tuple = (HeapTuple) palloc(HEAPTUPLESIZE + HeapTupleHeaderGetDatumLength(td)); + tuple->t_len = HeapTupleHeaderGetDatumLength(td); + tuple->t_self = td->t_ctid; + tuple->t_data = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE); + memcpy((char *) tuple->t_data, (char *) td, tuple->t_len); + + ExecClearTuple(slot); + + heap_deform_tuple(tuple, slot->tts_tupleDescriptor, + slot->tts_values, slot->tts_isnull); + ExecStoreVirtualTuple(slot); +} + /* -------------------------------- * ExecStoreMinimalTuple * diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 14ca3b976e..d7d79f845c 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -609,7 +609,7 @@ ExecDelete(ModifyTableState *mtstate, bool canSetTag, bool changingPart, bool *tupleDeleted, - TupleTableSlot **epqslot) + TupleTableSlot **epqreturnslot) { ResultRelInfo *resultRelInfo; Relation resultRelationDesc; @@ -634,7 +634,7 @@ ExecDelete(ModifyTableState *mtstate, bool dodelete; dodelete = ExecBRDeleteTriggers(estate, epqstate, resultRelInfo, - tupleid, oldtuple, epqslot); + tupleid, oldtuple, epqreturnslot); if (!dodelete) /* "do nothing" */ return NULL; @@ -727,6 +727,14 @@ ldelete:; /* Tuple no more passing quals, exiting... */ return NULL; } + + /**/ + if (epqreturnslot) + { + *epqreturnslot = epqslot; + return NULL; + } + goto ldelete; } } diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h index dec3e87a1e..4e49304ba7 100644 --- a/src/include/executor/tuptable.h +++ b/src/include/executor/tuptable.h @@ -313,6 +313,7 @@ extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup, extern void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot); +extern void ExecForceStoreHeapTupleDatum(Datum data, TupleTableSlot *slot); extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot); extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot); -- 2.18.0.windows.1