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

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

/*
 * Copyright 2014 Gregory Graham.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nz.co.gregs.dbvolution.expressions;

import nz.co.gregs.dbvolution.results.StringResult;
import nz.co.gregs.dbvolution.results.NumberResult;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import nz.co.gregs.dbvolution.DBRow;
import nz.co.gregs.dbvolution.columns.StringColumn;
import nz.co.gregs.dbvolution.databases.definitions.DBDefinition;
import nz.co.gregs.dbvolution.datatypes.*;
import nz.co.gregs.dbvolution.results.AnyResult;
import nz.co.gregs.dbvolution.results.IntegerResult;

/**
 * StringExpression implements standard functions that produce a character or
 * string result, including CHAR and VARCHAR.
 *
 * 

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

* Use a StringExpression to produce a string from an existing column, * expression, or value and perform string manipulation. * *

* Generally you get a StringExpression from a value or column using {@link StringExpression#value(java.lang.String) * } or {@link DBRow#column(nz.co.gregs.dbvolution.datatypes.DBString) }. * *

Support DBvolution at * Patreon

* * @author Gregory Graham */ public class StringExpression extends RangeExpression implements StringResult { // needed because of Oracle's difficulty with empty/null strings private final boolean stringNullProtectionRequired; /** * Creates a StringExpression that will return a database NULL. * *

Support DBvolution at * Patreon

* * @return a StringExpression that resolves to NULL within the database */ @Override public StringExpression nullExpression() { return new StringExpression() { @Override public String toSQLString(DBDefinition db) { return db.getNull(); } @Override public boolean getIncludesNull() { return true; } }; } /** * Default Constructor * */ protected StringExpression() { super(); stringNullProtectionRequired = false; } /** * Creates a StringExpression from an arbitrary StringResult object. * *

* {@link StringResult} objects are generally StringExpressions but they can * be {@link DBString}, {@link StringColumn}, or other types. * * @param stringVariable stringVariable */ public StringExpression(StringResult stringVariable) { super(stringVariable); stringNullProtectionRequired = stringVariable == null || stringVariable.getIncludesNull(); } /** * Creates a StringExpression from an arbitrary StringResult object. * *

* {@link StringResult} objects are generally StringExpressions but they can * be {@link DBString}, {@link StringColumn}, or other types. * * @param stringVariable stringVariable */ protected StringExpression(AnyResult stringVariable) { super(stringVariable); stringNullProtectionRequired = stringVariable == null || stringVariable.getIncludesNull(); } /** * Creates a StringExpression from an arbitrary String object. * *

* Essentially the same as {@link StringExpression#value(java.lang.String) } * * @param stringVariable stringVariable */ public StringExpression(String stringVariable) { super(new DBString(stringVariable)); stringNullProtectionRequired = stringVariable == null || stringVariable.isEmpty(); } /** * Creates a StringExpression from an arbitrary DBString object. * * @param stringVariable stringVariable */ public StringExpression(DBString stringVariable) { super(stringVariable); if (stringVariable == null) { stringNullProtectionRequired = true; } else { stringNullProtectionRequired = stringVariable.getIncludesNull(); } } /** * Creates a StringExpression from an arbitrary Number object. * *

* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult() * }. * *

* Refer to {@link NumberExpression#NumberExpression(java.lang.Number) } and {@link NumberExpression#stringResult() * } for more information. * * @param numberVariable numberVariable */ public StringExpression(NumberResult numberVariable) { super(numberVariable); if (numberVariable == null) { stringNullProtectionRequired = true; } else { stringNullProtectionRequired = numberVariable.getIncludesNull(); } } /** * Creates a StringExpression from an arbitrary Number object. * *

* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult() * }. * *

* Refer to {@link NumberExpression#NumberExpression(java.lang.Number) } and {@link NumberExpression#stringResult() * } for more information. * * @param numberVariable numberVariable */ public StringExpression(Number numberVariable) { super(value(numberVariable).stringResult()); if (numberVariable == null) { stringNullProtectionRequired = true; } else { stringNullProtectionRequired = new DBNumber(numberVariable).getIncludesNull(); } } /** * Creates a StringExpression from an arbitrary Number object. * *

* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult() * }. * *

* Refer to {@link NumberExpression#NumberExpression(java.lang.Number) } and {@link NumberExpression#stringResult() * } for more information. * * @param numberVariable numberVariable */ public StringExpression(long numberVariable) { super(value(numberVariable).stringResult()); stringNullProtectionRequired = false; } /** * Creates a StringExpression from an arbitrary Number object. * *

* Essentially the same as {@code NumberExpression.value(numberVariable).stringResult() * }. * *

* Refer to {@link NumberExpression#NumberExpression(java.lang.Number) } and {@link NumberExpression#stringResult() * } for more information. * * @param numberVariable numberVariable */ public StringExpression(int numberVariable) { super(value(numberVariable).stringResult()); stringNullProtectionRequired = false; } @Override public String toSQLString(DBDefinition db) { AnyResult stringInput = getInnerResult(); if (stringInput == null) { stringInput = StringExpression.value(""); } else if (!(stringInput instanceof StringResult)) { stringInput = stringInput.stringResult(); } return stringInput.toSQLString(db); } @Override public StringExpression copy() { return isNullSafetyTerminator() ? nullString() : new StringExpression(getInnerResult()); } @Override protected boolean isNullSafetyTerminator() { return stringNullProtectionRequired == false && super.isNullSafetyTerminator(); } @Override public boolean getIncludesNull() { return stringNullProtectionRequired || super.getIncludesNull(); } /** * Creates an expression that will return the most common value of the column * supplied. * *

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

* *

Support DBvolution at * Patreon

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

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

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

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

Support DBvolution at * Patreon

* @return a DBExpression instance that is appropriate to the subclass and the * value supplied. */ @Override public StringExpression expression(String string) { return new StringExpression(string); } /** * Create An Appropriate Expression Object For This Object * *

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

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

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

Support DBvolution at * Patreon

* @return a DBExpression instance that is appropriate to the subclass and the * value supplied. */ @Override public StringExpression expression(StringResult string) { return new StringExpression(string); } /** * Provides a default option when the StringExpression resolves to NULL within * the query. * * @param alternative alternative *

Support DBvolution at * Patreon

* @return a StringExpression that will substitute to the given value when the * StringExpression resolves to NULL. */ public StringExpression ifDBNull(String alternative) { return this.ifDBNull(new StringExpression(alternative)); } /** * Provides a default option when the StringExpression resolves to NULL within * the query. * * @param alternative alternative *

Support DBvolution at * Patreon

* @return a StringExpression that will substitute to the given value when the * StringExpression resolves to NULL. */ public StringExpression ifDBNull(StringResult alternative) { return new StringExpression( new StringExpression.DBBinaryStringFunction(this, new StringExpression(alternative)) { @Override public String toSQLString(DBDefinition db) { return db.doStringIfNullTransform(this.getFirst().toSQLString(db), getSecond().toSQLString(db)); } @Override public boolean getIncludesNull() { return false; } }); } /** * Creates a query comparison using the LIKE operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied SQL pattern. * *

* DBvolution does not process the SQL pattern so please ensure that it * conforms to the database's implementation of LIKE. Most implementations * only provide access to the "_" and "%" wildcards but there may be * exceptions. * * @param sqlPattern sqlPattern *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isLike(String sqlPattern) { return isLike(value(sqlPattern)); } /** * Like LESSTHAN_OR_EQUAL but only includes the EQUAL values if the fallback * matches. * *

* Often used to implement efficient paging by using LESSTHAN across 2 * columns. For example: * {@code table.column(table.name).isLessThan(5, table.column(table.pkid).isLessThan(1100));} * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param value the right side of the internal comparison * @param fallBackWhenEquals the comparison used when the two values are * equal. *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @Override public BooleanExpression isLessThan(String value, BooleanExpression fallBackWhenEquals) { return this.isLessThan(StringExpression.value(value), fallBackWhenEquals); } /** * Like GREATERTHAN_OR_EQUAL but only includes the EQUAL values if the * fallback matches. * *

* Often used to implement efficient paging by using LESSTHAN across 2 * columns. For example: * {@code table.column(table.name).isLessThan(5, table.column(table.pkid).isLessThan(1100));} * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param value the right side of the internal comparison * @param fallBackWhenEquals the comparison used when the two values are * equal. *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @Override public BooleanExpression isGreaterThan(String value, BooleanExpression fallBackWhenEquals) { return this.isGreaterThan(StringExpression.value(value), fallBackWhenEquals); } /** * Like LESSTHAN_OR_EQUAL but only includes the EQUAL values if the fallback * matches. * *

* Often used to implement efficient paging by using LESSTHAN across 2 * columns. For example: * {@code table.column(table.name).isLessThan(5, table.column(table.pkid).isLessThan(1100));} * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param value the right side of the internal comparison * @param fallBackWhenEquals the comparison used when the two values are * equal. *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @Override public BooleanExpression isLessThan(StringResult value, BooleanExpression fallBackWhenEquals) { return this.isLessThan(value).or(this.is(value).and(fallBackWhenEquals)); } /** * Like GREATERTHAN_OR_EQUAL but only includes the EQUAL values if the * fallback matches. * *

* Often used to implement efficient paging by using LESSTHAN across 2 * columns. For example: * {@code table.column(table.name).isLessThan(5, table.column(table.pkid).isLessThan(1100));} * *

* If you are using this for pagination, remember to sort by the columns as * well * * @param value the right side of the internal comparison * @param fallBackWhenEquals the comparison used when the two values are * equal. *

Support DBvolution at * Patreon

* @return a BooleanExpression */ @Override public BooleanExpression isGreaterThan(StringResult value, BooleanExpression fallBackWhenEquals) { return this.isGreaterThan(value).or(this.is(value).and(fallBackWhenEquals)); } /** * Creates a query comparison using the LIKE operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied SQL pattern. * *

* DBvolution does not process the SQL pattern so please ensure that it * conforms to the database's implementation of LIKE. Most implementations * only provide access to the "_" and "%" wildcards but there may be * exceptions. * * @param sqlPattern sqlPattern *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isLike(StringResult sqlPattern) { if (sqlPattern.getIncludesNull()) { return new BooleanExpression(this.isNull()); } else { return new BooleanExpression(new DBBinaryBooleanArithmetic(this, sqlPattern) { @Override protected String getEquationOperator(DBDefinition db) { return " LIKE "; } @Override public boolean getIncludesNull() { return false; } }); } } /** * Creates a query comparison using the LIKE operator and the LOWERCASE * function. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied SQL pattern changing both * expressions to lowercase first. * *

* DBvolution does not process the SQL pattern so please ensure that it * conforms to the database's implementation of LIKE. Most implementations * only provide access to the "_" and "%" wildcards but there may be * exceptions. * * @param sqlPattern sqlPattern *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isLikeIgnoreCase(String sqlPattern) { return isLikeIgnoreCase(value(sqlPattern)); } /** * Creates a query comparison using the LIKE operator and the LOWERCASE * function. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied SQL pattern changing both * expressions to lowercase first. * *

* DBvolution does not process the SQL pattern so please ensure that it * conforms to the database's implementation of LIKE. Most implementations * only provide access to the "_" and "%" wildcards but there may be * exceptions. * * @param sqlPattern sqlPattern *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isLikeIgnoreCase(StringResult sqlPattern) { return this.lowercase().isLike(value(sqlPattern).lowercase()); } /** * Creates a query comparison using the EQUALS operator and the LOWERCASE * function. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value changing both expressions to * lowercase first. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isIgnoreCase(String equivalentString) { return isIgnoreCase(value(equivalentString)); } /** * Creates a query comparison using the EQUALS operator and the LOWERCASE * function. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value changing both expressions to * lowercase first. * * @param numberResult numberResult *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isIgnoreCase(NumberResult numberResult) { return isIgnoreCase(numberResult.stringResult().lowercase()); } /** * Creates a query comparison using the EQUALS operator and the LOWERCASE * function. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value changing both expressions to * lowercase first. * * @param number number *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isIgnoreCase(Number number) { return isIgnoreCase(NumberExpression.value(number)); } /** * Creates a query comparison using the EQUALS operator and the LOWERCASE * function. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value changing both expressions to * lowercase first. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isIgnoreCase(StringResult equivalentString) { return isIgnoreCase(new StringExpression(equivalentString)); } /** * Creates a query comparison using the EQUALS operator and the LOWERCASE * function. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value changing both expressions to * lowercase first. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isIgnoreCase(StringExpression equivalentString) { return this.lowercase().is(equivalentString.lowercase()); } /** * Creates a query comparison using the EQUALS operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression is(String equivalentString) { if (equivalentString == null) { return this.isNull(); } else { return this.is(value(equivalentString)); } } /** * Creates a query comparison using the EQUALS operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param numberResult numberResult *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression is(NumberResult numberResult) { return this.is(numberResult.stringResult()); } /** * Creates a query comparison using the EQUALS operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param number number *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression is(Number number) { return is(NumberExpression.value(number)); } /** * Creates a query comparison using the EQUALS operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression is(StringExpression equivalentString) { return is((StringResult) equivalentString); } /** * Creates a query comparison using the EQUALS operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression is(StringResult equivalentString) { if (equivalentString == null) { return new BooleanExpression(this.isNull()); } else { final BooleanExpression is = new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) { @Override public String toSQLString(DBDefinition db) { return db.doStringEqualsTransform(super.first.toSQLString(db), super.second.toSQLString(db)); } @Override protected String getEquationOperator(DBDefinition db) { return " = "; } @Override public boolean getIncludesNull() { return false; } }); if (equivalentString.getIncludesNull()) { return BooleanExpression.anyOf(this.isNull(), is); } else { return is; } } } /** * Creates a query comparison using the NOT EQUALS operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isNot(String equivalentString) { return this.isNot(value(equivalentString)); } /** * Creates a query comparison using the NOT EQUALS operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param numberResult numberResult *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isNot(NumberResult numberResult) { return this.isNot(numberResult.stringResult()); } /** * Creates a query comparison using the NOT EQUALS operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param numberResult numberResult *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isNot(IntegerResult numberResult) { return this.isNot(numberResult.stringResult()); } /** * Creates a query comparison using the NOT EQUALS operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param number number *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isNot(Number number) { return isNot(NumberExpression.value(number)); } /** * Creates a query comparison using the NOT EQUALS operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isNot(StringResult equivalentString) { if (equivalentString.getIncludesNull()) { return this.isNotNull(); } else { return new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) { @Override public String toSQLString(DBDefinition db) { return (new StringExpression(first)).ifDBNull("").toSQLString(db) + this.getEquationOperator(db) + (new StringExpression(second)).ifDBNull("").toSQLString(db); } @Override protected String getEquationOperator(DBDefinition db) { return " <> "; } @Override public boolean getIncludesNull() { return false; } }); } } /** * Performs searches based on a range. * * if both ends of the range are specified the lower-bound will be included in * the search and the upper-bound excluded. I.e permittedRange(1,3) will * return 1 and 2. * *

* if the upper-bound is null the range will be open ended and inclusive. *
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended and exclusive. *
* I.e permittedRange(null, 5) will return 4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetween(StringResult lowerBound, StringResult upperBound) { return BooleanExpression.allOf( this.isGreaterThan(lowerBound), this.isLessThanOrEqual(upperBound) ); } /** * Performs searches based on a range. * * if both ends of the range are specified the lower-bound will be included in * the search and the upper-bound excluded. I.e permittedRange(1,3) will * return 1 and 2. * *

* if the upper-bound is null the range will be open ended and inclusive. *
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended and exclusive. *
* I.e permittedRange(null, 5) will return 4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetween(String lowerBound, StringResult upperBound) { return this.isBetween(value(lowerBound), upperBound); } /** * Performs searches based on a range. * * if both ends of the range are specified the lower-bound will be included in * the search and the upper-bound excluded. I.e permittedRange(1,3) will * return 1 and 2. * *

* if the upper-bound is null the range will be open ended and inclusive. *
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended and exclusive. *
* I.e permittedRange(null, 5) will return 4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetween(StringResult lowerBound, String upperBound) { return this.isBetween(lowerBound, value(upperBound)); } /** * Performs searches based on a range. * * if both ends of the range are specified the lower-bound will be included in * the search and the upper-bound excluded. I.e permittedRange(1,3) will * return 1 and 2. * *

* if the upper-bound is null the range will be open ended and inclusive. *
* I.e permittedRange(1,null) will return 1,2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended and exclusive. *
* I.e permittedRange(null, 5) will return 4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetween(String lowerBound, String upperBound) { return this.isBetween(value(lowerBound), value(upperBound)); } /** * Performs searches based on a range. * * if both ends of the range are specified both the lower- and upper-bound * will be included in the search. I.e permittedRangeInclusive(1,3) will * return 1, 2, and 3. * *

* if the upper-bound is null the range will be open ended and inclusive. *
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended and inclusive. *
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetweenInclusive(StringResult lowerBound, StringResult upperBound) { return BooleanExpression.allOf( this.isGreaterThanOrEqual(lowerBound), this.isLessThanOrEqual(upperBound) ); } /** * Performs searches based on a range. * * if both ends of the range are specified both the lower- and upper-bound * will be included in the search. I.e permittedRangeInclusive(1,3) will * return 1, 2, and 3. * *

* if the upper-bound is null the range will be open ended and inclusive. *
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended and inclusive. *
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetweenInclusive(String lowerBound, StringResult upperBound) { return this.isBetweenInclusive(value(lowerBound), upperBound); } /** * Performs searches based on a range. * * if both ends of the range are specified both the lower- and upper-bound * will be included in the search. I.e permittedRangeInclusive(1,3) will * return 1, 2, and 3. * *

* if the upper-bound is null the range will be open ended and inclusive. *
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended and inclusive. *
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetweenInclusive(StringResult lowerBound, String upperBound) { return this.isBetweenInclusive(lowerBound, value(upperBound)); } /** * Performs searches based on a range. * * if both ends of the range are specified both the lower- and upper-bound * will be included in the search. I.e permittedRangeInclusive(1,3) will * return 1, 2, and 3. * *

* if the upper-bound is null the range will be open ended and inclusive. *
* I.e permittedRangeInclusive(1,null) will return 1,2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended and inclusive. *
* I.e permittedRangeInclusive(null, 5) will return 5,4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetweenInclusive(String lowerBound, String upperBound) { return this.isBetweenInclusive(value(lowerBound), value(upperBound)); } /** * Performs searches based on a range. * * if both ends of the range are specified both the lower- and upper-bound * will be excluded in the search. I.e permittedRangeExclusive(1,3) will * return 2. * *

* if the upper-bound is null the range will be open ended upwards and * exclusive. *
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended downwards and * exclusive. *
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetweenExclusive(StringResult lowerBound, StringResult upperBound) { return BooleanExpression.allOf( this.isGreaterThan(lowerBound), this.isLessThan(upperBound) ); } /** * Performs searches based on a range. * * if both ends of the range are specified both the lower- and upper-bound * will be excluded in the search. I.e permittedRangeExclusive(1,3) will * return 2. * *

* if the upper-bound is null the range will be open ended upwards and * exclusive. *
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended downwards and * exclusive. *
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetweenExclusive(String lowerBound, StringResult upperBound) { return this.isBetweenExclusive(value(lowerBound), upperBound); } /** * Performs searches based on a range. * * if both ends of the range are specified both the lower- and upper-bound * will be excluded in the search. I.e permittedRangeExclusive(1,3) will * return 2. * *

* if the upper-bound is null the range will be open ended upwards and * exclusive. *
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended downwards and * exclusive. *
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetweenExclusive(StringResult lowerBound, String upperBound) { return this.isBetweenExclusive(lowerBound, value(upperBound)); } /** * Performs searches based on a range. * * if both ends of the range are specified both the lower- and upper-bound * will be excluded in the search. I.e permittedRangeExclusive(1,3) will * return 2. * *

* if the upper-bound is null the range will be open ended upwards and * exclusive. *
* I.e permittedRangeExclusive(1,null) will return 2,3,4,5, etc. * *

* if the lower-bound is null the range will be open ended downwards and * exclusive. *
* I.e permittedRangeExclusive(null, 5) will return 4,3,2,1, etc. * * @param lowerBound lowerBound * @param upperBound upperBound *

Support DBvolution at * Patreon

* @return a boolean expression representing the required comparison */ @Override public BooleanExpression isBetweenExclusive(String lowerBound, String upperBound) { return this.isBetweenExclusive(value(lowerBound), value(upperBound)); } /** * Creates a query comparison using the LESSTHAN operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isLessThan(String equivalentString) { return isLessThan(value(equivalentString)); } /** * Creates a query comparison using the LESSTHAN operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isLessThan(StringResult equivalentString) { if (equivalentString.getIncludesNull()) { return new BooleanExpression(this.isNull()); } else { return new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) { @Override protected String getEquationOperator(DBDefinition db) { return " < "; } @Override public boolean getIncludesNull() { return false; } }); } } /** * Creates a query comparison using the "<=" operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isLessThanOrEqual(String equivalentString) { return isLessThanOrEqual(value(equivalentString)); } /** * Creates a query comparison using the "<=" operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isLessThanOrEqual(StringResult equivalentString) { if (equivalentString.getIncludesNull()) { return new BooleanExpression(this.isNull()); } else { return new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) { @Override protected String getEquationOperator(DBDefinition db) { return " <= "; } @Override public boolean getIncludesNull() { return false; } }); } } /** * Creates a query comparison using the GREATERTHAN operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isGreaterThan(String equivalentString) { return isGreaterThan(value(equivalentString)); } /** * Creates a query comparison using the GREATERTHAN operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isGreaterThan(StringResult equivalentString) { if (equivalentString.getIncludesNull()) { return new BooleanExpression(this.isNotNull()); } else { return new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) { @Override protected String getEquationOperator(DBDefinition db) { return " > "; } @Override public boolean getIncludesNull() { return false; } }); } } /** * Creates a query comparison using the ">=" operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isGreaterThanOrEqual(String equivalentString) { return isGreaterThanOrEqual(value(equivalentString)); } /** * Creates a query comparison using the ">=" operator. * *

* Use this comparison to generate a BooleanExpression that compares the * current StringExpression to the supplied value. * * @param equivalentString equivalentString *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isGreaterThanOrEqual(StringResult equivalentString) { if (equivalentString.getIncludesNull()) { return this.is(equivalentString).not(); } else { return new BooleanExpression(new DBBinaryBooleanArithmetic(this, equivalentString) { @Override protected String getEquationOperator(DBDefinition db) { return " >= "; } @Override public boolean getIncludesNull() { return false; } }); } } /** * Creates a query comparison using the IN operator. * *

* Use this comparison to generate a BooleanExpression that indicates whether * the current StringExpression is included in the supplied values. * * @param possibleValues possibleValues *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isIn(String... possibleValues) { return isIn(expressions(possibleValues)); } /** * Creates a query comparison using the IN operator. * *

* Use this comparison to generate a BooleanExpression that indicates whether * the current StringExpression is included in the supplied values. * * @param possibleValues possibleValues *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ public BooleanExpression isIn(Collection possibleValues) { return isIn(expressions(possibleValues)); } /** * Creates a query comparison using the IN operator. * *

* Use this comparison to generate a BooleanExpression that indicates whether * the current StringExpression is included in the supplied values. * * @param possibleValues possibleValues *

Support DBvolution at * Patreon

* @return a BooleanExpression of the SQL comparison. */ @Override public BooleanExpression isIn(StringResult... possibleValues) { final BooleanExpression isInExpression = new BooleanExpression(new DBNnaryBooleanFunction(this, possibleValues) { @Override public String toSQLString(DBDefinition db) { List sqlValues = new ArrayList<>(); for (StringResult value : values) { if (!value.getIncludesNull()) { sqlValues.add(value.toSQLString(db)); } } return db.doInTransform(column.toSQLString(db), sqlValues); } @Override protected String getFunctionName(DBDefinition db) { return " IN "; } }); if (isInExpression.getIncludesNull()) { return BooleanExpression.anyOf(new BooleanExpression(this.isNull()), isInExpression); } else { return isInExpression; } } /** * Creates a query expression that appends the supplied value to the current * StringExpression. * * @param string2 string2 *

Support DBvolution at * Patreon

* @return a StringExpression. */ public StringExpression append(StringResult string2) { return new StringExpression(new DBBinaryStringArithmetic(this, string2) { @Override public String toSQLString(DBDefinition db) { return db.doConcatTransform(super.first.toSQLString(db), super.second.toSQLString(db)); } @Override protected String getEquationOperator(DBDefinition db) { return ""; } }); } /** * Creates a query expression that appends the supplied value to the current * StringExpression. * * @param string2 string2 *

Support DBvolution at * Patreon

* @return a StringExpression. */ public StringExpression append(String string2) { return this.append(StringExpression.value(string2)); } /** * Creates a query expression that appends the supplied value to the current * StringExpression. * * @param number1 number1 *

Support DBvolution at * Patreon

* @return a StringExpression. */ public StringExpression append(NumberResult number1) { return this.append(new NumberExpression(number1).stringResult()); } /** * Creates a query expression that appends the supplied value to the current * StringExpression. * * @param number1 number1 *

Support DBvolution at * Patreon

* @return a StringExpression. */ public StringExpression append(Number number1) { return this.append(NumberExpression.value(number1)); } /** * Creates a query expression that replaces the supplied value within the * current StringExpression. * * @param findString findString * @param replaceWith replaceWith *

Support DBvolution at * Patreon

* @return a StringExpression. */ public StringExpression replace(String findString, String replaceWith) { return this.replace(new StringExpression(findString), new StringExpression(replaceWith)); } /** * Creates a query expression that replaces the supplied value within the * current StringExpression. * * @param findString findString * @param replaceWith replaceWith *

Support DBvolution at * Patreon

* @return a StringExpression. */ public StringExpression replace(StringResult findString, String replaceWith) { return this.replace(findString, StringExpression.value(replaceWith)); } /** * Creates a query expression that replaces the supplied value within the * current StringExpression. * * @param findString findString * @param replaceWith replaceWith *

Support DBvolution at * Patreon

* @return a StringExpression. */ public StringExpression replace(String findString, StringResult replaceWith) { return this.replace(StringExpression.value(findString), replaceWith); } /** * Creates a query expression that replaces the supplied value within the * current StringExpression. * * @param findString findString * @param replaceWith replaceWith *

Support DBvolution at * Patreon

* @return a StringExpression. */ public StringExpression replace(StringResult findString, StringResult replaceWith) { StringResult replaceValue = replaceWith; if (replaceWith.getIncludesNull()) { replaceValue = StringExpression.value(""); } return new StringExpression( new DBTrinaryStringFunction(this, findString, replaceValue) { @Override public String toSQLString(DBDefinition db) { return db.doReplaceTransform( this.getFirst().toSQLString(db), this.getSecond().toSQLString(db), this.getThird().toSQLString(db)); } @Override String getFunctionName(DBDefinition db) { return "REPLACE"; } @Override public boolean getIncludesNull() { // handled before creation return false; } }); } /** * Retrieve the substring that precedes the supplied value. * *

* Complements {@link #substringAfter(java.lang.String) }. * *

* Within this expression, find the supplied value and return all characters * before the value, not including the value itself. * * @param splitBeforeThis the value marks the end of the required string. *

Support DBvolution at * Patreon

* @return a string expression */ public StringExpression substringBefore(String splitBeforeThis) { return substringBefore(value(splitBeforeThis)); } /** * Retrieve the substring that precedes the supplied value. * *

* Complements {@link #substringAfter(java.lang.String) }. * *

* Within this expression, find the supplied value and return all characters * before the value, not including the value itself. * * @param splitBeforeThis the value that marks the end of the required string *

Support DBvolution at * Patreon

* @return a string expression */ public StringExpression substringBefore(StringResult splitBeforeThis) { return new StringExpression(new DBBinaryStringFunction(this, new StringExpression(splitBeforeThis)) { @Override public String toSQLString(DBDefinition db) { try { return db.doSubstringBeforeTransform(getFirst().toSQLString(db), getSecond().toSQLString(db)); } catch (UnsupportedOperationException exp) { return getFirst().locationOf(getSecond()).isGreaterThan(0).ifThenElse(getFirst().substring(0, getFirst().locationOf(getSecond()).minus(1).integerResult()), value("")).toSQLString(db); } } }); } /** * Retrieve the substring that follows the supplied value. * *

* Complements {@link #substringBefore(java.lang.String) }. * *

* Within this expression, find the supplied value and return all characters * after the value, not including the value itself. * * @param splitAfterThis the value that marks the beginning of the required * string *

Support DBvolution at * Patreon

* @return a string expression */ public StringExpression substringAfter(String splitAfterThis) { return substringAfter(value(splitAfterThis)); } /** * Retrieve the substring that follows the supplied value. * *

* Complements {@link #substringBefore(java.lang.String) }. * *

* Within this expression, find the supplied value and return all characters * after the value, not including the value itself. * * @param splitAfterThis the value that marks the beginning of the required * string *

Support DBvolution at * Patreon

* @return a string expression */ public StringExpression substringAfter(StringResult splitAfterThis) { return new StringExpression(new DBBinaryStringFunction(this, new StringExpression(splitAfterThis)) { @Override public String toSQLString(DBDefinition db) { try { return db.doSubstringAfterTransform(getFirst().toSQLString(db), getSecond().toSQLString(db)); } catch (UnsupportedOperationException exp) { return getFirst().locationOf(getSecond()).isGreaterThan(0).ifThenElse(getFirst().substring(getFirst().locationOf(getSecond()).integerResult(), getFirst().length()), value("")).toSQLString(db); } } }); } /** * Retrieve the substring that follows the first supplied value but precedes * the second value. * *

* Complements {@link #substringBefore(java.lang.String) } and {@link #substringAfter(java.lang.String) * }. * *

* Within this expression, find the first supplied value and return all * characters after the value, not including the value itself, but prior to * the second value. * *

* for an expression like "(1234)", substringBetween("(", ")") will return * "1234". * * @param splitAfterThis the value that marks the beginning of the required * string * @param butBeforeThis the value that marks the end of the required string *

Support DBvolution at * Patreon

* @return a string expression */ public StringExpression substringBetween(String splitAfterThis, String butBeforeThis) { return substringBetween(value(splitAfterThis), value(butBeforeThis)); } /** * Retrieve the substring that follows the first supplied value but precedes * the second value. * *

* Complements {@link #substringBefore(java.lang.String) } and {@link #substringAfter(java.lang.String) * }. * *

* Within this expression, find the first supplied value and return all * characters after the value, not including the value itself, but prior to * the second value. * *

* for an expression like "(1234)", substringBetween("(", ")") will return * "1234". * * @param splitAfterThis the value that marks the beginning of the required * string * @param butBeforeThis the value that marks the end of the required string *

Support DBvolution at * Patreon

* @return a string expression */ public StringExpression substringBetween(StringResult splitAfterThis, StringResult butBeforeThis) { return substringAfter(splitAfterThis).substringBefore(butBeforeThis); } /** * Creates a query expression that trims all leading and trailing spaces from * the current StringExpression. * *

Support DBvolution at * Patreon

* * @return a StringExpression. */ public StringExpression trim() { return new StringExpression( new StringExpression(this) { @Override public String toSQLString(DBDefinition db) { return db.doTrimFunction(this.getInnerResult().toSQLString(db)); } }); } /** * Tests that a string expression is shorter than or equal to the specified * length. * *

* This method is useful to test strings will fit within a specific field * size

* * @param maxLength the longest possible number of characters *

Support DBvolution at * Patreon

* @return a StringExpression. */ public BooleanExpression isShorterThanOrAsLongAs(int maxLength) { return this.length().isLessThanOrEqual(maxLength); } /** * Finds and returns the first number in the string or NULL if no number is * found. * *

Support DBvolution at * Patreon

* * @return a StringExpression. */ public StringExpression getFirstNumberAsSubstring() { StringExpression exp = new StringExpression( new StringExpression(this) { @Override public String toSQLString(DBDefinition db) { return db.doFindNumberInStringTransform(this.getInnerResult().toSQLString(db)); } }); return exp; } /** * Finds and returns the first integer in the string or NULL if no integer is * found. * *

Support DBvolution at * Patreon

* * @return a StringExpression. */ public StringExpression getFirstIntegerAsSubstring() { final StringExpression exp = new StringExpression( new StringExpression(this) { @Override public String toSQLString(DBDefinition db) { return db.doFindIntegerInStringTransform(this.getInnerResult().toSQLString(db)); } }); return exp; } /** * Finds and returns the first number in the string or NULL if no number is * found. * *

Support DBvolution at * Patreon

* * @return a NumberExpression. */ public NumberExpression getFirstNumber() { return getFirstNumberAsSubstring().numberResult(); } /** * Finds and returns the first integer in the string or NULL if no integer is * found. * *

Support DBvolution at * Patreon

* * @return an IntegerExpression. */ public IntegerExpression getFirstInteger() { return getFirstIntegerAsSubstring().integerResult(); } /** * Creates a query expression that trims all leading spaces from the current * StringExpression. * *

Support DBvolution at * Patreon

* * @return a StringExpression. */ public StringExpression leftTrim() { return new StringExpression( new StringExpression(this) { @Override public String toSQLString(DBDefinition db) { return db.doLeftTrimTransform(this.getInnerResult().toSQLString(db)); } }); } /** * Creates a query expression that trims all trailing spaces from the current * StringExpression. * *

Support DBvolution at * Patreon

* * @return a StringExpression. */ public StringExpression rightTrim() { return new StringExpression( new StringExpression(this) { @Override public String toSQLString(DBDefinition defn) { return defn.getRightTrimFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")"; } }); } /** * Creates a query expression that changes all the letters in the current * StringExpression to lowercase. * *

Support DBvolution at * Patreon

* * @return a StringExpression. */ public StringExpression lowercase() { return new StringExpression( new StringExpression(this) { @Override public String toSQLString(DBDefinition defn) { return defn.getLowercaseFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")"; } }); } /** * Creates a query expression that changes all the letters in the current * StringExpression to UPPERCASE. * *

Support DBvolution at * Patreon

* * @return a StringExpression. */ public StringExpression uppercase() { return new StringExpression( new StringExpression(this) { @Override public String toSQLString(DBDefinition defn) { return defn.getUppercaseFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")"; } }); } /** * Create a substring of the current StringExpression starting from the * position supplied and continuing until the end of the string. * *

* The first character is at position zero (0). * * @param startingIndex0Based startingIndex0Based *

Support DBvolution at * Patreon

* @return a StringExpression */ public StringExpression substring(Integer startingIndex0Based) { return substring(NumberExpression.value(startingIndex0Based)); } /** * Create a substring of the current StringExpression starting from the * position supplied and continuing until the end of the string. * *

* The first character is at position zero (0). * * @param startingIndex0Based startingIndex0Based *

Support DBvolution at * Patreon

* @return a StringExpression */ public StringExpression substring(Long startingIndex0Based) { return substring(NumberExpression.value(startingIndex0Based)); } /** * Create a substring of the current StringExpression starting from the * position supplied and continuing until the end of the string. * *

* The first character is at position zero (0). * * @param startingIndex0Based startingIndex0Based *

Support DBvolution at * Patreon

* @return a StringExpression */ public StringExpression substring(IntegerResult startingIndex0Based) { return new Substring(this, startingIndex0Based); } /** * Create a substring of the current StringExpression starting from the * position supplied and continuing until the end position supplied.. * *

* The first character is at position zero (0). * * @param startingIndex0Based startingIndex0Based * @param endIndex0Based endIndex0Based *

Support DBvolution at * Patreon

* @return a StringExpression */ public StringExpression substring(Integer startingIndex0Based, Integer endIndex0Based) { return new Substring(this, startingIndex0Based, endIndex0Based); } /** * Create a substring of the current StringExpression starting from the * position supplied and continuing until the end position supplied.. * *

* The first character is at position zero (0). * * @param startingIndex0Based startingIndex0Based * @param endIndex0Based endIndex0Based *

Support DBvolution at * Patreon

* @return a StringExpression */ public StringExpression substring(Long startingIndex0Based, Long endIndex0Based) { return new Substring(this, startingIndex0Based, endIndex0Based); } /** * Create a substring of the current StringExpression starting from the * position supplied and continuing until the end position supplied.. * *

* The first character is at position zero (0). * * @param startingIndex0Based startingIndex0Based * @param endIndex0Based endIndex0Based *

Support DBvolution at * Patreon

* @return a StringExpression */ public StringExpression substring(IntegerResult startingIndex0Based, Integer endIndex0Based) { return new Substring(this, startingIndex0Based, value(endIndex0Based)); } /** * Create a substring of the current StringExpression starting from the * position supplied and continuing until the end position supplied.. * *

* The first character is at position zero (0). * * @param startingIndex0Based startingIndex0Based * @param endIndex0Based endIndex0Based *

Support DBvolution at * Patreon

* @return a StringExpression */ public StringExpression substring(IntegerResult startingIndex0Based, Long endIndex0Based) { return new Substring(this, startingIndex0Based, value(endIndex0Based)); } /** * Create a substring of the current StringExpression starting from the * position supplied and continuing until the end position supplied.. * *

* The first character is at position zero (0). * * @param startingIndex0Based startingIndex0Based * @param endIndex0Based endIndex0Based *

Support DBvolution at * Patreon

* @return a StringExpression */ public StringExpression substring(Integer startingIndex0Based, IntegerResult endIndex0Based) { return new Substring(this, value(startingIndex0Based), endIndex0Based); } /** * Create a substring of the current StringExpression starting from the * position supplied and continuing until the end position supplied.. * *

* The first character is at position zero (0). * * @param startingIndex0Based startingIndex0Based * @param endIndex0Based endIndex0Based *

Support DBvolution at * Patreon

* @return a StringExpression */ public StringExpression substring(Long startingIndex0Based, IntegerResult endIndex0Based) { return new Substring(this, value(startingIndex0Based), endIndex0Based); } /** * Create a substring of the current StringExpression starting from the * position supplied and continuing until the end position supplied.. * *

* The first character is at position zero (0). * * @param startingIndex0Based startingIndex0Based * @param endIndex0Based endIndex0Based *

Support DBvolution at * Patreon

* @return a StringExpression */ public StringExpression substring(IntegerResult startingIndex0Based, IntegerResult endIndex0Based) { return new Substring(this, startingIndex0Based, endIndex0Based); } /** * Create a expression that returns the length of the current expression. * *

Support DBvolution at * Patreon

* * @return a NumberExpression of the expression's length. */ public IntegerExpression length() { return new IntegerExpression( new IntegerExpression(this) { @Override public String toSQLString(DBDefinition db) { return db.doStringLengthTransform(getInnerResult().toSQLString(db)); } }); } /** * Create a {@link StringExpression} that returns the name of the current * user. * *

* This should be the current username under which the application is * accessing the database. * *

Support DBvolution at * Patreon

* * @return a StringExpression */ public static StringExpression currentUser() { return new StringExpression( new StringExpression() { @Override public String toSQLString(DBDefinition db) { return db.getCurrentUserFunctionName(); } @Override public boolean getIncludesNull() { return false; } @Override public boolean isPurelyFunctional() { return true; } }); } /** * Returns the 1-based index of the first occurrence of searchString within * the StringExpression. * *

* The index is 1-based, and returns 0 when the searchString is not found.

* * @param searchString searchString *

Support DBvolution at * Patreon

* @return an expression that will find the location of the searchString. */ public IntegerExpression locationOf(String searchString) { return locationOf(value(searchString)); } /** * Returns the 1-based index of the first occurrence of searchString within * the StringExpression. * *

* The index is 1-based, and returns 0 when the searchString is not found.

* * @param searchString searchString *

Support DBvolution at * Patreon

* @return an expression that will find the location of the searchString. */ public IntegerExpression locationOf(StringResult searchString) { return new NumberExpression(new BinaryComplicatedNumberFunction(this, searchString) { @Override public String toSQLString(DBDefinition db) { return db.doPositionInStringTransform(this.first.toSQLString(db), this.second.toSQLString(db)); } }).integerResult(); } /** * Creates an expression that will find the largest value in the column * supplied. * *

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

Support DBvolution at * Patreon

* * @return a String expression. */ public StringExpression max() { return new StringExpression( new StringExpression(this) { @Override public String toSQLString(DBDefinition defn) { return defn.getMaxFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")"; } @Override public boolean isAggregator() { return true; } }); } /** * Creates an expression that will find the smallest value in the column * supplied. * *

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

Support DBvolution at * Patreon

* * @return a String expression. */ public StringExpression min() { return new StringExpression(new StringExpression(this) { @Override public String toSQLString(DBDefinition defn) { return defn.getMinFunctionName() + "(" + getInnerResult().toSQLString(defn) + ")"; } @Override public boolean isAggregator() { return true; } }); } @Override public DBString getQueryableDatatypeForExpressionValue() { return new DBString(); } /** * Creates a BooleanExpression that tests to ensure the database value is not * a database NULL value. * *

* The expression will be true if the value is not NULL, and false otherwise. * *

Support DBvolution at * Patreon

* * @return a BooleanExpression */ public BooleanExpression isNotNull() { return BooleanExpression.isNotNull(this); } /** * Creates a BooleanExpression that tests to ensure the database value is not * a database NULL value AND is not an empty string. * *

* The expression will be true if the value is not NULL and is not an empty * string, and false otherwise. * *

* This method provides the maximum portability as some database differentiate * between a NULL string and a empty string, and some do not. To protect your * queries against this fundamental variation use this method. * *

Support DBvolution at * Patreon

* * @return a BooleanExpression */ public BooleanExpression isNotNullAndNotEmpty() { return BooleanExpression.allOf( BooleanExpression.isNotNull(this), this.isNot("") ); } /** * Creates a BooleanExpression that tests to ensure the database value is a * database NULL value. * *

* The expression will be true if the value is NULL, and false otherwise. * *

Support DBvolution at * Patreon

* * @return a BooleanExpression */ public BooleanExpression isNull() { return BooleanExpression.isNull(this); } /** * Creates a BooleanExpression that tests to ensure the database value is a * database NULL value OR is an empty string. * *

* The expression will be true if the value is NULL OR the expression produces * an empty string, and false otherwise. * *

* This method provides the maximum portability as some database differentiate * between a NULL string and a empty string, and some do not. To protect your * queries against this fundamental variation use this method. * *

Support DBvolution at * Patreon

* * @return a BooleanExpression */ public BooleanExpression isNullOrEmpty() { return BooleanExpression.anyOf( BooleanExpression.isNull(this), this.is("") ); } /** * Adds an explicit bracket at this point in the expression chain. * *

Support DBvolution at * Patreon

* * @return a StringExpression that will have the current expression wrapped in * brackets. */ public StringExpression bracket() { return new StringExpression(new StringExpression(this) { @Override public String toSQLString(DBDefinition defn) { return "(" + getInnerResult().toSQLString(defn) + ")"; } }); } /** * Provides direct access to the IN operator. * *

* isInIgnoreCase creates a BooleanExpression that compares the current * expression to the list of values using the IN operator. The resulting * expression will return true if the current expression's value is included * in the list of potential values, otherwise it will return false. * * @param potentialValues potentialValues *

Support DBvolution at * Patreon

* @return a BooleanExpression */ public BooleanExpression isInIgnoreCase(String... potentialValues) { return this.isInIgnoreCase(expressions(potentialValues)); } public StringResult[] expressions(String... potentialValues) { List possVals = new ArrayList<>(0); for (String str : potentialValues) { if (str == null) { possVals.add(nullString()); } else { possVals.add(StringExpression.value(str)); } } return possVals.toArray(new StringResult[]{}); } public StringResult[] expressions(Collection potentialValues) { List possVals = new ArrayList<>(0); for (String str : potentialValues) { if (str == null) { possVals.add(nullString()); } else { possVals.add(StringExpression.value(str)); } } return possVals.toArray(new StringResult[]{}); } /** * Provides direct access to the IN operator. * *

* isInIgnoreCase creates a BooleanExpression that compares the current * expression to the list of values using the IN operator. The resulting * expression will return true if the current expression's value is included * in the list of potential values, otherwise it will return false. * * @param potentialValues potentialValues *

Support DBvolution at * Patreon

* @return a BooleanExpression */ public BooleanExpression isInIgnoreCase(Collection potentialValues) { return this.isInIgnoreCase(expressions(potentialValues)); } /** * Provides direct access to the IN operator. * *

* isInIgnoreCase creates a BooleanExpression that compares the current * expression to the list of values using the IN operator. The resulting * expression will return true if the current expression's value is included * in the list of potential values, otherwise it will return false. * * @param potentialValues potentialValues *

Support DBvolution at * Patreon

* @return a BooleanExpression */ public BooleanExpression isInIgnoreCase(StringResult... potentialValues) { List lowerStrings = new ArrayList<>(); for (StringResult toArray1 : potentialValues) { StringExpression lowercase = new StringExpression(toArray1).lowercase(); lowerStrings.add(lowercase); } final BooleanExpression isInExpression = this.lowercase().isIn(lowerStrings.toArray(new StringResult[]{})); if (isInExpression.getIncludesNull()) { return BooleanExpression.anyOf(new BooleanExpression(this.isNull()), isInExpression); } else { return isInExpression; } } /** * In so far as it is possible, transform the value of this expression into a * number. * *

* You should probably use {@link #getFirstNumber() } or {@link #getFirstNumber() * } instead as they are more reliable.

* *

* Uses the database's own facilities to parse the value of this expression * into a number. * *

* May return NULL and all sorts of crazy things. * *

Support DBvolution at * Patreon

* * @return a number expression */ public NumberExpression numberResult() { return new NumberExpression( new NumberExpression(this) { @Override public String toSQLString(DBDefinition db) { return db.doStringToNumberTransform(getInnerResult().toSQLString(db)); } }); } /** * In so far as it is possible, transform the value of this expression into a * number. * *

* Uses the database's own facilities to parse the value of this expression * into a number. * *

* May return NULL and all sorts of crazy things. * *

Support DBvolution at * Patreon

* * @return a number expression */ public IntegerExpression integerResult() { return this.numberResult().isNotNull() .ifThenElse(this.numberResult().integerResult(), nullInteger()); } @Override public DBString asExpressionColumn() { return new DBString(this); } @Override public StringExpression stringResult() { return this; } @Override public StringResult expression(DBString value) { return new StringExpression(value); } private static abstract class DBBinaryStringArithmetic extends StringExpression { private StringResult first; private StringResult second; DBBinaryStringArithmetic(StringResult first, StringResult second) { this.first = first; this.second = second; } @Override public DBString getQueryableDatatypeForExpressionValue() { return new DBString(); } @Override public String toSQLString(DBDefinition db) { return first.toSQLString(db) + this.getEquationOperator(db) + second.toSQLString(db); } @Override public DBBinaryStringArithmetic copy() { DBBinaryStringArithmetic newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.first = first.copy(); newInstance.second = second.copy(); return newInstance; } protected abstract String getEquationOperator(DBDefinition db); @Override public Set getTablesInvolved() { HashSet hashSet = new HashSet<>(); if (first != null) { hashSet.addAll(first.getTablesInvolved()); } if (second != null) { hashSet.addAll(second.getTablesInvolved()); } return hashSet; } @Override public boolean isAggregator() { return this.first.isAggregator() || second.isAggregator(); } @Override public boolean isPurelyFunctional() { if (first == null && second == null) { return true; } else if (first == null) { return second.isPurelyFunctional(); } else if (second == null) { return first.isPurelyFunctional(); } else { return first.isPurelyFunctional() && second.isPurelyFunctional(); } } } private static abstract class DBTrinaryStringFunction extends StringExpression { private DBExpression first; private DBExpression second; private DBExpression third; DBTrinaryStringFunction(DBExpression first) { this.first = first; this.second = null; this.third = null; } DBTrinaryStringFunction(DBExpression first, DBExpression second) { this.first = first; this.second = second; } DBTrinaryStringFunction(DBExpression first, DBExpression second, DBExpression third) { this.first = first; this.second = second; this.third = third; } @Override public DBString getQueryableDatatypeForExpressionValue() { return new DBString(); } @Override public String toSQLString(DBDefinition db) { return this.beforeValue(db) + getFirst().toSQLString(db) + this.getSeparator(db) + (getSecond() == null ? "" : getSecond().toSQLString(db)) + this.getSeparator(db) + (getThird() == null ? "" : getThird().toSQLString(db)) + this.afterValue(db); } @Override public DBTrinaryStringFunction copy() { DBTrinaryStringFunction newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.first = getFirst() == null ? null : getFirst().copy(); newInstance.second = getSecond() == null ? null : getSecond().copy(); newInstance.third = getThird() == null ? null : getThird().copy(); return newInstance; } abstract String getFunctionName(DBDefinition db); protected String beforeValue(DBDefinition db) { return " " + getFunctionName(db) + "( "; } protected String getSeparator(DBDefinition db) { return ", "; } protected String afterValue(DBDefinition db) { return ") "; } @Override public Set getTablesInvolved() { HashSet hashSet = new HashSet<>(); if (getFirst() != null) { hashSet.addAll(getFirst().getTablesInvolved()); } if (getSecond() != null) { hashSet.addAll(getSecond().getTablesInvolved()); } if (getThird() != null) { hashSet.addAll(getThird().getTablesInvolved()); } return hashSet; } @Override public boolean isAggregator() { return getFirst().isAggregator() || getSecond().isAggregator() || getThird().isAggregator(); } /** *

Support DBvolution at * Patreon

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

Support DBvolution at * Patreon

* * @return the second */ protected DBExpression getSecond() { return second; } /** *

Support DBvolution at * Patreon

* * @return the third */ protected DBExpression getThird() { return third; } @Override public boolean isPurelyFunctional() { if (first == null && second == null && third == null) { return true; } else if (first == null) { return second.isPurelyFunctional(); } else if (second == null) { return first.isPurelyFunctional(); } else { return first.isPurelyFunctional() && second.isPurelyFunctional() && third.isPurelyFunctional(); } } } private static abstract class DBBinaryStringFunction extends StringExpression { private StringExpression first; private StringExpression second; DBBinaryStringFunction(StringExpression first) { this.first = first; this.second = null; } DBBinaryStringFunction(StringExpression first, StringExpression second) { this.first = first; this.second = second; } @Override public DBString getQueryableDatatypeForExpressionValue() { return new DBString(); } @Override public DBBinaryStringFunction copy() { DBBinaryStringFunction newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.first = getFirst() == null ? null : getFirst().copy(); newInstance.second = getSecond() == null ? null : getSecond().copy(); return newInstance; } @Override public Set getTablesInvolved() { HashSet hashSet = new HashSet<>(); if (getFirst() != null) { hashSet.addAll(getFirst().getTablesInvolved()); } if (getSecond() != null) { hashSet.addAll(getSecond().getTablesInvolved()); } return hashSet; } @Override public boolean isAggregator() { return getFirst().isAggregator() || getSecond().isAggregator(); } /** *

Support DBvolution at * Patreon

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

Support DBvolution at * Patreon

* * @return the second */ protected StringExpression getSecond() { return second; } @Override public boolean isPurelyFunctional() { if (first == null && second == null) { return true; } else if (first == null) { return second.isPurelyFunctional(); } else if (second == null) { return first.isPurelyFunctional(); } else { return first.isPurelyFunctional() && second.isPurelyFunctional(); } } } private static abstract class BinaryComplicatedNumberFunction extends NumberExpression { protected StringExpression first = null; protected StringResult second = null; BinaryComplicatedNumberFunction() { this.first = null; } BinaryComplicatedNumberFunction(StringExpression first, StringResult second) { this.first = first; this.second = second; } @Override public DBNumber getQueryableDatatypeForExpressionValue() { return new DBNumber(); } @Override public abstract String toSQLString(DBDefinition db); @Override public StringExpression.BinaryComplicatedNumberFunction copy() { StringExpression.BinaryComplicatedNumberFunction newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.first = first.copy(); newInstance.second = second.copy(); return newInstance; } @Override public Set getTablesInvolved() { HashSet hashSet = new HashSet<>(); if (first != null) { hashSet.addAll(first.getTablesInvolved()); } if (second != null) { hashSet.addAll(second.getTablesInvolved()); } return hashSet; } @Override public boolean isAggregator() { return first.isAggregator() || second.isAggregator(); } @Override public boolean getIncludesNull() { return false; } @Override public boolean isPurelyFunctional() { if (first == null && second == null) { return true; } else if (first == null) { return second.isPurelyFunctional(); } else if (second == null) { return first.isPurelyFunctional(); } else { return first.isPurelyFunctional() && second.isPurelyFunctional(); } } } private class Substring extends StringExpression { private IntegerResult startingPosition; private IntegerResult length; Substring(StringResult stringInput, Long startingIndex0Based) { super(stringInput); this.startingPosition = value(startingIndex0Based); this.length = new StringExpression(stringInput).length(); } Substring(StringResult stringInput, Integer startingIndex0Based) { super(stringInput); this.startingPosition = value(startingIndex0Based); this.length = new StringExpression(stringInput).length(); } Substring(StringResult stringInput, IntegerResult startingIndex0Based) { super(stringInput); this.startingPosition = startingIndex0Based.copy(); this.length = value(stringInput).length(); } Substring(StringResult stringInput, Long startingIndex0Based, Long endIndex0Based) { super(stringInput); this.startingPosition = value(startingIndex0Based); this.length = value(endIndex0Based); } Substring(StringResult stringInput, Integer startingIndex0Based, Integer endIndex0Based) { super(stringInput); this.startingPosition = value(startingIndex0Based); this.length = value(endIndex0Based); } Substring(StringResult stringInput, IntegerResult startingIndex0Based, IntegerResult endIndex0Based) { super(stringInput); this.startingPosition = startingIndex0Based.copy(); this.length = endIndex0Based.copy(); } private Substring(AnyResult stringInput, IntegerResult startingIndex0Based, IntegerResult endIndex0Based) { super(stringInput.stringResult()); this.startingPosition = startingIndex0Based.copy(); this.length = endIndex0Based.copy(); } @Override public Substring copy() { return new Substring(getInnerResult(), startingPosition, length); } @Override public String toSQLString(DBDefinition db) { if (getInnerResult() == null) { return ""; } else { return doSubstringTransform(db, getInnerResult(), startingPosition, length); } } public String doSubstringTransform(DBDefinition db, AnyResult enclosedValue, IntegerResult startingPosition, IntegerResult substringLength) { return db.doSubstringTransform( enclosedValue.stringResult().toSQLString(db), (startingPosition.toSQLString(db) + " + 1"), (substringLength != null ? (substringLength.toSQLString(db) + " - " + startingPosition.toSQLString(db)) : "") ); } @Override public DBString getQueryableDatatypeForExpressionValue() { return new DBString(); } @Override public boolean getIncludesNull() { return false; } @Override public boolean isPurelyFunctional() { final AnyResult string1 = getInnerResult(); if (startingPosition == null && length == null && string1 == null) { return true; } else { return (startingPosition == null || startingPosition.isPurelyFunctional()) && (length == null || length.isPurelyFunctional()) && (string1 == null || string1.isPurelyFunctional()); } } } private static abstract class DBBinaryBooleanArithmetic extends BooleanExpression { protected StringResult first; protected StringResult second; DBBinaryBooleanArithmetic(StringResult first, StringResult second) { this.first = first; this.second = second; } @Override public String toSQLString(DBDefinition db) { return first.toSQLString(db) + this.getEquationOperator(db) + second.toSQLString(db); } @Override public DBBinaryBooleanArithmetic copy() { DBBinaryBooleanArithmetic newInstance; try { newInstance = getClass().newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } newInstance.first = first.copy(); newInstance.second = second.copy(); return newInstance; } protected abstract String getEquationOperator(DBDefinition db); @Override public Set getTablesInvolved() { HashSet hashSet = new HashSet<>(); if (first != null) { hashSet.addAll(first.getTablesInvolved()); } if (second != null) { hashSet.addAll(second.getTablesInvolved()); } return hashSet; } @Override public boolean isAggregator() { return first.isAggregator() || second.isAggregator(); } } private static abstract class DBNnaryBooleanFunction extends BooleanExpression { protected final StringExpression column; protected final List values = new ArrayList<>(); private final boolean includesNulls; DBNnaryBooleanFunction() { column = null; includesNulls = false; } DBNnaryBooleanFunction(StringExpression leftHandSide, StringResult[] rightHandSide) { this.column = leftHandSide; boolean nulls = false; for (StringResult stringResult : rightHandSide) { if (stringResult == null) { nulls = true; } else if (stringResult.getIncludesNull()) { nulls = true; } else { values.add(stringResult); } } includesNulls = nulls; } abstract String getFunctionName(DBDefinition db); protected String beforeValue(DBDefinition db) { return "( "; } protected String afterValue(DBDefinition db) { return ") "; } @Override public String toSQLString(DBDefinition db) { StringBuilder builder = new StringBuilder(); builder .append(column.toSQLString(db)) .append(this.getFunctionName(db)) .append(this.beforeValue(db)); String separator = ""; for (StringResult val : values) { if (val != null) { builder.append(separator).append(val.toSQLString(db)); } separator = ", "; } builder.append(this.afterValue(db)); return builder.toString(); } @Override public Set getTablesInvolved() { HashSet hashSet = new HashSet<>(); if (column != null) { hashSet.addAll(column.getTablesInvolved()); } for (StringResult second : values) { if (second != null) { hashSet.addAll(second.getTablesInvolved()); } } return hashSet; } @Override public boolean isAggregator() { boolean result = column.isAggregator(); for (StringResult numer : values) { result = result || numer.isAggregator(); } return result; } @Override public boolean getIncludesNull() { return includesNulls; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy