Skip to content

Commit 5194024

Browse files
committed
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.
1 parent f5d576c commit 5194024

File tree

19 files changed

+49
-141
lines changed

19 files changed

+49
-141
lines changed

src/backend/commands/createas.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,6 @@ intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
373373
rte->rtekind = RTE_RELATION;
374374
rte->relid = intoRelationId;
375375
rte->relkind = relkind;
376-
rte->isResultRel = true;
377376
rte->requiredPerms = ACL_INSERT;
378377

379378
for (attnum = 1; attnum <= intoRelationDesc->rd_att->natts; attnum++)

src/backend/commands/matview.c

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,8 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
215215
List *rewritten;
216216
PlannedStmt *plan;
217217
QueryDesc *queryDesc;
218-
List *rtable;
219-
RangeTblEntry *initial_rte;
220-
RangeTblEntry *second_rte;
221218

219+
/* Rewrite, copying the given Query to make sure it's not changed */
222220
rewritten = QueryRewrite((Query *) copyObject(query));
223221

224222
/* SELECT should never rewrite to more or less than one SELECT query */
@@ -229,26 +227,6 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
229227
/* Check for user-requested abort. */
230228
CHECK_FOR_INTERRUPTS();
231229

232-
/*
233-
* Kludge here to allow refresh of a materialized view which is invalid
234-
* (that is, it was created or refreshed WITH NO DATA. We flag the first
235-
* two RangeTblEntry list elements, which were added to the front of the
236-
* rewritten Query to keep the rules system happy, with the isResultRel
237-
* flag to indicate that it is OK if they are flagged as invalid. See
238-
* UpdateRangeTableOfViewParse() for details.
239-
*
240-
* NOTE: The rewrite has switched the frist two RTEs, but they are still
241-
* in the first two positions. If that behavior changes, the asserts here
242-
* will fail.
243-
*/
244-
rtable = query->rtable;
245-
initial_rte = ((RangeTblEntry *) linitial(rtable));
246-
Assert(strcmp(initial_rte->alias->aliasname, "new"));
247-
initial_rte->isResultRel = true;
248-
second_rte = ((RangeTblEntry *) lsecond(rtable));
249-
Assert(strcmp(second_rte->alias->aliasname, "old"));
250-
second_rte->isResultRel = true;
251-
252230
/* Plan the query which will generate data for the refresh. */
253231
plan = pg_plan_query(query, 0, NULL);
254232

src/backend/executor/execMain.c

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ static char *ExecBuildSlotValueDescription(TupleTableSlot *slot,
8585
int maxfieldlen);
8686
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
8787
Plan *planTree);
88-
static bool RelationIdIsScannable(Oid relid);
8988

9089
/* end of local decls */
9190

@@ -494,63 +493,6 @@ ExecutorRewind(QueryDesc *queryDesc)
494493
}
495494

496495

497-
/*
498-
* ExecCheckRelationsScannable
499-
* Check that relations which are to be accessed are in a scannable
500-
* state.
501-
*
502-
* Currently the only relations which are not are materialized views which
503-
* have not been populated by their queries.
504-
*/
505-
static void
506-
ExecCheckRelationsScannable(List *rangeTable)
507-
{
508-
ListCell *l;
509-
510-
foreach(l, rangeTable)
511-
{
512-
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
513-
514-
if (rte->rtekind != RTE_RELATION)
515-
continue;
516-
517-
if (rte->relkind != RELKIND_MATVIEW)
518-
continue;
519-
520-
/* It is OK to target an unpopulated materialized for results. */
521-
if (rte->isResultRel)
522-
continue;
523-
524-
if (!RelationIdIsScannable(rte->relid))
525-
ereport(ERROR,
526-
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
527-
errmsg("materialized view \"%s\" has not been populated",
528-
get_rel_name(rte->relid)),
529-
errhint("Use the REFRESH MATERIALIZED VIEW command.")));
530-
}
531-
}
532-
533-
/*
534-
* Tells whether a relation is scannable based on its OID.
535-
*
536-
* Currently only non-populated materialized views are not. This is likely to
537-
* change to include other conditions.
538-
*
539-
* This should only be called while a lock is held on the relation.
540-
*/
541-
static bool
542-
RelationIdIsScannable(Oid relid)
543-
{
544-
Relation relation;
545-
bool result;
546-
547-
relation = heap_open(relid, NoLock);
548-
result = RelationIsScannable(relation);
549-
heap_close(relation, NoLock);
550-
551-
return result;
552-
}
553-
554496
/*
555497
* ExecCheckRTPerms
556498
* Check access permissions for all relations listed in a range table.
@@ -941,20 +883,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
941883
*/
942884
planstate = ExecInitNode(plan, estate, eflags);
943885

944-
/*
945-
* Unless we are creating a view or are creating a materialized view WITH
946-
* NO DATA, ensure that all referenced relations are scannable. The
947-
* omitted cases will be checked as SELECT statements in a different
948-
* phase, so checking again here would be wasteful and it would generate
949-
* errors on a materialized view referenced as a target.
950-
*
951-
* NB: This is being done after all relations are locked, files have been
952-
* opened, etc., to avoid duplicating that effort or creating deadlock
953-
* possibilities.
954-
*/
955-
if ((eflags & EXEC_FLAG_WITH_NO_DATA) == 0)
956-
ExecCheckRelationsScannable(rangeTable);
957-
958886
/*
959887
* Get the tuple descriptor describing the type of tuples to return.
960888
*/

