All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nz.co.gregs.dbvolution.expressions.BooleanExpression Maven / Gradle / Ivy

/*
 * Copyright 2014 Gregory Graham.
 *
 * 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 nz.co.gregs.dbvolution.expressions;

import nz.co.gregs.dbvolution.results.StringResult;
import nz.co.gregs.dbvolution.results.DateResult;
import nz.co.gregs.dbvolution.results.NumberResult;
import nz.co.gregs.dbvolution.results.BooleanResult;
import com.vividsolutions.jts.geom.Polygon;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import nz.co.gregs.dbvolution.DBQuery;
import nz.co.gregs.dbvolution.DBRow;
import nz.co.gregs.dbvolution.columns.ColumnProvider;
import nz.co.gregs.dbvolution.databases.definitions.DBDefinition;
import nz.co.gregs.dbvolution.datatypes.DBBoolean;
import nz.co.gregs.dbvolution.datatypes.DBInteger;
import nz.co.gregs.dbvolution.datatypes.DBNumber;
import nz.co.gregs.dbvolution.datatypes.DBString;
import nz.co.gregs.dbvolution.datatypes.QueryableDatatype;
import nz.co.gregs.dbvolution.results.AnyResult;
import nz.co.gregs.dbvolution.results.IntegerResult;
import nz.co.gregs.dbvolution.results.RangeComparable;
import nz.co.gregs.dbvolution.results.RangeResult;

/**
 * BooleanExpression implements standard functions that produce a Boolean or
 * TRUE/FALSE result.
 *
 * 

* Most query requirements are provided by {@link QueryableDatatype}s like * {@link DBString} or {@link DBInteger} but expressions can provide more * functions or more precise control. * *

* Use a BooleanExpression to produce a conditional expression as used in * {@link DBQuery#addCondition(nz.co.gregs.dbvolution.expressions.BooleanExpression)}. * *

* Generally you get a BooleanExpression using an "is" method from one of the * other DBExpressions but you can use * {@link BooleanExpression#value(java.lang.Boolean)} or * {@link DBRow#column(nz.co.gregs.dbvolution.datatypes.DBBoolean)} to start * your Boolean expression. * *

* BooleanExpression also provides the means for grouping BooleanExpressions * together with the * {@link #allOf(nz.co.gregs.dbvolution.expressions.BooleanExpression...) allOf} * or * {@link #anyOf(nz.co.gregs.dbvolution.expressions.BooleanExpression...) anyOf} * methods. * *

* There are also comparisons with NULL, negations, and static true and false * expressions. * *

Support DBvolution at * Patreon

* * @author Gregory Graham */ public class BooleanExpression extends EqualExpression implements BooleanResult { /** * Default Constructor for creating new BooleanExpressions. * *

* The BooleanExpression created has no value or operation and is generally * useless for the end user. however it is required for sub-classing. * */ protected BooleanExpression() { super(); } /** * The normal method for creating a BooleanExpression. * *

* BooleanExpressions generally wrap other BooleanExpressions or similar * objects and add functionality to them. Use this constructor to wrap an * existing BooleanExpression. * * @param booleanResult booleanResult */ public BooleanExpression(BooleanResult booleanResult) { super(booleanResult); } public BooleanExpression(AnyResult booleanResult) { super(booleanResult); } /** * The easy way to create a BooleanExpression based on a literal value. * *

* BooleanExpressions generally wrap other BooleanExpressions or similar * objects and add functionality to them. Use this constructor to wrap a known * value for use in a BooleanExpression. * * * @param bool */ public BooleanExpression(Boolean bool) { super(new DBBoolean(bool)); } @Override public BooleanExpression copy() { return isNullSafetyTerminator() ? nullBoolean() : new BooleanExpression(this.getInnerResult()); } /** * Returns a value of the required type that will evaluate to NULL. * * @return a NULL for use in boolean statements. */ @Override public BooleanExpression nullExpression() { return new BooleanExpression() { @Override public String toSQLString(DBDefinition db) { return db.getNull(); } }; } /** * Creates an expression that will return the most common value of the column * supplied. * *

* MODE: The number which appears most often in a set of numbers. For example: * in {6, 3, 9, 6, 6, 5, 9, 3} the Mode is 6.

* *

Support DBvolution at * Patreon

* * @return a number expression. */ @Override public BooleanExpression modeSimple() { BooleanExpression modeExpr = new BooleanExpression( new ModeSimpleExpression(this)); return modeExpr; } /** * Create An Appropriate BooleanExpression Object For This Object * *

* The expression framework requires a *Expression to work with. The easiest * way to get that is the {@code DBRow.column()} method. * *

* However if you wish your expression to start with a literal value it is a * little trickier. * *

* This method provides the easy route to a *Expression from a literal value. * Just call, for instance, {@code StringExpression.value("STARTING STRING")} * to get a StringExpression and start the expression chain. * *

    *
  • Only object classes that are appropriate need to be handle by the * DBExpression subclass.
  • *
  • The implementation should be {@code static}
  • *
* * @param bool the boolean value to be tested *

Support DBvolution at * Patreon

* @return a DBExpression instance that is appropriate to the subclass and the * value supplied. */ @Override public BooleanExpression expression(Boolean bool) { return value(bool); } @Override public BooleanExpression expression(DBBoolean bool) { return value(bool); } /** * Create An Appropriate BooleanExpression Object For This Object * *

* The expression framework requires a *Expression to work with. The easiest * way to get that is the {@code DBRow.column()} method. * *

* However if you wish your expression to start with a literal value it is a * little trickier. * *

* This method provides the easy route to a *Expression from a literal value. * Just call, for instance, {@code StringExpression.value("STARTING STRING")} * to get a StringExpression and start the expression chain. * *

    *
  • Only object classes that are appropriate need to be handle by the * DBExpression subclass.
  • *
  • The implementation should be {@code static}
  • *
* * @param bool the boolean value to be tested *

Support DBvolution at * Patreon

* @return a DBExpression instance that is appropriate to the subclass and the * value supplied. */ @Override public BooleanExpression expression(BooleanResult bool) { return new BooleanExpression(bool); } /** * Compare this BooleanExpression and the given boolean using the equality * operator, that is "=" or similar. * * @param bool the boolean value to be tested *

Support DBvolution at * Patreon

* @return a BooleanExpression that compares the previous BooleanExpression to * the Boolean supplied. */ @Override public BooleanExpression is(Boolean bool) { return bool == null ? isNull() : is(new BooleanExpression(bool)); } /** * Compare this BooleanExpression and the given {@link BooleanResult} using * the equality operator, that is "=" or similar. * *

* BooleanResult includes {@link BooleanExpression} and {@link DBBoolean}. * * @param bool the boolean value to be tested *

Support DBvolution at * Patreon

* @return a BooleanExpression that compares the previous BooleanExpression to * the Boolean supplied. */ public BooleanExpression is(BooleanExpression bool) { return bool.getIncludesNull() ? isNull() : is((BooleanResult) bool); } /** * Compare this BooleanExpression and the given {@link BooleanResult} using * the equality operator, that is "=" or similar. * *

* BooleanResult includes {@link BooleanExpression} and {@link DBBoolean}. * * @param bool the boolean value to be tested *

Support DBvolution at * Patreon

* @return a BooleanExpression that compares the previous BooleanExpression to * the Boolean supplied. */ @Override public BooleanExpression is(BooleanResult bool) { return new BooleanExpression(new DBBinaryBooleanArithmetic(this, bool) { @Override public String toSQLString(DBDefinition defn) { if (defn.supportsComparingBooleanResults()) { return super.toSQLString(defn); } else { BooleanExpression first = this.getFirst(); BooleanExpression second = this.getSecond(); String returnString = first.getComparableBooleanSQL(defn) + getEquationOperator(defn) + second.getComparableBooleanSQL(defn); return returnString; } } @Override protected String getEquationOperator(DBDefinition db) { return " = "; } }); } /** * Compare this BooleanExpression and the given {@link BooleanResult} using * the inequality operator, that is "<>" or similar. * *

* BooleanResult includes {@link BooleanExpression} and {@link DBBoolean}. * * @param bool the boolean value to be tested *

Support DBvolution at * Patreon

* @return a BooleanExpression that compares the previous BooleanExpression to * the Boolean supplied. */ @Override public BooleanExpression isNot(BooleanResult bool) { return new BooleanExpression(new DBBinaryBooleanArithmetic(this, bool) { @Override public String toSQLString(DBDefinition db) { DBDefinition defn = db; if (defn.supportsComparingBooleanResults()) { return super.toSQLString(db); } else { BooleanExpression first = this.getFirst(); BooleanExpression second = this.getSecond(); String returnString = "(" + first.getComparableBooleanSQL(db) + ")" + getEquationOperator(db) + "(" + second.getComparableBooleanSQL(db) + ")"; return returnString; } } @Override protected String getEquationOperator(DBDefinition db) { return " <> "; } }); } /** * Creates an expression that will count all the values of the column * supplied. * *

* Count is an aggregator function for use in DBReport or in a column * expression. * *

Support DBvolution at * Patreon

* * @return a number expression. */ @Override public IntegerExpression count() { return new IntegerExpression(new BooleanExpression(this) { @Override public String toSQLString(DBDefinition db) { DBDefinition defn = db; final String bool; if (defn.supportsComparingBooleanResults()) { bool = super.toSQLString(db); } else { BooleanExpression first = (BooleanExpression) this.getInnerResult(); bool = first.getComparableBooleanSQL(db); } String returnString = db.getCountFunctionName() + "(" + bool + ")"; return returnString; } @Override public boolean isAggregator() { return true; } @Override public boolean isBooleanStatement() { return true; } }); } protected String getComparableBooleanSQL(DBDefinition db) { String firstSQL; boolean firstIsStatement = this.isBooleanStatement(); if (firstIsStatement) { firstSQL = db.doBooleanStatementToBooleanComparisonValueTransform(this.toSQLString(db)); } else { firstSQL = db.doBooleanValueToBooleanComparisonValueTransform(this.toSQLString(db)); } return "(" + firstSQL + ")"; } /** * Compare this BooleanExpression and the given {@link BooleanResult} using * the inequality operator, that is "<>" or similar. * *

* BooleanResult includes {@link BooleanExpression} and {@link DBBoolean}. * * @param bool the boolean value to be tested *

Support DBvolution at * Patreon

* @return a BooleanExpression that compares the previous BooleanExpression to * the Boolean supplied. */ @Override public BooleanExpression isNot(Boolean bool) { return isNot(new BooleanExpression(bool)); } /** * Compare this BooleanExpression and the given {@link BooleanResult} using * the Exclusive OR operator, that is "=" or similar. * *

* BooleanResult includes {@link BooleanExpression} and {@link DBBoolean}. * * @param bool the boolean value to be tested *

Support DBvolution at * Patreon

* @return a BooleanExpression of an XOR operation. */ public BooleanExpression xor(BooleanResult bool) { return new BooleanExpression(new DBBinaryBooleanArithmetic(this, bool) { @Override public String toSQLString(DBDefinition db) { if (db.supportsXOROperator()) { return super.toSQLString(db); } else { return BooleanExpression.anyOf( BooleanExpression.allOf( this.getFirst(), this.getSecond().not() ), BooleanExpression.allOf( this.getFirst().not(), this.getSecond()) ).toSQLString(db); } } @Override protected String getEquationOperator(DBDefinition db) { return "^"; } }); } /** * Collects the expressions together and requires them all to be true. * *

* Creates a BooleanExpression of several Boolean Expressions by connecting * them using AND repeatedly. * *

* This expression returns true if and only if all the component expressions * are true. * * @param booleanExpressions the boolean expressions to be tested *

Support DBvolution at * Patreon

* @return a boolean expression that returns true IFF all the * booleanExpressions are true. * @see #anyOf(BooleanExpression...) */ public static BooleanExpression allOf(final BooleanExpression... booleanExpressions) { return new BooleanExpression(new DBNnaryBooleanArithmetic(booleanExpressions) { @Override protected String getEquationOperator(DBDefinition db) { return db.beginAndLine(); } }); } /** * Collects the expressions together and requires that at least one of them to * be false. * *

* Please note that this expression does not exclude the cases where all tests * fail. To exclude the ALL and NONE cases, use * {@link #someButNotAllOf(nz.co.gregs.dbvolution.expressions.BooleanExpression...) the SOME method}. * *

* Creates a BooleanExpression of several Boolean Expressions by connecting * them using NOT and OR repeatedly. * *

* This expression returns true if and only if some of the component * expressions are false. * * @param booleanExpressions the boolean expressions to be tested *

Support DBvolution at * Patreon

* @return a boolean expression that returns true IFF some of the * booleanExpressions are false. * @see #anyOf(BooleanExpression...) * @see #allOf(BooleanExpression...) */ public static BooleanExpression notAllOf(final BooleanExpression... booleanExpressions) { List notBools = new ArrayList<>(); for (BooleanExpression booleanExpression : booleanExpressions) { notBools.add(booleanExpression.not()); } return anyOf(notBools.toArray(booleanExpressions)); } /** * Collects the expressions together and requires that at least one of them to * be false and at least one to be false. * *

* This expression specifically excludes the cases where ALL and NONE of the * tests pass. * *

* This expression facilties finding partial matches that may need to be * handled separately. * *

* This expression returns true if and only if some of the component * expressions are false and some are true. * * @param booleanExpressions the boolean expressions to be tested *

Support DBvolution at * Patreon

* @return a boolean expression that returns true IFF some of the * booleanExpressions are false AND some of the booleanExpressions are true * @see #anyOf(BooleanExpression...) * @see #allOf(BooleanExpression...) */ public static BooleanExpression someButNotAllOf(final BooleanExpression... booleanExpressions) { return allOf( BooleanExpression.allOf(booleanExpressions).not(), BooleanExpression.noneOf(booleanExpressions).not() ); } /** * Collects the expressions together and only requires one to be true. * *

* Creates a BooleanExpression of several Boolean Expressions by connecting * them using OR repeatedly. * *

* This expression returns true if any of the component expressions is true * * @param booleanExpressions the boolean expressions to be tested *

Support DBvolution at * Patreon

* @return a boolean expression that returns true if any of the * booleanExpressions is true. * @see #allOf(BooleanExpression...) */ public static BooleanExpression anyOf(final BooleanExpression... booleanExpressions) { return new BooleanExpression(new DBNnaryBooleanArithmetic(booleanExpressions) { @Override protected String getEquationOperator(DBDefinition db) { return db.beginOrLine(); } }); } /** * Returns true only if all of the conditions are FALSE. * * @param booleanExpressions the boolean expressions to be tested *

Support DBvolution at * Patreon

* @return a boolean expression that returns true if all of the * booleanExpressions evaluate to FALSE. * @see #allOf(BooleanExpression...) * @see #anyOf(BooleanExpression...) */ public static BooleanExpression noneOf(final BooleanExpression... booleanExpressions) { return BooleanExpression.anyOf(booleanExpressions).not(); } /** * Negates this BooleanExpression. * *

* The 3 main boolean operators are AND, OR, and NOT. This method implements * NOT. * *

* The boolean result of the expression will be negated by this call so that * TRUE becomes FALSE and FALSE becomes TRUE. * *

* Please note that databases use * Three-valued * logic * so {@link QueryableDatatype#isDBNull NULL} is also a valid result of this * expression * *

Support DBvolution at * Patreon

* * @return a Boolean expression representing the negation of the current * expression. */ public BooleanExpression negate() { return new BooleanExpression(new BooleanExpression(this) { @Override public String toSQLString(DBDefinition db) { return db.getNegationFunctionName() + "(" + getInnerResult().toSQLString(db) + ")"; } }); } /** * Converts boolean values to the database integer representation. * *

* TRUE values will become 1 and FALSE values will become 0. * *

Support DBvolution at * Patreon

* * @return a 0 or 1 depending on the expression */ public IntegerExpression integerValue() { return IntegerExpression.value(new IntegerValueFunction(this)); } /** * Converts boolean values to the database number representation. * *

* TRUE values will become 1.0 and FALSE values will become 0.0. * *

Support DBvolution at * Patreon

* * @return a 0 or 1 depending on the expression */ public NumberExpression numberValue() { return new NumberExpression() { BooleanExpression innerBool = new BooleanExpression(getInnerResult()); @Override public String toSQLString(DBDefinition db) { return db.doBooleanToIntegerTransform(this.innerBool.toSQLString(db)); } @Override public NumberExpression copy() { try { return (NumberExpression) this.clone(); } catch (CloneNotSupportedException ex) { throw new RuntimeException(ex); } } @Override public boolean getIncludesNull() { return innerBool.getIncludesNull(); } @Override public boolean isAggregator() { return false; } @Override public Set getTablesInvolved() { return innerBool.getTablesInvolved(); } }; } /** * Returns FALSE if this expression is TRUE, or TRUE if it is FALSE. * *

* Synonym for {@link #negate() the negate() method} * *

* The 3 main boolean operators are AND, OR, and NOT. This method implements * NOT. * *

* The boolean result of the expression will be negated by this call so that * TRUE becomes FALSE and FALSE becomes TRUE. * *

* Please note that databases use * Three-valued * logic * so {@link QueryableDatatype#isDBNull NULL} is also a valid result of this * expression * *

Support DBvolution at * Patreon

* * @return a Boolean expression representing the negation of the current * expression. */ public BooleanExpression not() { return this.negate(); } /** * Returns FALSE if the given {@link DBExpression} evaluates to NULL, * otherwise TRUE. * *

Support DBvolution at * Patreon

* * @return a BooleanExpression */ public BooleanExpression isNotNull() { return BooleanExpression.isNotNull(this); } /** * Returns FALSE if the given {@link DBExpression} evaluates to NULL, * otherwise TRUE. * *

* DBExpression subclasses include * {@link QueryableDatatype QueryableDatatypes} like {@link DBString} and * {@link DBInteger} as well as * {@link NumberExpression}, {@link StringExpression}, {@link DateExpression}, * and {@link LargeObjectExpression}. * * @param possibleNullExpression the expression to be tested *

Support DBvolution at * Patreon

* @return a BooleanExpression */ public static BooleanExpression isNotNull(DBExpression possibleNullExpression) { return new BooleanExpression(new DBUnaryBooleanArithmetic(possibleNullExpression) { @Override protected String getEquationOperator(DBDefinition db) { return " IS NOT " + db.getNull(); } @Override public boolean getIncludesNull() { return false; } }); } /** * Returns FALSE if the given {@link ColumnProvider} evaluates to NULL, * otherwise TRUE. * *

* Obtain a {@link ColumnProvider} by using the column method of * {@link DBRow}. * * @param possibleNullExpression the expression to be tested *

Support DBvolution at * Patreon

* @return a BooleanExpression */ public static BooleanExpression isNotNull(ColumnProvider possibleNullExpression) { return isNotNull(possibleNullExpression.getColumn().asExpression()); } /** * Returns TRUE if the given {@link ColumnProvider} evaluates to NULL, * otherwise FALSE. * *

* Obtain a {@link ColumnProvider} by using the column method of * {@link DBRow}. * * @param possibleNullExpression the expression to be tested *

Support DBvolution at * Patreon

* @return a BooleanExpression */ public static BooleanExpression isNull(ColumnProvider possibleNullExpression) { return isNull(possibleNullExpression.getColumn().asExpression()); } /** * Returns TRUE if the given {@link DBExpression} evaluates to NULL, otherwise * FALSE. * *

* DBExpression subclasses include * {@link QueryableDatatype QueryableDatatypes} like {@link DBString} and * {@link DBInteger} as well as * {@link NumberExpression}, {@link StringExpression}, {@link DateExpression}, * and {@link LargeObjectExpression}. * * @param possibleNullExpression the expression to be tested *

Support DBvolution at * Patreon

* @return a BooleanExpression */ public static BooleanExpression isNull(DBExpression possibleNullExpression) { return new BooleanExpression(new DBUnaryBooleanArithmetic(possibleNullExpression) { @Override protected String getEquationOperator(DBDefinition db) { return " IS " + db.getNull(); } @Override public boolean getIncludesNull() { return false; } }); } /** * Returns TRUE if this expression evaluates to NULL, otherwise FALSE. * *

Support DBvolution at * Patreon

* * @return a BooleanExpression */ public BooleanExpression isNull() { return BooleanExpression.isNull(this); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public StringExpression ifThenElse(String thenExpr, String elseExpr) { return this.ifThenElse(new StringExpression(thenExpr), new StringExpression(elseExpr)); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public StringExpression ifThenElse(StringExpression thenExpr, StringExpression elseExpr) { return new StringExpression(new DBBooleanStringStringFunction(this, thenExpr, elseExpr) { @Override public boolean getIncludesNull() { return false; } @Override public String toSQLString(DBDefinition db) { return db.doIfThenElseTransform(onlyBool.toSQLString(db), first.toSQLString(db), second.toSQLString(db)); } @Override String getFunctionName(DBDefinition db) { return ""; } }); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public NumberExpression ifThenElse(Number thenExpr, Number elseExpr) { return this.ifThenElse(new NumberExpression(thenExpr), new NumberExpression(elseExpr)); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public IntegerExpression ifThenElse(Long thenExpr, Long elseExpr) { return this.ifThenElse(new IntegerExpression(thenExpr), new IntegerExpression(elseExpr)); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public IntegerExpression ifThenElse(Integer thenExpr, Integer elseExpr) { return this.ifThenElse(new IntegerExpression(thenExpr), new IntegerExpression(elseExpr)); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public NumberExpression ifThenElse(NumberResult thenExpr, NumberResult elseExpr) { return new NumberExpression(new DBBooleanNumberNumberFunction(this, thenExpr, elseExpr) { @Override public boolean getIncludesNull() { return false; } @Override public String toSQLString(DBDefinition db) { return db.doIfThenElseTransform(onlyBool.toSQLString(db), first.toSQLString(db), second.toSQLString(db)); } @Override String getFunctionName(DBDefinition db) { return ""; } }); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* * @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public IntegerExpression ifThenElse(IntegerResult thenExpr, IntegerResult elseExpr) { return new IntegerExpression(new DBBooleanIntegerIntegerFunction(this, thenExpr, elseExpr) { @Override public boolean getIncludesNull() { return false; } @Override public String toSQLString(DBDefinition db) { return db.doIfThenElseTransform(onlyBool.toSQLString(db), first.toSQLString(db), second.toSQLString(db)); } @Override String getFunctionName(DBDefinition db) { return ""; } }); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public DateExpression ifThenElse(Date thenExpr, Date elseExpr) { return this.ifThenElse(new DateExpression(thenExpr), new DateExpression(elseExpr)); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public DateExpression ifThenElse(DateExpression thenExpr, DateExpression elseExpr) { return new DateExpression(new DBBinaryDateDateFunction(this, thenExpr, elseExpr) { @Override public boolean getIncludesNull() { return false; } @Override public String toSQLString(DBDefinition db) { return db.doIfThenElseTransform(onlyBool.toSQLString(db), first.toSQLString(db), second.toSQLString(db)); } @Override String getFunctionName(DBDefinition db) { return ""; } }); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public Polygon2DExpression ifThenElse(Polygon thenExpr, Polygon elseExpr) { return this.ifThenElse(new Polygon2DExpression(thenExpr), new Polygon2DExpression(elseExpr)); } /** * Allows you to specify different return values based on the value of this * boolean expression. * *

* The first expression is returned if this expression is TRUE, otherwise the * second is returned. * * @param thenExpr expression to use when this expression is TRUE * @param elseExpr expression to use when this expression is FALSE *

Support DBvolution at * Patreon

* @return an expression that will generate a SQL clause conceptually similar * to "if (this) then thenExpr else elseExpr". */ public Polygon2DExpression ifThenElse(Polygon2DExpression thenExpr, Polygon2DExpression elseExpr) { return new Polygon2DExpression(new DBBinaryGeometryGeometryFunction(this, thenExpr, elseExpr) { @Override public boolean getIncludesNull() { return false; } @Override public String toSQLString(DBDefinition db) { return db.doIfThenElseTransform(onlyBool.toSQLString(db), first.toSQLString(db), second.toSQLString(db)); } }); } /** * Creates an expression that will always return FALSE. * *

Support DBvolution at * Patreon

* * @return an expression that will always evaluate to FALSE. */ public static BooleanExpression falseExpression() { return new BooleanExpression() { @Override public String toSQLString(DBDefinition db) { return db.getFalseOperation(); } @Override public boolean isAggregator() { return false; } }; } /** * Creates an expression that will always return TRUE. * *

Support DBvolution at * Patreon

* * @return an expression that will always evaluate to TRUE. */ public static BooleanExpression trueExpression() { return new BooleanExpression() { @Override public String toSQLString(DBDefinition db) { return db.getTrueOperation(); } @Override public boolean isAggregator() { return false; } }; } /** * Specifies that the expression will return TRUE if this OR the specified * expression are TRUE. * *

* This is a convenience method that wraps this and anotherBooleanExpr in {@link BooleanExpression#anyOf(nz.co.gregs.dbvolution.expressions.BooleanExpression...) * }. * * @param anotherBooleanExpr if this expression does not evaluate to TRUE, * return the value of anotherBooleanExpression. *

Support DBvolution at * Patreon

* @return a expression that will evaluate to TRUE if either of the * expressions are TRUE. */ public BooleanExpression or(BooleanExpression anotherBooleanExpr) { return BooleanExpression.anyOf( this, anotherBooleanExpr); } /** * Specifies that the expression will return TRUE only if this AND the * specified expression are TRUE. * *

* This is a convenience method that wraps this and anotherBooleanExpr in {@link BooleanExpression#allOf(nz.co.gregs.dbvolution.expressions.BooleanExpression...) * }. * * @param anotherBooleanExpr only return TRUE if both this expression and * anotherBooleanExpr evaluate to TRUE. *

Support DBvolution at * Patreon

* @return a expression that will evaluate to TRUE only if both of the * expressions are TRUE. */ public BooleanExpression and(BooleanExpression anotherBooleanExpr) { return BooleanExpression.allOf( this, anotherBooleanExpr); } /** * Implements the little-known (and implemented) SQL Row Value syntax. * *

* in PostgreSQL you can do (colA, colB) < (valA, valB). In other databases * you need to write: ((colA < valA) OR (colA = valA AND colB < valB)). * Similarly for >. * *

* Essentially seek looks at both parameters and returns the rows that sort * below both. * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param a base class like String, Number, or Date * @param a value that can be compared to Z, probably StringResult, * NumberResult, or DateResult * @param columnA the left side of the internal comparison * @param valueA the right side of the internal comparison * @param whenEqualsFallbackComparison the comparison used when the ColumnA * and ValueA are equal. *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @SuppressWarnings("unchecked") public static > BooleanExpression seekLessThan( RangeComparable columnA, R valueA, BooleanExpression whenEqualsFallbackComparison) { return columnA.isLessThan(valueA).or(columnA.is(valueA).and(whenEqualsFallbackComparison)); } /** * Implements the little-known (and implemented) SQL Row Value syntax. * *

* in PostgreSQL you can do (colA, colB) < (valA, valB). In other databases * you need to write: ((colA < valA) OR (colA = valA AND colB < valB)). * Similarly for >. * *

* Essentially seek looks at both parameters and returns the rows that sort * above both. * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param a base class like String, Number, or Date * @param a value that can be compared to Z, probably StringResult, * NumberResult, or DateResult * @param columnA the left side of the internal comparison * @param valueA the right side of the internal comparison * @param whenEqualsFallbackComparison the comparison used when the ColumnA * and ValueA are equal. *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @SuppressWarnings("unchecked") public static > BooleanExpression seekGreaterThan(RangeComparable columnA, R valueA, BooleanExpression whenEqualsFallbackComparison) { return columnA.isGreaterThan(valueA).or(columnA.is(valueA).and(whenEqualsFallbackComparison)); } /** * Implements the little-known (and implemented) SQL Row Value syntax. * *

* in PostgreSQL you can do (colA, colB) < (valA, valB). In other databases * you need to write: ((colA < valA) OR (colA = valA AND colB < valB)). * Similarly for >. * *

* Essentially seek looks at both parameters and returns the rows that sort * below both. * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param * @param * @param * @param * @param columnA the left side of the internal comparison * @param valueA the right side of the internal comparison * @param columnB the left side of the internal comparison * @param valueB the right side of the internal comparison and ValueA are * equal. *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @SuppressWarnings("unchecked") public static , C, S extends RangeResult> BooleanExpression seekLessThan(RangeComparable columnA, R valueA, RangeComparable columnB, S valueB) { return BooleanExpression.anyOf( columnA.isLessThan(valueA), BooleanExpression.allOf(columnA.is(valueA), columnB.isLessThanOrEqual(valueB))); } /** * Implements the little-known (and implemented) SQL Row Value syntax. * *

* in PostgreSQL you can do (colA, colB) < (valA, valB). In other databases * you need to write: ((colA < valA) OR (colA = valA AND colB < valB)). * Similarly for >. * *

* Essentially seek looks at both parameters and returns the rows that sort * above both. * *

* This version provides a second level of sorting. If you only need to seek * on one column/value use {@link #seekGreaterThan(nz.co.gregs.dbvolution.results.RangeComparable, nz.co.gregs.dbvolution.results.RangeResult, nz.co.gregs.dbvolution.expressions.BooleanExpression) * } * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param * @param * @param * @param * @param columnA the left side of the internal comparison * @param valueA the right side of the internal comparison * @param columnB the left side of the internal comparison * @param valueB the right side of the internal comparison *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @SuppressWarnings("unchecked") public static , C, S extends RangeResult> BooleanExpression seekGreaterThan(RangeComparable columnA, R valueA, RangeComparable columnB, S valueB) { return BooleanExpression.anyOf( columnA.isGreaterThan(valueA), BooleanExpression.allOf(columnA.is(valueA), columnB.isGreaterThanOrEqual(valueB))); } /** * Implements the little-known (and implemented) SQL Row Value syntax. * *

* in PostgreSQL you can do (colA, colB) < (valA, valB). In other databases * you need to write: ((colA < valA) OR (colA = valA AND colB < valB)). * Similarly for >. * *

* Essentially seek looks at both parameters and returns the rows that sort * below both. * *

* This version provides three levels of sorting. If you only need to seek on * one column/value use {@link #seekLessThan(nz.co.gregs.dbvolution.results.RangeComparable, nz.co.gregs.dbvolution.results.RangeResult, nz.co.gregs.dbvolution.expressions.BooleanExpression) * } * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param * @param * @param * @param * @param * @param * @param columnA the left side of the internal comparison * @param valueA the right side of the internal comparison * @param columnB the left side of the internal comparison * @param valueB the right side of the internal comparison * @param columnC the left side of the internal comparison * @param valueC the right side of the internal comparison *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @SuppressWarnings("unchecked") public static , C, S extends RangeResult, D, T extends RangeResult> BooleanExpression seekLessThan(RangeComparable columnA, R valueA, RangeComparable columnB, S valueB, RangeComparable columnC, T valueC) { return BooleanExpression.anyOf( columnA.isLessThan(valueA), BooleanExpression.allOf(columnA.is(valueA), BooleanExpression.seekLessThan(columnB, valueB, columnC, valueC))); } /** * Implements the little-known (and implemented) SQL Row Value syntax. * *

* in PostgreSQL you can do (colA, colB) < (valA, valB). In other databases * you need to write: ((colA < valA) OR (colA = valA AND colB < valB)). * Similarly for >. * *

* Essentially seek looks at both parameters and returns the rows that sort * below both. * *

* This version provides four levels of sorting. If you only need to seek on * one column/value use {@link #seekLessThan(nz.co.gregs.dbvolution.results.RangeComparable, nz.co.gregs.dbvolution.results.RangeResult, nz.co.gregs.dbvolution.expressions.BooleanExpression) * } * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param * @param * @param * @param * @param * @param * @param * @param * @param columnA the left side of the internal comparison * @param valueA the right side of the internal comparison * @param columnB the left side of the internal comparison * @param valueB the right side of the internal comparison * @param columnC the left side of the internal comparison * @param valueC the right side of the internal comparison * @param columnD the left side of the internal comparison * @param valueD the right side of the internal comparison *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @SuppressWarnings("unchecked") public static , C, S extends RangeResult, D, T extends RangeResult, E, U extends RangeResult> BooleanExpression seekLessThan(RangeComparable columnA, R valueA, RangeComparable columnB, S valueB, RangeComparable columnC, T valueC, RangeComparable columnD, U valueD) { return BooleanExpression.anyOf( columnA.isLessThan(valueA), BooleanExpression.allOf(columnA.is(valueA), BooleanExpression.seekLessThan(columnB, valueB, columnC, valueC, columnD, valueD))); } /** * Implements the little-known (and implemented) SQL Row Value syntax. * *

* in PostgreSQL you can do (colA, colB) < (valA, valB). In other databases * you need to write: ((colA < valA) OR (colA = valA AND colB < valB)). * Similarly for >. * *

* Essentially seek looks at both parameters and returns the rows that sort * below both. * *

* This version provides 3 levels of sorting. If you only need to seek on one * column/value use {@link #seekLessThan(nz.co.gregs.dbvolution.results.RangeComparable, nz.co.gregs.dbvolution.results.RangeResult, nz.co.gregs.dbvolution.expressions.BooleanExpression) * } * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param * @param * @param * @param * @param * @param * @param columnA the left side of the internal comparison * @param valueA the right side of the internal comparison * @param columnB the left side of the internal comparison * @param valueB the right side of the internal comparison * @param columnC the left side of the internal comparison * @param valueC the right side of the internal comparison *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @SuppressWarnings("unchecked") public static , C, S extends RangeResult, D, T extends RangeResult> BooleanExpression seekGreaterThan(RangeComparable columnA, R valueA, RangeComparable columnB, S valueB, RangeComparable columnC, T valueC) { return BooleanExpression.anyOf( columnA.isGreaterThan(valueA), BooleanExpression.allOf(columnA.is(valueA), BooleanExpression.seekGreaterThan(columnB, valueB, columnC, valueC))); } /** * Implements the little-known (and implemented) SQL Row Value syntax. * *

* in PostgreSQL you can do (colA, colB) < (valA, valB). In other databases * you need to write: ((colA < valA) OR (colA = valA AND colB < valB)). * Similarly for >. * *

* Essentially seek looks at both parameters and returns the rows that sort * above both. * *

* This version provides four levels of sorting. If you only need to seek on * one column/value use {@link #seekGreaterThan(nz.co.gregs.dbvolution.results.RangeComparable, nz.co.gregs.dbvolution.results.RangeResult, nz.co.gregs.dbvolution.expressions.BooleanExpression) * } * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param * @param * @param * @param * @param * @param * @param * @param * @param columnA the left side of the internal comparison * @param valueA the right side of the internal comparison * @param columnB the left side of the internal comparison * @param valueB the right side of the internal comparison * @param columnC the left side of the internal comparison * @param valueC the right side of the internal comparison * @param columnD the left side of the internal comparison * @param valueD the right side of the internal comparison *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @SuppressWarnings("unchecked") public static , C, S extends RangeResult, D, T extends RangeResult, E, U extends RangeResult> BooleanExpression seekGreaterThan(RangeComparable columnA, R valueA, RangeComparable columnB, S valueB, RangeComparable columnC, T valueC, RangeComparable columnD, U valueD) { return BooleanExpression.anyOf( columnA.isGreaterThan(valueA), BooleanExpression.allOf(columnA.is(valueA), BooleanExpression.seekGreaterThan(columnB, valueB, columnC, valueC, columnD, valueD))); } @Override public DBBoolean getQueryableDatatypeForExpressionValue() { return new DBBoolean(); } /** * Indicates if this expression is a relationship between 2, or more, tables. * *

Support DBvolution at * Patreon

* * @return the relationship */ public boolean isRelationship() { return this.getTablesInvolved().size() > 1; } @Override public StringExpression stringResult() { return this.ifThenElse("TRUE", "FALSE"); } @Override public DBBoolean asExpressionColumn() { return new DBBoolean(this); } @Override public boolean isBooleanStatement() { AnyResult onlyBool1 = this.getInnerResult(); if (onlyBool1 instanceof BooleanResult) { return ((BooleanResult) onlyBool1).isBooleanStatement(); } else { return true; } } private static abstract class DBUnaryBooleanArithmetic extends BooleanExpression { private DBExpression onlyBool; DBUnaryBooleanArithmetic(DBExpression bool) { this.onlyBool = bool.copy(); } @Override public DBBoolean getQueryableDatatypeForExpressionValue() { return new DBBoolean(); } @Override public String toSQLString(DBDefinition db) { String op = this.getEquationOperator(db); String returnStr = onlyBool.toSQLString(db) + " " + op; return returnStr; } @Override public DBUnaryBooleanArithmetic copy() { DBUnaryBooleanArithmetic newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.onlyBool = onlyBool.copy(); return newInstance; } @Override public Set getTablesInvolved() { return onlyBool == null ? new HashSet() : onlyBool.getTablesInvolved(); } @Override public boolean isAggregator() { return onlyBool.isAggregator(); } protected abstract String getEquationOperator(DBDefinition db); @Override public boolean isPurelyFunctional() { if (onlyBool == null) { return true; } else { return onlyBool.isPurelyFunctional(); } } } private static abstract class DBNnaryBooleanArithmetic extends BooleanExpression { private BooleanResult[] bools; DBNnaryBooleanArithmetic(BooleanResult... bools) { this.bools = bools; } @Override public DBBoolean getQueryableDatatypeForExpressionValue() { return new DBBoolean(); } @Override public String toSQLString(DBDefinition db) { StringBuilder returnStr = new StringBuilder(); String separator = ""; String op = this.getEquationOperator(db); for (BooleanResult boo : bools) { returnStr.append(separator).append(boo.toSQLString(db)); separator = op; } return "(" + returnStr + ")"; } @Override public DBNnaryBooleanArithmetic copy() { DBNnaryBooleanArithmetic newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.bools = new BooleanResult[bools.length]; for (int i = 0; i < newInstance.bools.length; i++) { newInstance.bools[i] = bools[i].copy(); } return newInstance; } @Override public Set getTablesInvolved() { HashSet hashSet = new HashSet<>(); for (BooleanResult boo : bools) { hashSet.addAll(boo.getTablesInvolved()); } return hashSet; } protected abstract String getEquationOperator(DBDefinition db); @Override public boolean isAggregator() { boolean result = false; for (BooleanResult boex : bools) { result = result || boex.isAggregator(); } return result; } @Override public boolean isPurelyFunctional() { if (bools.length == 0) { return true; } else { boolean result = true; for (BooleanResult bool : bools) { result = result && bool.isPurelyFunctional(); } return result; } } } private static abstract class DBBinaryBooleanArithmetic extends BooleanExpression { private BooleanExpression first; private BooleanExpression second; DBBinaryBooleanArithmetic(BooleanExpression first, BooleanExpression second) { this.first = first; this.second = second; } DBBinaryBooleanArithmetic(BooleanExpression first, BooleanResult second) { this(first, new BooleanExpression(second)); } @Override public String toSQLString(DBDefinition db) { String sqlString = getFirst().toSQLString(db) + this.getEquationOperator(db) + getSecond().toSQLString(db); if (getFirst().getIncludesNull()) { sqlString = getSecond().toSQLString(db) + " IS " + db.getNull() + db.beginOrLine() + sqlString; } if (getSecond().getIncludesNull()) { sqlString = getFirst().toSQLString(db) + " IS " + db.getNull() + db.beginOrLine() + sqlString; } return "(" + sqlString + ")"; } @Override public DBBinaryBooleanArithmetic copy() { DBBinaryBooleanArithmetic newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.first = getFirst().copy(); newInstance.second = getSecond().copy(); return newInstance; } protected abstract String getEquationOperator(DBDefinition db); @Override public Set getTablesInvolved() { HashSet hashSet = new HashSet<>(); if (getFirst() != null) { hashSet.addAll(getFirst().getTablesInvolved()); } if (getSecond() != null) { hashSet.addAll(getSecond().getTablesInvolved()); } return hashSet; } @Override public boolean isAggregator() { return getFirst().isAggregator() || getSecond().isAggregator(); } @Override public boolean getIncludesNull() { return false; } /** *

Support DBvolution at * Patreon

* * @return the first */ protected BooleanExpression getFirst() { return first; } /** *

Support DBvolution at * Patreon

* * @return the second */ protected BooleanExpression getSecond() { return second; } @Override public boolean isPurelyFunctional() { if (first == null && second == null) { return true; } else { return (first == null ? true : first.isPurelyFunctional()) && (second == null ? true : second.isPurelyFunctional()); } } } private static abstract class DBBooleanStringStringFunction extends StringExpression { protected BooleanExpression onlyBool = null; protected StringResult first = null; protected StringResult second = null; DBBooleanStringStringFunction() { } DBBooleanStringStringFunction(BooleanExpression only, StringResult first, StringResult second) { this.onlyBool = only; this.first = first; this.second = second; } abstract String getFunctionName(DBDefinition db); protected String beforeValue(DBDefinition db) { return "" + getFunctionName(db) + "( "; } protected String afterValue(DBDefinition db) { return ") "; } @Override public String toSQLString(DBDefinition db) { return this.beforeValue(db) + (onlyBool == null ? "" : onlyBool.toSQLString(db)) + this.afterValue(db); } @Override @SuppressWarnings("unchecked") public DBBooleanStringStringFunction copy() { DBBooleanStringStringFunction newInstance; try { newInstance = this.getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.onlyBool = (onlyBool == null ? null : onlyBool.copy()); newInstance.first = (first == null ? null : first.copy()); newInstance.second = (second == null ? null : second.copy()); return newInstance; } @Override public boolean isAggregator() { return onlyBool.isAggregator() || first.isAggregator() || second.isAggregator(); } @Override public Set getTablesInvolved() { return onlyBool.getTablesInvolved(); } @Override public boolean isPurelyFunctional() { if (onlyBool == null) { return true; } else { return onlyBool.isPurelyFunctional() && first.isPurelyFunctional() && second.isPurelyFunctional(); } } } private static abstract class DBBooleanNumberNumberFunction extends NumberExpression { protected BooleanExpression onlyBool = null; protected NumberResult first = null; protected NumberResult second = null; DBBooleanNumberNumberFunction() { } DBBooleanNumberNumberFunction(BooleanExpression only, NumberResult first, NumberResult second) { this.onlyBool = (only == null ? nullBoolean() : only); this.first = (first == null ? nullNumber() : first); this.second = (second == null ? nullNumber() : second); } abstract String getFunctionName(DBDefinition db); protected String beforeValue(DBDefinition db) { return "" + getFunctionName(db) + "( "; } protected String afterValue(DBDefinition db) { return ") "; } @Override public String toSQLString(DBDefinition db) { return this.beforeValue(db) + (onlyBool == null ? "" : onlyBool.toSQLString(db)) + this.afterValue(db); } @Override public DBBooleanNumberNumberFunction copy() { DBBooleanNumberNumberFunction newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.onlyBool = (onlyBool == null ? null : onlyBool.copy()); newInstance.first = (first == null ? null : first.copy()); newInstance.second = (second == null ? null : second.copy()); return newInstance; } @Override public boolean isAggregator() { return onlyBool.isAggregator() || first.isAggregator() || second.isAggregator(); } @Override public Set getTablesInvolved() { return onlyBool.getTablesInvolved(); } @Override public boolean isPurelyFunctional() { if (onlyBool == null) { return true; } else { return onlyBool.isPurelyFunctional() && first.isPurelyFunctional() && second.isPurelyFunctional(); } } } private static abstract class DBBooleanIntegerIntegerFunction extends IntegerExpression { protected BooleanExpression onlyBool = null; protected IntegerResult first = null; protected IntegerResult second = null; DBBooleanIntegerIntegerFunction() { } DBBooleanIntegerIntegerFunction(BooleanExpression only, IntegerResult first, IntegerResult second) { this.onlyBool = (only == null ? nullBoolean() : only); this.first = (first == null ? nullInteger() : first); this.second = (second == null ? nullInteger() : second); } abstract String getFunctionName(DBDefinition db); protected String beforeValue(DBDefinition db) { return "" + getFunctionName(db) + "( "; } protected String afterValue(DBDefinition db) { return ") "; } @Override public String toSQLString(DBDefinition db) { return this.beforeValue(db) + (onlyBool == null ? "" : onlyBool.toSQLString(db)) + this.afterValue(db); } @Override public DBBooleanIntegerIntegerFunction copy() { DBBooleanIntegerIntegerFunction newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.onlyBool = (onlyBool == null ? null : onlyBool.copy()); newInstance.first = (first == null ? null : first.copy()); newInstance.second = (second == null ? null : second.copy()); return newInstance; } @Override public boolean isAggregator() { return onlyBool.isAggregator() || first.isAggregator() || second.isAggregator(); } @Override public Set getTablesInvolved() { return onlyBool.getTablesInvolved(); } @Override public boolean isPurelyFunctional() { if (onlyBool == null) { return true; } else { return onlyBool.isPurelyFunctional() && first.isPurelyFunctional() && second.isPurelyFunctional(); } } } private static abstract class DBBinaryDateDateFunction extends DateExpression { protected BooleanExpression onlyBool = null; protected DateResult first = null; protected DateResult second = null; DBBinaryDateDateFunction() { } DBBinaryDateDateFunction(BooleanExpression only, DateExpression first, DateExpression second) { this.onlyBool = only; this.first = first; this.second = second; } abstract String getFunctionName(DBDefinition db); protected String beforeValue(DBDefinition db) { return "" + getFunctionName(db) + "( "; } protected String afterValue(DBDefinition db) { return ") "; } @Override public String toSQLString(DBDefinition db) { return this.beforeValue(db) + (onlyBool == null ? "" : onlyBool.toSQLString(db)) + this.afterValue(db); } @Override public DBBinaryDateDateFunction copy() { DBBinaryDateDateFunction newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.onlyBool = (onlyBool == null ? null : onlyBool.copy()); newInstance.first = (first == null ? null : first.copy()); newInstance.second = (second == null ? null : second.copy()); return newInstance; } @Override public boolean isAggregator() { return onlyBool.isAggregator() || first.isAggregator() || second.isAggregator(); } @Override public Set getTablesInvolved() { return onlyBool.getTablesInvolved(); } @Override public boolean isPurelyFunctional() { if (onlyBool == null) { return true; } else { return onlyBool.isPurelyFunctional() && first.isPurelyFunctional() && second.isPurelyFunctional(); } } } private static abstract class DBBinaryGeometryGeometryFunction extends Polygon2DExpression { protected BooleanExpression onlyBool = null; protected Polygon2DExpression first = null; protected Polygon2DExpression second = null; DBBinaryGeometryGeometryFunction() { } DBBinaryGeometryGeometryFunction(BooleanExpression only, Polygon2DExpression first, Polygon2DExpression second) { this.onlyBool = only; this.first = first; this.second = second; } @Override public DBBinaryGeometryGeometryFunction copy() { DBBinaryGeometryGeometryFunction newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.onlyBool = (onlyBool == null ? null : onlyBool.copy()); newInstance.first = (first == null ? null : first.copy()); newInstance.second = (second == null ? null : second.copy()); return newInstance; } @Override public boolean isAggregator() { return onlyBool.isAggregator() || first.isAggregator() || second.isAggregator(); } @Override public Set getTablesInvolved() { return onlyBool.getTablesInvolved(); } @Override public boolean isPurelyFunctional() { if (onlyBool == null) { return true; } else { return onlyBool.isPurelyFunctional() && first.isPurelyFunctional() && second.isPurelyFunctional(); } } } private static class IntegerValueFunction extends IntegerExpression { private BooleanExpression innerBool = new BooleanExpression(); public IntegerValueFunction(BooleanExpression bool) { innerBool = bool; } @Override public String toSQLString(DBDefinition db) { return db.doBooleanToIntegerTransform(this.innerBool.toSQLString(db)); } @Override public IntegerExpression copy() { try { return (IntegerExpression) this.clone(); } catch (CloneNotSupportedException ex) { throw new RuntimeException(ex); } } @Override public boolean getIncludesNull() { return innerBool.getIncludesNull(); } @Override public boolean isAggregator() { return false; } @Override public Set getTablesInvolved() { return innerBool.getTablesInvolved(); } } }