aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-04-27 17:48:57 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2013-04-27 17:48:57 -0400
commit5194024d72f33fb209e10f9ab0ada7cc67df45b7 (patch)
tree81de10ef02d808084d0b62d2ed2bd609954be176 /src/backend/executor
parentf5d576c6d278a61beec282b9b276a3a3cb2aec50 (diff)
downloadpostgresql-5194024d72f33fb209e10f9ab0ada7cc67df45b7.tar.gz
postgresql-5194024d72f33fb209e10f9ab0ada7cc67df45b7.zip
Incidental cleanup of matviews code.
Move checking for unscannable matviews into ExecOpenScanRelation, which is a better place for it first because the open relation is already available (saving a relcache lookup cycle), and second because this eliminates the problem of telling the difference between rangetable entries that will or will not be scanned by the query. In particular we can get rid of the not-terribly-well-thought-out-or-implemented isResultRel field that the initial matviews patch added to RangeTblEntry. Also get rid of entirely unnecessary scannability check in the rewriter, and a bogus decision about whether RefreshMatViewStmt requires a parse-time snapshot. catversion bump due to removal of a RangeTblEntry field, which changes stored rules.
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execMain.c72
-rw-r--r--src/backend/executor/execUtils.c22
-rw-r--r--src/backend/executor/nodeBitmapHeapscan.c2
-rw-r--r--src/backend/executor/nodeForeignscan.c2
-rw-r--r--src/backend/executor/nodeIndexonlyscan.c2
-rw-r--r--src/backend/executor/nodeIndexscan.c2
-rw-r--r--src/backend/executor/nodeSeqscan.c14
-rw-r--r--src/backend/executor/nodeTidscan.c2
8 files changed, 32 insertions, 86 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 8d1d0aa927d..e1b280a065c 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -85,7 +85,6 @@ static char *ExecBuildSlotValueDescription(TupleTableSlot *slot,
int maxfieldlen);
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
Plan *planTree);
-static bool RelationIdIsScannable(Oid relid);
/* end of local decls */
@@ -495,63 +494,6 @@ ExecutorRewind(QueryDesc *queryDesc)
/*
- * ExecCheckRelationsScannable
- * Check that relations which are to be accessed are in a scannable
- * state.
- *
- * Currently the only relations which are not are materialized views which
- * have not been populated by their queries.
- */
-static void
-ExecCheckRelationsScannable(List *rangeTable)
-{
- ListCell *l;
-
- foreach(l, rangeTable)
- {
- RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
-
- if (rte->rtekind != RTE_RELATION)
- continue;
-
- if (rte->relkind != RELKIND_MATVIEW)
- continue;
-
- /* It is OK to target an unpopulated materialized for results. */
- if (rte->isResultRel)
- continue;
-
- if (!RelationIdIsScannable(rte->relid))
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("materialized view \"%s\" has not been populated",
- get_rel_name(rte->relid)),
- errhint("Use the REFRESH MATERIALIZED VIEW command.")));
- }
-}
-
-/*
- * Tells whether a relation is scannable based on its OID.
- *
- * Currently only non-populated materialized views are not. This is likely to
- * change to include other conditions.
- *
- * This should only be called while a lock is held on the relation.
- */
-static bool
-RelationIdIsScannable(Oid relid)
-{
- Relation relation;
- bool result;
-
- relation = heap_open(relid, NoLock);
- result = RelationIsScannable(relation);
- heap_close(relation, NoLock);
-
- return result;
-}
-
-/*
* ExecCheckRTPerms
* Check access permissions for all relations listed in a range table.
*
@@ -942,20 +884,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
planstate = ExecInitNode(plan, estate, eflags);
/*
- * Unless we are creating a view or are creating a materialized view WITH
- * NO DATA, ensure that all referenced relations are scannable. The
- * omitted cases will be checked as SELECT statements in a different
- * phase, so checking again here would be wasteful and it would generate
- * errors on a materialized view referenced as a target.
- *
- * NB: This is being done after all relations are locked, files have been
- * opened, etc., to avoid duplicating that effort or creating deadlock
- * possibilities.
- */
- if ((eflags & EXEC_FLAG_WITH_NO_DATA) == 0)
- ExecCheckRelationsScannable(rangeTable);
-
- /*
* Get the tuple descriptor describing the type of tuples to return.
*/
tupType = ExecGetResultType(planstate);
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 11be62e9153..cf7fb72ffcf 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -798,8 +798,9 @@ ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
* ----------------------------------------------------------------
*/
Relation
-ExecOpenScanRelation(EState *estate, Index scanrelid)
+ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
{
+ Relation rel;
Oid reloid;
LOCKMODE lockmode;
@@ -827,9 +828,24 @@ ExecOpenScanRelation(EState *estate, Index scanrelid)
}
}
- /* OK, open the relation and acquire lock as needed */
+ /* Open the relation and acquire lock as needed */
reloid = getrelid(scanrelid, estate->es_range_table);
- return heap_open(reloid, lockmode);
+ rel = heap_open(reloid, lockmode);
+
+ /*
+ * Complain if we're attempting a scan of an unscannable relation, except
+ * when the query won't actually be run. This is a slightly klugy place
+ * to do this, perhaps, but there is no better place.
+ */
+ if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
+ !RelationIsScannable(rel))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("materialized view \"%s\" has not been populated",
+ RelationGetRelationName(rel)),
+ errhint("Use the REFRESH MATERIALIZED VIEW command.")));
+
+ return rel;
}
/* ----------------------------------------------------------------
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c83f9722cf9..d2b27213ffe 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -587,7 +587,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
/*
* open the base relation and acquire appropriate lock on it.
*/
- currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
+ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
scanstate->ss.ss_currentRelation = currentRelation;
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index 448fd6a912f..c0b3525e50d 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -143,7 +143,7 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
/*
* open the base relation and acquire appropriate lock on it.
*/
- currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
+ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
scanstate->ss.ss_currentRelation = currentRelation;
/*
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index 7d01f8166e6..2f30c55c54a 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -410,7 +410,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
/*
* open the base relation and acquire appropriate lock on it.
*/
- currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
+ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
indexstate->ss.ss_currentRelation = currentRelation;
indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index c71a382af81..f1062f19f43 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -511,7 +511,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
/*
* open the base relation and acquire appropriate lock on it.
*/
- currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
+ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
indexstate->ss.ss_currentRelation = currentRelation;
indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index c6f2eabedee..c4edec0750b 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -29,7 +29,7 @@
#include "executor/nodeSeqscan.h"
#include "utils/rel.h"
-static void InitScanRelation(SeqScanState *node, EState *estate);
+static void InitScanRelation(SeqScanState *node, EState *estate, int eflags);
static TupleTableSlot *SeqNext(SeqScanState *node);
/* ----------------------------------------------------------------
@@ -118,12 +118,11 @@ ExecSeqScan(SeqScanState *node)
/* ----------------------------------------------------------------
* InitScanRelation
*
- * This does the initialization for scan relations and
- * subplans of scans.
+ * Set up to access the scan relation.
* ----------------------------------------------------------------
*/
static void
-InitScanRelation(SeqScanState *node, EState *estate)
+InitScanRelation(SeqScanState *node, EState *estate, int eflags)
{
Relation currentRelation;
HeapScanDesc currentScanDesc;
@@ -133,8 +132,10 @@ InitScanRelation(SeqScanState *node, EState *estate)
* open that relation and acquire appropriate lock on it.
*/
currentRelation = ExecOpenScanRelation(estate,
- ((SeqScan *) node->ps.plan)->scanrelid);
+ ((SeqScan *) node->ps.plan)->scanrelid,
+ eflags);
+ /* initialize a heapscan */
currentScanDesc = heap_beginscan(currentRelation,
estate->es_snapshot,
0,
@@ -143,6 +144,7 @@ InitScanRelation(SeqScanState *node, EState *estate)
node->ss_currentRelation = currentRelation;
node->ss_currentScanDesc = currentScanDesc;
+ /* and report the scan tuple slot's rowtype */
ExecAssignScanType(node, RelationGetDescr(currentRelation));
}
@@ -196,7 +198,7 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
/*
* initialize scan relation
*/
- InitScanRelation(scanstate, estate);
+ InitScanRelation(scanstate, estate, eflags);
scanstate->ps.ps_TupFromTlist = false;
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index ced9c8b1b58..316a4ed0136 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -531,7 +531,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
/*
* open the base relation and acquire appropriate lock on it.
*/
- currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
+ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
tidstate->ss.ss_currentRelation = currentRelation;
tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */