Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
692a65e6
Commit
692a65e6
authored
Jan 26, 1999
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
pgindent file.
parent
2ee52295
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
234 additions
and
224 deletions
+234
-224
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/plan/setrefs.c
+234
-224
No files found.
src/backend/optimizer/plan/setrefs.c
View file @
692a65e6
...
...
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.3
3 1999/01/25 18:02:18
momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.3
4 1999/01/26 05:57:14
momjian Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -916,195 +916,195 @@ del_agg_clause(Node *clause)
return
NULL
;
}
/***S*H***/
/***S*H***/
/* check_having_qual_for_vars takes the the havingQual and the actual targetlist as arguments
* and recursively scans the havingQual for attributes that are not included in the targetlist
* yet. Attributes contained in the havingQual but not in the targetlist show up with queries
* like:
* SELECT sid
* like:
* SELECT sid
* FROM part
* GROUP BY sid
* HAVING MIN(pid) > 1; (pid is used but never selected for!!!).
* HAVING MIN(pid) > 1; (pid is used but never selected for!!!).
* To be able to handle queries like that correctly we have to extend the actual targetlist
*
(which will be the one used for the GROUP node later on) by these attributes. */
*
(which will be the one used for the GROUP node later on) by these attributes. */
List
*
check_having_qual_for_vars
(
Node
*
clause
,
List
*
targetlist_so_far
)
{
List
*
t
;
List
*
t
;
if
(
IsA
(
clause
,
Var
))
{
RelOptInfo
tmp_rel
;
if
(
IsA
(
clause
,
Var
))
{
RelOptInfo
tmp_rel
;
tmp_rel
.
targetlist
=
targetlist_so_far
;
/*
* Ha! A Var node!
*/
tmp_rel
.
targetlist
=
targetlist_so_far
;
/* Check if the VAR is already contained in the targetlist */
if
(
tlist_member
((
Var
*
)
clause
,
(
List
*
)
targetlist_so_far
)
==
NULL
)
/*
* Ha! A Var node!
*/
/* Check if the VAR is already contained in the targetlist */
if
(
tlist_member
((
Var
*
)
clause
,
(
List
*
)
targetlist_so_far
)
==
NULL
)
add_tl_element
(
&
tmp_rel
,
(
Var
*
)
clause
);
return
tmp_rel
.
targetlist
;
}
else
if
(
is_funcclause
(
clause
)
||
not_clause
(
clause
)
||
or_clause
(
clause
)
||
and_clause
(
clause
))
{
add_tl_element
(
&
tmp_rel
,
(
Var
*
)
clause
);
}
return
tmp_rel
.
targetlist
;
}
else
if
(
is_funcclause
(
clause
)
||
not_clause
(
clause
)
||
or_clause
(
clause
)
||
and_clause
(
clause
))
{
/*
* This is a function. Recursively call this routine for its
* arguments...
*/
foreach
(
t
,
((
Expr
*
)
clause
)
->
args
)
/*
* This is a function. Recursively call this routine for its
* arguments...
*/
foreach
(
t
,
((
Expr
*
)
clause
)
->
args
)
targetlist_so_far
=
check_having_qual_for_vars
(
lfirst
(
t
),
targetlist_so_far
);
return
targetlist_so_far
;
}
else
if
(
IsA
(
clause
,
Aggref
))
{
targetlist_so_far
=
check_having_qual_for_vars
(
lfirst
(
t
),
targetlist_so_far
);
targetlist_so_far
=
check_having_qual_for_vars
(((
Aggref
*
)
clause
)
->
target
,
targetlist_so_far
);
return
targetlist_so_far
;
}
return
targetlist_so_far
;
}
else
if
(
IsA
(
clause
,
Aggref
))
{
targetlist_so_far
=
check_having_qual_for_vars
(((
Aggref
*
)
clause
)
->
target
,
targetlist_so_far
);
return
targetlist_so_far
;
}
else
if
(
IsA
(
clause
,
ArrayRef
))
{
ArrayRef
*
aref
=
(
ArrayRef
*
)
clause
;
/*
* This is an arrayref. Recursively call this routine for its
* expression and its index expression...
*/
foreach
(
t
,
aref
->
refupperindexpr
)
else
if
(
IsA
(
clause
,
ArrayRef
))
{
targetlist_so_far
=
check_having_qual_for_vars
(
lfirst
(
t
),
targetlist_so_far
);
ArrayRef
*
aref
=
(
ArrayRef
*
)
clause
;
/*
* This is an arrayref. Recursively call this routine for its
* expression and its index expression...
*/
foreach
(
t
,
aref
->
refupperindexpr
)
targetlist_so_far
=
check_having_qual_for_vars
(
lfirst
(
t
),
targetlist_so_far
);
foreach
(
t
,
aref
->
reflowerindexpr
)
targetlist_so_far
=
check_having_qual_for_vars
(
lfirst
(
t
),
targetlist_so_far
);
targetlist_so_far
=
check_having_qual_for_vars
(
aref
->
refexpr
,
targetlist_so_far
);
targetlist_so_far
=
check_having_qual_for_vars
(
aref
->
refassgnexpr
,
targetlist_so_far
);
return
targetlist_so_far
;
}
foreach
(
t
,
aref
->
reflowerindexpr
)
else
if
(
is_opclause
(
clause
)
)
{
targetlist_so_far
=
check_having_qual_for_vars
(
lfirst
(
t
),
targetlist_so_far
);
/*
* This is an operator. Recursively call this routine for both its
* left and right operands
*/
Node
*
left
=
(
Node
*
)
get_leftop
((
Expr
*
)
clause
);
Node
*
right
=
(
Node
*
)
get_rightop
((
Expr
*
)
clause
);
if
(
left
!=
(
Node
*
)
NULL
)
targetlist_so_far
=
check_having_qual_for_vars
(
left
,
targetlist_so_far
);
if
(
right
!=
(
Node
*
)
NULL
)
targetlist_so_far
=
check_having_qual_for_vars
(
right
,
targetlist_so_far
);
return
targetlist_so_far
;
}
else
if
(
IsA
(
clause
,
Param
)
||
IsA
(
clause
,
Const
))
{
/* do nothing! */
return
targetlist_so_far
;
}
targetlist_so_far
=
check_having_qual_for_vars
(
aref
->
refexpr
,
targetlist_so_far
);
targetlist_so_far
=
check_having_qual_for_vars
(
aref
->
refassgnexpr
,
targetlist_so_far
);
return
targetlist_so_far
;
}
else
if
(
is_opclause
(
clause
))
{
/*
* This is an operator. Recursively call this routine for both its
* left and right operands
*/
Node
*
left
=
(
Node
*
)
get_leftop
((
Expr
*
)
clause
);
Node
*
right
=
(
Node
*
)
get_rightop
((
Expr
*
)
clause
);
if
(
left
!=
(
Node
*
)
NULL
)
targetlist_so_far
=
check_having_qual_for_vars
(
left
,
targetlist_so_far
);
if
(
right
!=
(
Node
*
)
NULL
)
targetlist_so_far
=
check_having_qual_for_vars
(
right
,
targetlist_so_far
);
return
targetlist_so_far
;
}
else
if
(
IsA
(
clause
,
Param
)
||
IsA
(
clause
,
Const
))
{
/* do nothing! */
return
targetlist_so_far
;
}
/* If we get to a sublink, then we only have to check the lefthand side of the expression
* to see if there are any additional VARs */
else
if
(
IsA
(
clause
,
SubLink
))
{
foreach
(
t
,((
List
*
)((
SubLink
*
)
clause
)
->
lefthand
))
/*
* If we get to a sublink, then we only have to check the lefthand
* side of the expression to see if there are any additional VARs
*/
else
if
(
IsA
(
clause
,
SubLink
))
{
foreach
(
t
,
((
List
*
)
((
SubLink
*
)
clause
)
->
lefthand
))
targetlist_so_far
=
check_having_qual_for_vars
(
lfirst
(
t
),
targetlist_so_far
);
return
targetlist_so_far
;
}
else
{
targetlist_so_far
=
check_having_qual_for_vars
(
lfirst
(
t
),
targetlist_so_far
);
/*
* Ooops! we can not handle that!
*/
elog
(
ERROR
,
"check_having_qual_for_vars: Can not handle this having_qual! %d
\n
"
,
nodeTag
(
clause
));
return
NIL
;
}
return
targetlist_so_far
;
}
else
{
/*
* Ooops! we can not handle that!
*/
elog
(
ERROR
,
"check_having_qual_for_vars: Can not handle this having_qual! %d
\n
"
,
nodeTag
(
clause
));
return
NIL
;
}
}
/* check_having_qual_for_aggs takes the havingQual, the targetlist and the groupClause
/* check_having_qual_for_aggs takes the havingQual, the targetlist and the groupClause
* as arguments and scans the havingQual recursively for aggregates. If an aggregate is
* found it is attached to a list and returned by the function. (All the returned lists
* found it is attached to a list and returned by the function. (All the returned lists
* are concenated to result_plan->aggs in planner.c:union_planner() */
List
*
check_having_qual_for_aggs
(
Node
*
clause
,
List
*
subplanTargetList
,
List
*
groupClause
)
{
List
*
t
,
*
l1
;
List
*
t
,
*
l1
;
List
*
agg_list
=
NIL
;
int
contained_in_group_clause
=
0
;
int
contained_in_group_clause
=
0
;
if
(
IsA
(
clause
,
Var
))
{
TargetEntry
*
subplanVar
;
/*
* Ha! A Var node!
*/
subplanVar
=
match_varid
((
Var
*
)
clause
,
subplanTargetList
);
/*
* Change the varno & varattno fields of the var node to point to the resdom->resn
o
* fields of the subplan (lefttree)
*/
((
Var
*
)
clause
)
->
varattno
=
subplanVar
->
resdom
->
resno
;
return
NIL
;
TargetEntry
*
subplanVar
;
/*
* Ha! A Var node!
*/
subplanVar
=
match_varid
((
Var
*
)
clause
,
subplanTargetList
);
/*
* Change the varno & varattno fields of the var node to point t
o
* the resdom->resno fields of the subplan (lefttree)
*/
((
Var
*
)
clause
)
->
varattno
=
subplanVar
->
resdom
->
resno
;
return
NIL
;
}
/***S*H***/
else
if
(
is_funcclause
(
clause
)
||
not_clause
(
clause
)
||
or_clause
(
clause
)
||
and_clause
(
clause
))
/***S*H***/
else
if
(
is_funcclause
(
clause
)
||
not_clause
(
clause
)
||
or_clause
(
clause
)
||
and_clause
(
clause
))
{
int
new_length
=
0
,
old_length
=
0
;
int
new_length
=
0
,
old_length
=
0
;
/*
* This is a function. Recursively call this routine for its
* arguments... (i.e. for AND, OR, ... clauses!)
*/
foreach
(
t
,
((
Expr
*
)
clause
)
->
args
)
{
old_length
=
length
((
List
*
)
agg_list
);
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
lfirst
(
t
),
subplanTargetList
,
groupClause
));
/* The arguments of OR or AND clauses are comparisons or relations
* and because we are in the havingQual there must be at least one operand
* using an aggregate function. If so, we will find it and the length of the
* agg_list will be increased after the above call to
* check_having_qual_for_aggs. If there are no aggregates used, the query
* could have been formulated using the 'where' clause */
if
(((
new_length
=
length
((
List
*
)
agg_list
))
==
old_length
)
||
(
new_length
==
0
))
{
elog
(
ERROR
,
"This could have been done in a where clause!!"
);
return
NIL
;
}
old_length
=
length
((
List
*
)
agg_list
);
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
lfirst
(
t
),
subplanTargetList
,
groupClause
));
/*
* The arguments of OR or AND clauses are comparisons or
* relations and because we are in the havingQual there must
* be at least one operand using an aggregate function. If so,
* we will find it and the length of the agg_list will be
* increased after the above call to
* check_having_qual_for_aggs. If there are no aggregates
* used, the query could have been formulated using the
* 'where' clause
*/
if
(((
new_length
=
length
((
List
*
)
agg_list
))
==
old_length
)
||
(
new_length
==
0
))
{
elog
(
ERROR
,
"This could have been done in a where clause!!"
);
return
NIL
;
}
}
return
agg_list
;
}
else
if
(
IsA
(
clause
,
Aggref
))
{
return
lcons
(
clause
,
check_having_qual_for_aggs
(((
Aggref
*
)
clause
)
->
target
,
subplanTargetList
,
groupClause
));
check_having_qual_for_aggs
(((
Aggref
*
)
clause
)
->
target
,
subplanTargetList
,
groupClause
));
}
else
if
(
IsA
(
clause
,
ArrayRef
))
{
...
...
@@ -1117,21 +1117,21 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla
foreach
(
t
,
aref
->
refupperindexpr
)
{
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
lfirst
(
t
),
subplanTargetList
,
groupClause
));
check_having_qual_for_aggs
(
lfirst
(
t
),
subplanTargetList
,
groupClause
));
}
foreach
(
t
,
aref
->
reflowerindexpr
)
{
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
lfirst
(
t
),
subplanTargetList
,
groupClause
));
check_having_qual_for_aggs
(
lfirst
(
t
),
subplanTargetList
,
groupClause
));
}
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
aref
->
refexpr
,
subplanTargetList
,
groupClause
));
check_having_qual_for_aggs
(
aref
->
refexpr
,
subplanTargetList
,
groupClause
));
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
aref
->
refassgnexpr
,
subplanTargetList
,
groupClause
));
check_having_qual_for_aggs
(
aref
->
refassgnexpr
,
subplanTargetList
,
groupClause
));
return
agg_list
;
}
...
...
@@ -1147,92 +1147,102 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla
if
(
left
!=
(
Node
*
)
NULL
)
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
left
,
subplanTargetList
,
groupClause
));
check_having_qual_for_aggs
(
left
,
subplanTargetList
,
groupClause
));
if
(
right
!=
(
Node
*
)
NULL
)
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
right
,
subplanTargetList
,
groupClause
));
groupClause
));
return
agg_list
;
}
else
if
(
IsA
(
clause
,
Param
)
||
IsA
(
clause
,
Const
))
else
if
(
IsA
(
clause
,
Param
)
||
IsA
(
clause
,
Const
))
{
/* do nothing! */
return
NIL
;
}
/* This is for Sublinks which show up as EXPR nodes. All the other EXPR nodes
* (funcclauses, and_clauses, or_clauses) were caught above */
/*
* This is for Sublinks which show up as EXPR nodes. All the other
* EXPR nodes (funcclauses, and_clauses, or_clauses) were caught above
*/
else
if
(
IsA
(
clause
,
Expr
))
{
/* Only the lefthand side of the sublink has to be checked for aggregates
* to be attached to result_plan->aggs (see planner.c:union_planner() )
*/
foreach
(
t
,((
List
*
)((
SubLink
*
)((
SubPlan
*
)
((
Expr
*
)
clause
)
->
oper
)
->
sublink
)
->
lefthand
))
{
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
lfirst
(
t
),
subplanTargetList
,
groupClause
));
}
/* The first argument of ...->oper has also to be checked */
{
List
*
tmp_ptr
;
foreach
(
tmp_ptr
,
((
SubLink
*
)((
SubPlan
*
)
((
Expr
*
)
clause
)
->
oper
)
->
sublink
)
->
oper
)
{
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
((
Node
*
)
lfirst
(((
Expr
*
)
lfirst
(
tmp_ptr
))
->
args
),
subplanTargetList
,
groupClause
));
{
/*
* Only the lefthand side of the sublink has to be checked for
* aggregates to be attached to result_plan->aggs (see
* planner.c:union_planner() )
*/
foreach
(
t
,
((
List
*
)
((
SubLink
*
)
((
SubPlan
*
)
((
Expr
*
)
clause
)
->
oper
)
->
sublink
)
->
lefthand
))
{
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
lfirst
(
t
),
subplanTargetList
,
groupClause
));
}
}
/* All arguments to the Sublink node are attributes from outside used within
* the sublink. Here we have to check that only attributes that is grouped for
* are used! */
foreach
(
t
,((
Expr
*
)
clause
)
->
args
)
{
contained_in_group_clause
=
0
;
foreach
(
l1
,
groupClause
)
{
if
(
tlist_member
(
lfirst
(
t
),
lcons
(((
GroupClause
*
)
lfirst
(
l1
))
->
entry
,
NIL
))
!=
NULL
)
{
contained_in_group_clause
=
1
;
}
}
/* If the use of the attribute is allowed (i.e. it is in the groupClause)
* we have to adjust the varnos and varattnos */
if
(
contained_in_group_clause
)
{
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
lfirst
(
t
),
subplanTargetList
,
groupClause
));
}
else
{
elog
(
ERROR
,
"You must group by the attribute used from outside!"
);
return
NIL
;
}
}
return
agg_list
;
}
/* The first argument of ...->oper has also to be checked */
{
List
*
tmp_ptr
;
foreach
(
tmp_ptr
,
((
SubLink
*
)
((
SubPlan
*
)
((
Expr
*
)
clause
)
->
oper
)
->
sublink
)
->
oper
)
{
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
((
Node
*
)
lfirst
(((
Expr
*
)
lfirst
(
tmp_ptr
))
->
args
),
subplanTargetList
,
groupClause
));
}
}
/*
* All arguments to the Sublink node are attributes from outside
* used within the sublink. Here we have to check that only
* attributes that is grouped for are used!
*/
foreach
(
t
,
((
Expr
*
)
clause
)
->
args
)
{
contained_in_group_clause
=
0
;
foreach
(
l1
,
groupClause
)
{
if
(
tlist_member
(
lfirst
(
t
),
lcons
(((
GroupClause
*
)
lfirst
(
l1
))
->
entry
,
NIL
))
!=
NULL
)
contained_in_group_clause
=
1
;
}
/*
* If the use of the attribute is allowed (i.e. it is in the
* groupClause) we have to adjust the varnos and varattnos
*/
if
(
contained_in_group_clause
)
{
agg_list
=
nconc
(
agg_list
,
check_having_qual_for_aggs
(
lfirst
(
t
),
subplanTargetList
,
groupClause
));
}
else
{
elog
(
ERROR
,
"You must group by the attribute used from outside!"
);
return
NIL
;
}
}
return
agg_list
;
}
else
{
/*
* Ooops! we can not handle that!
*/
elog
(
ERROR
,
"check_having_qual_for_aggs: Can not handle this having_qual! %d
\n
"
,
nodeTag
(
clause
));
return
NIL
;
}
{
/*
* Ooops! we can not handle that!
*/
elog
(
ERROR
,
"check_having_qual_for_aggs: Can not handle this having_qual! %d
\n
"
,
nodeTag
(
clause
));
return
NIL
;
}
}
/***S*H***/
/* End */
/***S*H***//* End */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment