/* Copyright (c) 2001-2019, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb;

import org.hsqldb.HsqlNameManager.HsqlName;
import org.hsqldb.ParserDQL.CompileContext;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.index.Index;
import org.hsqldb.lib.ArrayListIdentity;
import org.hsqldb.lib.ArrayUtil;
import org.hsqldb.lib.HashMappedList;
import org.hsqldb.lib.HsqlList;
import org.hsqldb.lib.OrderedHashSet;
import org.hsqldb.lib.OrderedIntHashSet;
import org.hsqldb.lib.Set;
import org.hsqldb.map.ValuePool;
import org.hsqldb.navigator.RowSetNavigatorData;
import org.hsqldb.navigator.RowSetNavigatorDataTable;
import org.hsqldb.result.Result;
import org.hsqldb.result.ResultMetaData;
import org.hsqldb.types.Type;
import org.hsqldb.types.Types;

/**
 * Implementation of an SQL query expression
 *
 * @author Fred Toussi (fredt@users dot sourceforge.net)
 * @version 2.3.4
 * @since 1.9.0
 */

@todo1.9.0 - review these - work out usage of getMainSelect etc and add relevant methods - Result metadata for the final result of QueryExpression
/** * @todo 1.9.0 - review these * - work out usage of getMainSelect etc and add relevant methods * - Result metadata for the final result of QueryExpression * */
public class QueryExpression implements RangeGroup { public static final int NOUNION = 0, UNION = 1, UNION_ALL = 2, INTERSECT = 3, INTERSECT_ALL = 4, EXCEPT_ALL = 5, EXCEPT = 6, UNION_TERM = 7; // int columnCount; private QueryExpression leftQueryExpression; private QueryExpression rightQueryExpression; SortAndSlice sortAndSlice; private int unionType; private boolean unionCorresponding; private OrderedHashSet unionCorrespondingColumns; int[] unionColumnMap; Type[] unionColumnTypes; boolean isFullOrder; // HsqlList unresolvedExpressions; // boolean isReferencesResolved; boolean isPartOneResolved; boolean isPartTwoResolved; boolean isResolved; // int persistenceScope = TableBase.SCOPE_STATEMENT; // ResultMetaData resultMetaData; boolean[] accessibleColumns; // View view; boolean isBaseMergeable; boolean isMergeable; boolean isUpdatable; boolean isInsertable; boolean isCheckable; boolean isTopLevel; boolean isRecursive; boolean isSingleRow; boolean acceptsSequences; boolean isCorrelated; boolean isTable; boolean isValueList; // TableDerived recursiveTable; // public TableBase resultTable; public Index mainIndex; public Index fullIndex; public Index orderIndex; public Index idIndex; // CompileContext compileContext; // QueryExpression(CompileContext compileContext) { this.compileContext = compileContext; sortAndSlice = SortAndSlice.noSort; } public QueryExpression(CompileContext compileContext, QueryExpression leftQueryExpression) { this(compileContext); sortAndSlice = SortAndSlice.noSort; this.leftQueryExpression = leftQueryExpression; } public RangeVariable[] getRangeVariables() { return RangeVariable.emptyArray; } public void setCorrelated() { isCorrelated = true; } public boolean isVariable() { return false; } public void setSingleRow() { isSingleRow = true; } public boolean isRecursive() { return isRecursive; } void addUnion(QueryExpression queryExpression, int unionType) { sortAndSlice = SortAndSlice.noSort; this.rightQueryExpression = queryExpression; this.unionType = unionType; setFullOrder(); } void addSortAndSlice(SortAndSlice sortAndSlice) { this.sortAndSlice = sortAndSlice; sortAndSlice.sortUnion = true; } public void setUnionCorresoponding() { unionCorresponding = true; } public void setUnionCorrespondingColumns(OrderedHashSet names) { unionCorrespondingColumns = names; } public void setFullOrder() { isFullOrder = true; if (leftQueryExpression != null) { leftQueryExpression.setFullOrder(); } if (rightQueryExpression != null) { rightQueryExpression.setFullOrder(); } } public void resolve(Session session) { resolveReferences(session, RangeGroup.emptyArray); ExpressionColumn.checkColumnsResolved(unresolvedExpressions); resolveTypes(session); } public void resolve(Session session, RangeGroup[] rangeGroups, Type[] targetTypes) { resolveReferences(session, rangeGroups); ExpressionColumn.checkColumnsResolved(unresolvedExpressions); resolveTypesPartOne(session); if (targetTypes != null) { for (int i = 0; i < unionColumnTypes.length && i < targetTypes.length; i++) { if (unionColumnTypes[i] == null) { unionColumnTypes[i] = targetTypes[i]; } } } resolveTypesPartTwo(session); resolveTypesPartThree(session); } public void resolveReferences(Session session, RangeGroup[] rangeGroups) { if (isReferencesResolved) { return; } leftQueryExpression.resolveReferences(session, rangeGroups); rightQueryExpression.resolveReferences(session, rangeGroups); addUnresolvedExpressions(leftQueryExpression.unresolvedExpressions); addUnresolvedExpressions(rightQueryExpression.unresolvedExpressions); if (leftQueryExpression.isCorrelated || rightQueryExpression.isCorrelated) { setCorrelated(); } if (!unionCorresponding) { columnCount = leftQueryExpression.getColumnCount(); int rightCount = rightQueryExpression.getColumnCount(); if (columnCount != rightCount) { throw Error.error(ErrorCode.X_42594); } unionColumnTypes = new Type[columnCount]; leftQueryExpression.unionColumnMap = rightQueryExpression.unionColumnMap = new int[columnCount]; ArrayUtil.fillSequence(leftQueryExpression.unionColumnMap); resolveColumnReferencesInUnionOrderBy(); accessibleColumns = leftQueryExpression.accessibleColumns; isReferencesResolved = true; return; } String[] leftNames = leftQueryExpression.getColumnNames(); String[] rightNames = rightQueryExpression.getColumnNames(); if (unionCorrespondingColumns == null) { unionCorrespondingColumns = new OrderedHashSet(); OrderedIntHashSet leftColumns = new OrderedIntHashSet(); OrderedIntHashSet rightColumns = new OrderedIntHashSet(); for (int i = 0; i < leftNames.length; i++) { String name = leftNames[i]; int index = ArrayUtil.find(rightNames, name); if (name.length() > 0 && index != -1) { if (!leftQueryExpression.accessibleColumns[i]) { throw Error.error(ErrorCode.X_42578); } if (!rightQueryExpression.accessibleColumns[index]) { throw Error.error(ErrorCode.X_42578); } leftColumns.add(i); rightColumns.add(index); unionCorrespondingColumns.add(name); } } if (unionCorrespondingColumns.isEmpty()) { throw Error.error(ErrorCode.X_42578); } leftQueryExpression.unionColumnMap = leftColumns.toArray(); rightQueryExpression.unionColumnMap = rightColumns.toArray(); } else { leftQueryExpression.unionColumnMap = new int[unionCorrespondingColumns.size()]; rightQueryExpression.unionColumnMap = new int[unionCorrespondingColumns.size()]; for (int i = 0; i < unionCorrespondingColumns.size(); i++) { String name = (String) unionCorrespondingColumns.get(i); int index = ArrayUtil.find(leftNames, name); if (index == -1) { throw Error.error(ErrorCode.X_42501); } if (!leftQueryExpression.accessibleColumns[index]) { throw Error.error(ErrorCode.X_42578); } leftQueryExpression.unionColumnMap[i] = index; index = ArrayUtil.find(rightNames, name); if (index == -1) { throw Error.error(ErrorCode.X_42501); } if (!rightQueryExpression.accessibleColumns[index]) { throw Error.error(ErrorCode.X_42578); } rightQueryExpression.unionColumnMap[i] = index; } } columnCount = unionCorrespondingColumns.size(); unionColumnTypes = new Type[columnCount]; resolveColumnReferencesInUnionOrderBy(); accessibleColumns = new boolean[columnCount]; ArrayUtil.fillArray(accessibleColumns, true); isReferencesResolved = true; }
Only simple column reference or column position allowed
/** * Only simple column reference or column position allowed */
void resolveColumnReferencesInUnionOrderBy() { int orderCount = sortAndSlice.getOrderLength(); if (orderCount == 0) { return; } String[] unionColumnNames = getColumnNames(); for (int i = 0; i < orderCount; i++) { Expression sort = (Expression) sortAndSlice.exprList.get(i); Expression e = sort.getLeftNode(); if (e.getType() == OpTypes.VALUE) { if (e.getDataType().typeCode == Types.SQL_INTEGER) { int index = ((Integer) e.getValue(null)).intValue(); if (0 < index && index <= unionColumnNames.length) { sort.getLeftNode().queryTableColumnIndex = index - 1; continue; } } } else if (e.getType() == OpTypes.COLUMN) { int index = ArrayUtil.find(unionColumnNames, e.getColumnName()); if (index >= 0) { sort.getLeftNode().queryTableColumnIndex = index; continue; } } throw Error.error(ErrorCode.X_42576); } sortAndSlice.prepare(0); } private void addUnresolvedExpressions(HsqlList expressions) { if (expressions == null) { return; } if (unresolvedExpressions == null) { unresolvedExpressions = new ArrayListIdentity(); } unresolvedExpressions.addAll(expressions); } public void resolveTypes(Session session) { if (isResolved) { return; } resolveTypesPartOne(session); resolveTypesPartTwo(session); resolveTypesPartThree(session); } void resolveTypesPartOne(Session session) { if (isPartOneResolved) { return; } ArrayUtil.projectRowReverse(leftQueryExpression.unionColumnTypes, leftQueryExpression.unionColumnMap, unionColumnTypes); leftQueryExpression.resolveTypesPartOne(session); ArrayUtil.projectRow(leftQueryExpression.unionColumnTypes, leftQueryExpression.unionColumnMap, unionColumnTypes); ArrayUtil.projectRowReverse(rightQueryExpression.unionColumnTypes, rightQueryExpression.unionColumnMap, unionColumnTypes); rightQueryExpression.resolveTypesPartOne(session); ArrayUtil.projectRow(rightQueryExpression.unionColumnTypes, rightQueryExpression.unionColumnMap, unionColumnTypes); isPartOneResolved = true; } void resolveTypesPartTwoRecursive(Session session) { resolveTypesPartTwo(session); } void resolveTypesPartTwo(Session session) { if (isPartTwoResolved) { return; } ArrayUtil.projectRowReverse(leftQueryExpression.unionColumnTypes, leftQueryExpression.unionColumnMap, unionColumnTypes); if (isRecursive) { leftQueryExpression.resolveTypesPartTwoRecursive(session); recursiveTable.colTypes = leftQueryExpression.getColumnTypes(); for (int i = 0; i < recursiveTable.colTypes.length; i++) { recursiveTable.getColumn(i).setType( recursiveTable.colTypes[i]); } recursiveTable.getFullIndex(session); } else { leftQueryExpression.resolveTypesPartTwo(session); } leftQueryExpression.resolveTypesPartThree(session); ArrayUtil.projectRowReverse(rightQueryExpression.unionColumnTypes, rightQueryExpression.unionColumnMap, unionColumnTypes); rightQueryExpression.resolveTypesPartTwo(session); rightQueryExpression.resolveTypesPartThree(session); // ResultMetaData leftMeta = leftQueryExpression.getMetaData(); ResultMetaData rightMeta = rightQueryExpression.getMetaData(); for (int i = 0; i < leftQueryExpression.unionColumnMap.length; i++) { int leftIndex = leftQueryExpression.unionColumnMap[i]; int rightIndex = rightQueryExpression.unionColumnMap[i]; ColumnBase column = leftMeta.columns[leftIndex]; byte leftNullability = leftMeta.columns[leftIndex].getNullability(); byte rightNullability = rightMeta.columns[rightIndex].getNullability(); if (rightNullability == SchemaObject.Nullability .NULLABLE || (rightNullability == SchemaObject.Nullability .NULLABLE_UNKNOWN && leftNullability == SchemaObject .Nullability.NO_NULLS)) { if (column instanceof ColumnSchema) { column = new ColumnBase(); column.setType(leftQueryExpression.unionColumnTypes[i]); leftMeta.columns[leftIndex] = column; } column.setNullability(rightNullability); } } if (unionCorresponding || isRecursive) { resultMetaData = leftQueryExpression.getMetaData().getNewMetaData( leftQueryExpression.unionColumnMap); createTable(session); } if (sortAndSlice.hasOrder()) { QueryExpression queryExpression = this; while (true) { if (queryExpression.leftQueryExpression == null || queryExpression.unionCorresponding) { sortAndSlice.setIndex(session, queryExpression.resultTable); break; } queryExpression = queryExpression.leftQueryExpression; } } isPartTwoResolved = true; } void resolveTypesPartThree(Session session) { compileContext = null; isResolved = true; if (isRecursive) { recursiveTable.queryExpression.isCorrelated = false; } } public Object[] getValues(Session session) { Result r = getResult(session, 2); int size = r.getNavigator().getSize(); if (size == 0) { return new Object[r.metaData.getColumnCount()]; } else if (size == 1) { return r.getSingleRowData(); } else { throw Error.error(ErrorCode.X_21000); } } public void addExtraConditions(Expression e) {} public Object[] getSingleRowValues(Session session) { Result r = getResult(session, 2); int size = r.getNavigator().getSize(); if (size == 0) { return null; } else if (size == 1) { return r.getSingleRowData(); } else { throw Error.error(ErrorCode.X_21000); } } public Object getValue(Session session) { Object[] values = getValues(session); return values[0]; } Result getResult(Session session, int maxRows) { if (isRecursive) { return getResultRecursive(session); } int currentMaxRows = unionType == UNION_ALL ? maxRows : 0; Result first = leftQueryExpression.getResult(session, currentMaxRows); RowSetNavigatorData navigator = (RowSetNavigatorData) first.getNavigator(); Result second = rightQueryExpression.getResult(session, currentMaxRows); RowSetNavigatorData rightNavigator = (RowSetNavigatorData) second.getNavigator(); if (unionCorresponding) { RowSetNavigatorData rowSet; boolean memory = session.resultMaxMemoryRows == 0 || (navigator.getSize() < session.resultMaxMemoryRows && rightNavigator.getSize() < session.resultMaxMemoryRows); if (memory) { rowSet = new RowSetNavigatorData(session, this); } else { rowSet = new RowSetNavigatorDataTable(session, this); } rowSet.copy(navigator, leftQueryExpression.unionColumnMap); navigator.release(); navigator = rowSet; first.setNavigator(navigator); first.metaData = getMetaData(); if (memory) { rowSet = new RowSetNavigatorData(session, this); } else { rowSet = new RowSetNavigatorDataTable(session, this); } rowSet.copy(rightNavigator, rightQueryExpression.unionColumnMap); rightNavigator.release(); rightNavigator = rowSet; } switch (unionType) { case UNION : navigator.union(session, rightNavigator); break; case UNION_ALL : navigator.unionAll(session, rightNavigator); break; case INTERSECT : navigator.intersect(session, rightNavigator); break; case INTERSECT_ALL : navigator.intersectAll(session, rightNavigator); break; case EXCEPT : navigator.except(session, rightNavigator); break; case EXCEPT_ALL : navigator.exceptAll(session, rightNavigator); break; default : throw Error.runtimeError(ErrorCode.U_S0500, "QueryExpression"); } if (sortAndSlice.hasOrder()) { navigator.sortOrderUnion(session, sortAndSlice); } if (sortAndSlice.hasLimit()) { int[] limits = sortAndSlice.getLimits(session, this, maxRows); navigator.trim(limits[0], limits[1]); } navigator.reset(); return first; } Result getResultRecursive(Session session) { Result tempResult; recursiveTable.materialise(session); RowSetNavigatorData recNav = recursiveTable.getNavigator(session); Result result = Result.newResult(recNav); result.metaData = resultMetaData; for (int round = 0; ; round++) { tempResult = rightQueryExpression.getResult(session, 0); RowSetNavigatorData tempNavigator = (RowSetNavigatorData) tempResult.getNavigator(); if (tempNavigator.isEmpty()) { break; } int startSize = recNav.getSize(); switch (unionType) { case UNION : recNav.union(session, tempNavigator); break; case UNION_ALL : recNav.unionAll(session, tempNavigator); break; default : throw Error.runtimeError(ErrorCode.U_S0500, "QueryExpression"); } if (startSize == recNav.getSize()) { break; } if (round > 256) { throw Error.error(ErrorCode.X_22522); } } return result; } public OrderedHashSet getSubqueries() { OrderedHashSet subqueries = leftQueryExpression.getSubqueries(); subqueries = OrderedHashSet.addAll(subqueries, rightQueryExpression.getSubqueries()); return subqueries; } public boolean isSingleColumn() { return leftQueryExpression.isSingleColumn(); } public ResultMetaData getMetaData() { if (resultMetaData != null) { return resultMetaData; } return leftQueryExpression.getMetaData(); } public QuerySpecification getMainSelect() { if (leftQueryExpression == null) { return (QuerySpecification) this; } return leftQueryExpression.getMainSelect(); }
@todo1.9.0 review
/** @todo 1.9.0 review */
public String describe(Session session, int blanks) { StringBuilder sb; String temp; StringBuilder b = new StringBuilder(blanks); for (int i = 0; i < blanks; i++) { b.append(' '); } sb = new StringBuilder(); switch (unionType) { case UNION : temp = Tokens.T_UNION; break; case UNION_ALL : temp = Tokens.T_UNION + ' ' + Tokens.T_ALL; break; case INTERSECT : temp = Tokens.T_INTERSECT; break; case INTERSECT_ALL : temp = Tokens.T_INTERSECT + ' ' + Tokens.T_ALL; break; case EXCEPT : temp = Tokens.T_EXCEPT; break; case EXCEPT_ALL : temp = Tokens.T_EXCEPT + ' ' + Tokens.T_ALL; break; default : throw Error.runtimeError(ErrorCode.U_S0500, "QueryExpression"); } sb.append(b).append(temp).append("\n"); sb.append(b).append("Left Query=[\n"); sb.append(b).append(leftQueryExpression.describe(session, blanks + 2)); sb.append(b).append("]\n"); sb.append(b).append("Right Query=[\n"); sb.append(b).append(rightQueryExpression.describe(session, blanks + 2)); sb.append(b).append("]\n"); return sb.toString(); } public HsqlList getUnresolvedExpressions() { return unresolvedExpressions; } public boolean areColumnsResolved() { if (unresolvedExpressions == null || unresolvedExpressions.isEmpty()) { return true; } for (int i = 0; i < unresolvedExpressions.size(); i++) { Expression e = (Expression) unresolvedExpressions.get(i); if (e.getRangeVariable() == null) { return false; } if (e.getRangeVariable().rangeType == RangeVariable.TABLE_RANGE) { return false; } } return true; } String[] getColumnNames() { if (unionCorrespondingColumns == null) { return leftQueryExpression.getColumnNames(); } String[] names = new String[unionCorrespondingColumns.size()]; unionCorrespondingColumns.toArray(names); return names; } public Type[] getColumnTypes() { return unionColumnTypes; } public int getColumnCount() { if (unionCorrespondingColumns == null) { int left = leftQueryExpression.getColumnCount(); int right = rightQueryExpression.getColumnCount(); if (left != right) { throw Error.error(ErrorCode.X_42594); } return left; } return unionCorrespondingColumns.size(); } public OrderedHashSet collectAllExpressions(OrderedHashSet set, OrderedIntHashSet typeSet, OrderedIntHashSet stopAtTypeSet) { set = leftQueryExpression.collectAllExpressions(set, typeSet, stopAtTypeSet); if (rightQueryExpression != null) { set = rightQueryExpression.collectAllExpressions(set, typeSet, stopAtTypeSet); } return set; } OrderedHashSet collectRangeVariables(RangeVariable[] rangeVars, OrderedHashSet set) { set = leftQueryExpression.collectRangeVariables(rangeVars, set); if (rightQueryExpression != null) { set = rightQueryExpression.collectRangeVariables(rangeVars, set); } return set; } OrderedHashSet collectRangeVariables(OrderedHashSet set) { set = leftQueryExpression.collectRangeVariables(set); if (rightQueryExpression != null) { set = rightQueryExpression.collectRangeVariables(set); } return set; } public void collectObjectNames(Set set) { leftQueryExpression.collectObjectNames(set); if (rightQueryExpression != null) { rightQueryExpression.collectObjectNames(set); } } public HashMappedList getColumns() { TableDerived table = (TableDerived) getResultTable(); return table.columnList; }
Used prior to type resolution
/** * Used prior to type resolution */
public void setView(View view) { this.view = view; this.isUpdatable = true; this.acceptsSequences = true; this.isTopLevel = true; }
Used in views after full type resolution
/** * Used in views after full type resolution */
public void setTableColumnNames(HashMappedList list) { if (resultTable != null) { ((TableDerived) resultTable).columnList = list; return; } leftQueryExpression.setTableColumnNames(list); } void createTable(Session session) { createResultTable(session); mainIndex = resultTable.getPrimaryIndex(); if (sortAndSlice.hasOrder()) { orderIndex = sortAndSlice.getNewIndex(session, resultTable); } int[] fullCols = new int[columnCount]; ArrayUtil.fillSequence(fullCols); fullIndex = resultTable.createAndAddIndexStructure(session, null, fullCols, null, null, false, false, false); resultTable.fullIndex = fullIndex; } void createResultTable(Session session) { HsqlName tableName; HashMappedList columnList; int tableType; tableName = session.database.nameManager.getSubqueryTableName(); tableType = persistenceScope == TableBase.SCOPE_STATEMENT ? TableBase.SYSTEM_SUBQUERY : TableBase.RESULT_TABLE; columnList = leftQueryExpression.getUnionColumns(); resultTable = new TableDerived(session.database, tableName, tableType, unionColumnTypes, columnList, ValuePool.emptyIntArray); } public void setColumnsDefined() { if (leftQueryExpression != null) { leftQueryExpression.setColumnsDefined(); } }
Not for views. Only used on root node.
/** * Not for views. Only used on root node. */
public void setReturningResult() { if (compileContext.getSequences().length > 0) { throw Error.error(ErrorCode.X_42598); } isTopLevel = true; setReturningResultSet(); }
Sets the scope to SESSION for the QueryExpression object that creates the table
/** * Sets the scope to SESSION for the QueryExpression object that creates * the table */
void setReturningResultSet() { if (unionCorresponding) { persistenceScope = TableBase.SCOPE_SESSION; return; } leftQueryExpression.setReturningResultSet(); } private HashMappedList getUnionColumns() { if (unionCorresponding || leftQueryExpression == null) { HashMappedList columns = ((TableDerived) resultTable).columnList; HashMappedList list = new HashMappedList(); for (int i = 0; i < unionColumnMap.length; i++) { ColumnSchema column = (ColumnSchema) columns.get(unionColumnMap[i]); String name = (String) columns.getKey(unionColumnMap[i]); list.add(name, column); } return list; } return leftQueryExpression.getUnionColumns(); } public HsqlName[] getResultColumnNames() { if (resultTable == null) { return leftQueryExpression.getResultColumnNames(); } HashMappedList list = ((TableDerived) resultTable).columnList; HsqlName[] resultColumnNames = new HsqlName[list.size()]; for (int i = 0; i < resultColumnNames.length; i++) { resultColumnNames[i] = ((ColumnSchema) list.get(i)).getName(); } return resultColumnNames; } public TableBase getResultTable() { if (resultTable != null) { return resultTable; } if (leftQueryExpression != null) { return leftQueryExpression.getResultTable(); } return null; } // public Table getBaseTable() { return null; } public boolean isUpdatable() { return isUpdatable; } public boolean isInsertable() { return isInsertable; } public int[] getBaseTableColumnMap() { return null; } public Expression getCheckCondition() { return null; } public boolean hasReference(RangeVariable range) { if (leftQueryExpression.hasReference(range)) { return true; } if (rightQueryExpression.hasReference(range)) { return true; } return false; } void getBaseTableNames(OrderedHashSet set) { leftQueryExpression.getBaseTableNames(set); rightQueryExpression.getBaseTableNames(set); } boolean isEquivalent(QueryExpression other) { return leftQueryExpression.isEquivalent(other.leftQueryExpression) && unionType == other.unionType && (rightQueryExpression == null ? other.rightQueryExpression == null : rightQueryExpression.isEquivalent( other.rightQueryExpression)); } public void replaceColumnReferences(Session session, RangeVariable range, Expression[] list) { leftQueryExpression.replaceColumnReferences(session, range, list); rightQueryExpression.replaceColumnReferences(session, range, list); } public void replaceRangeVariables(RangeVariable[] ranges, RangeVariable[] newRanges) { leftQueryExpression.replaceRangeVariables(ranges, newRanges); rightQueryExpression.replaceRangeVariables(ranges, newRanges); }
non-working temp code for replacing aggregate functions with simple column
/** * non-working temp code for replacing aggregate functions with simple column */
public void replaceExpressions(OrderedHashSet expressions, int resultRangePosition) { leftQueryExpression.replaceExpressions(expressions, resultRangePosition); rightQueryExpression.replaceExpressions(expressions, resultRangePosition); } public void setAsExists() {} }