/* * #! * 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 net.ontopia.utils.OntopiaRuntimeException; /** * INTERNAL: Class used to build SQL queries from JDO queries. */ public abstract class BooleanSQLOptimizer { public abstract SQLQuery optimize(SQLQuery query); protected void optimizeQuery(SQLQuery query) { optimizeSelect(query); optimizeFilter(query); optimizeOrderBy(query); } protected void optimizeSelect(SQLQuery query) { //! Iterator iter = query.getSelect().iterator(); //! while (iter.hasNext()) { //! Object selected = iter.next(); //! if (selected instanceof SQLAggregateIF) //! optimizeValue(((SQLAggregateIF)selected).getValue()); //! else //! optimzeValue((SQLValueIF)selected); //! } } protected void optimizeFilter(SQLQuery query) { optimizeExpression(query.getFilter()); } protected void optimizeOrderBy(SQLQuery query) { //! Iterator iter = query.getOrderBy().iterator(); //! while (iter.hasNext()) { //! SQLOrderBy order = (SQLOrderBy)iter.next(); //! //! if (order.isAggregate()) //! optimizeValue(order.getAggregate().getValue()); //! else //! optimizeValue(order.getValue()); //! } } protected int optimizeExpression(SQLExpressionIF sqlexpr) { switch (sqlexpr.getType()) { case SQLExpressionIF.AND: return optimizeAnd((SQLAnd)sqlexpr); case SQLExpressionIF.EQUALS: return optimizeEquals((SQLEquals)sqlexpr); case SQLExpressionIF.EXISTS: return optimizeExists((SQLExists)sqlexpr); case SQLExpressionIF.FALSE: return optimizeFalse((SQLFalse)sqlexpr); case SQLExpressionIF.IN: return optimizeIn((SQLIn)sqlexpr); case SQLExpressionIF.IS_NULL: return optimizeIsNull((SQLIsNull)sqlexpr); case SQLExpressionIF.JOIN: return optimizeJoin((SQLJoin)sqlexpr); case SQLExpressionIF.LIKE: return optimizeLike((SQLLike)sqlexpr); case SQLExpressionIF.NOT: return optimizeNot((SQLNot)sqlexpr); case SQLExpressionIF.NOT_EQUALS: return optimizeNotEquals((SQLNotEquals)sqlexpr); case SQLExpressionIF.OR: return optimizeOr((SQLOr)sqlexpr); case SQLExpressionIF.SET_OPERATION: return optimizeSetOperation((SQLSetOperation)sqlexpr); case SQLExpressionIF.VERBATIM: return optimizeVerbatimExpression((SQLVerbatimExpression)sqlexpr); case SQLExpressionIF.VALUE_EXPRESSION: return optimizeValueExpression((SQLValueExpression)sqlexpr); default: throw new OntopiaRuntimeException("Invalid SQLExpressionIF: '" + sqlexpr + "'"); } } protected int optimizeAnd(SQLAnd expr) { int totcount = 0; int truecount = 0; // NOTE: is true if all subexpressions are true SQLExpressionIF[] exprs = expr.getExpressions(); for (int i=0; i < exprs.length; i++) { if (exprs[i] == null) continue; totcount++; int result = optimizeExpression(exprs[i]); // Remove removable expression if (result == 1) { exprs[i] = null; truecount++; } else if (result == -1) return -1; } // If all subexpressions are true so is the whole expression, // otherwise it is non-optimizable. if (totcount == truecount) return 1; else return 0; } protected int optimizeEquals(SQLEquals expr) { return 0; } protected int optimizeExists(SQLExists expr) { return optimizeExpression(expr.getExpression()); } protected int optimizeFalse(SQLFalse expr) { return 0; } protected int optimizeIn(SQLIn expr) { //! optimizeValue(expr.getLeft()); //! optimizeValue(expr.getRight()); return 0; } protected int optimizeIsNull(SQLIsNull expr) { //! optimizeValue(expr.getValue()); return 0; } protected int optimizeJoin(SQLJoin expr) { // ISSUE: Same optimization as for SQLEqual? //! optimizeValue(expr.getLeft()); //! optimizeValue(expr.getRight()); return 0; } protected int optimizeLike(SQLLike expr) { //! optimizeValue(expr.getLeft()); //! optimizeValue(expr.getRight()); return 0; } protected int optimizeNot(SQLNot expr) { return optimizeExpression(expr.getExpression()); } protected int optimizeNotEquals(SQLNotEquals expr) { return 0; } protected int optimizeOr(SQLOr expr) { int totcount = 0; int falsecount = 0; // NOTE: is true if any of the subexpressions are true SQLExpressionIF[] exprs = expr.getExpressions(); for (int i=0; i < exprs.length; i++) { if (exprs[i] == null) continue; totcount++; int result = optimizeExpression(exprs[i]); // Remove removable expression if (result == 1) return 1; else if (result == -1) { exprs[i] = null; falsecount++; } } // If all subexpressions are false so is the whole expression, // otherwise it is non-optimizable. if (totcount == falsecount) return 1; else return 0; } protected int optimizeSetOperation(SQLSetOperation expr) { // TODO: Optimize individual queries return 0; } protected int optimizeVerbatimExpression(SQLVerbatimExpression expr) { return 0; } protected int optimizeValueExpression(SQLValueExpression expr) { return 0; } //! protected int optimizeValues(SQLValueIF[] values) { //! // Loop over SQL values and optimize them individually //! for (int i=0; i < values.length; i++) { //! optimizeValue(values[i]); //! } //! } //! //! protected int optimizeValue(SQLValueIF sqlvalue) { //! switch (sqlvalue.getType()) { //! case SQLValueIF.COLUMNS: //! return optimizeColumns((SQLColumns)sqlvalue); //! case SQLValueIF.NULL: //! return optimizeNull((SQLNull)sqlvalue); //! case SQLValueIF.PARAMETER: //! return optimizeParameter((SQLParameter)sqlvalue); //! case SQLValueIF.PRIMITIVE: //! return optimizePrimitive((SQLPrimitive)sqlvalue); //! case SQLValueIF.TUPLE: //! return optimizeTuple((SQLTuple)sqlvalue); //! case SQLValueIF.VERBATIM: //! return optimizeVerbatim((SQLVerbatim)sqlvalue); //! case SQLValueIF.FUNCTION: //! return optimizeFunction((SQLFunction)sqlvalue); //! default: //! throw new OntopiaRuntimeException("Invalid SQLValueIF: '" + sqlvalue + "'"); //! } //! } //! //! protected int optimizeColumns(SQLColumns value) { //! } //! //! protected int optimizeNull(SQLNull value) { //! } //! //! protected int optimizeParameter(SQLParameter value) { //! } //! //! protected int optimizePrimitive(SQLPrimitive value) { //! } //! //! protected int optimizeTuple(SQLTuple value) { //! } //! //! protected int optimizeVerbatim(SQLVerbatim value) { //! SQLTable[] tables = value.getTables(); //! for (int i=0; i < tables.length; i++) { //! addTable(tables[i]); //! } //! } //! //! protected int optimizeFunction(SQLFunction value) { //! ... //! } }