StringExpression.java
/*
* 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.expressions.windows.WindowFunctionFramable;
import nz.co.gregs.dbvolution.expressions.windows.CanBeWindowingFunctionWithFrame;
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.DBQuery;
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.expressions.search.SearchAcross;
import nz.co.gregs.dbvolution.results.AnyResult;
import nz.co.gregs.dbvolution.results.ExpressionHasStandardStringResult;
import nz.co.gregs.dbvolution.results.IntegerResult;
import nz.co.gregs.separatedstring.SeparatedString;
import nz.co.gregs.dbvolution.expressions.search.SearchString;
import nz.co.gregs.dbvolution.expressions.windows.CanBeWindowingFunctionRequiresOrderBy;
import nz.co.gregs.dbvolution.expressions.windows.WindowFunctionRequiresOrderBy;
import nz.co.gregs.separatedstring.SeparatedStringBuilder;
/**
* StringExpression implements standard functions that produce a character or
* string result, including CHAR and VARCHAR.
*
* <p>
* 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.
*
* <p>
* Use a StringExpression to produce a string from an existing column,
* expression, or value and perform string manipulation.
*
* <p>
* 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) }.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @author Gregory Graham
*/
public class StringExpression extends RangeExpression<String, StringResult, DBString> implements StringResult {
private final static long serialVersionUID = 1l;
// needed because of Oracle's difficulty with empty/null strings
private final boolean stringNullProtectionRequired;
/**
* Creates a StringExpression that will return a database NULL.
*
* @return a StringExpression that resolves to NULL within the database
*/
@Override
public StringExpression nullExpression() {
return new StringExpression(new NullStringExpression());
}
public final static StringExpression emptyString() {
return new EmptyStringExpression();
}
/**
* Default Constructor
*
*/
protected StringExpression() {
super();
stringNullProtectionRequired = false;
}
/**
* Creates a StringExpression from an arbitrary StringResult object.
*
* <p>
* {@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.
*
* <p>
* {@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 DBString object.
*
* @param stringVariable stringVariable
*/
public StringExpression(DBString stringVariable) {
super(stringVariable);
if (stringVariable == null) {
stringNullProtectionRequired = true;
} else {
final String value = stringVariable.getValue();
stringNullProtectionRequired = value == null || value.isEmpty();
}
}
/**
* Creates a StringExpression from an arbitrary Number object.
*
* <p>
* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult()
* }.
*
* <p>
* 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.
*
* <p>
* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult()
* }.
*
* <p>
* Refer to {@link NumberExpression#NumberExpression(java.lang.Number) } and {@link NumberExpression#stringResult()
* } for more information.
*
* @param numberVariable numberVariable
*/
public StringExpression(IntegerResult numberVariable) {
super(numberVariable);
if (numberVariable == null) {
stringNullProtectionRequired = true;
} else {
stringNullProtectionRequired = numberVariable.getIncludesNull();
}
}
/**
* Creates a StringExpression from an arbitrary Number object.
*
* <p>
* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult()
* }.
*
* <p>
* 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.
*
* <p>
* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult()
* }.
*
* <p>
* 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.
*
* <p>
* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult()
* }.
*
* <p>
* 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("<NULL>");
} else if (!(stringInput instanceof StringResult)
&& (stringInput instanceof ExpressionHasStandardStringResult)) {
stringInput = ((ExpressionHasStandardStringResult) stringInput).stringResult();
}
return stringInput.toSQLString(db);
}
@Override
public StringExpression copy() {
//return isNullSafetyTerminator() ? nullString() : new StringExpression((AnyResult<?>) getInnerResult().copy());
return new StringExpression((AnyResult<?>) (getInnerResult() == null ? null : getInnerResult().copy()));
}
@Override
protected boolean isNullSafetyTerminator() {
return stringNullProtectionRequired == false
&& super.isNullSafetyTerminator();
}
@Override
public boolean getIncludesNull() {
return stringNullProtectionRequired == true || super.getIncludesNull();
}
/**
* Creates an expression that will return the most common value of the column
* supplied.
*
* <p>
* 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.</p>
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the most common string
*/
public StringExpression modeSimple() {
StringExpression modeExpr = new StringExpression(
new ModeSimpleExpression<>(this));
return modeExpr;
}
/**
* Creates an expression that will return the most common value of the column
* supplied.
*
* <p>
* 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.</p>
*
* <p>
* This version of Mode implements a stricter definition that will return null
* if the mode is undefined. The mode can be undefined if there are 2 or more
* values with the highest frequency value. </p>
*
* <p>
* For example in the list {0,0,0,0,1,1,2,2,2,2,3,4} both 0 and 2 occur four
* times and no other value occurs more frequently so the mode is undefined.
* {@link #modeSimple() The modeSimple()} method would return either 0 or 2
* randomly for the same set.</p>
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the mode or null if undefined.
*/
public StringExpression modeStrict() {
StringExpression modeExpr = new StringExpression(
new ModeStrictExpression<>(this));
return modeExpr;
}
/**
* Create An Appropriate Expression Object For This Object
*
* <p>
* The expression framework requires a *Expression to work with. The easiest
* way to get that is the {@code DBRow.column()} method.
*
* <p>
* 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.
*
* <ul>
* <li>Only object classes that are appropriate need to be handle by the
* DBExpression subclass.<li>
* <li>The implementation should be {@code static}</li>
* </ul>
*
* @param string string
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a DBExpression instance that is appropriate to the subclass and the
* value supplied.
*/
@Override
public StringExpression expression(String string) {
return new StringLiteral(string);
}
/**
* Create An Appropriate Expression Object For This Object
*
* <p>
* The expression framework requires a *Expression to work with. The easiest
* way to get that is the {@code DBRow.column()} method.
*
* <p>
* 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.
*
* <ul>
* <li>Only object classes that are appropriate need to be handle by the
* DBExpression subclass.<li>
* <li>The implementation should be {@code static}</li>
* </ul>
*
* @param number string
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a DBExpression instance that is appropriate to the subclass and the
* value supplied.
*/
public StringExpression expression(Number number) {
return new NumberExpression(number).stringResult();
}
/**
* Create An Appropriate Expression Object For This Object
*
* <p>
* The expression framework requires a *Expression to work with. The easiest
* way to get that is the {@code DBRow.column()} method.
*
* <p>
* 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.
*
* <ul>
* <li>Only object classes that are appropriate need to be handle by the
* DBExpression subclass.<li>
* <li>The implementation should be {@code static}</li>
* </ul>
*
* @param number string
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a DBExpression instance that is appropriate to the subclass and the
* value supplied.
*/
public StringExpression expression(NumberResult number) {
return new NumberExpression(number).stringResult();
}
/**
* Create An Appropriate Expression Object For This Object
*
* <p>
* The expression framework requires a *Expression to work with. The easiest
* way to get that is the {@code DBRow.column()} method.
*
* <p>
* 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.
*
* <ul>
* <li>Only object classes that are appropriate need to be handle by the
* DBExpression subclass.<li>
* <li>The implementation should be {@code static}</li>
* </ul>
*
* @param string string
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a StringExpression that will substitute to the given value when the
* StringExpression resolves to NULL.
*/
public StringExpression ifDBNull(String alternative) {
return this.ifDBNull(StringExpression.value(alternative));
}
/**
* Provides a default option when the StringExpression resolves to NULL within
* the query.
*
* @param alternative alternative
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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 StringIfDBNullExpression(this, new StringExpression(alternative)));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isLike(String sqlPattern) {
return isLike(value(sqlPattern));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* <p>
* 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 string a literal value to find
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression contains(String string) {
return contains(value(string));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* <p>
* 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 strings literal values to find
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression containsAnyOf(String... strings) {
List<BooleanExpression> bools = new ArrayList<>();
for (String string : strings) {
bools.add(this.contains(string));
}
BooleanExpression[] boolArray = bools.toArray(new BooleanExpression[]{});
return BooleanExpression.anyOf(boolArray);
}
/**
* Advanced search that lowercases everything, requires search terms with a
* plus (+requiredterm), and removes search terms with a minus (-neverthis).
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.</p>
*
* <p>
* 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.</p>
*
* <p>
* See
* {@link DBQuery#addCondition(nz.co.gregs.dbvolution.expressions.search.HasComparisonExpression) }
* and {@link SearchAcross} for using this method with multiple columns
* easily.</p>
*
* @param searchString a collection of search terms to find
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression searchFor(SearchString searchString) {
return searchString.setExpression(this).getComparisonExpression();
}
/**
* Advanced search that lowercases everything, requires search terms with a
* plus (+requiredterm), and removes search terms with a minus (-neverthis).
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.</p>
*
* <p>
* 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.</p>
*
* <p>
* See
* {@link DBQuery#addCondition(nz.co.gregs.dbvolution.expressions.search.HasComparisonExpression) }
* and {@link SearchAcross} for using this method with multiple columns
* easily.</p>
*
* @param strings search terms to find
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression searchFor(String... strings) {
final SearchString searchStr = new SearchString(this, SeparatedStringBuilder.bySpaces().addAll(strings).toString());
return searchStr.getComparisonExpression();
}
/**
* Standardised searching using string terms and expression aliases.
*
* <p>
* Designed to provide easy access to complex user-driven searching such as
* 'terminator -schwarzenagger "come with me if" desc:quote author:+"james
* cameron"'.</p>
*
* <p>
* Search terms can be single words or sequence, or quoted phrases. Terms can
* also be prioritized with + and - and restricted to a single column using an
* alias followed by a colon (alias:term). Searching for any empty value can
* be done with an alias followed by empty quotes, for example
* description:""</p>
*
* <p>
* Use with a single column using {@link StringExpression#searchFor(nz.co.gregs.dbvolution.expressions.search.SearchString)
* } and {@link StringExpression#searchForRanking(nz.co.gregs.dbvolution.expressions.search.SearchString)
* }: e.g. marq.column(marq.name).searchFor(searchString). If you have
* individual strings use
* {@link StringExpression#searchFor(java.lang.String...)} and {@link StringExpression#searchForRanking(java.lang.String...)
* }.</p>
*
* <p>
* searchForRanking produces a number value that can be used for sorting. </p>
*
*
* @param strings search terms to find
* @return a BooleanExpression of the SQL comparison.
*/
public NumberExpression searchForRanking(SearchString strings) {
return strings.setExpression(this).getRankingExpression();
}
/**
* Standardised searching using string terms and expression aliases.
*
* <p>
* Designed to provide easy access to complex user-driven searching such as
* 'terminator -schwarzenagger "come with me if" desc:quote author:+"james
* cameron"'.</p>
*
* <p>
* Search terms can be single words or sequence, or quoted phrases. Terms can
* also be prioritized with + and - and restricted to a single column using an
* alias followed by a colon (alias:term). Searching for any empty value can
* be done with an alias followed by empty quotes, for example
* description:""</p>
*
* <p>
* Use with a single column using {@link StringExpression#searchFor(nz.co.gregs.dbvolution.expressions.search.SearchString)
* } and {@link StringExpression#searchForRanking(nz.co.gregs.dbvolution.expressions.search.SearchString)
* }: e.g. marq.column(marq.name).searchFor(searchString). If you have
* individual strings use
* {@link StringExpression#searchFor(java.lang.String...)} and {@link StringExpression#searchForRanking(java.lang.String...)
* }.</p>
*
* <p>
* searchForRanking produces a number value that can be used for sorting. </p>
*
* @param strings terms to find and rank
* @return an expression
*
*/
public NumberExpression searchForRanking(String... strings) {
SeparatedString separatedBySpaces = SeparatedStringBuilder.bySpaces();
separatedBySpaces.addAll(strings);
final SearchString searchStr = new SearchString(this, separatedBySpaces.toString());
return searchForRanking(searchStr);
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* <p>
* 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 string the literal value to search for
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression contains(StringResult string) {
return contains(value(string));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* <p>
* 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 string an expression to search for
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression contains(StringExpression string) {
return this.isLike(string.prepend("%").append("%"));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* <p>
* 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 string a literal string to find
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression containsIgnoreCase(String string) {
return containsIgnoreCase(value(string));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* <p>
* 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 string an expression to search for
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression containsIgnoreCase(StringResult string) {
return containsIgnoreCase(value(string));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* <p>
* 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 string an expression to search for
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression containsIgnoreCase(StringExpression string) {
return this.lowercase().isLike(string.lowercase().prepend("%").append("%"));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* @param string a literal to search for
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression startsWith(String string) {
return startsWith(value(string));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* @param string a literal to search for
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression endsWith(String string) {
return endsWith(value(string));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* @param string an expression to search for
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression startsWith(StringResult string) {
return isLike(value(string).append("%"));
}
/**
* Creates a query comparison using the LIKE operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* @param string an expression to find
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression endsWith(StringResult string) {
return isLike(value(string).prepend("%"));
}
/**
* Like LESSTHAN_OR_EQUAL but only includes the EQUAL values if the fallback
* matches.
*
* <p>
* 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));}
*
* <p>
* 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.
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* 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));}
*
* <p>
* 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.
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* 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));}
*
* <p>
* 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.
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* 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));}
*
* <p>
* 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.
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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 StringIsLikeExpression(this, sqlPattern));
}
}
/**
* Creates a query comparison using the LIKE operator and the LOWERCASE
* function.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern changing both
* expressions to lowercase first.
*
* <p>
* 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
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied SQL pattern changing both
* expressions to lowercase first.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* 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
* @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.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param numberResult numberResult
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param number number
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression is(StringExpression equivalentString) {
return is((StringResult) equivalentString);
}
/**
* Creates a query comparison using the EQUALS operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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 StringIsExpression(this, equivalentString));
if (equivalentString.getIncludesNull()) {
return BooleanExpression.anyOf(this.isNull(), is);
} else {
return is;
}
}
}
/**
* Creates a query comparison using the NOT EQUALS operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param numberResult numberResult
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param numberResult numberResult
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param number number
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isNot(StringResult equivalentString) {
if (equivalentString.getIncludesNull()) {
return this.isNotNull();
} else {
return new BooleanExpression(new StringIsNotExpression(this, equivalentString));
}
}
public BooleanExpression isEmpty() {
return this.length().is(0);
}
public BooleanExpression isNotEmpty() {
return this.length().isGreaterThan(0);
}
/**
* 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.
*
* <p>
* if the upper-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended and exclusive.
* <br>
* I.e permittedRange(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended and exclusive.
* <br>
* I.e permittedRange(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended and exclusive.
* <br>
* I.e permittedRange(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended and exclusive.
* <br>
* I.e permittedRange(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended and inclusive.
* <br>
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended upwards and
* exclusive.
* <br>
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended downwards and
* exclusive.
* <br>
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended upwards and
* exclusive.
* <br>
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended downwards and
* exclusive.
* <br>
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended upwards and
* exclusive.
* <br>
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended downwards and
* exclusive.
* <br>
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* if the upper-bound is null the range will be open ended upwards and
* exclusive.
* <br>
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc.
*
* <p>
* if the lower-bound is null the range will be open ended downwards and
* exclusive.
* <br>
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc.
*
* @param lowerBound lowerBound
* @param upperBound upperBound
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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 StringIsLessThanExpression(this, equivalentString));
}
}
/**
* Creates a query comparison using the "<=" operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isLessThanOrEqual(String equivalentString) {
return isLessThanOrEqual(value(equivalentString));
}
/**
* Creates a query comparison using the "<=" operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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 StringIsLessThanOrEqualExpression(this, equivalentString));
}
}
/**
* Creates a query comparison using the GREATERTHAN operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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 StringIsGreaterThanExpression(this, equivalentString));
}
}
/**
* Creates a query comparison using the ">=" operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isGreaterThanOrEqual(String equivalentString) {
return isGreaterThanOrEqual(value(equivalentString));
}
/**
* Creates a query comparison using the ">=" operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that compares the
* current StringExpression to the supplied value.
*
* @param equivalentString equivalentString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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 StringIsGreaterThanOrEqualExpression(this, equivalentString));
}
}
/**
* Creates a query comparison using the IN operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that indicates whether
* the current StringExpression is included in the supplied values.
*
* @param possibleValues possibleValues
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Use this comparison to generate a BooleanExpression that indicates whether
* the current StringExpression is included in the supplied values.
*
* @param possibleValues possibleValues
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression of the SQL comparison.
*/
public BooleanExpression isIn(Collection<String> possibleValues) {
return isIn(expressions(possibleValues));
}
/**
* Creates a query comparison using the IN operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that indicates whether
* the current StringExpression is included in the supplied values.
*
* @param possibleValues possibleValues
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isInCollection(Collection<StringResult> possibleValues) {
final BooleanExpression isInExpression
= new BooleanExpression(new StringIsInExpression(this, possibleValues));
if (isInExpression.getIncludesNull()) {
return BooleanExpression.anyOf(new BooleanExpression(this.isNull()), isInExpression);
} else {
return isInExpression;
}
}
/**
* Creates a query comparison using the IN operator.
*
* <p>
* Use this comparison to generate a BooleanExpression that indicates whether
* the current StringExpression is included in the supplied values.
*
* @param possibleValues possibleValues
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression of the SQL comparison.
*/
@Override
public BooleanExpression isNotInCollection(Collection<StringResult> possibleValues) {
final BooleanExpression isNotInExpression
= new BooleanExpression(new StringIsNotInExpression(this, possibleValues));
if (isNotInExpression.getIncludesNull()) {
return BooleanExpression.noneOf(new BooleanExpression(this.isNull()), isNotInExpression);
} else {
return isNotInExpression;
}
}
/**
* Creates a query expression that appends the supplied value to the current
* StringExpression.
*
* @param string2 string2
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a StringExpression.
*/
public StringExpression append(StringResult string2) {
return new StringExpression(new StringAppendExpression(this, string2));
}
/**
* Creates a query expression that appends the supplied value to the current
* StringExpression.
*
* @param string2 string2
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a StringExpression.
*/
public StringExpression append(Number number1) {
return this.append(NumberExpression.value(number1));
}
/**
* Creates a query expression that aggregates the current StringExpression
* into a single string value.
*
* <p>
* For a table with rows like {"First"} and {"Second"}, using aggregate(", ")
* will return "First, Second".</p>
*
* <p>
* Like all aggregates, return values will vary based on the other fields
* returned by the queries. For instance if the table has rows like {1,
* "First", 3} and {2, "Second", 3} and the query returns all the columns and
* the string aggregate, the result will be {1, "First", 3, "First"} and {2,
* "Second", 3, "Second"}. However if only the third column and the string
* aggregate are returned then the result will be {3, "First, Second"}. Use {@link DBRow#setReturnFields(nz.co.gregs.dbvolution.columns.ColumnProvider...)}, {@link DBRow#setReturnFieldsToNone()
* }, and similar methods to change the returned fields.
* </p>
*
* @param separator separator to place between the values
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a StringExpression.
*/
public StringExpression aggregate(String separator) {
return new StringAggregateExpression(this, separator);
}
/**
* Creates a query expression that aggregates the current StringExpression
* into a single string value.
*
* <p>
* For a table with rows like {"First"} and {"Second"}, using aggregate(", ")
* will return "First, Second".</p>
*
* <p>
* Like all aggregates, return values will vary based on the other fields
* returned by the queries. For instance if the table has rows like {1,
* "First", 3} and {2, "Second", 3} and the query returns all the columns and
* the string aggregate, the result will be {1, "First", 3, "First"} and {2,
* "Second", 3, "Second"}. However if only the third column and the string
* aggregate are returned then the result will be {3, "First, Second"}. Use {@link DBRow#setReturnFields(nz.co.gregs.dbvolution.columns.ColumnProvider...)}, {@link DBRow#setReturnFieldsToNone()
* }, and similar methods to change the returned fields.
* </p>
*
* @param separator separator placed between all values
* @param orderBy the sort ordering to use in the aggregator
* @return a StringExpression.
*/
public StringExpression aggregate(String separator, SortProvider orderBy) {
return new StringAggregateWithOrderByExpression(
this,
separator,
orderBy
);
}
/**
* Convenience method to replace any null results from the expression into
* empty strings.
*
* @return a StringExpression.
*/
public StringExpression replaceNullWithEmptyString() {
return this.replace(AnyExpression.nullString(), StringExpression.emptyString());
}
/**
* Creates a query expression that replaces the supplied value within the
* current StringExpression.
*
* @param findString findString
* @param replaceWith replaceWith
* @return a StringExpression.
*/
public StringExpression replace(String findString, String replaceWith) {
return this.replace(StringExpression.value(findString), StringExpression.value(replaceWith));
}
/**
* Creates a query expression that replaces the supplied value within the
* current StringExpression.
*
* @param findString findString
* @param replaceWith replaceWith
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a StringExpression.
*/
public StringExpression replace(StringResult findString, StringResult replaceWith) {
StringResult replaceValue = replaceWith;
if (replaceWith.getIncludesNull()) {
replaceValue = StringExpression.value("");
}
return new StringExpression(
new StringReplaceExpression(
this,
StringExpression.value(findString),
StringExpression.value(replaceValue)));
}
/**
* Retrieve the substring that precedes the supplied value.
*
* <p>
* Complements {@link #substringAfter(java.lang.String) }.
*
* <p>
* 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.
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a string expression
*/
public StringExpression substringBefore(String splitBeforeThis) {
return substringBefore(value(splitBeforeThis));
}
/**
* Retrieve the substring that precedes the supplied value.
*
* <p>
* Complements {@link #substringAfter(java.lang.String) }.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a string expression
*/
public StringExpression substringBefore(StringResult splitBeforeThis) {
return new StringExpression(new StringSubstringBeforeExpression(this, new StringExpression(splitBeforeThis)));
}
/**
* Retrieve the substring that follows the supplied value.
*
* <p>
* Complements {@link #substringBefore(java.lang.String) }.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a string expression
*/
public StringExpression substringAfter(String splitAfterThis) {
return substringAfter(value(splitAfterThis));
}
/**
* Retrieve the substring that follows the supplied value.
*
* <p>
* Complements {@link #substringBefore(java.lang.String) }.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a string expression
*/
public StringExpression substringAfter(StringResult splitAfterThis) {
return new StringExpression(new StringSubstringAfterExpression(this, new StringExpression(splitAfterThis)));
}
/**
* Retrieve the substring that follows the first supplied value but precedes
* the second value.
*
* <p>
* Complements {@link #substringBefore(java.lang.String) } and {@link #substringAfter(java.lang.String)
* }.
*
* <p>
* 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.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* Complements {@link #substringBefore(java.lang.String) } and {@link #substringAfter(java.lang.String)
* }.
*
* <p>
* 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.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a StringExpression.
*/
public StringExpression trim() {
return new StringExpression(
new StringTrimExpression(this));
}
/**
* Tests that a string expression is shorter than or equal to the specified
* length.
*
* <p>
* This method is useful to test strings will fit within a specific field
* size</p>
*
* @param maxLength the longest possible number of characters
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a StringExpression.
*/
public StringExpression getFirstNumberAsSubstring() {
StringExpression exp = new StringExpression(
new StringFirstNumberAsSubstringExpression(this));
return exp;
}
/**
* Finds and returns the first integer in the string or NULL if no integer is
* found.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a StringExpression.
*/
public StringExpression getFirstIntegerAsSubstring() {
final StringExpression exp = new StringExpression(
new StringFirstIntegerAsSubstringExpression(this));
return exp;
}
/**
* Finds and returns the first number in the string or NULL if no number is
* found.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @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.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return an IntegerExpression.
*/
public IntegerExpression getFirstInteger() {
return getFirstIntegerAsSubstring().integerResult();
}
/**
* Creates a query expression that trims all leading spaces from the current
* StringExpression.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a StringExpression.
*/
public StringExpression leftTrim() {
return new StringExpression(
new StringLeftTrimExpression(this));
}
/**
* Creates a query expression that trims all trailing spaces from the current
* StringExpression.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a StringExpression.
*/
public StringExpression rightTrim() {
return new StringExpression(
new StringRightTrimExpression(this));
}
/**
* Creates a query expression that changes all the letters in the current
* StringExpression to lowercase.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a StringExpression.
*/
public StringExpression lowercase() {
return new StringExpression(
new StringLowercaseExpression(this));
}
/**
* Creates a query expression that changes all the letters in the current
* StringExpression to UPPERCASE.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a StringExpression.
*/
public StringExpression uppercase() {
return new StringExpression(
new StringUppercaseExpression(this));
}
/**
* Create a substring of the current StringExpression starting from the
* position supplied and continuing until the end of the string.
*
* <p>
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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..
*
* <p>
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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..
*
* <p>
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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..
*
* <p>
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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..
*
* <p>
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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..
*
* <p>
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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..
*
* <p>
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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..
*
* <p>
* The first character is at position zero (0).
*
* @param startingIndex0Based startingIndex0Based
* @param endIndex0Based endIndex0Based
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a NumberExpression of the expression's length.
*/
public IntegerExpression length() {
return new IntegerExpression(
new IntegerLengthExpression(this));
}
/**
* Create a {@link StringExpression} that returns the name of the current
* user.
*
* <p>
* This should be the current username under which the application is
* accessing the database.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a StringExpression
*/
public static StringExpression currentUser() {
return new StringExpression(
new StringCurrentUserExpression());
}
/**
* Returns the 1-based index of the first occurrence of searchString within
* the StringExpression.
*
* <p>
* The index is 1-based, and returns 0 when the searchString is not found.</p>
*
* @param searchString searchString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @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.
*
* <p>
* The index is 1-based, and returns 0 when the searchString is not found.</p>
*
* @param searchString searchString
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return an expression that will find the location of the searchString.
*/
public IntegerExpression locationOf(StringResult searchString) {
return new NumberExpression(new StringLocationOfExpression(this, searchString)).integerResult();
}
/**
* Creates an expression that will find the largest value in the column
* supplied.
*
* <p>
* Max is an aggregator function for use in DBReport or in a column
* expression.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a String expression.
*/
public StringExpression max() {
return new StringExpression(
new StringMaxExpression(this));
}
/**
* Creates an expression that will find the smallest value in the column
* supplied.
*
* <p>
* Min is an aggregator function for use in DBReport or in a column
* expression.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a String expression.
*/
public StringExpression min() {
return new StringExpression(new StringMinExpression(this));
}
@Override
public DBString getQueryableDatatypeForExpressionValue() {
return new DBString();
}
/**
* Creates a BooleanExpression that tests to ensure the database value is not
* a database NULL value.
*
* <P>
* The expression will be true if the value is not NULL, and false otherwise.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a BooleanExpression
*/
@Override
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.
*
* <P>
* The expression will be true if the value is not NULL and is not an empty
* string, and false otherwise.
*
* <p>
* 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.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a BooleanExpression
*/
public BooleanExpression isNotNullAndNotEmpty() {
return BooleanExpression.allOf(
BooleanExpression.isNotNull(this),
this.isNotEmpty()
);
}
/**
* Creates a BooleanExpression that tests to ensure the database value is a
* database NULL value.
*
* <P>
* The expression will be true if the value is NULL, and false otherwise.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a BooleanExpression
*/
@Override
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.
*
* <P>
* The expression will be true if the value is NULL OR the expression produces
* an empty string, and false otherwise.
*
* <p>
* 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.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a BooleanExpression
*/
public BooleanExpression isNullOrEmpty() {
return BooleanExpression.anyOf(
BooleanExpression.isNull(this),
this.isEmpty()
);
}
/**
* Adds an explicit bracket at this point in the expression chain.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a StringExpression that will have the current expression wrapped in
* brackets.
*/
public StringExpression bracket() {
return new StringExpression(new StringBracketExpression(this));
}
/**
* Provides direct access to the IN operator.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
public BooleanExpression isInIgnoreCase(String... potentialValues) {
return this.isInIgnoreCase(expressions(potentialValues));
}
public StringResult[] expressions(String... potentialValues) {
List<StringResult> 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<String> potentialValues) {
List<StringResult> 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.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
public BooleanExpression isInIgnoreCase(Collection<String> potentialValues) {
return this.isInIgnoreCase(expressions(potentialValues));
}
/**
* Provides direct access to the IN operator.
*
* <p>
* 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
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
public BooleanExpression isInIgnoreCase(StringResult... potentialValues) {
List<StringResult> 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.
*
* <p>
* You should probably use {@link #getFirstNumber() } or {@link #getFirstNumber()
* } instead as they are more reliable.</p>
*
* <p>
* Uses the database's own facilities to parse the value of this expression
* into a number.
*
* <p>
* May return NULL and all sorts of crazy things.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a number expression
*/
public NumberExpression numberResult() {
return new NumberExpression(
new StringNumberResultExpression(this));
}
/**
* In so far as it is possible, transform the value of this expression into a
* number.
*
* <p>
* Uses the database's own facilities to parse the value of this expression
* into a number.
*
* <p>
* May return NULL and all sorts of crazy things.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @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);
}
public StringExpression prepend(String string) {
return StringExpression.value(string).append(this);
}
public StringExpression prepend(StringResult string) {
return value(string).append(this);
}
public StringExpression append(IntegerExpression value) {
return append(value.stringResult());
}
public StringExpression leftPad(String padWith, int ensureLength) {
return new LeftPadExpression(this, AnyExpression.value(padWith), AnyExpression.value(ensureLength));
}
public StringExpression leftPad(StringExpression padWith, IntegerExpression ensureLength) {
return new LeftPadExpression(this, padWith, ensureLength);
}
private static class LeftPadExpression extends StringExpression {
private final StringExpression string;
private final IntegerExpression length;
private final StringExpression padding;
public LeftPadExpression(StringExpression string, StringExpression padding, IntegerExpression i) {
super();
this.string = string;
this.padding = padding;
this.length = i;
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
if (db.supportsLeftPadTransform()) {
return db.doLeftPadTransform(this.string.toSQLString(db), this.padding.toSQLString(db), this.length.toSQLString(db));
} else {
return "LPAD_SUBSTITUTE_REQUIRED("
+ SeparatedStringBuilder
.startsWith("LPAD_SUBSTITUTE_REQUIRED(")
.addAll(this.string.toSQLString(db), this.padding.toSQLString(db), this.length.toSQLString(db))
.separatedBy(", ")
.withSuffix(")")
.toString();
}
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public LeftPadExpression copy() {
return new LeftPadExpression(
string == null ? null : string.copy(),
padding == null ? null : padding.copy(),
length == null ? null : length.copy()
);
}
}
private static abstract class DBBinaryStringArithmetic extends StringExpression {
private static final long serialVersionUID = 1L;
protected StringResult first;
protected 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);
}
protected abstract String getEquationOperator(DBDefinition db);
@Override
public Set<DBRow> getTablesInvolved() {
HashSet<DBRow> 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 static final long serialVersionUID = 1L;
private StringExpression first;
private StringExpression second;
private StringExpression third;
DBTrinaryStringFunction(StringExpression first) {
this.first = first;
this.second = null;
this.third = null;
}
DBTrinaryStringFunction(StringExpression first, StringExpression second) {
this.first = first;
this.second = second;
}
DBTrinaryStringFunction(StringExpression first, StringExpression second, StringExpression 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);
}
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<DBRow> getTablesInvolved() {
HashSet<DBRow> 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();
}
/**
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the first
*/
protected StringExpression getFirst() {
return first;
}
/**
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the second
*/
protected StringExpression getSecond() {
return second;
}
/**
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the third
*/
protected StringExpression 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();
}
}
}
protected static abstract class DBBinaryStringFunction extends StringExpression {
private static final long serialVersionUID = 1L;
protected StringExpression first;
protected 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 Set<DBRow> getTablesInvolved() {
HashSet<DBRow> 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();
}
/**
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the first
*/
protected StringExpression getFirst() {
return first;
}
/**
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @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 {
private static final long serialVersionUID = 1L;
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 Set<DBRow> getTablesInvolved() {
HashSet<DBRow> 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 static class Substring extends StringExpression {
private final static long serialVersionUID = 1l;
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;
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;
this.length = endIndex0Based;
}
private Substring(ExpressionHasStandardStringResult stringInput, IntegerResult startingIndex0Based, IntegerResult endIndex0Based) {
super(stringInput.stringResult());
this.startingPosition = startingIndex0Based;
this.length = endIndex0Based;
}
@Override
public Substring copy() {
return new Substring(
getInnerResult() == null ? null : (ExpressionHasStandardStringResult) getInnerResult().copy(),
startingPosition == null ? null : startingPosition.copy(),
length == null ? null : length.copy()
);
}
@Override
public String toSQLString(DBDefinition db) {
if (getInnerResult() == null) {
return "";
} else {
return doSubstringTransform(db, (ExpressionHasStandardStringResult) getInnerResult(), startingPosition, length);
}
}
public String doSubstringTransform(DBDefinition db, ExpressionHasStandardStringResult 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 {
private static final long serialVersionUID = 1L;
protected final StringResult first;
protected final 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);
}
protected abstract String getEquationOperator(DBDefinition db);
@Override
public Set<DBRow> getTablesInvolved() {
HashSet<DBRow> 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 {
private static final long serialVersionUID = 1L;
protected final StringExpression column;
protected final List<StringResult> values = new ArrayList<>();
private final boolean includesNulls;
DBNnaryBooleanFunction() {
column = null;
includesNulls = false;
}
DBNnaryBooleanFunction(StringExpression leftHandSide, Collection<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<DBRow> getTablesInvolved() {
HashSet<DBRow> hashSet = new HashSet<>();
if (column != null) {
hashSet.addAll(column.getTablesInvolved());
}
values.stream()
.filter(second -> (second != null))
.forEachOrdered(second -> 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;
}
}
private static class NullStringExpression extends StringExpression {
public NullStringExpression() {
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
if (db.requiredToProduceEmptyStringsForNull()) {
return db.getEmptyString();
} else {
return db.getNull();
}
}
@Override
public boolean getIncludesNull() {
return true;
}
@Override
public NullStringExpression copy() {
return new NullStringExpression();
}
}
private static class EmptyStringExpression extends StringExpression {
public EmptyStringExpression() {
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.getEmptyString();
}
@Override
public boolean getIncludesNull() {
return true;
}
@Override
public EmptyStringExpression copy() {
return new EmptyStringExpression();
}
}
protected class StringIfDBNullExpression extends DBBinaryStringFunction {
public StringIfDBNullExpression(StringExpression first, StringExpression second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.doStringIfNullTransform(this.getFirst().toSQLString(db), getSecond().toSQLString(db));
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public StringIfDBNullExpression copy() {
return new StringIfDBNullExpression(
getFirst() == null ? null : getFirst().copy(),
getSecond() == null ? null : getSecond().copy());
}
}
protected static class StringIsLikeExpression extends DBBinaryBooleanArithmetic {
public StringIsLikeExpression(StringResult first, StringResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
protected String getEquationOperator(DBDefinition db) {
return " LIKE ";
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public StringIsLikeExpression copy() {
return new StringIsLikeExpression(
first == null ? null : first.copy(),
second == null ? null : second.copy()
);
}
}
protected class StringIsExpression extends DBBinaryBooleanArithmetic {
public StringIsExpression(StringResult first, StringResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@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;
}
@Override
public StringIsExpression copy() {
return new StringIsExpression(
first == null ? null : first.copy(),
second == null ? null : second.copy()
);
}
}
protected class StringIsNotExpression extends DBBinaryBooleanArithmetic {
public StringIsNotExpression(StringResult first, StringResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return (new StringExpression(first)).ifDBNull("<DBV NULL PROTECTION>").toSQLString(db)
+ this.getEquationOperator(db)
+ (new StringExpression(second)).ifDBNull("<DBV NULL PROTECTION>").toSQLString(db);
}
@Override
protected String getEquationOperator(DBDefinition db) {
return " <> ";
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public StringIsNotExpression copy() {
return new StringIsNotExpression(
first == null ? null : first.copy(),
second == null ? null : second.copy()
);
}
}
protected static class StringIsLessThanExpression extends DBBinaryBooleanArithmetic {
public StringIsLessThanExpression(StringResult first, StringResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
protected String getEquationOperator(DBDefinition db) {
return " < ";
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public StringIsLessThanExpression copy() {
return new StringIsLessThanExpression(
first == null ? null : first.copy(),
second == null ? null : second.copy()
);
}
}
protected static class StringIsLessThanOrEqualExpression extends DBBinaryBooleanArithmetic {
public StringIsLessThanOrEqualExpression(StringResult first, StringResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
protected String getEquationOperator(DBDefinition db) {
return " <= ";
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public StringIsLessThanOrEqualExpression copy() {
return new StringIsLessThanOrEqualExpression(
first == null ? null : first.copy(),
second == null ? null : second.copy()
);
}
}
protected static class StringIsGreaterThanExpression extends DBBinaryBooleanArithmetic {
public StringIsGreaterThanExpression(StringResult first, StringResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
protected String getEquationOperator(DBDefinition db) {
return " > ";
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public StringIsGreaterThanExpression copy() {
return new StringIsGreaterThanExpression(
first == null ? null : first.copy(),
second == null ? null : second.copy()
);
}
}
protected static class StringIsGreaterThanOrEqualExpression extends DBBinaryBooleanArithmetic {
public StringIsGreaterThanOrEqualExpression(StringResult first, StringResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
protected String getEquationOperator(DBDefinition db) {
return " >= ";
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public StringIsGreaterThanOrEqualExpression copy() {
return new StringIsGreaterThanOrEqualExpression(
first == null ? null : first.copy(),
second == null ? null : second.copy()
);
}
}
protected class StringIsInExpression extends DBNnaryBooleanFunction {
public StringIsInExpression(StringExpression leftHandSide, Collection<StringResult> rightHandSide) {
super(leftHandSide, rightHandSide);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
List<String> sqlValues = new ArrayList<>();
values.stream()
.filter(value -> (!value.getIncludesNull()))
.forEachOrdered(value -> sqlValues.add(value.toSQLString(db)));
return db.doInTransform(column.toSQLString(db), sqlValues);
}
@Override
protected String getFunctionName(DBDefinition db) {
return " IN ";
}
@Override
public StringIsInExpression copy() {
return new StringIsInExpression(
column == null ? null : column.copy(),
values
);
}
}
protected class StringIsNotInExpression extends DBNnaryBooleanFunction {
public StringIsNotInExpression(StringExpression leftHandSide, Collection<StringResult> rightHandSide) {
super(leftHandSide, rightHandSide);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
List<String> sqlValues = new ArrayList<>();
values.stream()
.filter(value -> (!value.getIncludesNull()))
.forEachOrdered(value -> sqlValues.add(value.toSQLString(db)));
return db.doNotInTransform(column.toSQLString(db), sqlValues);
}
@Override
protected String getFunctionName(DBDefinition db) {
return " NOT IN ";
}
@Override
public StringIsNotInExpression copy() {
return new StringIsNotInExpression(
column == null ? null : column.copy(),
values
);
}
}
protected class StringAppendExpression extends DBBinaryStringArithmetic {
public StringAppendExpression(StringResult first, StringResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.doConcatTransform(super.first.toSQLString(db), super.second.toSQLString(db));
}
@Override
protected String getEquationOperator(DBDefinition db) {
return "";
}
@Override
public StringAppendExpression copy() {
return new StringAppendExpression(
first == null ? null : first.copy(),
second == null ? null : second.copy()
);
}
}
public static class StringAggregateExpression extends StringExpression implements CanBeWindowingFunctionWithFrame<StringExpression> {
public StringAggregateExpression(StringExpression columnToAccumulate, String separator) {
this.column = columnToAccumulate;
this.separator = separator;
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.doStringAccumulateTransform(column.toSQLString(db),
separator,
column.getTablesInvolved().toArray(new DBRow[]{})[0].getTableName());
}
@Override
public StringAggregateExpression copy() {
return new StringAggregateExpression(
column == null ? null : column.copy(),
separator == null ? null : separator
);
}
@Override
public boolean isAggregator() {
return true;
}
@Override
public WindowFunctionFramable<StringExpression> over() {
return new WindowFunctionFramable<>(new StringExpression(this));
}
protected StringExpression column;
protected String separator;
@Override
public DBString getQueryableDatatypeForExpressionValue() {
return new DBString();
}
@Override
public Set<DBRow> getTablesInvolved() {
HashSet<DBRow> hashSet = new HashSet<>();
if (column != null) {
hashSet.addAll(column.getTablesInvolved());
}
return hashSet;
}
@Override
public boolean isPurelyFunctional() {
if (column == null) {
return true;
} else {
return column.isPurelyFunctional();
}
}
}
public static class StringAggregateWithOrderByExpression extends StringExpression implements CanBeWindowingFunctionWithFrame<StringExpression> {
private final static long serialVersionUID = 1l;
private final StringExpression columnToAccumulate;
private final String separator;
private final SortProvider orderBy;
public StringAggregateWithOrderByExpression(StringExpression columnToAccumulate, String separator, SortProvider orderBy) {
super();
this.columnToAccumulate = columnToAccumulate;
this.separator = separator;
this.orderBy = orderBy.copy();
orderBy
.getTablesInvolved()
.forEach(table -> table.setSortedSubselectRequired(orderBy));
}
@Override
public String toSQLString(DBDefinition db) {
return db.doStringAccumulateTransform(
columnToAccumulate,
separator,
orderBy
);
}
@Override
public StringAggregateWithOrderByExpression copy() {
return new StringAggregateWithOrderByExpression(
columnToAccumulate == null ? StringExpression.nullString() : columnToAccumulate.copy(),
separator == null ? null : separator,
orderBy == null ? null : orderBy.copy()
);
}
@Override
public boolean isAggregator() {
return true;
}
@Override
public WindowFunctionFramable<StringExpression> over() {
return new WindowFunctionFramable<>(new StringExpression(this));
}
}
protected static class StringReplaceExpression extends DBTrinaryStringFunction {
public StringReplaceExpression(StringExpression first, StringExpression second, StringExpression third) {
super(first, second, third);
}
private final static long serialVersionUID = 1l;
@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;
}
@Override
public StringReplaceExpression copy() {
return new StringReplaceExpression(
getFirst() == null ? null : getFirst().copy(),
getSecond() == null ? null : getSecond().copy(),
getThird() == null ? null : getThird().copy()
);
}
}
protected static class StringSubstringBeforeExpression extends DBBinaryStringFunction {
public StringSubstringBeforeExpression(StringExpression first, StringExpression second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@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);
}
}
@Override
public StringSubstringBeforeExpression copy() {
StringSubstringBeforeExpression newInstance;
newInstance
= new StringSubstringBeforeExpression(
getFirst() == null ? null : getFirst().copy(),
getSecond() == null ? null : getSecond().copy()
);
return newInstance;
}
}
protected static class StringSubstringAfterExpression extends DBBinaryStringFunction {
public StringSubstringAfterExpression(StringExpression first, StringExpression second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@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);
}
}
@Override
public StringSubstringAfterExpression copy() {
StringSubstringAfterExpression newInstance;
newInstance
= new StringSubstringAfterExpression(
getFirst() == null ? null : getFirst().copy(),
getSecond() == null ? null : getSecond().copy()
);
return newInstance;
}
}
protected static class StringTrimExpression extends StringExpression {
public StringTrimExpression(StringResult stringVariable) {
super(stringVariable);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.doTrimFunction(this.getInnerResult().toSQLString(db));
}
@Override
public StringTrimExpression copy() {
return new StringTrimExpression(
(StringResult) (getInnerResult() == null ? null : getInnerResult().copy())
);
}
}
protected static class StringFirstNumberAsSubstringExpression extends StringExpression {
public StringFirstNumberAsSubstringExpression(StringResult stringVariable) {
super(stringVariable);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.doFindNumberInStringTransform(this.getInnerResult().toSQLString(db));
}
@Override
public StringFirstNumberAsSubstringExpression copy() {
return new StringFirstNumberAsSubstringExpression(
(StringResult) (getInnerResult() == null ? null : getInnerResult().copy())
);
}
}
protected static class StringFirstIntegerAsSubstringExpression extends StringExpression {
public StringFirstIntegerAsSubstringExpression(StringResult stringVariable) {
super(stringVariable);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.doFindIntegerInStringTransform(this.getInnerResult().toSQLString(db));
}
@Override
public StringFirstIntegerAsSubstringExpression copy() {
return new StringFirstIntegerAsSubstringExpression(
(StringResult) (getInnerResult() == null ? null : getInnerResult().copy())
);
}
}
protected static class StringLeftTrimExpression extends StringExpression {
public StringLeftTrimExpression(StringResult stringVariable) {
super(stringVariable);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.doLeftTrimTransform(this.getInnerResult().toSQLString(db));
}
@Override
public StringLeftTrimExpression copy() {
return new StringLeftTrimExpression((StringResult) (getInnerResult() == null ? null : getInnerResult().copy()));
}
}
protected static class StringRightTrimExpression extends StringExpression {
public StringRightTrimExpression(StringResult stringVariable) {
super(stringVariable);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition defn) {
return defn.getRightTrimFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")";
}
@Override
public StringRightTrimExpression copy() {
return new StringRightTrimExpression((StringResult) (getInnerResult() == null ? null : getInnerResult().copy()));
}
}
protected static class StringLowercaseExpression extends StringExpression {
public StringLowercaseExpression(StringResult stringVariable) {
super(stringVariable);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition defn) {
return defn.getLowercaseFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")";
}
@Override
public StringLowercaseExpression copy() {
return new StringLowercaseExpression((StringResult) (getInnerResult() == null ? null : getInnerResult().copy()));
}
}
protected static class StringUppercaseExpression extends StringExpression {
public StringUppercaseExpression(StringResult stringVariable) {
super(stringVariable);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition defn) {
return defn.getUppercaseFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")";
}
@Override
public StringUppercaseExpression copy() {
return new StringUppercaseExpression((StringResult) (getInnerResult() == null ? null : getInnerResult().copy()));
}
}
protected static class IntegerLengthExpression extends IntegerExpression {
public IntegerLengthExpression(AnyResult<?> only) {
super(only);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.doStringLengthTransform(getInnerResult().toSQLString(db));
}
@Override
public IntegerLengthExpression copy() {
return new IntegerLengthExpression((AnyResult<?>) (getInnerResult() == null ? null : getInnerResult().copy()));
}
}
protected static class StringCurrentUserExpression extends StringExpression {
public StringCurrentUserExpression() {
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.getCurrentUserFunctionName();
}
@Override
public boolean getIncludesNull() {
return false;
}
@Override
public boolean isPurelyFunctional() {
return true;
}
@Override
public StringCurrentUserExpression copy() {
return new StringCurrentUserExpression();
}
}
protected static class StringLocationOfExpression extends BinaryComplicatedNumberFunction {
public StringLocationOfExpression(StringExpression first, StringResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.doPositionInStringTransform(this.first.toSQLString(db), this.second.toSQLString(db));
}
@Override
public StringLocationOfExpression copy() {
return new StringLocationOfExpression(
first == null ? null : first.copy(),
second == null ? null : second.copy()
);
}
}
public static class StringMaxExpression extends StringExpression implements CanBeWindowingFunctionWithFrame<StringExpression> {
public StringMaxExpression(StringResult stringVariable) {
super(stringVariable);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition defn) {
return defn.getMaxFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")";
}
@Override
public boolean isAggregator() {
return true;
}
@Override
public StringMaxExpression copy() {
return new StringMaxExpression((StringResult) (getInnerResult() == null ? null : getInnerResult().copy()));
}
@Override
public WindowFunctionFramable<StringExpression> over() {
return new WindowFunctionFramable<>(new StringExpression(this));
}
}
public static class StringMinExpression extends StringExpression implements CanBeWindowingFunctionWithFrame<StringExpression> {
public StringMinExpression(StringResult stringVariable) {
super(stringVariable);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition defn) {
return defn.getMinFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")";
}
@Override
public boolean isAggregator() {
return true;
}
@Override
public StringMinExpression copy() {
return new StringMinExpression((StringResult) (getInnerResult() == null ? null : getInnerResult().copy()));
}
@Override
public WindowFunctionFramable<StringExpression> over() {
return new WindowFunctionFramable<>(new StringExpression(this));
}
}
protected static class StringBracketExpression extends StringExpression {
public StringBracketExpression(StringResult stringVariable) {
super(stringVariable);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition defn) {
return "(" + getInnerResult().toSQLString(defn) + ")";
}
@Override
public StringBracketExpression copy() {
return new StringBracketExpression((StringResult) (getInnerResult() == null ? null : getInnerResult().copy()));
}
}
protected static class StringNumberResultExpression extends NumberExpression {
public StringNumberResultExpression(AnyResult<?> value) {
super(value);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.doStringToNumberTransform(getInnerResult().toSQLString(db));
}
@Override
public StringNumberResultExpression copy() {
return new StringNumberResultExpression((AnyResult<?>) (getInnerResult() == null ? null : getInnerResult().copy()));
}
}
public static WindowFunctionFramable<StringExpression> firstValue() {
return new FirstValueExpression().over();
}
public static class FirstValueExpression extends StringExpression implements CanBeWindowingFunctionWithFrame<StringExpression> {
public FirstValueExpression() {
super();
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.getFirstValueFunctionName() + "()";
}
@Override
public boolean isAggregator() {
return true;
}
@Override
@SuppressWarnings("unchecked")
public FirstValueExpression copy() {
return new FirstValueExpression();
}
@Override
public WindowFunctionFramable<StringExpression> over() {
return new WindowFunctionFramable<StringExpression>(new StringExpression(this));
}
}
public static WindowFunctionFramable<StringExpression> lastValue() {
return new LastValueExpression().over();
}
public static class LastValueExpression extends StringExpression implements CanBeWindowingFunctionWithFrame<StringExpression> {
public LastValueExpression() {
super();
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.getLastValueFunctionName() + "()";
}
@Override
public boolean isAggregator() {
return true;
}
@Override
@SuppressWarnings("unchecked")
public StringExpression copy() {
return new LastValueExpression();
}
@Override
public WindowFunctionFramable<StringExpression> over() {
return new WindowFunctionFramable<StringExpression>(new StringExpression(this));
}
}
public static WindowFunctionFramable<StringExpression> nthValue(IntegerExpression indexExpression) {
return new NthValueExpression(indexExpression).over();
}
public static class NthValueExpression extends StringExpression implements CanBeWindowingFunctionWithFrame<StringExpression> {
public NthValueExpression(IntegerExpression only) {
super(only);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.getNthValueFunctionName() + "(" + getInnerResult().toSQLString(db) + ")";
}
@Override
public boolean isAggregator() {
return true;
}
@Override
@SuppressWarnings("unchecked")
public NthValueExpression copy() {
return new NthValueExpression(
(IntegerExpression) (getInnerResult() == null ? null : getInnerResult().copy()));
}
@Override
public WindowFunctionFramable<StringExpression> over() {
return new WindowFunctionFramable<StringExpression>(new StringExpression(this));
}
}
/**
* LAG() is a window function that provides access to a row at a specified
* physical offset which comes before the current row.
*
* <p>
* The function will "look" back one row and return the value there. If there
* is no previous row NULL will be returned.</p>
*
* @return a lag expression ready for additional configuration
*/
public LagLeadWindow lag() {
return lag(IntegerExpression.value(1));
}
/**
*
* Synonym for lag.
*
* <p>
* LAG() is a window function that provides access to a row at a specified
* physical offset which comes before the current row.</p>
*
* <p>
* The function will "look" back one row and return the value there. If there
* is no previous row NULL will be returned.</p>
*
* @return a lag expression ready for additional configuration
*/
public LagLeadWindow previousRowValue() {
return lag(IntegerExpression.value(1));
}
/**
* LAG() is a window function that provides access to a row at a specified
* physical offset which comes before the current row.
*
* <p>
* When there is no row at the offset NULL will be returned.</p>
*
* @param offset the number of rows to look backwards
* @return a lag expression ready for additional configuration
*/
public LagLeadWindow lag(IntegerExpression offset) {
return lag(offset, nullExpression());
}
/**
* LAG() is a window function that provides access to a row at a specified
* physical offset which comes before the current row.
*
* @param offset the number of rows to look backwards
* @param defaultExpression the expression to return when there is no row at
* the offset
* @return a lag expression ready for additional configuration
*/
public LagLeadWindow lag(IntegerExpression offset, StringExpression defaultExpression) {
return new LagExpression(this, offset, defaultExpression).over();
}
/**
* Synonym for lead.
*
* <p>
* LEAD() is a window function that provides access to a row at a specified
* physical offset which comes after the current row.</p>
*
* <p>
* The function will "look" forward one row and return the value there. If
* there is no next row NULL will be returned.</p>
*
* @return a lag expression ready for additional configuration
*/
public LagLeadWindow nextRowValue() {
return lead();
}
/**
* LEAD() is a window function that provides access to a row at a specified
* physical offset which comes after the current row.
*
* <p>
* The function will "look" forward one row and return the value there. If
* there is no next row NULL will be returned.</p>
*
* @return a lag expression ready for additional configuration
*/
public LagLeadWindow lead() {
return lead(value(1));
}
/**
* LEAD() is a window function that provides access to a row at a specified
* physical offset which comes after the current row.
*
* <p>
* When there is no row at the offset NULL will be returned.</p>
*
* @param offset the number of rows to look backwards
* @return a lag expression ready for additional configuration
*/
public LagLeadWindow lead(IntegerExpression offset) {
return lead(offset, nullExpression());
}
/**
* LEAD() is a window function that provides access to a row at a specified
* physical offset which comes after the current row.
*
* @param offset the number of rows to look forwards
* @param defaultExpression the expression to use when there is no row at the
* offset
* @return a lag expression ready for additional configuration
*/
public LagLeadWindow lead(IntegerExpression offset, StringExpression defaultExpression) {
return new LeadExpression(this, offset, defaultExpression).over();
}
private static abstract class LagLeadExpression extends StringExpression implements CanBeWindowingFunctionRequiresOrderBy<StringExpression> {
private static final long serialVersionUID = 1L;
protected StringExpression first;
protected IntegerExpression second;
protected StringExpression third;
LagLeadExpression(StringExpression first, IntegerExpression second, StringExpression third) {
this.first = first;
this.second = second == null ? value(1) : second;
this.third = third == null ? nullString() : 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.afterValue(db);
}
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<DBRow> getTablesInvolved() {
HashSet<DBRow> hashSet = new HashSet<DBRow>();
hashSet.addAll(getFirst().getTablesInvolved());
hashSet.addAll(getSecond().getTablesInvolved());
hashSet.addAll(getThird().getTablesInvolved());
return hashSet;
}
@Override
public boolean isAggregator() {
return getFirst().isAggregator() || getSecond().isAggregator() || getThird().isAggregator();
}
@Override
public boolean getIncludesNull() {
return false;
}
/**
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the first
*/
protected StringExpression getFirst() {
return first;
}
/**
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the second
*/
protected IntegerExpression getSecond() {
return second;
}
/**
*
* @return the third
*/
protected StringExpression getThird() {
return third;
}
@Override
public boolean isPurelyFunctional() {
return first.isPurelyFunctional() && second.isPurelyFunctional() && third.isPurelyFunctional();
}
@Override
public LagLeadWindow over() {
return new LagLeadWindow(new StringExpression(this));
}
}
public static class LagLeadWindow extends WindowFunctionRequiresOrderBy<StringExpression> {
public LagLeadWindow(StringExpression expression) {
super(expression);
}
}
public static class LagExpression extends LagLeadExpression {
private static final long serialVersionUID = 1L;
public LagExpression(StringExpression first, IntegerExpression second, StringExpression third) {
super(first, second, third);
}
@Override
String getFunctionName(DBDefinition db) {
return db.getLagFunctionName();
}
@Override
public LagExpression copy() {
return new LagExpression(first, second, third);
}
}
public static class LeadExpression extends LagLeadExpression {
private static final long serialVersionUID = 1L;
public LeadExpression(StringExpression first, IntegerExpression second, StringExpression third) {
super(first, second, third);
}
@Override
String getFunctionName(DBDefinition db) {
return db.getLeadFunctionName();
}
@Override
public LeadExpression copy() {
return new LeadExpression(first, second, third);
}
}
}