8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.123 2003/01/17 02:01:16 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.124 2003/01/17 03:25:03 tgl Exp $
12
12
*
13
13
* HISTORY
14
14
* AUTHOR DATE MAJOR EVENT
20
20
#include "postgres.h"
21
21
22
22
#include "catalog/pg_language.h"
23
- #include "catalog/pg_operator.h"
24
23
#include "catalog/pg_proc.h"
25
24
#include "catalog/pg_type.h"
26
25
#include "executor/executor.h"
27
26
#include "miscadmin.h"
28
27
#include "nodes/makefuncs.h"
29
28
#include "nodes/nodeFuncs.h"
30
29
#include "optimizer/clauses.h"
31
- #include "optimizer/tlist.h"
32
30
#include "optimizer/var.h"
33
31
#include "parser/analyze.h"
34
- #include "parser/parsetree.h"
35
32
#include "tcop/tcopprot.h"
36
33
#include "utils/acl.h"
37
34
#include "utils/builtins.h"
45
42
#define MAKEBOOLCONST (val ,isnull ) \
46
43
((Node *) makeConst(BOOLOID, 1, (Datum) (val), (isnull), true))
47
44
48
- typedef struct
49
- {
50
- Query * query ;
51
- List * groupClauses ;
52
- } check_subplans_for_ungrouped_vars_context ;
53
-
54
45
typedef struct
55
46
{
56
47
int nargs ;
@@ -64,8 +55,6 @@ static bool pull_agg_clause_walker(Node *node, List **listptr);
64
55
static bool expression_returns_set_walker (Node * node , void * context );
65
56
static bool contain_subplans_walker (Node * node , void * context );
66
57
static bool pull_subplans_walker (Node * node , List * * listptr );
67
- static bool check_subplans_for_ungrouped_vars_walker (Node * node ,
68
- check_subplans_for_ungrouped_vars_context * context );
69
58
static bool contain_mutable_functions_walker (Node * node , void * context );
70
59
static bool contain_volatile_functions_walker (Node * node , void * context );
71
60
static bool contain_nonstrict_functions_walker (Node * node , void * context );
@@ -552,157 +541,6 @@ pull_subplans_walker(Node *node, List **listptr)
552
541
(void * ) listptr );
553
542
}
554
543
555
- /*
556
- * check_subplans_for_ungrouped_vars
557
- * Check for subplans that are being passed ungrouped variables as
558
- * parameters; generate an error message if any are found.
559
- *
560
- * In most contexts, ungrouped variables will be detected by the parser (see
561
- * parse_agg.c, check_ungrouped_columns()). But that routine currently does
562
- * not check subplans, because the necessary info is not computed until the
563
- * planner runs. So we do it here, after we have processed sublinks into
564
- * subplans. This ought to be cleaned up someday.
565
- *
566
- * A deficiency in this scheme is that any outer reference var must be
567
- * grouped by itself; we don't recognize groupable expressions within
568
- * subselects. For example, consider
569
- * SELECT
570
- * (SELECT x FROM bar where y = (foo.a + foo.b))
571
- * FROM foo
572
- * GROUP BY a + b;
573
- * This query will be rejected although it could be allowed.
574
- */
575
- void
576
- check_subplans_for_ungrouped_vars (Query * query )
577
- {
578
- check_subplans_for_ungrouped_vars_context context ;
579
- List * gl ;
580
-
581
- context .query = query ;
582
-
583
- /*
584
- * Build a list of the acceptable GROUP BY expressions for use in the
585
- * walker (to avoid repeated scans of the targetlist within the
586
- * recursive routine).
587
- */
588
- context .groupClauses = NIL ;
589
- foreach (gl , query -> groupClause )
590
- {
591
- GroupClause * grpcl = lfirst (gl );
592
- Node * expr ;
593
-
594
- expr = get_sortgroupclause_expr (grpcl , query -> targetList );
595
- context .groupClauses = lcons (expr , context .groupClauses );
596
- }
597
-
598
- /*
599
- * Recursively scan the targetlist and the HAVING clause. WHERE and
600
- * JOIN/ON conditions are not examined, since they are evaluated
601
- * before grouping.
602
- */
603
- check_subplans_for_ungrouped_vars_walker ((Node * ) query -> targetList ,
604
- & context );
605
- check_subplans_for_ungrouped_vars_walker (query -> havingQual ,
606
- & context );
607
-
608
- freeList (context .groupClauses );
609
- }
610
-
611
- static bool
612
- check_subplans_for_ungrouped_vars_walker (Node * node ,
613
- check_subplans_for_ungrouped_vars_context * context )
614
- {
615
- List * gl ;
616
-
617
- if (node == NULL )
618
- return false;
619
- if (IsA (node , Const ) ||
620
- IsA (node , Param ))
621
- return false; /* constants are always acceptable */
622
-
623
- /*
624
- * If we find an aggregate function, do not recurse into its
625
- * arguments. Subplans invoked within aggregate calls are allowed to
626
- * receive ungrouped variables. (This test and the next one should
627
- * match the logic in parse_agg.c's check_ungrouped_columns().)
628
- */
629
- if (IsA (node , Aggref ))
630
- return false;
631
-
632
- /*
633
- * Check to see if subexpression as a whole matches any GROUP BY item.
634
- * We need to do this at every recursion level so that we recognize
635
- * GROUPed-BY expressions before reaching variables within them.
636
- */
637
- foreach (gl , context -> groupClauses )
638
- {
639
- if (equal (node , lfirst (gl )))
640
- return false; /* acceptable, do not descend more */
641
- }
642
-
643
- /*
644
- * We can ignore Vars other than in subplan args lists, since the
645
- * parser already checked 'em.
646
- */
647
- if (is_subplan (node ))
648
- {
649
- /*
650
- * The args list of the subplan node represents attributes from
651
- * outside passed into the sublink.
652
- */
653
- List * t ;
654
-
655
- foreach (t , ((SubPlan * ) node )-> args )
656
- {
657
- Node * thisarg = lfirst (t );
658
- Var * var ;
659
- bool contained_in_group_clause ;
660
-
661
- /*
662
- * We do not care about args that are not local variables;
663
- * params or outer-level vars are not our responsibility to
664
- * check. (The outer-level query passing them to us needs to
665
- * worry, instead.)
666
- */
667
- if (!IsA (thisarg , Var ))
668
- continue ;
669
- var = (Var * ) thisarg ;
670
- if (var -> varlevelsup > 0 )
671
- continue ;
672
-
673
- /*
674
- * Else, see if it is a grouping column.
675
- */
676
- contained_in_group_clause = false;
677
- foreach (gl , context -> groupClauses )
678
- {
679
- if (equal (thisarg , lfirst (gl )))
680
- {
681
- contained_in_group_clause = true;
682
- break ;
683
- }
684
- }
685
-
686
- if (!contained_in_group_clause )
687
- {
688
- /* Found an ungrouped argument. Complain. */
689
- RangeTblEntry * rte ;
690
- char * attname ;
691
-
692
- Assert (var -> varno > 0 &&
693
- (int ) var -> varno <= length (context -> query -> rtable ));
694
- rte = rt_fetch (var -> varno , context -> query -> rtable );
695
- attname = get_rte_attribute_name (rte , var -> varattno );
696
- elog (ERROR , "Sub-SELECT uses un-GROUPed attribute %s.%s from outer query" ,
697
- rte -> eref -> aliasname , attname );
698
- }
699
- }
700
- }
701
- return expression_tree_walker (node ,
702
- check_subplans_for_ungrouped_vars_walker ,
703
- (void * ) context );
704
- }
705
-
706
544
707
545
/*****************************************************************************
708
546
* Check clauses for mutable functions
0 commit comments