
dk.eobjects.metamodel.QueryPostprocessDataContextStrategy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of MetaModel Show documentation
Show all versions of MetaModel Show documentation
The eobjects.dk MetaModel is a common domain model, query-engine
and optimizer for different kinds of datastores.
The newest version!
/*
* Copyright 2008 eobjects.dk
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dk.eobjects.metamodel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import dk.eobjects.metamodel.data.DataSet;
import dk.eobjects.metamodel.data.MaxRowsDataSetStrategyWrapper;
import dk.eobjects.metamodel.query.FilterItem;
import dk.eobjects.metamodel.query.FromItem;
import dk.eobjects.metamodel.query.GroupByItem;
import dk.eobjects.metamodel.query.JoinType;
import dk.eobjects.metamodel.query.OperatorType;
import dk.eobjects.metamodel.query.OrderByItem;
import dk.eobjects.metamodel.query.Query;
import dk.eobjects.metamodel.query.SelectItem;
import dk.eobjects.metamodel.schema.Column;
import dk.eobjects.metamodel.schema.Table;
/**
* Abstract DataContextStrategy for data sources that do not support SQL
* queries. Instead this superclass only requires that a subclass can
* materialize a single table at a time. Then the query will be executed by post
* processing data client-side.
*/
public abstract class QueryPostprocessDataContextStrategy implements
IDataContextStrategy {
public DataSet executeQuery(Query query) {
List selectItems = query.getSelectClause().getItems();
List fromItems = query.getFromClause().getItems();
List whereItems = query.getWhereClause().getItems();
List whereSelectItems = query.getWhereClause()
.getEvaluatedSelectItems();
List groupByItems = query.getGroupByClause().getItems();
List havingSelectItems = query.getHavingClause()
.getEvaluatedSelectItems();
List havingItems = query.getHavingClause().getItems();
List orderByItems = query.getOrderByClause().getItems();
// Check for very simple queries with max rows property set (typically
// preview), see Ticket #187
previewTable: if (query.getMaxRows() != null && whereItems.isEmpty()
&& groupByItems.isEmpty() && havingItems.isEmpty()
&& orderByItems.isEmpty() && fromItems.size() == 1) {
Table table = fromItems.get(0).getTable();
if (table != null) {
Column[] columns = new Column[selectItems.size()];
int i = 0;
for (Iterator it = selectItems.iterator(); it
.hasNext();) {
SelectItem item = it.next();
if (item.getFunction() != null
|| item.getExpression() != null) {
break previewTable;
}
columns[i] = item.getColumn();
i++;
}
DataSet dataSet = materializeTable(table, columns, query
.getMaxRows());
dataSet = MetaModelHelper.getSelection(selectItems, dataSet);
return dataSet;
}
}
// Materialize the tables in the from clause
DataSet[] fromDataSets = new DataSet[fromItems.size()];
for (int i = 0; i < fromDataSets.length; i++) {
FromItem fromItem = fromItems.get(i);
fromDataSets[i] = materializeFromItem(fromItem);
}
// 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 workSelectItems = collectSelectItems(selectItems,
whereSelectItems, havingSelectItems);
// Execute the query using the raw data
DataSet dataSet = MetaModelHelper.getCarthesianProduct(fromDataSets,
whereItems);
if (groupByItems.size() > 0) {
dataSet = MetaModelHelper.getGrouped(workSelectItems, dataSet,
groupByItems);
} else {
dataSet = MetaModelHelper.getAggregated(workSelectItems, dataSet);
}
dataSet = MetaModelHelper.getFiltered(dataSet, havingItems);
dataSet = MetaModelHelper.getOrdered(dataSet, orderByItems);
dataSet = MetaModelHelper.getSelection(selectItems, dataSet);
if (query.getMaxRows() != null) {
dataSet = new DataSet(new MaxRowsDataSetStrategyWrapper(dataSet,
query.getMaxRows()));
}
return dataSet;
}
public DataSet materializeFromItem(FromItem fromItem) {
DataSet dataSet;
JoinType joinType = fromItem.getJoin();
if (fromItem.getTable() != null) {
Table table = fromItem.getTable();
Column[] columns = table.getColumns();
Query query = fromItem.getQuery();
if (query != null) {
List selectItems = collectSelectItems(query
.getSelectClause().getItems(), query.getWhereClause()
.getEvaluatedSelectItems(), query.getHavingClause()
.getEvaluatedSelectItems());
List colsToMaterialize = new ArrayList();
for (Iterator it = selectItems.iterator(); it
.hasNext();) {
SelectItem selectItem = it.next();
Column column = selectItem.getColumn();
if (column != null && column.getTable() != null
&& column.getTable().equals(table)) {
colsToMaterialize.add(column);
}
}
selectItems = null;
columns = colsToMaterialize
.toArray(new Column[colsToMaterialize.size()]);
}
dataSet = materializeTable(table, columns, -1);
} else if (joinType != null) {
DataSet[] fromItemDataSets = new DataSet[2];
fromItemDataSets[0] = materializeFromItem(fromItem.getLeftSide());
fromItemDataSets[1] = materializeFromItem(fromItem.getRightSide());
SelectItem[] leftOn = fromItem.getLeftOn();
SelectItem[] rightOn = fromItem.getRightOn();
FilterItem[] onConditions = new FilterItem[leftOn.length];
for (int i = 0; i < onConditions.length; i++) {
FilterItem whereItem = new FilterItem(leftOn[i],
OperatorType.EQUALS_TO, rightOn[i]);
onConditions[i] = whereItem;
}
if (joinType == JoinType.INNER) {
dataSet = MetaModelHelper.getCarthesianProduct(
fromItemDataSets, onConditions);
} else if (joinType == JoinType.LEFT) {
dataSet = MetaModelHelper.getLeftJoin(fromItemDataSets[0],
fromItemDataSets[1], onConditions);
} else if (joinType == JoinType.RIGHT) {
dataSet = MetaModelHelper.getRightJoin(fromItemDataSets[0],
fromItemDataSets[1], onConditions);
} else {
throw new IllegalArgumentException(
"FromItem type not supported: " + fromItem);
}
} else if (fromItem.getSubQuery() != null) {
dataSet = executeQuery(fromItem.getSubQuery());
} else {
throw new IllegalArgumentException("FromItem type not supported: "
+ fromItem);
}
return dataSet;
}
private List collectSelectItems(
List selectClauseItems,
List whereClauseItems,
List havingClauseItems) {
ArrayList result = new ArrayList(
selectClauseItems);
for (SelectItem selectItem : whereClauseItems) {
if (!result.contains(selectItem)) {
result.add(selectItem);
}
}
for (SelectItem selectItem : havingClauseItems) {
if (!result.contains(selectItem)) {
result.add(selectItem);
}
}
return result;
}
/**
* Executes a simple one-table query.
*
* @param table
* @param columns
* @param maxRows
* the maximum amount of rows needed or -1 if all rows are
* wanted.
* @return
*/
public abstract DataSet materializeTable(Table table, Column[] columns,
int maxRows);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy