create_append_plan(PlannerInfo *root, AppendPath *best_path)
{
Append *plan;
- RelOptInfo *rel = best_path->path.parent;
- List *tlist = build_relation_tlist(rel);
+ List *tlist = build_relation_tlist(best_path->path.parent);
List *subplans = NIL;
ListCell *subpaths;
/*
- * The subpaths list could be empty, if every child was proven empty by
- * constraint exclusion. In that case generate a dummy plan that returns
- * no rows.
+ * It is possible for the subplans list to contain only one entry, or even
+ * no entries. Handle these cases specially.
*
- * Note that an AppendPath with no members is also generated in certain
- * cases where there was no appending construct at all, but we know the
- * relation is empty (see set_dummy_rel_pathlist).
+ * XXX ideally, if there's just one entry, we'd not bother to generate an
+ * Append node but just return the single child. At the moment this does
+ * not work because the varno of the child scan plan won't match the
+ * parent-rel Vars it'll be asked to emit.
*/
if (best_path->subpaths == NIL)
{
- /*
- * If this is a dummy path for a subquery, we have to wrap the
- * subquery's original plan in a SubqueryScan so that setrefs.c will
- * do the right things. (In particular, it must pull up the
- * subquery's rangetable so that the executor will apply permissions
- * checks to those rels at runtime.)
- */
- if (rel->rtekind == RTE_SUBQUERY)
- {
- Assert(is_dummy_plan(rel->subplan));
- return (Plan *) make_subqueryscan(tlist,
- NIL,
- rel->relid,
- rel->subplan);
- }
- else
- {
- /* Generate a Result plan with constant-FALSE gating qual */
- return (Plan *) make_result(root,
- tlist,
- (Node *) list_make1(makeBoolConst(false,
- false)),
- NULL);
- }
+ /* Generate a Result plan with constant-FALSE gating qual */
+ return (Plan *) make_result(root,
+ tlist,
+ (Node *) list_make1(makeBoolConst(false,
+ false)),
+ NULL);
}
- /* Build the plan for each child */
+ /* Normal case with multiple subpaths */
foreach(subpaths, best_path->subpaths)
{
Path *subpath = (Path *) lfirst(subpaths);
subplans = lappend(subplans, create_plan_recurse(root, subpath));
}
- /*
- * XXX ideally, if there's just one child, we'd not bother to generate an
- * Append node but just return the single child. At the moment this does
- * not work because the varno of the child scan plan won't match the
- * parent-rel Vars it'll be asked to emit.
- */
-
plan = make_append(subplans, tlist);
return (Plan *) plan;
/* The next *should* fail, but it's not implemented that way yet. */
CREATE VIEW atestv2 AS SELECT * FROM atest2;
CREATE VIEW atestv3 AS SELECT * FROM atest3; -- ok
-/* Empty view is a corner case that failed in 9.2. */
-CREATE VIEW atestv0 AS SELECT 0 as x WHERE false; -- ok
SELECT * FROM atestv1; -- ok
a | b
---+-----
-----+-----+-------
(0 rows)
-SELECT * FROM atestv0; -- fail
-ERROR: permission denied for relation atestv0
CREATE VIEW atestv4 AS SELECT * FROM atestv3; -- nested view
SELECT * FROM atestv4; -- ok
one | two | three
drop sequence x_seq;
DROP FUNCTION testfunc2(int);
DROP FUNCTION testfunc4(boolean);
-DROP VIEW atestv0;
DROP VIEW atestv1;
DROP VIEW atestv2;
-- this should cascade to drop atestv4
/* The next *should* fail, but it's not implemented that way yet. */
CREATE VIEW atestv2 AS SELECT * FROM atest2;
CREATE VIEW atestv3 AS SELECT * FROM atest3; -- ok
-/* Empty view is a corner case that failed in 9.2. */
-CREATE VIEW atestv0 AS SELECT 0 as x WHERE false; -- ok
SELECT * FROM atestv1; -- ok
SELECT * FROM atestv2; -- fail
SELECT * FROM atestv1; -- ok
SELECT * FROM atestv2; -- fail
SELECT * FROM atestv3; -- ok
-SELECT * FROM atestv0; -- fail
CREATE VIEW atestv4 AS SELECT * FROM atestv3; -- nested view
SELECT * FROM atestv4; -- ok
DROP FUNCTION testfunc2(int);
DROP FUNCTION testfunc4(boolean);
-DROP VIEW atestv0;
DROP VIEW atestv1;
DROP VIEW atestv2;
-- this should cascade to drop atestv4