/*
* #!
* Ontopia Engine
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* 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 net.ontopia.persistence.query.sql;
import java.util.List;
import net.ontopia.utils.OntopiaRuntimeException;
/**
* INTERNAL: Class used to build SQL queries from JDO queries.
*/
public abstract class FilterSQLOptimizer {
public SQLQuery optimize(SQLQuery query) {
filterSelect(query);
filterFilter(query);
filterOrderBy(query);
return query;
}
protected void filterSelect(SQLQuery query) {
List select = query.getSelect();
for (int i=0; i < select.size(); i++) {
Object selected = select.get(i);
if (selected instanceof SQLAggregateIF) {
select.set(i, filterAggregate((SQLAggregateIF)selected));
} else {
// replace value
select.set(i, filterValue((SQLValueIF)selected));
}
}
}
protected void filterFilter(SQLQuery query) {
filterExpression(query.getFilter());
}
protected void filterOrderBy(SQLQuery query) {
List orderby = query.getOrderBy();
for (int i=0; i < orderby.size(); i++) {
SQLOrderBy ordered = (SQLOrderBy)orderby.get(i);
if (ordered.isAggregate()) {
ordered.setAggregate(filterAggregate(ordered.getAggregate()));
//! orderby.set(i, ordered));
} else {
// replace value
ordered.setValue(filterValue(ordered.getValue()));
//! orderby.set(i, ordered);
}
}
}
protected SQLExpressionIF[] filterExpressions(SQLExpressionIF[] exprs) {
// Loop over SQL expressions and filter them individually
for (int i=0; i < exprs.length; i++) {
exprs[i] = filterExpression(exprs[i]);
}
return exprs;
}
protected SQLExpressionIF filterExpression(SQLExpressionIF sqlexpr) {
if (sqlexpr == null) return null;
switch (sqlexpr.getType()) {
case SQLExpressionIF.AND:
return filterAnd((SQLAnd)sqlexpr);
case SQLExpressionIF.EQUALS:
return filterEquals((SQLEquals)sqlexpr);
case SQLExpressionIF.EXISTS:
return filterExists((SQLExists)sqlexpr);
case SQLExpressionIF.FALSE:
return filterFalse((SQLFalse)sqlexpr);
case SQLExpressionIF.IN:
return filterIn((SQLIn)sqlexpr);
case SQLExpressionIF.IS_NULL:
return filterIsNull((SQLIsNull)sqlexpr);
case SQLExpressionIF.JOIN:
return filterJoin((SQLJoin)sqlexpr);
case SQLExpressionIF.LIKE:
return filterLike((SQLLike)sqlexpr);
case SQLExpressionIF.NOT:
return filterNot((SQLNot)sqlexpr);
case SQLExpressionIF.NOT_EQUALS:
return filterNotEquals((SQLNotEquals)sqlexpr);
case SQLExpressionIF.OR:
return filterOr((SQLOr)sqlexpr);
case SQLExpressionIF.SET_OPERATION:
return filterSetOperation((SQLSetOperation)sqlexpr);
case SQLExpressionIF.VERBATIM:
return filterVerbatimExpression((SQLVerbatimExpression)sqlexpr);
case SQLExpressionIF.VALUE_EXPRESSION:
return filterValueExpression((SQLValueExpression)sqlexpr);
default:
throw new OntopiaRuntimeException("Invalid SQLExpressionIF: '" + sqlexpr + "'");
}
}
protected SQLExpressionIF filterAnd(SQLAnd expr) {
expr.setExpressions(filterExpressions(expr.getExpressions()));
return expr;
}
protected SQLExpressionIF filterEquals(SQLEquals expr) {
expr.setLeft(filterValue(expr.getLeft()));
expr.setRight(filterValue(expr.getRight()));
return expr;
}
protected SQLExpressionIF filterExists(SQLExists expr) {
expr.setExpression(filterExpression(expr.getExpression()));
return expr;
}
protected SQLExpressionIF filterFalse(SQLFalse expr) {
return expr;
}
protected SQLExpressionIF filterIn(SQLIn expr) {
expr.setLeft(filterValue(expr.getLeft()));
expr.setRight(filterValue(expr.getRight()));
return expr;
}
protected SQLExpressionIF filterIsNull(SQLIsNull expr) {
expr.setValue(filterValue(expr.getValue()));
return expr;
}
protected SQLExpressionIF filterJoin(SQLJoin expr) {
expr.setLeft((SQLColumns)filterValue(expr.getLeft()));
expr.setRight((SQLColumns)filterValue(expr.getRight()));
return expr;
}
protected SQLExpressionIF filterLike(SQLLike expr) {
expr.setLeft(filterValue(expr.getLeft()));
expr.setRight(filterValue(expr.getRight()));
return expr;
}
protected SQLExpressionIF filterNot(SQLNot expr) {
expr.setExpression(filterExpression(expr.getExpression()));
return expr;
}
protected SQLExpressionIF filterNotEquals(SQLNotEquals expr) {
expr.setLeft(filterValue(expr.getLeft()));
expr.setRight(filterValue(expr.getRight()));
return expr;
}
protected SQLExpressionIF filterOr(SQLOr expr) {
expr.setExpressions(filterExpressions(expr.getExpressions()));
return expr;
}
protected SQLExpressionIF filterSetOperation(SQLSetOperation expr) {
// TODO: Filter individual queries
throw new UnsupportedOperationException();
}
protected SQLExpressionIF filterVerbatimExpression(SQLVerbatimExpression expr) {
return expr;
}
protected SQLExpressionIF filterValueExpression(SQLValueExpression expr) {
expr.setValue(filterValue(expr.getValue()));
return expr;
}
protected SQLValueIF[] filterValues(SQLValueIF[] values) {
// Loop over SQL values filter them individually
for (int i=0; i < values.length; i++) {
values[i] = filterValue(values[i]);
}
return values;
}
protected SQLAggregateIF filterAggregate(SQLAggregateIF sqlagg) {
sqlagg.setValue(filterValue(sqlagg.getValue()));
return sqlagg;
}
protected SQLValueIF filterValue(SQLValueIF sqlvalue) {
if (sqlvalue == null) return null;
switch (sqlvalue.getType()) {
case SQLValueIF.COLUMNS:
return filterColumns((SQLColumns)sqlvalue);
case SQLValueIF.NULL:
return filterNull((SQLNull)sqlvalue);
case SQLValueIF.PARAMETER:
return filterParameter((SQLParameter)sqlvalue);
case SQLValueIF.PRIMITIVE:
return filterPrimitive((SQLPrimitive)sqlvalue);
case SQLValueIF.TUPLE:
return filterTuple((SQLTuple)sqlvalue);
case SQLValueIF.VERBATIM:
return filterVerbatim((SQLVerbatim)sqlvalue);
case SQLValueIF.FUNCTION:
return filterFunction((SQLFunction)sqlvalue);
default:
throw new OntopiaRuntimeException("Invalid SQLValueIF: '" + sqlvalue + "'");
}
}
protected SQLValueIF filterColumns(SQLColumns value) {
return value;
}
protected SQLValueIF filterNull(SQLNull value) {
return value;
}
protected SQLValueIF filterParameter(SQLParameter value) {
return value;
}
protected SQLValueIF filterPrimitive(SQLPrimitive value) {
return value;
}
protected SQLValueIF filterTuple(SQLTuple value) {
value.setValues(filterValues(value.getValues()));
return value;
}
protected SQLValueIF filterVerbatim(SQLVerbatim value) {
return value;
}
protected SQLValueIF filterFunction(SQLFunction value) {
value.setArguments(filterValues(value.getArguments()));
return value;
}
}