src/backend/executor/execUtils.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -798,8 +798,9 @@ ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
798798
* ----------------------------------------------------------------
799799
*/
800800
Relation
801-
ExecOpenScanRelation(EState *estate, Index scanrelid)
801+
ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
802802
{
803+
Relation rel;
803804
Oid reloid;
804805
LOCKMODE lockmode;
805806

@@ -827,9 +828,24 @@ ExecOpenScanRelation(EState *estate, Index scanrelid)
827828
}
828829
}
829830

830-
/* OK, open the relation and acquire lock as needed */
831+
/* Open the relation and acquire lock as needed */
831832
reloid = getrelid(scanrelid, estate->es_range_table);
832-
return heap_open(reloid, lockmode);
833+
rel = heap_open(reloid, lockmode);
834+
835+
/*
836+
* Complain if we're attempting a scan of an unscannable relation, except
837+
* when the query won't actually be run. This is a slightly klugy place
838+
* to do this, perhaps, but there is no better place.
839+
*/
840+
if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
841+
!RelationIsScannable(rel))
842+
ereport(ERROR,
843+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
844+
errmsg("materialized view \"%s\" has not been populated",
845+
RelationGetRelationName(rel)),
846+
errhint("Use the REFRESH MATERIALIZED VIEW command.")));
847+
848+
return rel;
833849
}
834850

835851
/* ----------------------------------------------------------------

src/backend/executor/nodeBitmapHeapscan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
587587
/*
588588
* open the base relation and acquire appropriate lock on it.
589589
*/
590-
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
590+
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
591591

592592
scanstate->ss.ss_currentRelation = currentRelation;
593593

src/backend/executor/nodeForeignscan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
143143
/*
144144
* open the base relation and acquire appropriate lock on it.
145145
*/
146-
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
146+
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
147147
scanstate->ss.ss_currentRelation = currentRelation;
148148

149149
/*

src/backend/executor/nodeIndexonlyscan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
410410
/*
411411
* open the base relation and acquire appropriate lock on it.
412412
*/
413-
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
413+
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
414414

415415
indexstate->ss.ss_currentRelation = currentRelation;
416416
indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */

src/backend/executor/nodeIndexscan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
511511
/*
512512
* open the base relation and acquire appropriate lock on it.
513513
*/
514-
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
514+
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
515515

516516
indexstate->ss.ss_currentRelation = currentRelation;
517517
indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */

src/backend/executor/nodeSeqscan.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include "executor/nodeSeqscan.h"
3030
#include "utils/rel.h"
3131

32-
static void InitScanRelation(SeqScanState *node, EState *estate);
32+
static void InitScanRelation(SeqScanState *node, EState *estate, int eflags);
3333
static TupleTableSlot *SeqNext(SeqScanState *node);
3434

3535
/* ----------------------------------------------------------------
@@ -118,12 +118,11 @@ ExecSeqScan(SeqScanState *node)
118118
/* ----------------------------------------------------------------
119119
* InitScanRelation
120120
*
121-
* This does the initialization for scan relations and
122-
* subplans of scans.
121+
* Set up to access the scan relation.
123122
* ----------------------------------------------------------------
124123
*/
125124
static void
126-
InitScanRelation(SeqScanState *node, EState *estate)
125+
InitScanRelation(SeqScanState *node, EState *estate, int eflags)
127126
{
128127
Relation currentRelation;
129128
HeapScanDesc currentScanDesc;
@@ -133,8 +132,10 @@ InitScanRelation(SeqScanState *node, EState *estate)
133132
* open that relation and acquire appropriate lock on it.
134133
*/
135134
currentRelation = ExecOpenScanRelation(estate,
136-
((SeqScan *) node->ps.plan)->scanrelid);
135+
((SeqScan *) node->ps.plan)->scanrelid,
136+
eflags);
137137

138+
/* initialize a heapscan */
138139
currentScanDesc = heap_beginscan(currentRelation,
139140
estate->es_snapshot,
140141
0,
@@ -143,6 +144,7 @@ InitScanRelation(SeqScanState *node, EState *estate)
143144
node->ss_currentRelation = currentRelation;
144145
node->ss_currentScanDesc = currentScanDesc;
145146

147+
/* and report the scan tuple slot's rowtype */
146148
ExecAssignScanType(node, RelationGetDescr(currentRelation));
147149
}
148150

@@ -196,7 +198,7 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
196198
/*
197199
* initialize scan relation
198200
*/
199-
InitScanRelation(scanstate, estate);
201+
InitScanRelation(scanstate, estate, eflags);
200202

201203
scanstate->ps.ps_TupFromTlist = false;
202204

src/backend/executor/nodeTidscan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
531531
/*
532532
* open the base relation and acquire appropriate lock on it.
533533
*/
534-
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
534+
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
535535

536536
tidstate->ss.ss_currentRelation = currentRelation;
537537
tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */

0 commit comments

Comments
 (0)