/*
* <A NAME="tableExpression">tableExpression</A>
*/
final public SelectNode tableExpression(ResultColumnList selectList) throws ParseException, StandardException {
SelectNode selectNode;
FromList fromList;
ValueNode whereClause = null;
GroupByList groupByList = null;
ValueNode havingClause = null;
Token whereToken;
fromList = fromClause();
switch (jj_nt.kind) {
case WHERE:
whereToken = jj_consume_token(WHERE);
whereClause = whereClause(whereToken);
break;
default:
jj_la1[161] = jj_gen;
;
}
switch (jj_nt.kind) {
case GROUP:
groupByList = groupByClause();
break;
default:
jj_la1[162] = jj_gen;
;
}
switch (jj_nt.kind) {
case HAVING:
havingClause = havingClause();
break;
default:
jj_la1[163] = jj_gen;
;
}
selectNode = (SelectNode) nodeFactory.getNode(
C_NodeTypes.SELECT_NODE,
selectList,
null, /* AGGREGATE list */
fromList,
whereClause,
groupByList,
getContextManager());
/* A SELECT with a GROUP BY or HAVING clause is the one instance where the
* parser will generate a tree that does not exactly match the query.
* The resulting tree is an outer SelectNode with the HAVING clause
* as its WHERE clause and a FromList containing a single FromSubquery -
* the user SELECT, minus the HAVING clause.
* The outer SELECT gets a SELECT *.
* The FromSubquery will have a null name, something that the user cannot do,
* to enable the binding of any correlated columns in the HAVING clause.
*/
if (groupByList != null || havingClause != null)
{
FromSubquery fromSubquery;
ResultColumnList outerRCL =
(ResultColumnList) nodeFactory.getNode(
C_NodeTypes.RESULT_COLUMN_LIST,
getContextManager());
/* Wrap the user SELECT in a FromSubquery */
fromList = (FromList) nodeFactory.getNode(
C_NodeTypes.FROM_LIST,
getNodeFactory().doJoinOrderOptimization(),
getContextManager());
fromSubquery = (FromSubquery) nodeFactory.getNode(
C_NodeTypes.FROM_SUBQUERY,
selectNode,
null,
null,
null,
getContextManager());
fromList.addElement(fromSubquery);
/* Pull any aggregates out of the HAVING clause and append them to
* SELECT list in the user's select, replacing the aggregates in
* the HAVING clause with ColumnReferences to the aggregate.
* Do NOT replace anything below a ResultSetNode. This means that