nz.co.gregs.dbvolution.expressions.StringExpression 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.NumberResult;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import nz.co.gregs.dbvolution.DBRow;
import nz.co.gregs.dbvolution.columns.StringColumn;
import nz.co.gregs.dbvolution.databases.definitions.DBDefinition;
import nz.co.gregs.dbvolution.datatypes.*;
import nz.co.gregs.dbvolution.results.AnyResult;
import nz.co.gregs.dbvolution.results.IntegerResult;
/**
* StringExpression implements standard functions that produce a character or
* string result, including CHAR and VARCHAR.
*
*
* 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 StringExpression to produce a string from an existing column,
* expression, or value and perform string manipulation.
*
*
* Generally you get a StringExpression from a value or column using {@link StringExpression#value(java.lang.String)
* } or {@link DBRow#column(nz.co.gregs.dbvolution.datatypes.DBString) }.
*
*
Support DBvolution at
* Patreon
*
* @author Gregory Graham
*/
public class StringExpression extends RangeExpression implements StringResult {
// needed because of Oracle's difficulty with empty/null strings
private final boolean stringNullProtectionRequired;
/**
* Creates a StringExpression that will return a database NULL.
*
* Support DBvolution at
* Patreon
*
* @return a StringExpression that resolves to NULL within the database
*/
@Override
public StringExpression nullExpression() {
return new StringExpression() {
@Override
public String toSQLString(DBDefinition db) {
return db.getNull();
}
@Override
public boolean getIncludesNull() {
return true;
}
};
}
/**
* Default Constructor
*
*/
protected StringExpression() {
super();
stringNullProtectionRequired = false;
}
/**
* Creates a StringExpression from an arbitrary StringResult object.
*
*
* {@link StringResult} objects are generally StringExpressions but they can
* be {@link DBString}, {@link StringColumn}, or other types.
*
* @param stringVariable stringVariable
*/
public StringExpression(StringResult stringVariable) {
super(stringVariable);
stringNullProtectionRequired = stringVariable == null || stringVariable.getIncludesNull();
}
/**
* Creates a StringExpression from an arbitrary StringResult object.
*
*
* {@link StringResult} objects are generally StringExpressions but they can
* be {@link DBString}, {@link StringColumn}, or other types.
*
* @param stringVariable stringVariable
*/
protected StringExpression(AnyResult> stringVariable) {
super(stringVariable);
stringNullProtectionRequired = stringVariable == null || stringVariable.getIncludesNull();
}
/**
* Creates a StringExpression from an arbitrary String object.
*
*
* Essentially the same as {@link StringExpression#value(java.lang.String) }
*
* @param stringVariable stringVariable
*/
public StringExpression(String stringVariable) {
super(new DBString(stringVariable));
stringNullProtectionRequired = stringVariable == null || stringVariable.isEmpty();
}
/**
* Creates a StringExpression from an arbitrary DBString object.
*
* @param stringVariable stringVariable
*/
public StringExpression(DBString stringVariable) {
super(stringVariable);
if (stringVariable == null) {
stringNullProtectionRequired = true;
} else {
stringNullProtectionRequired = stringVariable.getIncludesNull();
}
}
/**
* Creates a StringExpression from an arbitrary Number object.
*
*
* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult()
* }.
*
*
* Refer to {@link NumberExpression#NumberExpression(java.lang.Number) } and {@link NumberExpression#stringResult()
* } for more information.
*
* @param numberVariable numberVariable
*/
public StringExpression(NumberResult numberVariable) {
super(numberVariable);
if (numberVariable == null) {
stringNullProtectionRequired = true;
} else {
stringNullProtectionRequired = numberVariable.getIncludesNull();
}
}
/**
* Creates a StringExpression from an arbitrary Number object.
*
*
* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult()
* }.
*
*
* Refer to {@link NumberExpression#NumberExpression(java.lang.Number) } and {@link NumberExpression#stringResult()
* } for more information.
*
* @param numberVariable numberVariable
*/
public StringExpression(Number numberVariable) {
super(value(numberVariable).stringResult());
if (numberVariable == null) {
stringNullProtectionRequired = true;
} else {
stringNullProtectionRequired = new DBNumber(numberVariable).getIncludesNull();
}
}
/**
* Creates a StringExpression from an arbitrary Number object.
*
*
* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult()
* }.
*
*
* Refer to {@link NumberExpression#NumberExpression(java.lang.Number) } and {@link NumberExpression#stringResult()
* } for more information.
*
* @param numberVariable numberVariable
*/
public StringExpression(long numberVariable) {
super(value(numberVariable).stringResult());
stringNullProtectionRequired = false;
}
/**
* Creates a StringExpression from an arbitrary Number object.
*
*
* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult()
* }.
*
*
* Refer to {@link NumberExpression#NumberExpression(java.lang.Number) } and {@link NumberExpression#stringResult()
* } for more information.
*
* @param numberVariable numberVariable
*/
public StringExpression(int numberVariable) {
super(value(numberVariable).stringResult());
stringNullProtectionRequired = false;
}
@Override
public String toSQLString(DBDefinition db) {
AnyResult> stringInput = getInnerResult();
if (stringInput == null) {
stringInput = StringExpression.value("");
} else if (!(stringInput instanceof StringResult)) {
stringInput = stringInput.stringResult();
}
return stringInput.toSQLString(db);
}
@Override
public StringExpression copy() {
return isNullSafetyTerminator() ? nullString() : new StringExpression(getInnerResult());
}
@Override
protected boolean isNullSafetyTerminator() {
return stringNullProtectionRequired == false
&& super.isNullSafetyTerminator();
}
@Override
public boolean getIncludesNull() {
return stringNullProtectionRequired || super.getIncludesNull();
}
/**
* 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 StringExpression modeSimple() {
StringExpression modeExpr = new StringExpression(
new ModeSimpleExpression(this));
return modeExpr;
}
/**
* Create An Appropriate Expression 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.
*
*
* 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 string string
* Support DBvolution at
* Patreon
* @return a DBExpression instance that is appropriate to the subclass and the
* value supplied.
*/
@Override
public StringExpression expression(String string) {
return new StringExpression(string);
}
/**
* Create An Appropriate Expression 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.
*
*
* 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 string string
* Support DBvolution at
* Patreon
* @return a DBExpression instance that is appropriate to the subclass and the
* value supplied.
*/
@Override
public StringExpression expression(StringResult string) {
return new StringExpression(string);
}
/**
* Provides a default option when the StringExpression resolves to NULL within
* the query.
*
* @param alternative alternative
* Support DBvolution at
* Patreon
* @return a StringExpression that will substitute to the given value when the
* StringExpression resolves to NULL.
*/
public StringExpression ifDBNull(String alternative) {
return this.ifDBNull(new StringExpression(alternative));
}
/**
* Provides a default option when the StringExpression resolves to NULL within
* the query.
*
* @param alternative alternative
* Support DBvolution at
* Patreon
* @return a StringExpression that will substitute to the given value when the
* StringExpression resolves to NULL.
*/
public StringExpression ifDBNull(StringResult alternative) {
return new StringExpression(
new StringExpression.DBBinaryStringFunction(this, new StringExpression(alternative)) {
@Override
public String toSQLString(DBDefinition db) {
return db.doStringIfNullTransform(this.getFirst().toSQLString(db), getSecond().toSQLString(db));
}
@Override
public boolean getIncludesNull() {
return false;
}
});
}
/**
* Creates a query comparison using the LIKE operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
*
* DBvolution does not process the SQL pattern so please ensure that it
* conforms to the database's implementation of LIKE. Most implementations
* only provide access to the "_" and "%" wildcards but there may be
* exceptions.
*
* @param sqlPattern sqlPattern
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isLike(String sqlPattern) {
return isLike(value(sqlPattern));
}
/**
* Like LESSTHAN_OR_EQUAL but only includes the EQUAL values if the fallback
* matches.
*
*
* Often used to implement efficient paging by using LESSTHAN across 2
* columns. For example:
* {@code table.column(table.name).isLessThan(5, table.column(table.pkid).isLessThan(1100));}
*
*
* If you are using this for pagination, remember to sort by the columns as
* well
*
* @param value the right side of the internal comparison
* @param fallBackWhenEquals the comparison used when the two values are
* equal.
*
Support DBvolution at
* Patreon
* @return a BooleanExpression
*/
@Override
public BooleanExpression isLessThan(String value, BooleanExpression fallBackWhenEquals) {
return this.isLessThan(StringExpression.value(value), fallBackWhenEquals);
}
/**
* Like GREATERTHAN_OR_EQUAL but only includes the EQUAL values if the
* fallback matches.
*
*
* Often used to implement efficient paging by using LESSTHAN across 2
* columns. For example:
* {@code table.column(table.name).isLessThan(5, table.column(table.pkid).isLessThan(1100));}
*
*
* If you are using this for pagination, remember to sort by the columns as
* well
*
* @param value the right side of the internal comparison
* @param fallBackWhenEquals the comparison used when the two values are
* equal.
*
Support DBvolution at
* Patreon
* @return a BooleanExpression
*/
@Override
public BooleanExpression isGreaterThan(String value, BooleanExpression fallBackWhenEquals) {
return this.isGreaterThan(StringExpression.value(value), fallBackWhenEquals);
}
/**
* Like LESSTHAN_OR_EQUAL but only includes the EQUAL values if the fallback
* matches.
*
*
* Often used to implement efficient paging by using LESSTHAN across 2
* columns. For example:
* {@code table.column(table.name).isLessThan(5, table.column(table.pkid).isLessThan(1100));}
*
*
* If you are using this for pagination, remember to sort by the columns as
* well
*
* @param value the right side of the internal comparison
* @param fallBackWhenEquals the comparison used when the two values are
* equal.
*
Support DBvolution at
* Patreon
* @return a BooleanExpression
*/
@Override
public BooleanExpression isLessThan(StringResult value, BooleanExpression fallBackWhenEquals) {
return this.isLessThan(value).or(this.is(value).and(fallBackWhenEquals));
}
/**
* Like GREATERTHAN_OR_EQUAL but only includes the EQUAL values if the
* fallback matches.
*
*
* Often used to implement efficient paging by using LESSTHAN across 2
* columns. For example:
* {@code table.column(table.name).isLessThan(5, table.column(table.pkid).isLessThan(1100));}
*
*
* If you are using this for pagination, remember to sort by the columns as
* well
*
* @param value the right side of the internal comparison
* @param fallBackWhenEquals the comparison used when the two values are
* equal.
*
Support DBvolution at
* Patreon
* @return a BooleanExpression
*/
@Override
public BooleanExpression isGreaterThan(StringResult value, BooleanExpression fallBackWhenEquals) {
return this.isGreaterThan(value).or(this.is(value).and(fallBackWhenEquals));
}
/**
* Creates a query comparison using the LIKE operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
*
* DBvolution does not process the SQL pattern so please ensure that it
* conforms to the database's implementation of LIKE. Most implementations
* only provide access to the "_" and "%" wildcards but there may be
* exceptions.
*
* @param sqlPattern sqlPattern
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isLike(StringResult sqlPattern) {
if (sqlPattern.getIncludesNull()) {
return new BooleanExpression(this.isNull());
} else {
return new BooleanExpression(new DBBinaryBooleanArithmetic(this, sqlPattern) {
@Override
protected String getEquationOperator(DBDefinition db) {
return " LIKE ";
}
@Override
public boolean getIncludesNull() {
return false;
}
});
}
}
/**
* Creates a query comparison using the LIKE operator and the LOWERCASE
* function.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern changing both
* expressions to lowercase first.
*
*
* DBvolution does not process the SQL pattern so please ensure that it
* conforms to the database's implementation of LIKE. Most implementations
* only provide access to the "_" and "%" wildcards but there may be
* exceptions.
*
* @param sqlPattern sqlPattern
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isLikeIgnoreCase(String sqlPattern) {
return isLikeIgnoreCase(value(sqlPattern));
}
/**
* Creates a query comparison using the LIKE operator and the LOWERCASE
* function.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern changing both
* expressions to lowercase first.
*
*
* DBvolution does not process the SQL pattern so please ensure that it
* conforms to the database's implementation of LIKE. Most implementations
* only provide access to the "_" and "%" wildcards but there may be
* exceptions.
*
* @param sqlPattern sqlPattern
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isLikeIgnoreCase(StringResult sqlPattern) {
return this.lowercase().isLike(value(sqlPattern).lowercase());
}
/**
* Creates a query comparison using the EQUALS operator and the LOWERCASE
* function.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value changing both expressions to
* lowercase first.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isIgnoreCase(String equivalentString) {
return isIgnoreCase(value(equivalentString));
}
/**
* Creates a query comparison using the EQUALS operator and the LOWERCASE
* function.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value changing both expressions to
* lowercase first.
*
* @param numberResult numberResult
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isIgnoreCase(NumberResult numberResult) {
return isIgnoreCase(numberResult.stringResult().lowercase());
}
/**
* Creates a query comparison using the EQUALS operator and the LOWERCASE
* function.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value changing both expressions to
* lowercase first.
*
* @param number number
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isIgnoreCase(Number number) {
return isIgnoreCase(NumberExpression.value(number));
}
/**
* Creates a query comparison using the EQUALS operator and the LOWERCASE
* function.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value changing both expressions to
* lowercase first.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isIgnoreCase(StringResult equivalentString) {
return isIgnoreCase(new StringExpression(equivalentString));
}
/**
* Creates a query comparison using the EQUALS operator and the LOWERCASE
* function.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value changing both expressions to
* lowercase first.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isIgnoreCase(StringExpression equivalentString) {
return this.lowercase().is(equivalentString.lowercase());
}
/**
* Creates a query comparison using the EQUALS operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression is(String equivalentString) {
if (equivalentString == null) {
return this.isNull();
} else {
return this.is(value(equivalentString));
}
}
/**
* Creates a query comparison using the EQUALS operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param numberResult numberResult
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression is(NumberResult numberResult) {
return this.is(numberResult.stringResult());
}
/**
* Creates a query comparison using the EQUALS operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param number number
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression is(Number number) {
return is(NumberExpression.value(number));
}
/**
* Creates a query comparison using the EQUALS operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression is(StringExpression equivalentString) {
return is((StringResult) equivalentString);
}
/**
* Creates a query comparison using the EQUALS operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression is(StringResult equivalentString) {
if (equivalentString == null) {
return new BooleanExpression(this.isNull());
} else {
final BooleanExpression is = new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) {
@Override
public String toSQLString(DBDefinition db) {
return db.doStringEqualsTransform(super.first.toSQLString(db), super.second.toSQLString(db));
}
@Override
protected String getEquationOperator(DBDefinition db) {
return " = ";
}
@Override
public boolean getIncludesNull() {
return false;
}
});
if (equivalentString.getIncludesNull()) {
return BooleanExpression.anyOf(this.isNull(), is);
} else {
return is;
}
}
}
/**
* Creates a query comparison using the NOT EQUALS operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isNot(String equivalentString) {
return this.isNot(value(equivalentString));
}
/**
* Creates a query comparison using the NOT EQUALS operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param numberResult numberResult
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isNot(NumberResult numberResult) {
return this.isNot(numberResult.stringResult());
}
/**
* Creates a query comparison using the NOT EQUALS operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param numberResult numberResult
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isNot(IntegerResult numberResult) {
return this.isNot(numberResult.stringResult());
}
/**
* Creates a query comparison using the NOT EQUALS operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param number number
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isNot(Number number) {
return isNot(NumberExpression.value(number));
}
/**
* Creates a query comparison using the NOT EQUALS operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isNot(StringResult equivalentString) {
if (equivalentString.getIncludesNull()) {
return this.isNotNull();
} else {
return new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) {
@Override
public String toSQLString(DBDefinition db) {
return (new StringExpression(first)).ifDBNull("").toSQLString(db)
+ this.getEquationOperator(db)
+ (new StringExpression(second)).ifDBNull("").toSQLString(db);
}
@Override
protected String getEquationOperator(DBDefinition db) {
return " <> ";
}
@Override
public boolean getIncludesNull() {
return false;
}
});
}
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified the lower-bound will be included in
* the search and the upper-bound excluded. I.e permittedRange(1,3) will
* return 1 and 2.
*
*
* if the upper-bound is null the range will be open ended and inclusive.
*
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended and exclusive.
*
* I.e permittedRange(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetween(StringResult lowerBound, StringResult upperBound) {
return BooleanExpression.allOf(
this.isGreaterThan(lowerBound),
this.isLessThanOrEqual(upperBound)
);
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified the lower-bound will be included in
* the search and the upper-bound excluded. I.e permittedRange(1,3) will
* return 1 and 2.
*
*
* if the upper-bound is null the range will be open ended and inclusive.
*
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended and exclusive.
*
* I.e permittedRange(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetween(String lowerBound, StringResult upperBound) {
return this.isBetween(value(lowerBound), upperBound);
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified the lower-bound will be included in
* the search and the upper-bound excluded. I.e permittedRange(1,3) will
* return 1 and 2.
*
*
* if the upper-bound is null the range will be open ended and inclusive.
*
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended and exclusive.
*
* I.e permittedRange(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetween(StringResult lowerBound, String upperBound) {
return this.isBetween(lowerBound, value(upperBound));
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified the lower-bound will be included in
* the search and the upper-bound excluded. I.e permittedRange(1,3) will
* return 1 and 2.
*
*
* if the upper-bound is null the range will be open ended and inclusive.
*
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended and exclusive.
*
* I.e permittedRange(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetween(String lowerBound, String upperBound) {
return this.isBetween(value(lowerBound), value(upperBound));
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified both the lower- and upper-bound
* will be included in the search. I.e permittedRangeInclusive(1,3) will
* return 1, 2, and 3.
*
*
* if the upper-bound is null the range will be open ended and inclusive.
*
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended and inclusive.
*
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetweenInclusive(StringResult lowerBound, StringResult upperBound) {
return BooleanExpression.allOf(
this.isGreaterThanOrEqual(lowerBound),
this.isLessThanOrEqual(upperBound)
);
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified both the lower- and upper-bound
* will be included in the search. I.e permittedRangeInclusive(1,3) will
* return 1, 2, and 3.
*
*
* if the upper-bound is null the range will be open ended and inclusive.
*
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended and inclusive.
*
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetweenInclusive(String lowerBound, StringResult upperBound) {
return this.isBetweenInclusive(value(lowerBound), upperBound);
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified both the lower- and upper-bound
* will be included in the search. I.e permittedRangeInclusive(1,3) will
* return 1, 2, and 3.
*
*
* if the upper-bound is null the range will be open ended and inclusive.
*
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended and inclusive.
*
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetweenInclusive(StringResult lowerBound, String upperBound) {
return this.isBetweenInclusive(lowerBound, value(upperBound));
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified both the lower- and upper-bound
* will be included in the search. I.e permittedRangeInclusive(1,3) will
* return 1, 2, and 3.
*
*
* if the upper-bound is null the range will be open ended and inclusive.
*
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended and inclusive.
*
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetweenInclusive(String lowerBound, String upperBound) {
return this.isBetweenInclusive(value(lowerBound), value(upperBound));
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified both the lower- and upper-bound
* will be excluded in the search. I.e permittedRangeExclusive(1,3) will
* return 2.
*
*
* if the upper-bound is null the range will be open ended upwards and
* exclusive.
*
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended downwards and
* exclusive.
*
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetweenExclusive(StringResult lowerBound, StringResult upperBound) {
return BooleanExpression.allOf(
this.isGreaterThan(lowerBound),
this.isLessThan(upperBound)
);
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified both the lower- and upper-bound
* will be excluded in the search. I.e permittedRangeExclusive(1,3) will
* return 2.
*
*
* if the upper-bound is null the range will be open ended upwards and
* exclusive.
*
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended downwards and
* exclusive.
*
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetweenExclusive(String lowerBound, StringResult upperBound) {
return this.isBetweenExclusive(value(lowerBound), upperBound);
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified both the lower- and upper-bound
* will be excluded in the search. I.e permittedRangeExclusive(1,3) will
* return 2.
*
*
* if the upper-bound is null the range will be open ended upwards and
* exclusive.
*
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended downwards and
* exclusive.
*
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetweenExclusive(StringResult lowerBound, String upperBound) {
return this.isBetweenExclusive(lowerBound, value(upperBound));
}
/**
* Performs searches based on a range.
*
* if both ends of the range are specified both the lower- and upper-bound
* will be excluded in the search. I.e permittedRangeExclusive(1,3) will
* return 2.
*
*
* if the upper-bound is null the range will be open ended upwards and
* exclusive.
*
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc.
*
*
* if the lower-bound is null the range will be open ended downwards and
* exclusive.
*
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
*
Support DBvolution at
* Patreon
* @return a boolean expression representing the required comparison
*/
@Override
public BooleanExpression isBetweenExclusive(String lowerBound, String upperBound) {
return this.isBetweenExclusive(value(lowerBound), value(upperBound));
}
/**
* Creates a query comparison using the LESSTHAN operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isLessThan(String equivalentString) {
return isLessThan(value(equivalentString));
}
/**
* Creates a query comparison using the LESSTHAN operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isLessThan(StringResult equivalentString) {
if (equivalentString.getIncludesNull()) {
return new BooleanExpression(this.isNull());
} else {
return new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) {
@Override
protected String getEquationOperator(DBDefinition db) {
return " < ";
}
@Override
public boolean getIncludesNull() {
return false;
}
});
}
}
/**
* Creates a query comparison using the "<=" operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isLessThanOrEqual(String equivalentString) {
return isLessThanOrEqual(value(equivalentString));
}
/**
* Creates a query comparison using the "<=" operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isLessThanOrEqual(StringResult equivalentString) {
if (equivalentString.getIncludesNull()) {
return new BooleanExpression(this.isNull());
} else {
return new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) {
@Override
protected String getEquationOperator(DBDefinition db) {
return " <= ";
}
@Override
public boolean getIncludesNull() {
return false;
}
});
}
}
/**
* Creates a query comparison using the GREATERTHAN operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isGreaterThan(String equivalentString) {
return isGreaterThan(value(equivalentString));
}
/**
* Creates a query comparison using the GREATERTHAN operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isGreaterThan(StringResult equivalentString) {
if (equivalentString.getIncludesNull()) {
return new BooleanExpression(this.isNotNull());
} else {
return new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) {
@Override
protected String getEquationOperator(DBDefinition db) {
return " > ";
}
@Override
public boolean getIncludesNull() {
return false;
}
});
}
}
/**
* Creates a query comparison using the ">=" operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isGreaterThanOrEqual(String equivalentString) {
return isGreaterThanOrEqual(value(equivalentString));
}
/**
* Creates a query comparison using the ">=" operator.
*
*
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isGreaterThanOrEqual(StringResult equivalentString) {
if (equivalentString.getIncludesNull()) {
return this.is(equivalentString).not();
} else {
return new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) {
@Override
protected String getEquationOperator(DBDefinition db) {
return " >= ";
}
@Override
public boolean getIncludesNull() {
return false;
}
});
}
}
/**
* Creates a query comparison using the IN operator.
*
*
* Use this comparison to generate a BooleanExpression that indicates whether
* the current StringExpression is included in the supplied values.
*
* @param possibleValues possibleValues
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isIn(String... possibleValues) {
return isIn(expressions(possibleValues));
}
/**
* Creates a query comparison using the IN operator.
*
*
* Use this comparison to generate a BooleanExpression that indicates whether
* the current StringExpression is included in the supplied values.
*
* @param possibleValues possibleValues
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isIn(Collection possibleValues) {
return isIn(expressions(possibleValues));
}
/**
* Creates a query comparison using the IN operator.
*
*
* Use this comparison to generate a BooleanExpression that indicates whether
* the current StringExpression is included in the supplied values.
*
* @param possibleValues possibleValues
*
Support DBvolution at
* Patreon
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isIn(StringResult... possibleValues) {
final BooleanExpression isInExpression
= new BooleanExpression(new DBNnaryBooleanFunction(this, possibleValues) {
@Override
public String toSQLString(DBDefinition db) {
List sqlValues = new ArrayList<>();
for (StringResult value : values) {
if (!value.getIncludesNull()) {
sqlValues.add(value.toSQLString(db));
}
}
return db.doInTransform(column.toSQLString(db), sqlValues);
}
@Override
protected String getFunctionName(DBDefinition db) {
return " IN ";
}
});
if (isInExpression.getIncludesNull()) {
return BooleanExpression.anyOf(new BooleanExpression(this.isNull()), isInExpression);
} else {
return isInExpression;
}
}
/**
* Creates a query expression that appends the supplied value to the current
* StringExpression.
*
* @param string2 string2
* Support DBvolution at
* Patreon
* @return a StringExpression.
*/
public StringExpression append(StringResult string2) {
return new StringExpression(new DBBinaryStringArithmetic(this, string2) {
@Override
public String toSQLString(DBDefinition db) {
return db.doConcatTransform(super.first.toSQLString(db), super.second.toSQLString(db));
}
@Override
protected String getEquationOperator(DBDefinition db) {
return "";
}
});
}
/**
* Creates a query expression that appends the supplied value to the current
* StringExpression.
*
* @param string2 string2
* Support DBvolution at
* Patreon
* @return a StringExpression.
*/
public StringExpression append(String string2) {
return this.append(StringExpression.value(string2));
}
/**
* Creates a query expression that appends the supplied value to the current
* StringExpression.
*
* @param number1 number1
* Support DBvolution at
* Patreon
* @return a StringExpression.
*/
public StringExpression append(NumberResult number1) {
return this.append(new NumberExpression(number1).stringResult());
}
/**
* Creates a query expression that appends the supplied value to the current
* StringExpression.
*
* @param number1 number1
* Support DBvolution at
* Patreon
* @return a StringExpression.
*/
public StringExpression append(Number number1) {
return this.append(NumberExpression.value(number1));
}
/**
* Creates a query expression that replaces the supplied value within the
* current StringExpression.
*
* @param findString findString
* @param replaceWith replaceWith
* Support DBvolution at
* Patreon
* @return a StringExpression.
*/
public StringExpression replace(String findString, String replaceWith) {
return this.replace(new StringExpression(findString), new StringExpression(replaceWith));
}
/**
* Creates a query expression that replaces the supplied value within the
* current StringExpression.
*
* @param findString findString
* @param replaceWith replaceWith
* Support DBvolution at
* Patreon
* @return a StringExpression.
*/
public StringExpression replace(StringResult findString, String replaceWith) {
return this.replace(findString, StringExpression.value(replaceWith));
}
/**
* Creates a query expression that replaces the supplied value within the
* current StringExpression.
*
* @param findString findString
* @param replaceWith replaceWith
* Support DBvolution at
* Patreon
* @return a StringExpression.
*/
public StringExpression replace(String findString, StringResult replaceWith) {
return this.replace(StringExpression.value(findString), replaceWith);
}
/**
* Creates a query expression that replaces the supplied value within the
* current StringExpression.
*
* @param findString findString
* @param replaceWith replaceWith
* Support DBvolution at
* Patreon
* @return a StringExpression.
*/
public StringExpression replace(StringResult findString, StringResult replaceWith) {
StringResult replaceValue = replaceWith;
if (replaceWith.getIncludesNull()) {
replaceValue = StringExpression.value("");
}
return new StringExpression(
new DBTrinaryStringFunction(this, findString, replaceValue) {
@Override
public String toSQLString(DBDefinition db) {
return db.doReplaceTransform(
this.getFirst().toSQLString(db),
this.getSecond().toSQLString(db),
this.getThird().toSQLString(db));
}
@Override
String getFunctionName(DBDefinition db) {
return "REPLACE";
}
@Override
public boolean getIncludesNull() {
// handled before creation
return false;
}
});
}
/**
* Retrieve the substring that precedes the supplied value.
*
*
* Complements {@link #substringAfter(java.lang.String) }.
*
*
* Within this expression, find the supplied value and return all characters
* before the value, not including the value itself.
*
* @param splitBeforeThis the value marks the end of the required string.
*
Support DBvolution at
* Patreon
* @return a string expression
*/
public StringExpression substringBefore(String splitBeforeThis) {
return substringBefore(value(splitBeforeThis));
}
/**
* Retrieve the substring that precedes the supplied value.
*
*
* Complements {@link #substringAfter(java.lang.String) }.
*
*
* Within this expression, find the supplied value and return all characters
* before the value, not including the value itself.
*
* @param splitBeforeThis the value that marks the end of the required string
*
Support DBvolution at
* Patreon
* @return a string expression
*/
public StringExpression substringBefore(StringResult splitBeforeThis) {
return new StringExpression(new DBBinaryStringFunction(this, new StringExpression(splitBeforeThis)) {
@Override
public String toSQLString(DBDefinition db) {
try {
return db.doSubstringBeforeTransform(getFirst().toSQLString(db), getSecond().toSQLString(db));
} catch (UnsupportedOperationException exp) {
return getFirst().locationOf(getSecond()).isGreaterThan(0).ifThenElse(getFirst().substring(0, getFirst().locationOf(getSecond()).minus(1).integerResult()), value("")).toSQLString(db);
}
}
});
}
/**
* Retrieve the substring that follows the supplied value.
*
*
* Complements {@link #substringBefore(java.lang.String) }.
*
*
* Within this expression, find the supplied value and return all characters
* after the value, not including the value itself.
*
* @param splitAfterThis the value that marks the beginning of the required
* string
*
Support DBvolution at
* Patreon
* @return a string expression
*/
public StringExpression substringAfter(String splitAfterThis) {
return substringAfter(value(splitAfterThis));
}
/**
* Retrieve the substring that follows the supplied value.
*
*
* Complements {@link #substringBefore(java.lang.String) }.
*
*
* Within this expression, find the supplied value and return all characters
* after the value, not including the value itself.
*
* @param splitAfterThis the value that marks the beginning of the required
* string
*
Support DBvolution at
* Patreon
* @return a string expression
*/
public StringExpression substringAfter(StringResult splitAfterThis) {
return new StringExpression(new DBBinaryStringFunction(this, new StringExpression(splitAfterThis)) {
@Override
public String toSQLString(DBDefinition db) {
try {
return db.doSubstringAfterTransform(getFirst().toSQLString(db), getSecond().toSQLString(db));
} catch (UnsupportedOperationException exp) {
return getFirst().locationOf(getSecond()).isGreaterThan(0).ifThenElse(getFirst().substring(getFirst().locationOf(getSecond()).integerResult(), getFirst().length()), value("")).toSQLString(db);
}
}
});
}
/**
* Retrieve the substring that follows the first supplied value but precedes
* the second value.
*
*
* Complements {@link #substringBefore(java.lang.String) } and {@link #substringAfter(java.lang.String)
* }.
*
*
* Within this expression, find the first supplied value and return all
* characters after the value, not including the value itself, but prior to
* the second value.
*
*
* for an expression like "(1234)", substringBetween("(", ")") will return
* "1234".
*
* @param splitAfterThis the value that marks the beginning of the required
* string
* @param butBeforeThis the value that marks the end of the required string
*
Support DBvolution at
* Patreon
* @return a string expression
*/
public StringExpression substringBetween(String splitAfterThis, String butBeforeThis) {
return substringBetween(value(splitAfterThis), value(butBeforeThis));
}
/**
* Retrieve the substring that follows the first supplied value but precedes
* the second value.
*
*
* Complements {@link #substringBefore(java.lang.String) } and {@link #substringAfter(java.lang.String)
* }.
*
*
* Within this expression, find the first supplied value and return all
* characters after the value, not including the value itself, but prior to
* the second value.
*
*
* for an expression like "(1234)", substringBetween("(", ")") will return
* "1234".
*
* @param splitAfterThis the value that marks the beginning of the required
* string
* @param butBeforeThis the value that marks the end of the required string
*
Support DBvolution at
* Patreon
* @return a string expression
*/
public StringExpression substringBetween(StringResult splitAfterThis, StringResult butBeforeThis) {
return substringAfter(splitAfterThis).substringBefore(butBeforeThis);
}
/**
* Creates a query expression that trims all leading and trailing spaces from
* the current StringExpression.
*
* Support DBvolution at
* Patreon
*
* @return a StringExpression.
*/
public StringExpression trim() {
return new StringExpression(
new StringExpression(this) {
@Override
public String toSQLString(DBDefinition db) {
return db.doTrimFunction(this.getInnerResult().toSQLString(db));
}
});
}
/**
* Tests that a string expression is shorter than or equal to the specified
* length.
*
*
* This method is useful to test strings will fit within a specific field
* size
*
* @param maxLength the longest possible number of characters
* Support DBvolution at
* Patreon
* @return a StringExpression.
*/
public BooleanExpression isShorterThanOrAsLongAs(int maxLength) {
return this.length().isLessThanOrEqual(maxLength);
}
/**
* Finds and returns the first number in the string or NULL if no number is
* found.
*
* Support DBvolution at
* Patreon
*
* @return a StringExpression.
*/
public StringExpression getFirstNumberAsSubstring() {
StringExpression exp = new StringExpression(
new StringExpression(this) {
@Override
public String toSQLString(DBDefinition db) {
return db.doFindNumberInStringTransform(this.getInnerResult().toSQLString(db));
}
});
return exp;
}
/**
* Finds and returns the first integer in the string or NULL if no integer is
* found.
*
* Support DBvolution at
* Patreon
*
* @return a StringExpression.
*/
public StringExpression getFirstIntegerAsSubstring() {
final StringExpression exp = new StringExpression(
new StringExpression(this) {
@Override
public String toSQLString(DBDefinition db) {
return db.doFindIntegerInStringTransform(this.getInnerResult().toSQLString(db));
}
});
return exp;
}
/**
* Finds and returns the first number in the string or NULL if no number is
* found.
*
* Support DBvolution at
* Patreon
*
* @return a NumberExpression.
*/
public NumberExpression getFirstNumber() {
return getFirstNumberAsSubstring().numberResult();
}
/**
* Finds and returns the first integer in the string or NULL if no integer is
* found.
*
* Support DBvolution at
* Patreon
*
* @return an IntegerExpression.
*/
public IntegerExpression getFirstInteger() {
return getFirstIntegerAsSubstring().integerResult();
}
/**
* Creates a query expression that trims all leading spaces from the current
* StringExpression.
*
* Support DBvolution at
* Patreon
*
* @return a StringExpression.
*/
public StringExpression leftTrim() {
return new StringExpression(
new StringExpression(this) {
@Override
public String toSQLString(DBDefinition db) {
return db.doLeftTrimTransform(this.getInnerResult().toSQLString(db));
}
});
}
/**
* Creates a query expression that trims all trailing spaces from the current
* StringExpression.
*
* Support DBvolution at
* Patreon
*
* @return a StringExpression.
*/
public StringExpression rightTrim() {
return new StringExpression(
new StringExpression(this) {
@Override
public String toSQLString(DBDefinition defn) {
return defn.getRightTrimFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")";
}
});
}
/**
* Creates a query expression that changes all the letters in the current
* StringExpression to lowercase.
*
* Support DBvolution at
* Patreon
*
* @return a StringExpression.
*/
public StringExpression lowercase() {
return new StringExpression(
new StringExpression(this) {
@Override
public String toSQLString(DBDefinition defn) {
return defn.getLowercaseFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")";
}
});
}
/**
* Creates a query expression that changes all the letters in the current
* StringExpression to UPPERCASE.
*
* Support DBvolution at
* Patreon
*
* @return a StringExpression.
*/
public StringExpression uppercase() {
return new StringExpression(
new StringExpression(this) {
@Override
public String toSQLString(DBDefinition defn) {
return defn.getUppercaseFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")";
}
});
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end of the string.
*
*
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
*
Support DBvolution at
* Patreon
* @return a StringExpression
*/
public StringExpression substring(Integer startingIndex0Based) {
return substring(NumberExpression.value(startingIndex0Based));
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end of the string.
*
*
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
*
Support DBvolution at
* Patreon
* @return a StringExpression
*/
public StringExpression substring(Long startingIndex0Based) {
return substring(NumberExpression.value(startingIndex0Based));
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end of the string.
*
*
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
*
Support DBvolution at
* Patreon
* @return a StringExpression
*/
public StringExpression substring(IntegerResult startingIndex0Based) {
return new Substring(this, startingIndex0Based);
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end position supplied..
*
*
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
*
Support DBvolution at
* Patreon
* @return a StringExpression
*/
public StringExpression substring(Integer startingIndex0Based, Integer endIndex0Based) {
return new Substring(this, startingIndex0Based, endIndex0Based);
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end position supplied..
*
*
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
*
Support DBvolution at
* Patreon
* @return a StringExpression
*/
public StringExpression substring(Long startingIndex0Based, Long endIndex0Based) {
return new Substring(this, startingIndex0Based, endIndex0Based);
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end position supplied..
*
*
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
*
Support DBvolution at
* Patreon
* @return a StringExpression
*/
public StringExpression substring(IntegerResult startingIndex0Based, Integer endIndex0Based) {
return new Substring(this, startingIndex0Based, value(endIndex0Based));
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end position supplied..
*
*
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
*
Support DBvolution at
* Patreon
* @return a StringExpression
*/
public StringExpression substring(IntegerResult startingIndex0Based, Long endIndex0Based) {
return new Substring(this, startingIndex0Based, value(endIndex0Based));
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end position supplied..
*
*
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
*
Support DBvolution at
* Patreon
* @return a StringExpression
*/
public StringExpression substring(Integer startingIndex0Based, IntegerResult endIndex0Based) {
return new Substring(this, value(startingIndex0Based), endIndex0Based);
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end position supplied..
*
*
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
*
Support DBvolution at
* Patreon
* @return a StringExpression
*/
public StringExpression substring(Long startingIndex0Based, IntegerResult endIndex0Based) {
return new Substring(this, value(startingIndex0Based), endIndex0Based);
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end position supplied..
*
*
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
*
Support DBvolution at
* Patreon
* @return a StringExpression
*/
public StringExpression substring(IntegerResult startingIndex0Based, IntegerResult endIndex0Based) {
return new Substring(this, startingIndex0Based, endIndex0Based);
}
/**
* Create a expression that returns the length of the current expression.
*
* Support DBvolution at
* Patreon
*
* @return a NumberExpression of the expression's length.
*/
public IntegerExpression length() {
return new IntegerExpression(
new IntegerExpression(this) {
@Override
public String toSQLString(DBDefinition db) {
return db.doStringLengthTransform(getInnerResult().toSQLString(db));
}
});
}
/**
* Create a {@link StringExpression} that returns the name of the current
* user.
*
*
* This should be the current username under which the application is
* accessing the database.
*
*
Support DBvolution at
* Patreon
*
* @return a StringExpression
*/
public static StringExpression currentUser() {
return new StringExpression(
new StringExpression() {
@Override
public String toSQLString(DBDefinition db) {
return db.getCurrentUserFunctionName();
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public boolean isPurelyFunctional() {
return true;
}
});
}
/**
* Returns the 1-based index of the first occurrence of searchString within
* the StringExpression.
*
*
* The index is 1-based, and returns 0 when the searchString is not found.
*
* @param searchString searchString
* Support DBvolution at
* Patreon
* @return an expression that will find the location of the searchString.
*/
public IntegerExpression locationOf(String searchString) {
return locationOf(value(searchString));
}
/**
* Returns the 1-based index of the first occurrence of searchString within
* the StringExpression.
*
*
* The index is 1-based, and returns 0 when the searchString is not found.
*
* @param searchString searchString
* Support DBvolution at
* Patreon
* @return an expression that will find the location of the searchString.
*/
public IntegerExpression locationOf(StringResult searchString) {
return new NumberExpression(new BinaryComplicatedNumberFunction(this, searchString) {
@Override
public String toSQLString(DBDefinition db) {
return db.doPositionInStringTransform(this.first.toSQLString(db), this.second.toSQLString(db));
}
}).integerResult();
}
/**
* Creates an expression that will find the largest value in the column
* supplied.
*
*
* Max is an aggregator function for use in DBReport or in a column
* expression.
*
*
Support DBvolution at
* Patreon
*
* @return a String expression.
*/
public StringExpression max() {
return new StringExpression(
new StringExpression(this) {
@Override
public String toSQLString(DBDefinition defn) {
return defn.getMaxFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")";
}
@Override
public boolean isAggregator() {
return true;
}
});
}
/**
* Creates an expression that will find the smallest value in the column
* supplied.
*
*
* Min is an aggregator function for use in DBReport or in a column
* expression.
*
*
Support DBvolution at
* Patreon
*
* @return a String expression.
*/
public StringExpression min() {
return new StringExpression(new StringExpression(this) {
@Override
public String toSQLString(DBDefinition defn) {
return defn.getMinFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")";
}
@Override
public boolean isAggregator() {
return true;
}
});
}
@Override
public DBString getQueryableDatatypeForExpressionValue() {
return new DBString();
}
/**
* Creates a BooleanExpression that tests to ensure the database value is not
* a database NULL value.
*
*
* The expression will be true if the value is not NULL, and false otherwise.
*
*
Support DBvolution at
* Patreon
*
* @return a BooleanExpression
*/
public BooleanExpression isNotNull() {
return BooleanExpression.isNotNull(this);
}
/**
* Creates a BooleanExpression that tests to ensure the database value is not
* a database NULL value AND is not an empty string.
*
*
* The expression will be true if the value is not NULL and is not an empty
* string, and false otherwise.
*
*
* This method provides the maximum portability as some database differentiate
* between a NULL string and a empty string, and some do not. To protect your
* queries against this fundamental variation use this method.
*
*
Support DBvolution at
* Patreon
*
* @return a BooleanExpression
*/
public BooleanExpression isNotNullAndNotEmpty() {
return BooleanExpression.allOf(
BooleanExpression.isNotNull(this),
this.isNot("")
);
}
/**
* Creates a BooleanExpression that tests to ensure the database value is a
* database NULL value.
*
*
* The expression will be true if the value is NULL, and false otherwise.
*
*
Support DBvolution at
* Patreon
*
* @return a BooleanExpression
*/
public BooleanExpression isNull() {
return BooleanExpression.isNull(this);
}
/**
* Creates a BooleanExpression that tests to ensure the database value is a
* database NULL value OR is an empty string.
*
*
* The expression will be true if the value is NULL OR the expression produces
* an empty string, and false otherwise.
*
*
* This method provides the maximum portability as some database differentiate
* between a NULL string and a empty string, and some do not. To protect your
* queries against this fundamental variation use this method.
*
*
Support DBvolution at
* Patreon
*
* @return a BooleanExpression
*/
public BooleanExpression isNullOrEmpty() {
return BooleanExpression.anyOf(
BooleanExpression.isNull(this),
this.is("")
);
}
/**
* Adds an explicit bracket at this point in the expression chain.
*
* Support DBvolution at
* Patreon
*
* @return a StringExpression that will have the current expression wrapped in
* brackets.
*/
public StringExpression bracket() {
return new StringExpression(new StringExpression(this) {
@Override
public String toSQLString(DBDefinition defn) {
return "(" + getInnerResult().toSQLString(defn) + ")";
}
});
}
/**
* Provides direct access to the IN operator.
*
*
* isInIgnoreCase creates a BooleanExpression that compares the current
* expression to the list of values using the IN operator. The resulting
* expression will return true if the current expression's value is included
* in the list of potential values, otherwise it will return false.
*
* @param potentialValues potentialValues
*
Support DBvolution at
* Patreon
* @return a BooleanExpression
*/
public BooleanExpression isInIgnoreCase(String... potentialValues) {
return this.isInIgnoreCase(expressions(potentialValues));
}
public StringResult[] expressions(String... potentialValues) {
List possVals = new ArrayList<>(0);
for (String str : potentialValues) {
if (str == null) {
possVals.add(nullString());
} else {
possVals.add(StringExpression.value(str));
}
}
return possVals.toArray(new StringResult[]{});
}
public StringResult[] expressions(Collection potentialValues) {
List possVals = new ArrayList<>(0);
for (String str : potentialValues) {
if (str == null) {
possVals.add(nullString());
} else {
possVals.add(StringExpression.value(str));
}
}
return possVals.toArray(new StringResult[]{});
}
/**
* Provides direct access to the IN operator.
*
*
* isInIgnoreCase creates a BooleanExpression that compares the current
* expression to the list of values using the IN operator. The resulting
* expression will return true if the current expression's value is included
* in the list of potential values, otherwise it will return false.
*
* @param potentialValues potentialValues
*
Support DBvolution at
* Patreon
* @return a BooleanExpression
*/
public BooleanExpression isInIgnoreCase(Collection potentialValues) {
return this.isInIgnoreCase(expressions(potentialValues));
}
/**
* Provides direct access to the IN operator.
*
*
* isInIgnoreCase creates a BooleanExpression that compares the current
* expression to the list of values using the IN operator. The resulting
* expression will return true if the current expression's value is included
* in the list of potential values, otherwise it will return false.
*
* @param potentialValues potentialValues
*
Support DBvolution at
* Patreon
* @return a BooleanExpression
*/
public BooleanExpression isInIgnoreCase(StringResult... potentialValues) {
List lowerStrings = new ArrayList<>();
for (StringResult toArray1 : potentialValues) {
StringExpression lowercase = new StringExpression(toArray1).lowercase();
lowerStrings.add(lowercase);
}
final BooleanExpression isInExpression = this.lowercase().isIn(lowerStrings.toArray(new StringResult[]{}));
if (isInExpression.getIncludesNull()) {
return BooleanExpression.anyOf(new BooleanExpression(this.isNull()), isInExpression);
} else {
return isInExpression;
}
}
/**
* In so far as it is possible, transform the value of this expression into a
* number.
*
*
* You should probably use {@link #getFirstNumber() } or {@link #getFirstNumber()
* } instead as they are more reliable.
*
*
* Uses the database's own facilities to parse the value of this expression
* into a number.
*
*
* May return NULL and all sorts of crazy things.
*
*
Support DBvolution at
* Patreon
*
* @return a number expression
*/
public NumberExpression numberResult() {
return new NumberExpression(
new NumberExpression(this) {
@Override
public String toSQLString(DBDefinition db) {
return db.doStringToNumberTransform(getInnerResult().toSQLString(db));
}
});
}
/**
* In so far as it is possible, transform the value of this expression into a
* number.
*
*
* Uses the database's own facilities to parse the value of this expression
* into a number.
*
*
* May return NULL and all sorts of crazy things.
*
*
Support DBvolution at
* Patreon
*
* @return a number expression
*/
public IntegerExpression integerResult() {
return this.numberResult().isNotNull()
.ifThenElse(this.numberResult().integerResult(), nullInteger());
}
@Override
public DBString asExpressionColumn() {
return new DBString(this);
}
@Override
public StringExpression stringResult() {
return this;
}
@Override
public StringResult expression(DBString value) {
return new StringExpression(value);
}
private static abstract class DBBinaryStringArithmetic extends StringExpression {
private StringResult first;
private StringResult second;
DBBinaryStringArithmetic(StringResult first, StringResult second) {
this.first = first;
this.second = second;
}
@Override
public DBString getQueryableDatatypeForExpressionValue() {
return new DBString();
}
@Override
public String toSQLString(DBDefinition db) {
return first.toSQLString(db) + this.getEquationOperator(db) + second.toSQLString(db);
}
@Override
public DBBinaryStringArithmetic copy() {
DBBinaryStringArithmetic newInstance;
try {
newInstance = getClass().newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
newInstance.first = first.copy();
newInstance.second = second.copy();
return newInstance;
}
protected abstract String getEquationOperator(DBDefinition db);
@Override
public Set getTablesInvolved() {
HashSet hashSet = new HashSet<>();
if (first != null) {
hashSet.addAll(first.getTablesInvolved());
}
if (second != null) {
hashSet.addAll(second.getTablesInvolved());
}
return hashSet;
}
@Override
public boolean isAggregator() {
return this.first.isAggregator() || second.isAggregator();
}
@Override
public boolean isPurelyFunctional() {
if (first == null && second == null) {
return true;
} else if (first == null) {
return second.isPurelyFunctional();
} else if (second == null) {
return first.isPurelyFunctional();
} else {
return first.isPurelyFunctional() && second.isPurelyFunctional();
}
}
}
private static abstract class DBTrinaryStringFunction extends StringExpression {
private DBExpression first;
private DBExpression second;
private DBExpression third;
DBTrinaryStringFunction(DBExpression first) {
this.first = first;
this.second = null;
this.third = null;
}
DBTrinaryStringFunction(DBExpression first, DBExpression second) {
this.first = first;
this.second = second;
}
DBTrinaryStringFunction(DBExpression first, DBExpression second, DBExpression third) {
this.first = first;
this.second = second;
this.third = third;
}
@Override
public DBString getQueryableDatatypeForExpressionValue() {
return new DBString();
}
@Override
public String toSQLString(DBDefinition db) {
return this.beforeValue(db) + getFirst().toSQLString(db)
+ this.getSeparator(db) + (getSecond() == null ? "" : getSecond().toSQLString(db))
+ this.getSeparator(db) + (getThird() == null ? "" : getThird().toSQLString(db))
+ this.afterValue(db);
}
@Override
public DBTrinaryStringFunction copy() {
DBTrinaryStringFunction newInstance;
try {
newInstance = getClass().newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
newInstance.first = getFirst() == null ? null : getFirst().copy();
newInstance.second = getSecond() == null ? null : getSecond().copy();
newInstance.third = getThird() == null ? null : getThird().copy();
return newInstance;
}
abstract String getFunctionName(DBDefinition db);
protected String beforeValue(DBDefinition db) {
return " " + getFunctionName(db) + "( ";
}
protected String getSeparator(DBDefinition db) {
return ", ";
}
protected String afterValue(DBDefinition db) {
return ") ";
}
@Override
public Set getTablesInvolved() {
HashSet hashSet = new HashSet<>();
if (getFirst() != null) {
hashSet.addAll(getFirst().getTablesInvolved());
}
if (getSecond() != null) {
hashSet.addAll(getSecond().getTablesInvolved());
}
if (getThird() != null) {
hashSet.addAll(getThird().getTablesInvolved());
}
return hashSet;
}
@Override
public boolean isAggregator() {
return getFirst().isAggregator() || getSecond().isAggregator() || getThird().isAggregator();
}
/**
* Support DBvolution at
* Patreon
*
* @return the first
*/
protected DBExpression getFirst() {
return first;
}
/**
* Support DBvolution at
* Patreon
*
* @return the second
*/
protected DBExpression getSecond() {
return second;
}
/**
* Support DBvolution at
* Patreon
*
* @return the third
*/
protected DBExpression getThird() {
return third;
}
@Override
public boolean isPurelyFunctional() {
if (first == null && second == null && third == null) {
return true;
} else if (first == null) {
return second.isPurelyFunctional();
} else if (second == null) {
return first.isPurelyFunctional();
} else {
return first.isPurelyFunctional() && second.isPurelyFunctional() && third.isPurelyFunctional();
}
}
}
private static abstract class DBBinaryStringFunction extends StringExpression {
private StringExpression first;
private StringExpression second;
DBBinaryStringFunction(StringExpression first) {
this.first = first;
this.second = null;
}
DBBinaryStringFunction(StringExpression first, StringExpression second) {
this.first = first;
this.second = second;
}
@Override
public DBString getQueryableDatatypeForExpressionValue() {
return new DBString();
}
@Override
public DBBinaryStringFunction copy() {
DBBinaryStringFunction newInstance;
try {
newInstance = getClass().newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
newInstance.first = getFirst() == null ? null : getFirst().copy();
newInstance.second = getSecond() == null ? null : getSecond().copy();
return newInstance;
}
@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();
}
/**
* Support DBvolution at
* Patreon
*
* @return the first
*/
protected StringExpression getFirst() {
return first;
}
/**
* Support DBvolution at
* Patreon
*
* @return the second
*/
protected StringExpression getSecond() {
return second;
}
@Override
public boolean isPurelyFunctional() {
if (first == null && second == null) {
return true;
} else if (first == null) {
return second.isPurelyFunctional();
} else if (second == null) {
return first.isPurelyFunctional();
} else {
return first.isPurelyFunctional() && second.isPurelyFunctional();
}
}
}
private static abstract class BinaryComplicatedNumberFunction extends NumberExpression {
protected StringExpression first = null;
protected StringResult second = null;
BinaryComplicatedNumberFunction() {
this.first = null;
}
BinaryComplicatedNumberFunction(StringExpression first, StringResult second) {
this.first = first;
this.second = second;
}
@Override
public DBNumber getQueryableDatatypeForExpressionValue() {
return new DBNumber();
}
@Override
public abstract String toSQLString(DBDefinition db);
@Override
public StringExpression.BinaryComplicatedNumberFunction copy() {
StringExpression.BinaryComplicatedNumberFunction newInstance;
try {
newInstance = getClass().newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
newInstance.first = first.copy();
newInstance.second = second.copy();
return newInstance;
}
@Override
public Set getTablesInvolved() {
HashSet hashSet = new HashSet<>();
if (first != null) {
hashSet.addAll(first.getTablesInvolved());
}
if (second != null) {
hashSet.addAll(second.getTablesInvolved());
}
return hashSet;
}
@Override
public boolean isAggregator() {
return first.isAggregator() || second.isAggregator();
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public boolean isPurelyFunctional() {
if (first == null && second == null) {
return true;
} else if (first == null) {
return second.isPurelyFunctional();
} else if (second == null) {
return first.isPurelyFunctional();
} else {
return first.isPurelyFunctional() && second.isPurelyFunctional();
}
}
}
private class Substring extends StringExpression {
private IntegerResult startingPosition;
private IntegerResult length;
Substring(StringResult stringInput, Long startingIndex0Based) {
super(stringInput);
this.startingPosition = value(startingIndex0Based);
this.length = new StringExpression(stringInput).length();
}
Substring(StringResult stringInput, Integer startingIndex0Based) {
super(stringInput);
this.startingPosition = value(startingIndex0Based);
this.length = new StringExpression(stringInput).length();
}
Substring(StringResult stringInput, IntegerResult startingIndex0Based) {
super(stringInput);
this.startingPosition = startingIndex0Based.copy();
this.length = value(stringInput).length();
}
Substring(StringResult stringInput, Long startingIndex0Based, Long endIndex0Based) {
super(stringInput);
this.startingPosition = value(startingIndex0Based);
this.length = value(endIndex0Based);
}
Substring(StringResult stringInput, Integer startingIndex0Based, Integer endIndex0Based) {
super(stringInput);
this.startingPosition = value(startingIndex0Based);
this.length = value(endIndex0Based);
}
Substring(StringResult stringInput, IntegerResult startingIndex0Based, IntegerResult endIndex0Based) {
super(stringInput);
this.startingPosition = startingIndex0Based.copy();
this.length = endIndex0Based.copy();
}
private Substring(AnyResult> stringInput, IntegerResult startingIndex0Based, IntegerResult endIndex0Based) {
super(stringInput.stringResult());
this.startingPosition = startingIndex0Based.copy();
this.length = endIndex0Based.copy();
}
@Override
public Substring copy() {
return new Substring(getInnerResult(), startingPosition, length);
}
@Override
public String toSQLString(DBDefinition db) {
if (getInnerResult() == null) {
return "";
} else {
return doSubstringTransform(db, getInnerResult(), startingPosition, length);
}
}
public String doSubstringTransform(DBDefinition db, AnyResult> enclosedValue, IntegerResult startingPosition, IntegerResult substringLength) {
return db.doSubstringTransform(
enclosedValue.stringResult().toSQLString(db),
(startingPosition.toSQLString(db) + " + 1"),
(substringLength != null ? (substringLength.toSQLString(db) + " - " + startingPosition.toSQLString(db)) : "")
);
}
@Override
public DBString getQueryableDatatypeForExpressionValue() {
return new DBString();
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public boolean isPurelyFunctional() {
final AnyResult> string1 = getInnerResult();
if (startingPosition == null && length == null && string1 == null) {
return true;
} else {
return (startingPosition == null || startingPosition.isPurelyFunctional())
&& (length == null || length.isPurelyFunctional())
&& (string1 == null || string1.isPurelyFunctional());
}
}
}
private static abstract class DBBinaryBooleanArithmetic extends BooleanExpression {
protected StringResult first;
protected StringResult second;
DBBinaryBooleanArithmetic(StringResult first, StringResult second) {
this.first = first;
this.second = second;
}
@Override
public String toSQLString(DBDefinition db) {
return first.toSQLString(db) + this.getEquationOperator(db) + second.toSQLString(db);
}
@Override
public DBBinaryBooleanArithmetic copy() {
DBBinaryBooleanArithmetic newInstance;
try {
newInstance = getClass().newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
newInstance.first = first.copy();
newInstance.second = second.copy();
return newInstance;
}
protected abstract String getEquationOperator(DBDefinition db);
@Override
public Set getTablesInvolved() {
HashSet hashSet = new HashSet<>();
if (first != null) {
hashSet.addAll(first.getTablesInvolved());
}
if (second != null) {
hashSet.addAll(second.getTablesInvolved());
}
return hashSet;
}
@Override
public boolean isAggregator() {
return first.isAggregator() || second.isAggregator();
}
}
private static abstract class DBNnaryBooleanFunction extends BooleanExpression {
protected final StringExpression column;
protected final List values = new ArrayList<>();
private final boolean includesNulls;
DBNnaryBooleanFunction() {
column = null;
includesNulls = false;
}
DBNnaryBooleanFunction(StringExpression leftHandSide, StringResult[] rightHandSide) {
this.column = leftHandSide;
boolean nulls = false;
for (StringResult stringResult : rightHandSide) {
if (stringResult == null) {
nulls = true;
} else if (stringResult.getIncludesNull()) {
nulls = true;
} else {
values.add(stringResult);
}
}
includesNulls = nulls;
}
abstract String getFunctionName(DBDefinition db);
protected String beforeValue(DBDefinition db) {
return "( ";
}
protected String afterValue(DBDefinition db) {
return ") ";
}
@Override
public String toSQLString(DBDefinition db) {
StringBuilder builder = new StringBuilder();
builder
.append(column.toSQLString(db))
.append(this.getFunctionName(db))
.append(this.beforeValue(db));
String separator = "";
for (StringResult val : values) {
if (val != null) {
builder.append(separator).append(val.toSQLString(db));
}
separator = ", ";
}
builder.append(this.afterValue(db));
return builder.toString();
}
@Override
public Set getTablesInvolved() {
HashSet hashSet = new HashSet<>();
if (column != null) {
hashSet.addAll(column.getTablesInvolved());
}
for (StringResult second : values) {
if (second != null) {
hashSet.addAll(second.getTablesInvolved());
}
}
return hashSet;
}
@Override
public boolean isAggregator() {
boolean result = column.isAggregator();
for (StringResult numer : values) {
result = result || numer.isAggregator();
}
return result;
}
@Override
public boolean getIncludesNull() {
return includesNulls;
}
}
}