diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execMain.c | 72 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 22 | ||||
-rw-r--r-- | src/backend/executor/nodeBitmapHeapscan.c | 2 | ||||
-rw-r--r-- | src/backend/executor/nodeForeignscan.c | 2 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexonlyscan.c | 2 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexscan.c | 2 | ||||
-rw-r--r-- | src/backend/executor/nodeSeqscan.c | 14 | ||||
-rw-r--r-- | src/backend/executor/nodeTidscan.c | 2 |
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 */ |