mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
Redesign tablesample method API, and do extensive code review.
The original implementation of TABLESAMPLE modeled the tablesample method API on index access methods, which wasn't a good choice because, without specialized DDL commands, there's no way to build an extension that can implement a TSM. (Raw inserts into system catalogs are not an acceptable thing to do, because we can't undo them during DROP EXTENSION, nor will pg_upgrade behave sanely.) Instead adopt an API more like procedural language handlers or foreign data wrappers, wherein the only SQL-level support object needed is a single handler function identified by having a special return type. This lets us get rid of the supporting catalog altogether, so that no custom DDL support is needed for the feature. Adjust the API so that it can support non-constant tablesample arguments (the original coding assumed we could evaluate the argument expressions at ExecInitSampleScan time, which is undesirable even if it weren't outright unsafe), and discourage sampling methods from looking at invisible tuples. Make sure that the BERNOULLI and SYSTEM methods are genuinely repeatable within and across queries, as required by the SQL standard, and deal more honestly with methods that can't support that requirement. Make a full code-review pass over the tablesample additions, and fix assorted bugs, omissions, infelicities, and cosmetic issues (such as failure to put the added code stanzas in a consistent ordering). Improve EXPLAIN's output of tablesample plans, too. Back-patch to 9.5 so that we don't have to support the original API in production.
This commit is contained in:
@ -80,8 +80,11 @@ bool synchronize_seqscans = true;
|
||||
static HeapScanDesc heap_beginscan_internal(Relation relation,
|
||||
Snapshot snapshot,
|
||||
int nkeys, ScanKey key,
|
||||
bool allow_strat, bool allow_sync, bool allow_pagemode,
|
||||
bool is_bitmapscan, bool is_samplescan,
|
||||
bool allow_strat,
|
||||
bool allow_sync,
|
||||
bool allow_pagemode,
|
||||
bool is_bitmapscan,
|
||||
bool is_samplescan,
|
||||
bool temp_snap);
|
||||
static HeapTuple heap_prepare_insert(Relation relation, HeapTuple tup,
|
||||
TransactionId xid, CommandId cid, int options);
|
||||
@ -207,7 +210,7 @@ static const int MultiXactStatusLock[MaxMultiXactStatus + 1] =
|
||||
* ----------------
|
||||
*/
|
||||
static void
|
||||
initscan(HeapScanDesc scan, ScanKey key, bool is_rescan)
|
||||
initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
|
||||
{
|
||||
bool allow_strat;
|
||||
bool allow_sync;
|
||||
@ -257,12 +260,12 @@ initscan(HeapScanDesc scan, ScanKey key, bool is_rescan)
|
||||
scan->rs_strategy = NULL;
|
||||
}
|
||||
|
||||
if (is_rescan)
|
||||
if (keep_startblock)
|
||||
{
|
||||
/*
|
||||
* If rescan, keep the previous startblock setting so that rewinding a
|
||||
* cursor doesn't generate surprising results. Reset the syncscan
|
||||
* setting, though.
|
||||
* When rescanning, we want to keep the previous startblock setting,
|
||||
* so that rewinding a cursor doesn't generate surprising results.
|
||||
* Reset the active syncscan setting, though.
|
||||
*/
|
||||
scan->rs_syncscan = (allow_sync && synchronize_seqscans);
|
||||
}
|
||||
@ -1313,6 +1316,10 @@ heap_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
|
||||
/* ----------------
|
||||
* heap_beginscan - begin relation scan
|
||||
*
|
||||
* heap_beginscan is the "standard" case.
|
||||
*
|
||||
* heap_beginscan_catalog differs in setting up its own temporary snapshot.
|
||||
*
|
||||
* heap_beginscan_strat offers an extended API that lets the caller control
|
||||
* whether a nondefault buffer access strategy can be used, and whether
|
||||
* syncscan can be chosen (possibly resulting in the scan not starting from
|
||||
@ -1323,8 +1330,11 @@ heap_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
|
||||
* really quite unlike a standard seqscan, there is just enough commonality
|
||||
* to make it worth using the same data structure.
|
||||
*
|
||||
* heap_beginscan_samplingscan is alternate entry point for setting up a
|
||||
* HeapScanDesc for a TABLESAMPLE scan.
|
||||
* heap_beginscan_sampling is an alternative entry point for setting up a
|
||||
* HeapScanDesc for a TABLESAMPLE scan. As with bitmap scans, it's worth
|
||||
* using the same data structure although the behavior is rather different.
|
||||
* In addition to the options offered by heap_beginscan_strat, this call
|
||||
* also allows control of whether page-mode visibility checking is used.
|
||||
* ----------------
|
||||
*/
|
||||
HeapScanDesc
|
||||
@ -1366,18 +1376,22 @@ heap_beginscan_bm(Relation relation, Snapshot snapshot,
|
||||
HeapScanDesc
|
||||
heap_beginscan_sampling(Relation relation, Snapshot snapshot,
|
||||
int nkeys, ScanKey key,
|
||||
bool allow_strat, bool allow_pagemode)
|
||||
bool allow_strat, bool allow_sync, bool allow_pagemode)
|
||||
{
|
||||
return heap_beginscan_internal(relation, snapshot, nkeys, key,
|
||||
allow_strat, false, allow_pagemode,
|
||||
allow_strat, allow_sync, allow_pagemode,
|
||||
false, true, false);
|
||||
}
|
||||
|
||||
static HeapScanDesc
|
||||
heap_beginscan_internal(Relation relation, Snapshot snapshot,
|
||||
int nkeys, ScanKey key,
|
||||
bool allow_strat, bool allow_sync, bool allow_pagemode,
|
||||
bool is_bitmapscan, bool is_samplescan, bool temp_snap)
|
||||
bool allow_strat,
|
||||
bool allow_sync,
|
||||
bool allow_pagemode,
|
||||
bool is_bitmapscan,
|
||||
bool is_samplescan,
|
||||
bool temp_snap)
|
||||
{
|
||||
HeapScanDesc scan;
|
||||
|
||||
@ -1461,6 +1475,27 @@ heap_rescan(HeapScanDesc scan,
|
||||
initscan(scan, key, true);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_rescan_set_params - restart a relation scan after changing params
|
||||
*
|
||||
* This call allows changing the buffer strategy, syncscan, and pagemode
|
||||
* options before starting a fresh scan. Note that although the actual use
|
||||
* of syncscan might change (effectively, enabling or disabling reporting),
|
||||
* the previously selected startblock will be kept.
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
heap_rescan_set_params(HeapScanDesc scan, ScanKey key,
|
||||
bool allow_strat, bool allow_sync, bool allow_pagemode)
|
||||
{
|
||||
/* adjust parameters */
|
||||
scan->rs_allow_strat = allow_strat;
|
||||
scan->rs_allow_sync = allow_sync;
|
||||
scan->rs_pageatatime = allow_pagemode && IsMVCCSnapshot(scan->rs_snapshot);
|
||||
/* ... and rescan */
|
||||
heap_rescan(scan, key);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* heap_endscan - end relation scan
|
||||
*
|
||||
|
Reference in New Issue
Block a user