/* * Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software;Designed and Developed mainly by many Chinese * opensource volunteers. you can redistribute it and/or modify it under the * terms of the GNU General Public License version 2 only, as published by the * Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Any questions about this component can be directed to it's project Web address * https://code.google.com/p/opencloudb/. * */ package com.akiban.sql.parser; import com.akiban.sql.StandardException; import java.util.List; /** * A SelectNode represents the result set for any of the basic DML * operations: SELECT, INSERT, UPDATE, and DELETE. (A RowResultSetNode * will be used for an INSERT with a VALUES clause.) For INSERT - SELECT, * any of the fields in a SelectNode can be used (the SelectNode represents * the SELECT statement in the INSERT - SELECT). For UPDATE and * DELETE, there will be one table in the fromList, and the groupByList * fields will be null. For both INSERT and UPDATE, * the resultColumns in the selectList will contain the names of the columns * being inserted into or updated. * */ public class SelectNode extends ResultSetNode { /** * List of tables in the FROM clause of this SELECT */ private FromList fromList; /** * The ValueNode for the WHERE clause must represent a boolean * expression. The binding phase will enforce this - the parser * does not have enough information to enforce it in all cases * (for example, user methods that return boolean). */ private ValueNode whereClause; /** * List of result columns in GROUP BY clause */ private GroupByList groupByList; /** * List of windows. */ private WindowList windows; private boolean isDistinct, isStraightJoin; private ValueNode havingClause; public void init(Object selectList, Object aggregateList, Object fromList, Object whereClause, Object groupByList, Object havingClause, Object windowDefinitionList) throws StandardException { /* RESOLVE - remove aggregateList from constructor. * Consider adding selectAggregates and whereAggregates */ resultColumns = (ResultColumnList)selectList; if (resultColumns != null) resultColumns.markInitialSize(); this.fromList = (FromList)fromList; this.whereClause = (ValueNode)whereClause; this.groupByList = (GroupByList)groupByList; this.havingClause = (ValueNode)havingClause; // This initially represents an explicit <window definition list>, as // opposed to <in-line window specifications>, see 2003, 6.10 and 6.11. // <in-line window specifications> are added later, see right below for // in-line window specifications used in window functions in the SELECT // column list and in genProjectRestrict for such window specifications // used in window functions in ORDER BY. this.windows = (WindowList)windowDefinitionList; // TODO: Walking to find window and subqueries in WHERE. } /** * Fill this node with a deep copy of the given node. */ public void copyFrom(QueryTreeNode node) throws StandardException { super.copyFrom(node); SelectNode other = (SelectNode)node; this.fromList = (FromList)getNodeFactory().copyNode(other.fromList, getParserContext()); this.whereClause = (ValueNode)getNodeFactory().copyNode(other.whereClause, getParserContext()); this.groupByList = (GroupByList)getNodeFactory().copyNode(other.groupByList, getParserContext()); this.windows = (WindowList)getNodeFactory().copyNode(other.windows, getParserContext()); this.isDistinct = other.isDistinct; this.havingClause = (ValueNode)getNodeFactory().copyNode(other.havingClause, getParserContext()); } /** * Convert this object to a String. See comments in QueryTreeNode.java * for how this should be done for tree printing. * * @return This object as a String */ public String toString() { return "isDistinct: "+ isDistinct + "\n"+ super.toString(); } public String statementToString() { return "SELECT"; } public void makeDistinct() { isDistinct = true; } public void clearDistinct() { isDistinct = false; } public boolean isDistinct() { return isDistinct; } public void makeStraightJoin() { isStraightJoin = true; } public boolean isStraightJoin() { return isStraightJoin; } /** * Prints the sub-nodes of this object. See QueryTreeNode.java for * how tree printing is supposed to work. * * @param depth The depth of this node in the tree */ public void printSubNodes(int depth) { super.printSubNodes(depth); printLabel(depth, "fromList: "); if (fromList != null) { fromList.treePrint(depth + 1); } if (whereClause != null) { printLabel(depth, "whereClause: "); whereClause.treePrint(depth + 1); } if (groupByList != null) { printLabel(depth, "groupByList:"); groupByList.treePrint(depth + 1); } if (havingClause != null) { printLabel(depth, "havingClause:"); havingClause.treePrint(depth + 1); } if (windows != null) { printLabel(depth, "windows: "); windows.treePrint(depth + 1); } } /** * Return the fromList for this SelectNode. * * @return FromList The fromList for this SelectNode. */ public FromList getFromList() { return fromList; } /** * Return the whereClause for this SelectNode. * * @return ValueNode The whereClause for this SelectNode. */ public ValueNode getWhereClause() { return whereClause; } public void setWhereClause(ValueNode whereClause) { this.whereClause = whereClause; } public GroupByList getGroupByList() { return groupByList; } public ValueNode getHavingClause() { return havingClause; } public void setHavingClause(ValueNode havingClause) { this.havingClause = havingClause; } /** * Accept the visitor for all visitable children of this node. * * @param v the visitor * * @exception StandardException on error */ void acceptChildren(Visitor v) throws StandardException { super.acceptChildren(v); if (fromList != null) { fromList = (FromList)fromList.accept(v); } if (whereClause != null) { whereClause = (ValueNode)whereClause.accept(v); } if (groupByList != null) { groupByList = (GroupByList)groupByList.accept(v); } if (havingClause != null) { havingClause = (ValueNode)havingClause.accept(v); } if (windows != null) { windows = (WindowList)windows.accept(v); } } /** * Used by SubqueryNode to avoid flattening of a subquery if a window is * defined on it. Note that any inline window definitions should have been * collected from both the selectList and orderByList at the time this * method is called, so the windows list is complete. This is true after * preprocess is completed. * * @return true if this select node has any windows on it */ public boolean hasWindows() { return windows != null; } public WindowList getWindows() { return windows; } }