} // getTableFromItems() public static List <FromItem> getTableFromItems(FromItem item) { List <FromItem> result = new List <FromItem>(); if (item.getTable() != null) { result.Add(item); } else if (item.getSubQuery() != null) { FromItem[] sqItems = getTableFromItems(item.getSubQuery()); for (int i = 0; i < sqItems.Length; i++) { result.Add(sqItems[i]); } } else if (item.getJoin() != JoinType.None) { FromItem leftSide = item.getLeftSide(); result.AddRange(getTableFromItems(leftSide)); FromItem rightSide = item.getRightSide(); result.AddRange(getTableFromItems(rightSide)); } else { throw new InvalidOperationException("FromItem was neither of Table type, SubQuery type or Join type: " + item); } return(result); } // getTableFromItems()
// @Override public SatisfiedFromBuilder on(String left, String right) // throws IllegalArgumentException { Table leftTable = leftItem.getTable(); if (leftTable == null) { throw new ArgumentException("Left side of join is not a Table, cannot resolve ON item: '" + left + "'."); } Table rightTable = rightItem.getTable(); if (rightTable == null) { throw new ArgumentException("Right side of join is not a Table, cannot resolve ON item: '" + right + "'."); } Column leftColumn = leftTable.getColumnByName(left); Column rightColumn = rightTable.getColumnByName(right); return(on(leftColumn, rightColumn)); }
private Column findColumnInAliasedTable(Column column, FromItem fromItem, String aliasPart, String columnPart) { if (column != null) { // ensure that if the column has already been found, return it return(column); } Table table = fromItem.getTable(); if (table != null) { String alias = fromItem.getAlias(); if (alias != null && alias.Equals(aliasPart)) { column = table.getColumnByName(columnPart); } } else { FromItem leftSide = fromItem.getLeftSide(); column = findColumnInAliasedTable(column, leftSide, aliasPart, columnPart); FromItem rightSide = fromItem.getRightSide(); column = findColumnInAliasedTable(column, rightSide, aliasPart, columnPart); if (column != null) { Query subQuery = fromItem.getSubQuery(); if (subQuery != null) { List <FromItem> items = subQuery.getFromClause().getItems(); foreach (FromItem subQueryFromItem in items) { column = findColumnInAliasedTable(column, subQueryFromItem, aliasPart, columnPart); } } } } return(column); }
} // constructor public DataSet executeQuery(Query query) { List <SelectItem> selectItems = query.getSelectClause().getItems(); List <FromItem> fromItems = query.getFromClause().getItems(); List <FilterItem> whereItems = query.getWhereClause().getItems(); List <SelectItem> whereSelectItems = query.getWhereClause().getEvaluatedSelectItems(); List <GroupByItem> groupByItems = query.getGroupByClause().getItems(); List <SelectItem> groupBySelectItems = query.getGroupByClause().getEvaluatedSelectItems(); List <SelectItem> havingSelectItems = query.getHavingClause().getEvaluatedSelectItems(); List <SelectItem> orderBySelectItems = query.getOrderByClause().getEvaluatedSelectItems(); List <FilterItem> havingItems = query.getHavingClause().getItems(); List <OrderByItem> orderByItems = query.getOrderByClause().getItems(); int firstRow = (query.getFirstRow() == null ? 1 : query.getFirstRow()); int maxRows = (query.getMaxRows() == null ? -1 : query.getMaxRows()); if (maxRows == 0) { // no rows requested - no reason to do anything return(new EmptyDataSet(selectItems)); } // check certain common query types that can often be optimized by // subclasses bool singleFromItem = fromItems.Count == 1; bool noGrouping = groupByItems.IsEmpty() && havingItems.IsEmpty(); if (singleFromItem && noGrouping) { FromItem fromItem = query.getFromClause().getItem(0); Table table = fromItem.getTable(); if (table != null) { // check for SELECT COUNT(*) queries if (selectItems.Count == 1) { SelectItem selectItem = query.getSelectClause().getItem(0); if (SelectItem.isCountAllItem(selectItem)) { bool functionApproximationAllowed = selectItem.isFunctionApproximationAllowed(); if (isMainSchemaTable(table)) { logger.debug("Query is a COUNT query with {} where items. Trying executeCountQuery(...)", whereItems.Count); NNumber count = executeCountQuery(table, whereItems, functionApproximationAllowed); if (count == null) { logger.debug( "DataContext did not return any count query results. Proceeding with manual counting."); } else { List <Row> data = new List <Row>(1); DataSetHeader header = new SimpleDataSetHeader(new SelectItem[] { selectItem }); data.Add(new DefaultRow(header, new Object[] { count })); return(new InMemoryDataSet(header, data)); } } } } bool is_simple_select = isSimpleSelect(query.getSelectClause()); if (is_simple_select) { // check for lookup query by primary key if (whereItems.Count == 1) { FilterItem whereItem = whereItems[0]; SelectItem selectItem = whereItem.getSelectItem(); if (!whereItem.isCompoundFilter() && selectItem != null && selectItem.getColumn() != null) { Column column = selectItem.getColumn(); if (column.isPrimaryKey() && OperatorType.EQUALS_TO.Equals(whereItem.getOperator())) { logger.debug( "Query is a primary key lookup query. Trying executePrimaryKeyLookupQuery(...)"); if (table != null) { if (isMainSchemaTable(table)) { Object operand = whereItem.getOperand(); Row row = executePrimaryKeyLookupQuery(table, selectItems, column, operand); if (row == null) { logger.debug( "DataContext did not return any GET query results. Proceeding with manual lookup."); } else { DataSetHeader header = new SimpleDataSetHeader(selectItems); return(new InMemoryDataSet(header, row)); } } } } } } // check for simple queries with or without simple criteria if (orderByItems.IsEmpty()) { DataSet ds = null; // no WHERE criteria set if (whereItems.IsEmpty()) { ds = materializeTable(table, selectItems, firstRow, maxRows); return(ds); } ds = materializeTable(table, selectItems, whereItems, firstRow, maxRows); return(ds); } } } } // Creates a list for all select items that are needed to execute query // (some may only be used as part of a filter, but not shown in result) List <SelectItem> workSelectItems = CollectionUtils.concat(true, selectItems, whereSelectItems, groupBySelectItems, havingSelectItems, orderBySelectItems); // Materialize the tables in the from clause DataSet[] fromDataSets = new DataSet[fromItems.Count]; for (int i = 0; i < fromDataSets.Length; i++) { FromItem fromItem = fromItems[i]; fromDataSets[i] = materializeFromItem(fromItem, workSelectItems); } // Execute the query using the raw data DataSet dataSet = null; // MetaModelHelper.getCarthesianProduct(fromDataSets, whereItems); // we can now exclude the select items imposed by the WHERE clause (and // should, to make the aggregation process faster) workSelectItems = CollectionUtils.concat(true, selectItems, groupBySelectItems, havingSelectItems, orderBySelectItems); if (groupByItems.Count > 0) { dataSet = MetaModelHelper.getGrouped(workSelectItems, dataSet, groupByItems); } else { dataSet = MetaModelHelper.getAggregated(workSelectItems, dataSet); } dataSet = MetaModelHelper.getFiltered(dataSet, havingItems); if (query.getSelectClause().isDistinct()) { dataSet = MetaModelHelper.getSelection(selectItems, dataSet); dataSet = MetaModelHelper.getDistinct(dataSet); dataSet = MetaModelHelper.getOrdered(dataSet, orderByItems); } else { dataSet = MetaModelHelper.getOrdered(dataSet, orderByItems); dataSet = MetaModelHelper.getSelection(selectItems, dataSet); } dataSet = MetaModelHelper.getPaged(dataSet, firstRow, maxRows); return(dataSet); } // executeQuery()
} // executePrimaryKeyLookupQuery() protected DataSet materializeFromItem(FromItem fromItem, List <SelectItem> selectItems) { DataSet dataSet; JoinType joinType = fromItem.getJoin(); if (fromItem.getTable() != null) { // We need to materialize a single table Table table = fromItem.getTable(); List <SelectItem> selectItemsToMaterialize = new List <SelectItem>(); foreach (SelectItem selectItem in selectItems) { FromItem selectedFromItem = selectItem.getFromItem(); if (selectedFromItem != null) { if (selectedFromItem.equals(fromItem)) { selectItemsToMaterialize.Add(selectItem.replaceFunction(null)); } } else { // the select item does not specify a specific // from-item Column selectedColumn = selectItem.getColumn(); if (selectedColumn != null) { // we assume that if the table matches, we will use the // column if (selectedColumn.getTable() != null && selectedColumn.getTable().Equals(table)) { selectItemsToMaterialize.Add(selectItem.replaceFunction(null)); } } } } if (logger.isDebugEnabled()) { logger.debug("calling materializeTable(" + table.getName() + "," + selectItemsToMaterialize + ",1,-1"); } // Dispatching to the concrete subclass of // QueryPostprocessDataContextStrategy dataSet = materializeTable(table, selectItemsToMaterialize, 1, -1); } else if (joinType != JoinType.None) { // We need to (recursively) materialize a joined FromItem if (fromItem.getLeftSide() == null || fromItem.getRightSide() == null) { throw new ArgumentException("Joined FromItem requires both left and right side: " + fromItem); } DataSet[] fromItemDataSets = new DataSet[2]; // materialize left side List <SelectItem> leftOn = NArrays.AsList(fromItem.getLeftOn()); fromItemDataSets[0] = materializeFromItem(fromItem.getLeftSide(), CollectionUtils.concat(true, selectItems, leftOn)); // materialize right side List <SelectItem> rightOn = NArrays.AsList(fromItem.getRightOn()); fromItemDataSets[1] = materializeFromItem(fromItem.getRightSide(), CollectionUtils.concat(true, selectItems, rightOn)); FilterItem[] onConditions = new FilterItem[leftOn.Count]; for (int i = 0; i < onConditions.Length; i++) { FilterItem whereItem = new FilterItem(leftOn[i], OperatorType.EQUALS_TO, rightOn[i]); onConditions[i] = whereItem; } switch (joinType) { case JoinType.INNER: dataSet = MetaModelHelper.getCarthesianProduct(fromItemDataSets, onConditions); break; case JoinType.LEFT: dataSet = MetaModelHelper.getLeftJoin(fromItemDataSets[0], fromItemDataSets[1], onConditions); break; case JoinType.RIGHT: dataSet = MetaModelHelper.getRightJoin(fromItemDataSets[0], fromItemDataSets[1], onConditions); break; default: throw new ArgumentException("FromItem type not supported: " + fromItem); } } else if (fromItem.getSubQuery() != null) { // We need to (recursively) materialize a subquery dataSet = executeQuery(fromItem.getSubQuery()); } else { throw new ArgumentException("FromItem type not supported: " + fromItem); } if (dataSet == null) { throw new ArgumentException("FromItem was not succesfully materialized: " + fromItem); } return(dataSet); } // materializeFromItem()
} // parse() /** * Finds/creates a SelectItem based on the given expression. Unlike the * {@link #parse(String, String)} method, this method will not actually add * the selectitem to the query. * * @param expression * @return * * @throws MultipleSelectItemsParsedException * if an expression yielding multiple select-items (such as "*") * was passed in the expression */ public SelectItem findSelectItem(String expression) // throws MultipleSelectItemsParsedException { if ("*".Equals(expression)) { throw new MultipleSelectItemsParsedException(null); } if ("COUNT(*)".Equals(expression, StringComparison.CurrentCultureIgnoreCase)) { return(SelectItem.getCountAllItem()); } String unmodifiedExpression = expression; bool functionApproximation; FunctionType function; int startParenthesis = expression.IndexOf('('); if (startParenthesis > 0 && expression.EndsWith(")")) { functionApproximation = (expression.StartsWith(SelectItem.FUNCTION_APPROXIMATION_PREFIX)); String functionName = expression.Substring( (functionApproximation ? SelectItem.FUNCTION_APPROXIMATION_PREFIX.Length : 0), startParenthesis); function = FunctionTypeFactory.get(functionName.ToUpper()); if (function != null) { expression = expression.Substring(startParenthesis + 1, expression.Length - 1).Trim(); if (function is CountAggregateFunction && "*".Equals(expression)) { SelectItem select_item = SelectItem.getCountAllItem(); select_item.setFunctionApproximationAllowed(functionApproximation); return(select_item); } } } else { function = null; functionApproximation = false; } String columnName = null; FromItem fromItem = null; // attempt to find from item by cutting up the string in prefix and // suffix around dot. { int splitIndex = expression.LastIndexOf('.'); while (fromItem == null && splitIndex != -1) { String prefix = expression.Substring(0, splitIndex); columnName = expression.Substring(splitIndex + 1); fromItem = _query.getFromClause().getItemByReference(prefix); splitIndex = expression.LastIndexOf('.', splitIndex - 1); } } if (fromItem == null) { if (_query.getFromClause().getItemCount() == 1) { fromItem = _query.getFromClause().getItem(0); columnName = expression; } else { fromItem = null; columnName = null; } } if (fromItem != null) { if ("*".Equals(columnName)) { throw new MultipleSelectItemsParsedException(fromItem); } else if (fromItem.getTable() != null) { Column column = fromItem.getTable().getColumnByName(columnName); int offset = -1; while (function == null && column == null) { // check for MAP_VALUE shortcut syntax offset = columnName.IndexOf('.', offset + 1); if (offset == -1) { break; } String part1 = columnName.Substring(0, offset); column = fromItem.getTable().getColumnByName(part1); if (column != null) { String part2 = columnName.Substring(offset + 1); return(new SelectItem(new MapValueFunction(), new Object[] { part2 }, column, fromItem)); } } if (column != null) { SelectItem select_item = new SelectItem(function, column, fromItem); select_item.setFunctionApproximationAllowed(functionApproximation); return(select_item); } } else if (fromItem.getSubQuery() != null) { Query subQuery = fromItem.getSubQuery(); SelectItem subQuerySelectItem = new SelectItemParser(subQuery, _allowExpressionBasedSelectItems) .findSelectItem(columnName); if (subQuerySelectItem == null) { return(null); } return(new SelectItem(subQuerySelectItem, fromItem)); } } // if the expression is alias of some select item defined return that // select item SelectItem aliasSelectItem = MetaModelHelper.getSelectItemByAlias(_query, unmodifiedExpression); if (aliasSelectItem != null) { return(aliasSelectItem); } if (_allowExpressionBasedSelectItems) { SelectItem select_item = new SelectItem(function, expression, null); select_item.setFunctionApproximationAllowed(functionApproximation); return(select_item); } return(null); } // findSelectItem()