Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit18e8f06

Browse files
committed
Arrange to give error when a SetOp member statement refers to a variable
of the containing query (which really can only happen in a rule context).Per example from Brandon Craig Rhodes. Also, make the error messagemore specific for the similar case with sub-select in FROM. The revisedcoding should be easier to adapt to SQL99's LATERAL(), when we get aroundto supporting that.
1 parent53c15ce commit18e8f06

File tree

3 files changed

+49
-37
lines changed

3 files changed

+49
-37
lines changed

‎src/backend/parser/analyze.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
*$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.262 2003/02/11 04:13:06 tgl Exp $
9+
*$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.263 2003/02/13 20:45:21 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -23,6 +23,7 @@
2323
#include"commands/prepare.h"
2424
#include"nodes/makefuncs.h"
2525
#include"optimizer/clauses.h"
26+
#include"optimizer/var.h"
2627
#include"parser/analyze.h"
2728
#include"parser/gramparse.h"
2829
#include"parser/parsetree.h"
@@ -1982,6 +1983,19 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
19821983

19831984
Assert(length(selectList)==1);
19841985
selectQuery= (Query*)lfirst(selectList);
1986+
Assert(IsA(selectQuery,Query));
1987+
1988+
/*
1989+
* Check for bogus references to Vars on the current query level
1990+
* (but upper-level references are okay).
1991+
* Normally this can't happen because the namespace will be empty,
1992+
* but it could happen if we are inside a rule.
1993+
*/
1994+
if (pstate->p_namespace)
1995+
{
1996+
if (contain_vars_of_level((Node*)selectQuery,1))
1997+
elog(ERROR,"UNION/INTERSECT/EXCEPT member statement may not refer to other relations of same query level");
1998+
}
19851999

19862000
/*
19872001
* Make the leaf query be a subquery in the top-level rangetable.

‎src/backend/parser/parse_clause.c

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.108 2003/02/1305:53:46 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.109 2003/02/1320:45:21 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -383,7 +383,6 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
383383
staticRangeTblRef*
384384
transformRangeSubselect(ParseState*pstate,RangeSubselect*r)
385385
{
386-
List*save_namespace;
387386
List*parsetrees;
388387
Query*query;
389388
RangeTblEntry*rte;
@@ -398,21 +397,10 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
398397
elog(ERROR,"sub-select in FROM must have an alias");
399398

400399
/*
401-
* Analyze and transform the subquery.This is a bit tricky because
402-
* we don't want the subquery to be able to see any FROM items already
403-
* created in the current query (per SQL92, the scope of a FROM item
404-
* does not include other FROM items).But it does need to be able to
405-
* see any further-up parent states, so we can't just pass a null
406-
* parent pstate link.So, temporarily make the current query level
407-
* have an empty namespace.
400+
* Analyze and transform the subquery.
408401
*/
409-
save_namespace=pstate->p_namespace;
410-
pstate->p_namespace=NIL;
411-
412402
parsetrees=parse_analyze(r->subquery,pstate);
413403

414-
pstate->p_namespace=save_namespace;
415-
416404
/*
417405
* Check that we got something reasonable.Some of these conditions
418406
* are probably impossible given restrictions of the grammar, but
@@ -429,6 +417,25 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
429417
if (query->resultRelation!=0||query->into!=NULL||query->isPortal)
430418
elog(ERROR,"Subselect in FROM may not have SELECT INTO");
431419

420+
/*
421+
* The subquery cannot make use of any variables from FROM items created
422+
* earlier in the current query. Per SQL92, the scope of a FROM item
423+
* does not include other FROM items. Formerly we hacked the namespace
424+
* so that the other variables weren't even visible, but it seems more
425+
* useful to leave them visible and give a specific error message.
426+
*
427+
* XXX this will need further work to support SQL99's LATERAL() feature,
428+
* wherein such references would indeed be legal.
429+
*
430+
* We can skip groveling through the subquery if there's not anything
431+
* visible in the current query. Also note that outer references are OK.
432+
*/
433+
if (pstate->p_namespace)
434+
{
435+
if (contain_vars_of_level((Node*)query,1))
436+
elog(ERROR,"Subselect in FROM may not refer to other relations of same query level");
437+
}
438+
432439
/*
433440
* OK, build an RTE for the subquery.
434441
*/
@@ -455,7 +462,6 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
455462
{
456463
Node*funcexpr;
457464
char*funcname;
458-
List*save_namespace;
459465
RangeTblEntry*rte;
460466
RangeTblRef*rtr;
461467

@@ -464,31 +470,24 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
464470
funcname=strVal(llast(((FuncCall*)r->funccallnode)->funcname));
465471

466472
/*
467-
* Transform the raw FuncCall node. This is a bit tricky because we
468-
* don't want the function expression to be able to see any FROM items
469-
* already created in the current query (compare to
470-
* transformRangeSubselect). But it does need to be able to see any
471-
* further-up parent states. So, temporarily make the current query
472-
* level have an empty namespace. NOTE: this code is OK only because
473-
* the expression can't legally alter the namespace by causing
474-
* implicit relation refs to be added.
473+
* Transform the raw FuncCall node.
475474
*/
476-
save_namespace=pstate->p_namespace;
477-
pstate->p_namespace=NIL;
478-
479475
funcexpr=transformExpr(pstate,r->funccallnode);
480476

481-
pstate->p_namespace=save_namespace;
482-
483477
/*
484-
* We still need to check that the function parameters don't refer to
485-
* any other rels.That could happen despite our hack on the
486-
* namespace if fully-qualified names are used. So, check there are
487-
* no local Var references in the transformed expression. (Outer
488-
* references are OK, and are ignored here.)
478+
* The function parameters cannot make use of any variables from other
479+
* FROM items. (Compare to transformRangeSubselect(); the coding is
480+
* different though because we didn't parse as a sub-select with its own
481+
* level of namespace.)
482+
*
483+
* XXX this will need further work to support SQL99's LATERAL() feature,
484+
* wherein such references would indeed be legal.
489485
*/
490-
if (!bms_is_empty(pull_varnos(funcexpr)))
491-
elog(ERROR,"FROM function expression may not refer to other relations of same query level");
486+
if (pstate->p_namespace)
487+
{
488+
if (contain_vars_of_level(funcexpr,0))
489+
elog(ERROR,"FROM function expression may not refer to other relations of same query level");
490+
}
492491

493492
/*
494493
* Disallow aggregate functions in the expression.(No reason to

‎src/test/regress/expected/rangefuncs.out

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ INSERT INTO foo2 VALUES(1, 111);
1818
CREATE FUNCTION foot(int) returns setof foo2 as 'SELECT * FROM foo2 WHERE fooid = $1;' LANGUAGE SQL;
1919
-- supposed to fail with ERROR
2020
select * from foo2, foot(foo2.fooid) z where foo2.f2 = z.f2;
21-
NOTICE: Adding missing FROM-clause entry for table "foo2"
2221
ERROR: FROM function expression may not refer to other relations of same query level
2322
-- function in subselect
2423
select * from foo2 where f2 in (select f2 from foot(foo2.fooid) z where z.fooid = foo2.fooid) ORDER BY 1,2;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp