blob: 3ff87166ec1e3f54d700ea46d1a871cacde9ff6c [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// 05/24/2011-2.3 Guy Pelletier
// - 345962: Join fetch query when using tenant discriminator column fails.
package org.eclipse.persistence.expressions;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.history.AsOfClause;
import org.eclipse.persistence.internal.expressions.ArgumentListFunctionExpression;
import org.eclipse.persistence.internal.expressions.BaseExpression;
import org.eclipse.persistence.internal.expressions.CollectionExpression;
import org.eclipse.persistence.internal.expressions.ConstantExpression;
import org.eclipse.persistence.internal.expressions.ExpressionIterator;
import org.eclipse.persistence.internal.expressions.ExpressionJavaPrinter;
import org.eclipse.persistence.internal.expressions.ExpressionNormalizer;
import org.eclipse.persistence.internal.expressions.ExpressionSQLPrinter;
import org.eclipse.persistence.internal.expressions.FunctionExpression;
import org.eclipse.persistence.internal.expressions.LiteralExpression;
import org.eclipse.persistence.internal.expressions.MapEntryExpression;
import org.eclipse.persistence.internal.expressions.ParameterExpression;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.internal.expressions.SubSelectExpression;
import org.eclipse.persistence.internal.expressions.TableAliasLookup;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.localization.ToStringLocalization;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.queries.ReportQuery;
/**
* <p>
* <b>Purpose</b>: Define an object-level representation of a database query where clause.</p>
* <p>
* <b>Description</b>: An expression is a tree-like structure that defines the selection
* criteria for a query against objects in the database. The expression has the advantage
* over SQL by being at the object-level, i.e. the object model attributes and relationships
* can be used to be query on instead of the database field names.
* Because it is an object, not a string the expression has the advantage that is can be
* easily manipulated through code to easily build complex selection criterias.</p>
* <p>
* <b>Responsibilities</b>:
* <ul>
* <li> Store the selection criteria in a tree-like structure.
* <li> Support public manipulation protocols for all comparison and function operators.
* <li> Use operator overloading to support all primitive types as well as objects.
* </ul>
*/
public abstract class Expression implements Serializable, Cloneable {
/** Required for serialization compatibility. */
static final long serialVersionUID = -5979150600092006081L;
/** Temporary values for table aliasing */
protected transient DatabaseTable lastTable;
protected transient DatabaseTable currentAlias;
protected boolean selectIfOrderedBy = true;
/** PERF: Cache the hashCode. */
protected int hashCode = 0;
/** Use the upper() function for case insensitive expression operations (default).
Seting this flag to false will use the lower() function instead. */
public static boolean shouldUseUpperCaseForIgnoreCase = true;
/**
* Base Expression Constructor. Not generally used by Developers
*/
protected Expression() {
super();
}
/**
* PUBLIC:
* Function, return an expression that adds to a date based on
* the specified datePart. This is equivalent to the Sybase DATEADD function.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("date").addDate("year", 2)
* Java: NA
* SQL: DATEADD(date, 2, year)
* </pre></blockquote>
*/
public Expression addDate(String datePart, int numberToAdd) {
return addDate(datePart, Integer.valueOf(numberToAdd));
}
/**
* PUBLIC:
* Function, return an expression that adds to a date based on
* the specified datePart. This is equivalent to the Sybase DATEADD function.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("date").addDate("year", 2)
* Java: NA
* SQL: DATEADD(date, 2, year)
* </pre></blockquote>
*/
public Expression addDate(String datePart, Object numberToAdd) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.AddDate);
List args = new ArrayList(2);
args.add(Expression.fromLiteral(datePart, this));
args.add(numberToAdd);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Function, to add months to a date.
*/
public Expression addMonths(int months) {
return addMonths(Integer.valueOf(months));
}
/**
* PUBLIC:
* Function, to add months to a date.
*/
public Expression addMonths(Object months) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.AddMonths);
return anOperator.expressionFor(this, months);
}
/**
* INTERNAL:
* Find the alias for a given table
*/
public DatabaseTable aliasForTable(DatabaseTable table) {
return null;
}
/**
* PUBLIC: Returns an expression equivalent to all of <code>attributeName</code>
* holding true for <code>criteria</code>.
* <p>
* For every expression with an anyOf, its negation has either an allOf or a
* noneOf. The following two examples will illustrate as the second is the
* negation of the first:
* <p>
* AnyOf Example: Employees with a non '613' area code phone number.
* <blockquote><pre>
* ReadAllQuery query = new ReadAllQuery(Employee.class);
* ExpressionBuilder employee = new ExpressionBuilder();
* Expression exp = employee.anyOf("phoneNumbers").get("areaCode").notEqual("613");
* </pre></blockquote>
* <p>
* AllOf Example: Employees with all '613' area code phone numbers.
* <blockquote><pre>
* ExpressionBuilder employee = new ExpressionBuilder();
* ExpressionBuilder phones = new ExpressionBuilder();
* Expression exp = employee.allOf("phoneNumbers", phones.get("areaCode").equal("613"));
* SQL:
* SELECT ... EMPLOYEE t0 WHERE NOT EXISTS (SELECT ... PHONE t1 WHERE
* (t0.EMP_ID = t1.EMP_ID) AND NOT (t1.AREACODE = '613'))
* </pre></blockquote>
* <p>
* allOf is the universal counterpart to the existential anyOf. To have the
* condition evaluated for each instance it must be put inside of a subquery,
* which can be expressed as not exists (any of attributeName some condition).
* (All x such that y = !Exist x such that !y).
* <p>Likewise the syntax employee.allOf("phoneNumbers").get("areaCode").equal("613")
* is not supported for the <pre>equal</pre> must go inside a subQuery.
* <p>
* This method saves you from writing the sub query yourself. The above is
* equivalent to the following expression:
* <blockquote><pre>
* ExpressionBuilder employee = new ExpressionBuilder();
* ExpressionBuilder phone = new ExpressionBuilder();
* ReportQuery subQuery = new ReportQuery(Phone.class, phone);
* subQuery.retreivePrimaryKeys();
* subQuery.setSelectionCriteria(phone.equal(employee.anyOf("phoneNumbers").and(
* phone.get("areaCode").notEqual("613")));
* Expression exp = employee.notExists(subQuery);
* </pre></blockquote>
* <p>
* Note if employee has no phone numbers allOf ~ noneOf.
* @param criteria must have its own builder, as it will become the
* separate selection criteria of a subQuery.
* @return a notExists subQuery expression
*/
public Expression allOf(String attributeName, Expression criteria) {
ReportQuery subQuery = new ReportQuery();
subQuery.setShouldRetrieveFirstPrimaryKey(true);
Expression builder = criteria.getBuilder();
criteria = builder.equal(anyOf(attributeName)).and(criteria.not());
subQuery.setSelectionCriteria(criteria);
return notExists(subQuery);
}
/**
* PUBLIC:
* Return an expression that is the boolean logical combination of both expressions.
* This is equivalent to the SQL "AND" operator and the Java {@literal "&&"} operator.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").equal("Bob").and(employee.get("lastName").equal("Smith"))
* Java: (employee.getFirstName().equals("Bob")) {@literal &&} (employee.getLastName().equals("Smith"))
* SQL: F_NAME = 'Bob' AND L_NAME = 'Smith'
* </pre></blockquote>
*/
public Expression and(Expression theExpression) {
// Allow ands with null.
if (theExpression == null) {
return this;
}
ExpressionBuilder base = getBuilder();
Expression expressionToUse = theExpression;
// Ensure the same builder, unless a parralel query is used.
// For flashback added an extra condition: if left side is a 'NullExpression'
// then rebuild on it regardless.
if ((theExpression.getBuilder() != base) && ((base == this) || (theExpression.getBuilder().getQueryClass() == null))) {
expressionToUse = theExpression.rebuildOn(base);
}
if (base == this) {// Allow and to be sent to the builder.
return expressionToUse;
}
ExpressionOperator anOperator = getOperator(ExpressionOperator.And);
return anOperator.expressionFor(this, expressionToUse);
}
/**
* PUBLIC:
* Return an expression representing traversal of a 1:many or many:many relationship.
* This allows you to query whether any of the "many" side of the relationship satisfies the remaining criteria.
* <p>Example:
* </p>
* <table>
* <caption>This table compares an example EclipseLink anyOf Expression to Java and SQL</caption>
* <tr>
* <th id="c1">Format</th>
* <th id="c2">Equivalent</th>
* </tr>
* <tr>
* <td headers="c1">EclipseLink</td>
* <td headers="c2">
* <pre>
* ReadAllQuery query = new ReadAllQuery(Employee.class);<br>
* ExpressionBuilder builder = new ExpressionBuilder();<br>
* Expression exp = builder.get("id").equal("14858");<br>
* exp = exp.or(builder.anyOf("managedEmployees").get("firstName").equal("Bob"));<br>
* </pre>
* </td>
* </tr>
* <tr>
* <td headers="c1">Java</td>
* <td headers="c2">No direct equivalent</td>
* </tr>
* <tr>
* <td headers="c1">SQL</td>
* <td headers="c2">SELECT DISTINCT ... WHERE (t2.MGR_ID (+) = t1.ID) AND (t2.F_NAME = 'Bob')</td>
* </tr>
* </table>
*/
public Expression anyOf(String attributeName) {
return anyOf(attributeName, true);
}
/**
* ADVANCED:
* Return an expression representing traversal of a 1:many or many:many relationship.
* This allows you to query whether any of the "many" side of the relationship satisfies the remaining criteria.
* <p>Example:
* </p>
* <table>
* <caption>This table compares an example EclipseLink anyOf Expression to Java and SQL</caption>
* <tr>
* <th id="c3">Format</th>
* <th id="c4">Equivalent</th>
* </tr>
* <tr>
* <td headers="c3">EclipseLink</td>
* <td headers="c4">
* <pre>
* ReadAllQuery query = new ReadAllQuery(Employee.class);<br>
* ExpressionBuilder builder = new ExpressionBuilder();<br>
* Expression exp = builder.get("id").equal("14858");<br>
* exp = exp.or(builder.anyOf("managedEmployees").get("firstName").equal("Bob"));<br>
* </pre>
* </td>
* </tr>
* <tr>
* <td headers="c3">Java</td>
* <td headers="c4">No direct equivalent</td>
* </tr>
* <tr>
* <td headers="c3">SQL</td>
* <td headers="c4">SELECT DISTINCT ... WHERE (t2.MGR_ID (+) = t1.ID) AND (t2.F_NAME = 'Bob')</td>
* </tr>
* </table>
* @param shouldJoinBeIndependent indicates whether a new expression should be created.
*/
public Expression anyOf(String attributeName, boolean shouldJoinBeIndependent) {
throw new UnsupportedOperationException("anyOf");
}
/**
* ADVANCED:
* Return an expression representing traversal of a 1:many or many:many relationship.
* This allows you to query whether any of the "many" side of the relationship satisfies the remaining criteria.
* This version of the anyOf operation performs an outer join.
* Outer joins allow the join to performed even if the target of the relationship is empty.
* NOTE: outer joins are not supported on all database and have differing semantics.
* <p>Example:
* </p>
* <table>
* <caption>This table compares an example EclipseLink anyOfAllowingNone Expression to Java and SQL</caption>
* <tr>
* <th id="c5">Format</th>
* <th id="c6">Equivalent</th>
* </tr>
* <tr>
* <td headers="c5">EclipseLink</td>
* <td headers="c6">
* <pre>
* ReadAllQuery query = new ReadAllQuery(Employee.class);<br>
* ExpressionBuilder builder = new ExpressionBuilder();<br>
* Expression exp = builder.get("id").equal("14858");<br>
* exp = exp.or(builder.anyOfAllowingNone("managedEmployees").get("firstName").equal("Bob"));<br>
* </pre>
* </td>
* </tr>
* <tr>
* <td headers="c5">Java</td>
* <td headers="c6">No direct equivalent</td>
* </tr>
* <tr>
* <td headers="c5">SQL</td>
* <td headers="c6">SELECT DISTINCT ... WHERE (t2.MGR_ID (+) = t1.ID) AND (t2.F_NAME = 'Bob')</td>
* </tr>
* </table>
*/
public Expression anyOfAllowingNone(String attributeName) {
return anyOfAllowingNone(attributeName, true);
}
/**
* ADVANCED:
* Return an expression representing traversal of a 1:many or many:many relationship.
* This allows you to query whether any of the "many" side of the relationship satisfies the remaining criteria.
* This version of the anyOf operation performs an outer join.
* Outer joins allow the join to performed even if the target of the relationship is empty.
* NOTE: outer joins are not supported on all database and have differing semantics.
* <p>Example:
* </p>
* <table>
* <caption>This table compares an example EclipseLink anyOfAllowingNone Expression to Java and SQL</caption>
* <tr>
* <th id="c7">Format</th>
* <th id="c8">Equivalent</th>
* </tr>
* <tr>
* <td headers="c7">EclipseLink</td>
* <td headers="c8">
* <pre>
* ReadAllQuery query = new ReadAllQuery(Employee.class);<br>
* ExpressionBuilder builder = new ExpressionBuilder();<br>
* Expression exp = builder.get("id").equal("14858");<br>
* exp = exp.or(builder.anyOfAllowingNone("managedEmployees").get("firstName").equal("Bob"));<br>
* </pre>
* </td>
* </tr>
* <tr>
* <td headers="c7">Java</td>
* <td headers="c8">No direct equivalent</td>
* </tr>
* <tr>
* <td headers="c7">SQL</td>
* <td headers="c8">SELECT DISTINCT ... WHERE (t2.MGR_ID (+) = t1.ID) AND (t2.F_NAME = 'Bob')</td>
* </tr>
* </table>
* @param shouldJoinBeIndependent indicates whether a new expression should be created.
*/
public Expression anyOfAllowingNone(String attributeName, boolean shouldJoinBeIndependent) {
throw new UnsupportedOperationException("anyOfAllowingNone");
}
/**
* ADVANCED:
* Assign an alias to the expression in the select clause.
*/
public Expression as(String alias) {
ExpressionOperator operator = getOperator(ExpressionOperator.As);
return operator.expressionFor(this, literal(alias));
}
/**
* ADVANCED:
* Return an expression that allows you to treat its base as if it were a subclass of the class returned by the base
* This can only be called on an ExpressionBuilder, the result of expression.get(String), expression.getAllowingNull(String),
* the result of expression.anyOf("String") or the result of expression.anyOfAllowingNull("String")
*
* downcast uses Expression.type() internally to guarantee the results are of the specified class.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("project").treat(LargeProject.class).get("budget").equal(1000)
* Java: ((LargeProject)employee.getProjects().get(0)).getBudget() == 1000
* SQL: LPROJ.PROJ_ID (+)= PROJ.PROJ_ID AND L_PROJ.BUDGET = 1000 AND PROJ.TYPE = "L"
* </pre></blockquote>
*/
public Expression treat(Class castClass) {
return this;
}
/**
* PUBLIC:
* This can only be used within an ordering expression.
* It will order the result ascending.
* Example:
* <blockquote><pre>
* readAllQuery.addOrderBy(expBuilder.get("address").get("city").ascending())
* </pre></blockquote>
*/
public Expression ascending() {
return getFunction(ExpressionOperator.Ascending);
}
/**
* PUBLIC:
* This can only be used within an ordering expression.
* Null results will be ordered first.
* Example:
* <blockquote><pre>
* readAllQuery.addOrderBy(expBuilder.get("address").get("city").ascending().nullsFirst())
* </pre></blockquote>
*/
public Expression nullsFirst() {
return getFunction(ExpressionOperator.NullsFirst);
}
/**
* PUBLIC:
* This can only be used within an ordering expression.
* Null results will be ordered last.
* Example:
* <blockquote><pre>
* readAllQuery.addOrderBy(expBuilder.get("address").get("city").ascending().nullsLast())
* </pre></blockquote>
*/
public Expression nullsLast() {
return getFunction(ExpressionOperator.NullsLast);
}
/**
* PUBLIC:
* Function, returns the single character strings ascii value.
*/
public Expression asciiValue() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Ascii);
return anOperator.expressionFor(this);
}
/**
* Sets all tables represented by this expression to be queried as of a past
* time.
* <p>
* Example:
* </p>
* <pre>
* EclipseLink: employee.asOf(new AsOfClause(pastTime))
* Java: None
* SQL (Flashback): SELECT ... FROM EMPLOYEE AS OF TIMESTAMP (pastTime) t0 ...
* SQL (Generic): .. WHERE (t1.START {@literal <=} pastTime) AND ((t1.END IS NULL) OR t1.END {@literal >} pastTime)
* </pre>
* <p>
* Set an as of clause at the expression level to still query for current objects
* while expressing selection criteria like:
* <ul>
* <li>query objects as of one time that met some condition at another time.
* <li>query objects that changed a certain way over a certain interval (querying for change).
* </ul>
* <p>
* Simultaneously querying on two versions of the same object (one past
* one present) lets you express these advanced selection criteria.
* <p>
* Example: Querying on past attributes using parallel expressions.
* </p>
* <blockquote><pre>
* // Finds all employees who lived in Ottawa as of a past time.
* ExpressionBuilder employee = new ExpressionBuilder();
* ExpressionBuilder pastEmployee = new ExpressionBuilder(Employee.class);
* pastEmployee.asOf(pastTime);
* Expression pastAddress = pastEmployee.get("address"); // by default address will also be as of past time.
* Expression selectionCriteria = pastAddress.get("city").equal("Ottawa").and(
* employee.equal(pastEmployee));
* </pre></blockquote>
* <p>
* The advantage of the parallel expression is that you can still read current
* objects, the as of clause will affect only the where clause / selection criteria.
* <p>
* You may be tempted to rewrite the above as employee.get("address").asOf(pastTime).
* That is allowed but see below for the finer points involved in this.
* <p>
* Example: Querying on object changes using parallel expressions.
* </p>
* <blockquote><pre>
* // Finds all employees who recently received a raise. Note that current
* // objects are returned, so can be cached normally.
* ExpressionBuilder employee = new ExpressionBuilder();
* Expression pastEmployee = new ExpressionBuilder(Employee.class);
* pastEmployee.asOf(yesterday);
* Expression parallelJoin = employee.equal(pastEmployee);
* Expression selectionCriteria = parallelJoin.and(
* employee.get("salary").greaterThan(pastEmployee.get("salary")));
* </pre></blockquote>
* <p>
* Example: Querying on object changes using custom query keys
* </p><blockquote><pre>
* // First define the custom query key and add it to your descriptor.
* ExpressionBuilder builder = new ExpressionBuilder(Employee.class);
* Expression joinCriteria = builder.getField("EMPLOYEE.EMP_ID").equal(builder.getParameter("EMPLOYEE.EMP_ID"));
* OneToOneQueryKey selfReferential = new OneToOneQueryKey();
* selfReferential.setName("this");
* selfReferential.setJoinCriteria(joinCriteria);
* selfReferential.setReferenceClass(Employee.class);
* getSession().getDescriptor(Employee.class).addQueryKey(selfReferential);
*
* // Now build query as before.
* Expression employee = new ExpessionBuilder();
* Expression pastEmployee = employee.get("this").asOf(yesterday);
* Expression selectionCriteria = employee.get("salary").greaterThan(pastEmployee.get("salary"));
* </pre></blockquote>
* <p>
* Note in general that any parallel expression can be rewritten using a custom query key.
* EclipseLink will even automatically interpret x.get("this") for you so you do
* not need to define the above query key first.
* <p>
* <b>Full Reference:</b>
* <p>
* If an object is mapped to multiple tables, then each table will be as of
* the same time. Two objects mapped to the same table can not have different
* as of times. Conversely only expressions which have associated tables can have an as
* of clause.
* <p>
* If an as of clause is not explicitly set an expression will use the clause
* of its base expression, and so on recursively until one is found or an
* ExpressionBuilder is reached. Some usage scenarios follow:
* <ul>
* <li>employee.asOf(pastTime).anyOf("projects"): projects as of past time.
* <li>expressionBuilder.asOf(pastTime): entire expression as of past time.
* <li>employee.asOf(pastTime).anyOf("projects").asOf(null): projects as of current time.
* <li>employee.anyOf("projects").asOf(pastTime): projects only as of past time.
* </ul>
* <p>
* Watch out for x.asOf(oneTime).get("y").asOf(anotherTime).
* <ul>
* <li>emp.anyOf("phoneNumbers").asOf(yesterday) = emp.asOf(yesterday).anyOf("phoneNumbers") but:
* <li>emp.get("address").asOf(yesterday) != emp.asOf(yesterday).get("address").
* </ul>
* Whether the join is also as of yesterday depends on which table the foreign
* key field resides on. In an anyOf the foreign key is always on the right, but
* in a get (1-1) it could be on either side. For this
* reason employee.get("address").asOf(yesterday) is undefined as it can mean
* either 'my address as of yesterday', or 'my address, as of yesterday.'
* @param pastTime A read only data object used to represent a past time.
* @return <code>this</code>
* @since OracleAS EclipseLink 10<i>g</i> (10.0.3)
* @see org.eclipse.persistence.history.AsOfClause
* @see #hasAsOfClause
* @see org.eclipse.persistence.sessions.Session#acquireHistoricalSession(org.eclipse.persistence.history.AsOfClause)
* @see org.eclipse.persistence.queries.ObjectLevelReadQuery#setAsOfClause(org.eclipse.persistence.history.AsOfClause)
*/
public Expression asOf(AsOfClause pastTime) {
throw new UnsupportedOperationException("anyOfAllowingNone");
}
/**
* INTERNAL:
* Alias a particular table within this node
*/
protected void assignAlias(String name, DatabaseTable tableOrExpression) {
// By default, do nothing.
}
/**
* INTERNAL:
* Assign aliases to any tables which I own. Start with t(initialValue),
* and return the new value of the counter , i.e. if initialValue is one
* and I have tables ADDRESS and EMPLOYEE I will assign them t1 and t2 respectively, and return 3.
*/
public int assignTableAliasesStartingAt(int initialValue) {
if (hasBeenAliased()) {
return initialValue;
}
int counter = initialValue;
List<DatabaseTable> ownedTables = getOwnedTables();
if (ownedTables != null) {
for (DatabaseTable table : ownedTables) {
assignAlias("t" + counter, table);
counter++;
}
}
return counter;
}
/**
* PUBLIC:
* Function, This represents the aggregate function Average. Can be used only within Report Queries.
*/
public Expression average() {
return getFunction(ExpressionOperator.Average);
}
/**
* PUBLIC:
* Function, between two bytes
*/
public Expression between(byte leftValue, byte rightValue) {
return between(Byte.valueOf(leftValue), Byte.valueOf(rightValue));
}
/**
* PUBLIC:
* Function, between two chars
*/
public Expression between(char leftChar, char rightChar) {
return between(Character.valueOf(leftChar), Character.valueOf(rightChar));
}
/**
* PUBLIC:
* Function, between two doubles
*/
public Expression between(double leftValue, double rightValue) {
return between(Double.valueOf(leftValue), Double.valueOf(rightValue));
}
/**
* PUBLIC:
* Function, between two floats
*/
public Expression between(float leftValue, float rightValue) {
return between(Float.valueOf(leftValue), Float.valueOf(rightValue));
}
/**
* PUBLIC:
* Function, between two ints
*/
public Expression between(int leftValue, int rightValue) {
return between(Integer.valueOf(leftValue), Integer.valueOf(rightValue));
}
/**
* PUBLIC:
* Function, between two longs
*/
public Expression between(long leftValue, long rightValue) {
return between(Long.valueOf(leftValue), Long.valueOf(rightValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receiver's value is between two other values.
* This means the receiver's value is greater than or equal to the leftValue argument and less than or equal to the
* rightValue argument.
* <p>
* This is equivalent to the SQL "BETWEEN AND" operator and Java {@literal ">=", "<=;"} operators.
* <p>Example:
* <pre>
* EclipseLink: employee.get("age").between(19,50)
* Java: (employee.getAge() {@literal >=} 19) {@literal &&} (employee.getAge() {@literal <=} 50)
* SQL: AGE BETWEEN 19 AND 50
* </pre>
*/
public Expression between(Object leftValue, Object rightValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Between);
List args = new ArrayList(2);
args.add(leftValue);
args.add(rightValue);
return anOperator.expressionForArguments(this, args);
}
public Expression between(Expression leftExpression, Expression rightExpression) {
return between(leftExpression, (Object)rightExpression);
}
/**
* PUBLIC:
* Function, between two shorts
*/
public Expression between(short leftValue, short rightValue) {
return between(Short.valueOf(leftValue), Short.valueOf(rightValue));
}
/**
* PUBLIC:
* Function Convert values returned by the query to values
* given in the caseItems Map. The equivalent of
* the Oracle CASE function
* <p>Example:
* <blockquote><pre>
* Map caseTable = new HashMap();
* caseTable.put("Robert", "Bob");
* caseTable.put("Susan", "Sue");
*
* EclipseLink: employee.get("name").caseStatement(caseTable, "No-Nickname")
* Java: NA
* SQL: CASE name WHEN "Robert" THEN "Bob"
* WHEN "Susan" THEN "Sue"
* ELSE "No-Nickname"
* </pre></blockquote>
* @param caseItems java.util.Map
* A Map containing the items to be processed.
* Keys represent the items to match coming from the query.
* Values represent what a key will be changed to.
* @param defaultItem java.lang.String the default value that will be used if none of the keys in the
* hashtable match
*/
public Expression caseStatement(Map caseItems, Object defaultItem) {
FunctionExpression expression = caseStatement();
expression.addChild(this);
Iterator iterator = caseItems.keySet().iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
expression.addChild(Expression.from(key, this));
expression.addChild(Expression.from(caseItems.get(key), this));
}
expression.addChild(Expression.from(defaultItem, this));
return expression;
}
/**
* INTERNAL:
* Creates an ArgumentListFunctionExpression that is capable of creating a case statement of the form:
* <blockquote><pre>
* SQL: CASE name WHEN "Robert" THEN "Bob"
* WHEN "Susan" THEN "Sue"
* ELSE "No-Nickname"
* </pre></blockquote>
*
* This expression must be manipulated to successfully build a case statement by adding appropriate
* children to it.
*
* A child must be added for the "case expression" (name above), a pair of children must be added for
* each "when then" expression and a child must be added for the else.
*
* @see ArgumentListFunctionExpression
*/
public ArgumentListFunctionExpression caseStatement() {
ListExpressionOperator caseOperator = (ListExpressionOperator)getOperator(ExpressionOperator.Case);
ListExpressionOperator clonedCaseOperator = new ListExpressionOperator();
caseOperator.copyTo(clonedCaseOperator);
ArgumentListFunctionExpression expression = new ArgumentListFunctionExpression();
expression.setBaseExpression(this);
expression.setOperator(clonedCaseOperator);
return expression;
}
/**
* PUBLIC:
* Function Convert values returned by the query to values
* given in the caseConditions Map. The equivalent of
* the SQL CASE function
* <p>Example:
* <blockquote><pre>
* Map caseTable = new HashMap();
* caseTable.put(employee.get("name").equals("Robert"), "Bob");
* caseTable.put(employee.get("name").equals("Susan"), "Sue");
*
* EclipseLink: expressionBuilder.caseConditionStatement(caseTable, "No-Nickname")
* Java: NA
* SQL: CASE WHEN name = "Robert" THEN "Bob"
* WHEN name = "Susan" THEN "Sue"
* ELSE "No-Nickname"
* </pre></blockquote>
* @param caseConditions java.util.Map
* A Map containing the items to be processed.
* Keys represent the items to match coming from the query.
* Values represent what a key will be changed to.
* @param defaultItem java.lang.Object the default value that will be used if none of the keys in the
* Map match
*/
public Expression caseConditionStatement(Map<Expression, Object> caseConditions, Object defaultItem) {
FunctionExpression expression = caseConditionStatement();
Iterator<Expression> iterator = caseConditions.keySet().iterator();
if (iterator.hasNext()){
Expression key = iterator.next();
expression.addChild(key);
expression.setBaseExpression(key);//base needs to be the same as the first child for reportQuery items.
expression.addChild(Expression.from(caseConditions.get(key), this));
while (iterator.hasNext()) {
key = iterator.next();
expression.addChild(key);
expression.addChild(Expression.from(caseConditions.get(key), this));
}
}
expression.addChild(Expression.from(defaultItem, this));
return expression;
}
/**
* INTERNAL:
* Creates an ArgumentListFunctionExpression that is capable of creating a case statement of the form:
* <blockquote><pre>
* SQL: CASE WHEN name = "Robert" THEN "Bob"
* WHEN name = "Susan" THEN "Sue"
* ELSE "No-Nickname"
* </pre></blockquote>
*
* This expression must be manipulated to successfully build a case statement by adding appropriate
* children to it.
*
* A pair of children must be added for each "when then" expression and a child must be added for the else.
*
* @see ArgumentListFunctionExpression
*/
public ArgumentListFunctionExpression caseConditionStatement() {
ListExpressionOperator caseOperator = (ListExpressionOperator)getOperator(ExpressionOperator.CaseCondition);
ListExpressionOperator clonedCaseOperator = new ListExpressionOperator();
caseOperator.copyTo(clonedCaseOperator);
ArgumentListFunctionExpression expression = new ArgumentListFunctionExpression();
expression.setBaseExpression(this);
expression.setOperator(clonedCaseOperator);
return expression;
}
/**
* PUBLIC:
* Function Test if arguments are equal, returning null if they are and the value of the
* first expression otherwise.
* <p>Example:
* <blockquote><pre>
* EclipseLink: builder.get("name").nullIf( "Bobby")
* Java: NA
* SQL: NULLIF(name, "Bobby")
* </pre></blockquote>
* @param object java.lang.Object the value/expression that will be compared to the base expression
*/
public Expression nullIf(Object object) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NullIf);
List args = new ArrayList(1);
args.add(Expression.from(object, this));
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Function Return null if all arguments are null and the first non-null argument otherwise
* The equivalent of the COALESCE SQL function
* <p>Example:
* <blockquote><pre>
* List list = new ArrayList(3);
* list.add(builder.get("firstName"));
* list.add(builder.get("lastName"));
* list.add(builder.get("nickname"));
*
* EclipseLink: expressionBuilder.coalesce(caseTable)
* Java: NA
* SQL: COALESCE(firstname, lastname, nickname)
* </pre></blockquote>
* @param expressions java.util.Collection
* A Collection containing the items to check if null
*/
public ArgumentListFunctionExpression coalesce(Collection expressions) {
ArgumentListFunctionExpression expression = coalesce();
Iterator iterator = expressions.iterator();
if (iterator.hasNext()){
Expression base = Expression.from(iterator.next(), this);
expression.addChild(base);
expression.setBaseExpression(base);//base needs to be the same as the first child for reportQuery items.
while (iterator.hasNext()) {
expression.addChild(Expression.from(iterator.next(), this));
}
}
return expression;
}
public ArgumentListFunctionExpression coalesce() {
ListExpressionOperator coalesceOperator = (ListExpressionOperator)getOperator(ExpressionOperator.Coalesce);
ListExpressionOperator clonedCoalesceOperator = new ListExpressionOperator();
coalesceOperator.copyTo(clonedCoalesceOperator);
ArgumentListFunctionExpression expression = new ArgumentListFunctionExpression();
expression.setBaseExpression(this);
expression.setOperator(clonedCoalesceOperator);
return expression;
}
/**
* INTERNAL:
* Clone the expression maintaining clone identity in the inter-connected expression graph.
*/
@Override
public Object clone() {
// 2612538 - the default size of Map (32) is appropriate
Map alreadyDone = new IdentityHashMap();
return copiedVersionFrom(alreadyDone);
}
/**
* INTERNAL:
* This expression is built on a different base than the one we want. Rebuild it and
* return the root of the new tree.
* This method will rebuildOn the receiver even it is a parallel select or a
* sub select: it will not replace every base with newBase.
* Also it will rebuild using anyOf as appropriate not get.
* @see org.eclipse.persistence.mappings.ForeignReferenceMapping#batchedValueFromRow
* @see #rebuildOn(Expression)
*/
public Expression cloneUsing(Expression newBase) {
// 2637484 INVALID QUERY KEY EXCEPTION THROWN USING BATCH READS AND PARALLEL EXPRESSIONS
// 2612567 CR4298- NULLPOINTEREXCEPTION WHEN USING SUBQUERY AND BATCH READING IN 4.6
// 2612140 CR2973- BATCHATTRIBUTE QUERIES WILL FAIL WHEN THE INITIAL QUERY HAS A SUBQUERY
// 2720149 INVALID SQL WHEN USING BATCH READS AND MULTIPLE ANYOFS
// 2612538 - the default size of Map (32) is appropriate
Map alreadyDone = new IdentityHashMap();
// cloneUsing is identical to cloning save that the primary builder
// will be replaced not with its clone but with newBase.
// ExpressionBuilder.registerIn() will check for this newBase with
// alreadyDone.get(alreadyDone);
// copiedVersionFrom() must be called on the primary builder before
// other builders.
alreadyDone.put(alreadyDone, newBase);
return copiedVersionFrom(alreadyDone);
}
/**
* PUBLIC:
* Function, returns the concatenation of the two string values.
*/
public Expression concat(Object left) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Concat);
return anOperator.expressionFor(this, left);
}
/**
* PUBLIC:
* Return an expression that performs a key word search.
* <p>Example:
* <blockquote><pre>
* EclipseLink: project.get("description").containsAllKeyWords("EclipseLink rdbms java")
* </pre></blockquote>
*/
public Expression containsAllKeyWords(String spaceSeparatedKeyWords) {
StringTokenizer tokenizer = new StringTokenizer(spaceSeparatedKeyWords);
Expression expression = null;
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
if (expression == null) {
expression = containsSubstringIgnoringCase(token);
} else {
expression = expression.and(containsSubstringIgnoringCase(token));
}
}
if (expression == null) {
return like("%");
} else {
return expression;
}
}
/**
* PUBLIC:
* Return an expression that performs a key word search.
* <p>Example:
* <blockquote><pre>
* EclipseLink: project.get("description").containsAllKeyWords("EclipseLink rdbms java")
* </pre></blockquote>
*/
public Expression containsAnyKeyWords(String spaceSeparatedKeyWords) {
StringTokenizer tokenizer = new StringTokenizer(spaceSeparatedKeyWords);
Expression expression = null;
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
if (expression == null) {
expression = containsSubstringIgnoringCase(token);
} else {
expression = expression.or(containsSubstringIgnoringCase(token));
}
}
if (expression == null) {
return like("%");
} else {
return expression;
}
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value contains the substring.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").containsSubstring("Bob")
* Java: employee.getFirstName().indexOf("Bob") != -1
* SQL: F_NAME LIKE '%BOB%'
* </pre></blockquote>
*/
public Expression containsSubstring(String theValue) {
return like("%" + theValue + "%");
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value contains the substring.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").containsSubstring("Bob")
* Java: employee.getFirstName().indexOf("Bob") != -1
* SQL: F_NAME LIKE '%BOB%'
* </pre></blockquote>
*/
public Expression containsSubstring(Expression expression) {
return like((value("%").concat(expression)).concat("%"));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value contains the substring, ignoring case.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").containsSubstringIgnoringCase("Bob")
* Java: employee.getFirstName().toUpperCase().indexOf("BOB") != -1
* SQL: UPPER(F_NAME) LIKE '%BOB%'
* </pre></blockquote>
*/
public Expression containsSubstringIgnoringCase(String theValue) {
if (shouldUseUpperCaseForIgnoreCase) {
return toUpperCase().containsSubstring(theValue.toUpperCase());
} else {
return toLowerCase().containsSubstring(theValue.toLowerCase());
}
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value contains the substring, ignoring case.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").containsSubstringIgnoringCase("Bob")
* Java: employee.getFirstName().toUpperCase().indexOf("BOB") != -1
* SQL: UPPER(F_NAME) LIKE '%BOB%'
* </pre></blockquote>
*/
public Expression containsSubstringIgnoringCase(Expression expression) {
if (shouldUseUpperCaseForIgnoreCase) {
return toUpperCase().containsSubstring(expression.toUpperCase());
} else {
return toLowerCase().containsSubstring(expression.toLowerCase());
}
}
/*
* Modify this individual expression node to use outer joins wherever there are
* equality operations between two field nodes.
*/
protected void convertNodeToUseOuterJoin() {
}
/**
* INTERNAL:
* Modify this expression to use outer joins wherever there are
* equality operations between two field nodes.
*/
public Expression convertToUseOuterJoin() {
ExpressionIterator iterator = new ExpressionIterator() {
@Override
public void iterate(Expression each) {
each.convertNodeToUseOuterJoin();
}
};
iterator.iterateOn(this);
return this;
}
/**
* INTERNAL:
*/
public Expression copiedVersionFrom(Map alreadyDone) {
if (alreadyDone == null) {
// For sub-selects no cloning is done.
return this;
}
Expression existing = (Expression)alreadyDone.get(this);
if (existing == null) {
return registerIn(alreadyDone);
} else {
return existing;
}
}
/**
* PUBLIC:
* This represents the aggregate function Average. Can be used only within Report Queries.
*/
public Expression count() {
return getFunction(ExpressionOperator.Count);
}
/**
* INTERNAL:
*/
public Expression create(Expression base, Object singleArgument, ExpressionOperator anOperator) {
// This is a replacement for real class methods in Java. Instead of returning a new instance we create it, then
// mutate it using this method.
return this;
}
/**
* INTERNAL:
*/
public Expression createWithBaseLast(Expression base, Object singleArgument, ExpressionOperator anOperator) {
// This is a replacement for real class methods in Java. Instead of returning a new instance we create it, then
// mutate it using this method.
return this;
}
/**
* INTERNAL:
*/
public Expression create(Expression base, List arguments, ExpressionOperator anOperator) {
// This is a replacement for real class methods in Java. Instead of returning a new instance we create it, then
// mutate it using this method.
return this;
}
/**
* PUBLIC:
* This gives access to the current timestamp on the database through expression.
* Please note, this method is added for consistency and returns the same
* result as currentDate.
*/
public Expression currentTimeStamp() {
return currentDate();
}
/**
* PUBLIC:
* This gives access to the current date on the database through expression.
*/
public Expression currentDate() {
return getFunction(ExpressionOperator.Today);
}
/**
* PUBLIC:
* This gives access to the current date only on the database through expression.
* Note the difference between currentDate() and this method. This method does
* not return the time portion of current date where as currentDate() does.
*/
public Expression currentDateDate() {
return getFunction(ExpressionOperator.CurrentDate);
}
/**
* PUBLIC:
* This gives access to the current time only on the database through expression.
* Note the difference between currentDate() and this method. This method does
* not return the date portion where as currentDate() does.
*/
public Expression currentTime() {
return getFunction(ExpressionOperator.CurrentTime);
}
/**
* PUBLIC:
* Function, Return the difference between the queried part of a date(i.e. years, days etc.)
* and same part of the given date. The equivalent of the Sybase function DateDiff
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("date").dateDifference("year", new Date(System.currentTimeMillis()))
* Java: NA
* SQL: DATEADD(date, 2, GETDATE)
* </pre></blockquote>
*/
public Expression dateDifference(String datePart, java.util.Date date) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.DateDifference);
FunctionExpression expression = new FunctionExpression();
expression.setBaseExpression(this);
expression.addChild(Expression.fromLiteral(datePart, this));
expression.addChild(Expression.from(date, this));
expression.addChild(this);
expression.setOperator(anOperator);
return expression;
}
/**
* PUBLIC:
* Function, Return the difference between the queried part of a date(i.e. years, days etc.)
* and same part of the given date. The equivalent of the Sybase function DateDiff
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("date").dateDifference("year", new Date(System.currentTimeMillis()))
* Java: NA
* SQL: DATEADD(date, 2, GETDATE)
* </pre></blockquote>
*/
public Expression dateDifference(String datePart, Expression comparisonExpression) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.DateDifference);
FunctionExpression expression = new FunctionExpression();
expression.setBaseExpression(this);
expression.addChild(Expression.fromLiteral(datePart, this));
expression.addChild(comparisonExpression);
expression.addChild(this);
expression.setOperator(anOperator);
return expression;
}
/**
* PUBLIC:
* return a string that represents the given part of a date. The equivalent
* of the Sybase DATENAME function
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("date").dateName("year")
* Java: new String(date.getYear())
* SQL: DATENAME(date, year)
* </pre></blockquote>
*/
public Expression dateName(String datePart) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.DateName);
FunctionExpression expression = new FunctionExpression();
expression.setBaseExpression(this);
expression.addChild(Expression.fromLiteral(datePart, this));
expression.addChild(this);
expression.setOperator(anOperator);
return expression;
}
/**
* PUBLIC:
* Function return an integer which represents the requested
* part of the date. Equivalent of the Sybase function DATEPART
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("date").datePart("year")
* Java: date.getYear()
* SQL: DATEPART(date, year)
* </pre></blockquote>
*/
public Expression datePart(String datePart) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.DatePart);
FunctionExpression expression = new FunctionExpression();
expression.setBaseExpression(this);
expression.addChild(Expression.fromLiteral(datePart, this));
expression.addChild(this);
expression.setOperator(anOperator);
return expression;
}
/**
* PUBLIC:
* Function, returns the date converted to the string value in the default database format.
*/
public Expression dateToString() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.DateToString);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Function Convert values returned by the query to values given in the decodeableItems Map.
* The equivalent of the Oracle DECODE function.
* Note: This will only work on databases that support Decode with the syntax below.
* <p>Example:
* <blockquote><pre>
* Map decodeTable = new HashMap();
* decodeTable.put("Robert", "Bob");
* decodeTable.put("Susan", "Sue");
*
* EclipseLink: employee.get("name").Decode(decodeTable, "No-Nickname")
* Java: NA
* SQL: DECODE(name, "Robert", "Bob", "Susan", "Sue", "No-Nickname")
* </pre></blockquote>
* @param decodeableItems java.util.Map
* a Map containing the items to be decoded. Keys represent
* the items to match coming from the query. Values represent what
* a key will be changed to.
* @param defaultItem
* the default value that will be used if none of the keys in the
* Map match
**/
public Expression decode(Map decodeableItems, String defaultItem) {
/**
* decode works differently than most of the functionality in the expression framework.
* It takes a variable number of arguments and as a result, the printed strings for
* a decode call have to be built when the number of arguments are known.
* As a result, we do not look up decode in the ExpressionOperator. Instead we build
* the whole operator here. The side effect of this is that decode will not thrown
* an invalid operator exception for any platform. (Even the ones that do not support
* decode)
*/
ExpressionOperator anOperator = new ExpressionOperator();
anOperator.setSelector(ExpressionOperator.Decode);
anOperator.setName("DECODE");
anOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
anOperator.setType(ExpressionOperator.FunctionOperator);
anOperator.bePrefix();
List<String> v = new ArrayList<>(decodeableItems.size() + 1);
v.add("DECODE(");
for (int i = 0; i < ((decodeableItems.size() * 2) + 1); i++) {
v.add(", ");
}
v.add(")");
anOperator.printsAs(v);
FunctionExpression expression = new FunctionExpression();
expression.setBaseExpression(this);
expression.addChild(this);
Iterator iterator = decodeableItems.keySet().iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
expression.addChild(Expression.from(key, this));
expression.addChild(Expression.from(decodeableItems.get(key), this));
}
expression.addChild(Expression.from(defaultItem, this));
expression.setOperator(anOperator);
return expression;
}
/**
* PUBLIC:
* This can only be used within an ordering expression.
* It will order the result descending.
* <p>Example:
* <blockquote><pre>
* readAllQuery.addOrderBy(expBuilder.get("address").get("city").descending())
* </pre></blockquote>
*/
public Expression descending() {
return getFunction(ExpressionOperator.Descending);
}
/**
* INTERNAL:
* Used in debug printing of this node.
*/
public String descriptionOfNodeType() {
return "Expression";
}
/**
* PUBLIC:
* Function return a value which indicates how much difference there is
* between two expressions. Equivalent of the Sybase DIFFERENCE function
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("name").difference("Frank")
* SQL: DIFFERENCE(name, 'Frank')
* </pre></blockquote>
*/
public Expression difference(String expression) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Difference);
return anOperator.expressionFor(this, expression);
}
/**
* PUBLIC:
* Function, This represents the distinct option inside an aggregate function. Can be used only within Report Queries.
*/
public Expression distinct() {
return getFunction(ExpressionOperator.Distinct);
}
/**
* INTERNAL:
* Check if the object conforms to the expression in memory.
* This is used for in-memory querying.
* By default throw an exception as all valid root expressions must override.
* If the expression in not able to determine if the object conform throw a not supported exception.
*/
public boolean doesConform(Object object, AbstractSession session, AbstractRecord translationRow, int valueHolderPolicy) throws QueryException {
return doesConform(object, session, translationRow, valueHolderPolicy, false);
}
/**
* INTERNAL:
* New parameter added to doesConform for feature 2612601
* @param objectIsUnregistered true if object possibly not a clone, but is being
* conformed against the unit of work cache; if object is not in the UOW cache
* but some of its attributes are, use the registered versions of
* object's attributes for the purposes of this method.
*/
public boolean doesConform(Object object, AbstractSession session, AbstractRecord translationRow, int valueHolderPolicy, boolean objectIsUnregistered) throws QueryException {
throw QueryException.cannotConformExpression();
}
/**
* INTERNAL:
* Return if the expression is equal to the other.
* This is used to allow dynamic expression's SQL to be cached.
* Two expressions should be considered equal if they have the same "parameterized" SQL.
* This must be over written by each subclass.
*/
@Override
public boolean equals(Object expression) {
return (this == expression) || ((expression != null) && getClass().equals(expression.getClass()) && (hashCode() == expression.hashCode()));
}
/**
* INTERNAL:
* Return a consistent hash-code for the expression.
* This is used to allow dynamic expression's SQL to be cached.
* Two expressions should have the same hashCode if they have the same "parameterized" SQL.
* This should be over written by each subclass to provide a consistent value.
*/
@Override
public int hashCode() {
if (this.hashCode == 0) {
this.hashCode = computeHashCode();
}
return this.hashCode;
}
/**
* INTERNAL:
* Compute a consistent hash-code for the expression.
* This is used to allow dynamic expression's SQL to be cached.
* Two expressions should have the same hashCode if they have the same "parameterized" SQL.
* This should be over written by each subclass to provide a consistent value.
*/
public int computeHashCode() {
return 32;
}
public Expression equal(byte theValue) {
return equal(Byte.valueOf(theValue));
}
public Expression equal(char theChar) {
return equal(Character.valueOf(theChar));
}
public Expression equal(double theValue) {
return equal(Double.valueOf(theValue));
}
public Expression equal(float theValue) {
return equal(Float.valueOf(theValue));
}
public Expression equal(int theValue) {
return equal(Integer.valueOf(theValue));
}
public Expression equal(long theValue) {
return equal(Long.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receiver's value is equal to the other value.
* This is equivalent to the SQL "=" operator and Java "equals" method.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").equal("Bob")
* Java: employee.getFirstName().equals("Bob")
* SQL: F_NAME = 'Bob'
* </pre></blockquote>
*/
public Expression equal(Object theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Equal);
return anOperator.expressionFor(this, theValue);
}
/**
* Returns an expression that compares if the receiver's value is equal to the other value.
* This is equivalent to the SQL "=" operator and Java "equals" method.
* <p>Since OracleAS EclipseLink 10<i>g</i> (9.0.4) if <code>this</code> is an <code>ExpressionBuilder</code> and <code>theValue</code>
* is not used elsewhere, both will be translated to the same table. This can
* generate SQL with one less join for most exists subqueries.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("manager").equal(employee)
* Java: employee.getManager().equals(employee)
* SQL (optimized): EMP_ID = MANAGER_ID
* SQL (unoptimized): t0.MANAGER_ID = t1.EMP_ID AND t0.EMP_ID = t1.EMP_ID
* </pre></blockquote>
* @see #equal(Object)
*/
public Expression equal(Expression theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Equal);
return anOperator.expressionFor(this, theValue);
}
public Expression equal(short theValue) {
return equal(Short.valueOf(theValue));
}
public Expression equal(boolean theBoolean) {
return equal(Boolean.valueOf(theBoolean));
}
/**
* INTERNAL:
* Return an expression representing an outer join comparison
*/
// cr3546
public Expression equalOuterJoin(Object theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.EqualOuterJoin);
return anOperator.expressionFor(this, theValue);
}
/**
* INTERNAL:
* Return an expression representing an outer join comparison
*/
public Expression equalOuterJoin(Expression theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.EqualOuterJoin);
return anOperator.expressionFor(this, theValue);
}
/**
* PUBLIC:
* Return an expression that compares if the receiver's value is equal to the other value, ignoring case.
* This is equivalent to the Java "equalsIgnoreCase" method.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").equalsIgnoreCase("Bob")
* Java: employee.getFirstName().equalsIgnoreCase("Bob")
* SQL: UPPER(F_NAME) = 'BOB'
* </pre></blockquote>
*/
public Expression equalsIgnoreCase(String theValue) {
if (shouldUseUpperCaseForIgnoreCase) {
return toUpperCase().equal(theValue.toUpperCase());
} else {
return toLowerCase().equal(theValue.toLowerCase());
}
}
/**
* PUBLIC:
* Return an expression that compares if the receiver's value is equal to the other value, ignoring case.
* This is equivalent to the Java "equalsIgnoreCase" method.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").equalsIgnoreCase("Bob")
* Java: employee.getFirstName().equalsIgnoreCase("Bob")
* SQL: UPPER(F_NAME) = 'BOB'
* </pre></blockquote>
*/
public Expression equalsIgnoreCase(Expression theValue) {
if (shouldUseUpperCaseForIgnoreCase) {
return toUpperCase().equal(theValue.toUpperCase());
} else {
return toLowerCase().equal(theValue.toLowerCase());
}
}
/**
* PUBLIC:
* Return a sub query expression.
* A sub query using a report query to define a subselect within another queries expression or select's where clause.
* The sub query (the report query) will use its own expression builder be can reference expressions from the base expression builder.
* <p>Example:
* <blockquote><pre>
* ExpressionBuilder builder = new ExpressionBuilder();
* ReportQuery subQuery = new ReportQuery(Employee.class, new ExpressionBuilder());
* subQuery.setSelectionCriteria(subQuery.getExpressionBuilder().get("name").equal(builder.get("name")));
* builder.exists(subQuery);
* </pre></blockquote>
*/
public Expression exists(ReportQuery subQuery) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Exists);
return anOperator.expressionFor(subQuery(subQuery));
}
/**
* INTERNAL:
* Extract the primary key from the expression into the row.
* Ensure that the query is querying the exact primary key.
* Return false if not on the primary key.
*/
public boolean extractPrimaryKeyValues(boolean requireExactMatch, ClassDescriptor descriptor, AbstractRecord primaryKeyRow, AbstractRecord translationRow) {
return extractValues(true, requireExactMatch, descriptor, primaryKeyRow, translationRow);
}
/**
* INTERNAL:
* Extract the primary key from the expression into the row.
* Ensure that the query is querying the exact primary key.
* Return false if not on the primary key.
*/
public boolean extractValues(boolean primaryKeyOnly, boolean requireExactMatch, ClassDescriptor descriptor, AbstractRecord primaryKeyRow, AbstractRecord translationRow) {
return false;
}
/**
* INTERNAL:
* Return if the expression is not a valid primary key expression and add all primary key fields to the set.
*/
public boolean extractFields(boolean requireExactMatch, boolean primaryKey, ClassDescriptor descriptor, List<DatabaseField> searchFields, Set<DatabaseField> foundFields) {
return false;
}
/**
* INTERNAL:
* Create an expression node.
*/
public static Expression from(Object value, Expression base) {
//CR#... null value used to return null, must build a null constant expression.
if (value instanceof Expression) {
Expression exp = (Expression)value;
if (exp.isValueExpression() || base.isExpressionBuilder()) {
exp.setLocalBase(base);
} else {
// We don't know which side of the relationship cares about the other one, so notify both
// However for 3107049 value.equal(value) would cause infinite loop if did that.
base.setLocalBase(exp);
}
return exp;
}
if (value instanceof ReportQuery) {
Expression exp = base.subQuery((ReportQuery)value);
exp.setLocalBase(base);// We don't know which side of the relationship cares about the other one, so notify both
base.setLocalBase(exp);
return exp;
}
return fromConstant(value, base);
}
/**
* INTERNAL:
* Create an expression node.
*/
public static Expression fromConstant(Object value, Expression base) {
return new ConstantExpression(value, base);
}
/**
* INTERNAL:
* Create an expression node.
*/
public static Expression fromLiteral(String value, Expression base) {
return new LiteralExpression(value, base);
}
/**
* PUBLIC:
* Return an expression that wraps the attribute or query key name.
* This method is used to construct user-defined queries containing joins.
* <p>Example:
* <blockquote><pre>
* builder.get("address").get("city").equal("Ottawa");
* </pre></blockquote>
*/
public Expression get(String attributeName) {
return get(attributeName, true);
}
/**
* PUBLIC:
* Return an expression that wraps the attribute or query key name.
* This method is used to construct user-defined queries containing joins.
* <p>Example:
* <blockquote><pre>
* builder.get("address", false).get("city").equal("Ottawa");
* </pre></blockquote>
* @param forceInnerJoin - allows the get to not force an inner-join (if getAllowingNull was used elsewhere).
*/
public Expression get(String attributeName, boolean forceInnerJoin) {
throw new UnsupportedOperationException("get");
}
/**
* ADVANCED:
* Return an expression that wraps the attribute or query key name.
* This is only applicable to 1:1 relationships, and allows the target of
* the relationship to be null if there is no corresponding relationship in the database.
* Implemented via an outer join in the database.
* <p>Example:
* <blockquote><pre>
* builder.getAllowingNull("address").get("city").equal("Ottawa");
* </pre></blockquote>
*/
public Expression getAllowingNull(String attributeName) {
throw new UnsupportedOperationException("getAllowingNull");
}
/**
* Answers the past time the expression is explicitly as of.
* @return An immutable object representation of the past time.
* <code>null</code> if no clause set, <code>AsOfClause.NO_CLAUSE</code> if
* clause explicitly set to <code>null</code>.
* @see #asOf(org.eclipse.persistence.history.AsOfClause)
* @see #hasAsOfClause()
*/
public AsOfClause getAsOfClause() {
return null;
}
/**
* INTERNAL:
* For Flashback: If this expression is not already as of some timestamp
* gets the clause from the base expression. Allows a clause to be set
* only on the builder and then propogated during normalize.
*/
public AsOfClause getAsOfClauseRecursively() {
return null;
}
/**
* INTERNAL:
* Return the expression builder which is the ultimate base of this expression, or
* null if there isn't one (shouldn't happen if we start from a root)
*/
public abstract ExpressionBuilder getBuilder();
/**
* INTERNAL:
* If there are any fields associated with this expression, return them
*/
public DatabaseField getClonedField() {
return null;
}
/**
* ADVANCED:
* Return an expression representing a field in a data-level query.
* This is used internally in EclipseLink, or to construct queries involving
* fields and/or tables that are not mapped.
* <p> Example:
* <blockquote><pre>
* builder.getField("ADDR_ID").greaterThan(100);
* builder.getTable("PROJ_EMP").getField("TYPE").equal("S");
* </pre></blockquote>
*/
public Expression getField(String fieldName) {
throw QueryException.illegalUseOfGetField(fieldName);
}
/**
* ADVANCED: Return an expression representing a field in a data-level query.
* This is used internally in EclipseLink, or to construct queries involving
* fields and/or tables that are not mapped.
* <p> Example:
* <blockquote><pre>
* builder.getField(aField).greaterThan(100);
* </pre></blockquote>
*/
public Expression getField(DatabaseField field) {
throw QueryException.illegalUseOfGetField(field);
}
/**
* INTERNAL:
*/
public List<DatabaseField> getFields() {
return new ArrayList<>(1);
}
/**
* INTERNAL:
*/
public List<DatabaseField> getSelectionFields() {
return getSelectionFields(null);
}
public List<DatabaseField> getSelectionFields(ReadQuery query) {
return getFields();
}
/**
* INTERNAL:
* Transform the object-level value into a database-level value
*/
public Object getFieldValue(Object objectValue, AbstractSession session) {
// Enums default to their ordinal
if (objectValue instanceof Enum){
return ((Enum)objectValue).ordinal();
}
return objectValue;
}
/**
* ADVANCED:
* Defines a join between the two objects based on the specified ON clause.
* This can be used to define a join condition on two unrelated objects,
* or to qualify a relationship join with additional criteria.
* <p> Example:
* <blockquote><pre>
* Expression address = employee.getAllowingNull("address");
* employee.join(address, address.get("city").equal("Ottawa"));
* query.addNonFetchJoin(address);
* </pre></blockquote>
*/
public Expression join(Expression target, Expression onClause) {
throw new UnsupportedOperationException("join");
}
/**
* ADVANCED:
* Defines an outer join between the two objects based on the specified ON clause.
* This can be used to define a join condition on two unrelated objects,
* or to qualify a relationship join with additional criteria.
* <p> Example:
* <blockquote><pre>
* Expression address = employee.getAllowingNull("address");
* employee.leftJoin(address, address.get("city").equal("Ottawa"));
* query.addNonFetchJoin(address);
* </pre></blockquote>
*/
public Expression leftJoin(Expression target, Expression onClause) {
throw new UnsupportedOperationException("leftJoin");
}
/**
* ADVANCED:
* This can be used for accessing user defined functions.
* The operator must be defined in ExpressionOperator to be able to reference it.
* @see ExpressionOperator
* <p> Example:
* <blockquote><pre>
* builder.get("name").getFunction(MyFunctions.FOO_BAR).greaterThan(100);
* </pre></blockquote>
*/
public Expression getFunction(int selector) {
ExpressionOperator anOperator = getOperator(selector);
return anOperator.expressionFor(this);
}
/**
* ADVANCED:
* This can be used for accessing user defined functions that have arguments.
* The operator must be defined in ExpressionOperator to be able to reference it.
* @see ExpressionOperator
* <p> Example:
* <blockquote><pre>
* List arguments = new ArrayList();
* arguments.add("blee");
* builder.get("name").getFunction(MyFunctions.FOO_BAR, arguments).greaterThan(100);
* </pre></blockquote>
*/
public Expression getFunction(int selector, List arguments) {
ExpressionOperator anOperator = getOperator(selector);
return anOperator.expressionForArguments(this, arguments);
}
/**
* ADVANCED:
* This can be used for accessing user defined operators that have arguments.
* The operator must be defined in ExpressionOperator to be able to reference it.
* @see ExpressionOperator
* <p> Example:
* <blockquote><pre>
* List arguments = new ArrayList();
* arguments.add("blee");
* builder.get("name").operator("FOO_BAR", arguments).greaterThan(100);
* </pre></blockquote>
*/
public Expression operator(String name, List arguments) {
Integer selector = ExpressionOperator.getPlatformOperatorSelectors().get(name);
if (selector == null) {
return getFunctionWithArguments(name, arguments);
}
return getFunction(selector, arguments);
}
/**
* ADVANCED:
* Return a user defined function accepting the argument.
* The function is assumed to be a normal prefix function and will print like, UPPER(base).
* <p> Example:
* <blockquote><pre>
* builder.get("firstName").getFunction("UPPER");
* </pre></blockquote>
*/
public Expression getFunction(String functionName) {
ExpressionOperator anOperator = ExpressionOperator.simpleFunction(0, functionName);
return anOperator.expressionFor(this);
}
/**
* ADVANCED:
* Return a user defined function accepting the argument.
* The function is assumed to be a normal prefix function and will print like, CONCAT(base, argument).
*/
public Expression getFunction(String functionName, Object argument) {
ExpressionOperator anOperator = ExpressionOperator.simpleTwoArgumentFunction(0, functionName);
return anOperator.expressionFor(this, argument);
}
/**
* ADVANCED:
* Return a user defined function accepting all of the arguments.
* The function is assumed to be a normal prefix function like, CONCAT(base, value1, value2, value3, ...).
*/
public Expression getFunctionWithArguments(String functionName, List arguments) {
ExpressionOperator anOperator = new ExpressionOperator();
anOperator.setType(ExpressionOperator.FunctionOperator);
List<String> v = new ArrayList<>(arguments.size());
v.add(functionName + "(");
for (int index = 0; index < arguments.size(); index++) {
v.add(", ");
}
v.add(")");
anOperator.printsAs(v);
anOperator.bePrefix();
anOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
return anOperator.expressionForArguments(this, arguments);
}
/**
* ADVANCED:
* Parse the SQL for parameter and return a custom function expression
* using a custom operator that will print itself as the SQL.
* Arguments are passed using '?', and must match the number of arguments.
*/
public Expression sql(String sql, List arguments) {
ExpressionOperator anOperator = new ExpressionOperator();
anOperator.setType(ExpressionOperator.FunctionOperator);
List<String> v = new ArrayList<>(arguments.size());
int start = 0;
int index = sql.indexOf('?');
while (index != -1) {
v.add(sql.substring(start, index));
start = index + 1;
index = sql.indexOf('?', start);
}
if (start <= sql.length()) {
v.add(sql.substring(start, sql.length()));
}
anOperator.printsAs(v);
anOperator.bePrefix();
anOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
return anOperator.expressionForArguments(this, arguments);
}
/**
* PUBLIC:
* Return an expression that wraps the inheritance type field in an expression.
* <p>Example:
* <blockquote><pre>
* builder.getClassForInheritance().equal(SmallProject.class);
* builder.anyOf("projects").getClassForInheritance().equal(builder.getParameter("projectClass"));
* </pre></blockquote>
*/
public Expression type() {
//Only valid on an ObjectExpression
return null;
}
/**
* INTERNAL:
*/
public String getName() {
return "";
}
/**
* INTERNAL:
* Most expression have operators, so this is just a convenience method.
*/
public ExpressionOperator getOperator() {
return null;
}
/**
* INTERNAL:
* Create a new expression tree with the named operator. Part of the implementation of user-level "get"
*/
public ExpressionOperator getOperator(int selector) {
ExpressionOperator result = ExpressionOperator.getOperator(selector);
if (result != null) {
return result;
}
// Make a temporary operator which we expect the platform
// to supply later.
result = new ExpressionOperator();
result.setSelector(selector);
result.setNodeClass(ClassConstants.FunctionExpression_Class);
return result;
}
/**
* INTERNAL:
* Return the tables that this node owns for purposes of table aliasing.
*/
public List<DatabaseTable> getOwnedTables() {
return null;
}
/**
* INTERNAL:
* Return an expression representing a parameter with the given name and type
*/
public Expression getParameter(String parameterName, Object type) {
return new ParameterExpression(parameterName, getBuilder(), type);
}
/**
* ADVANCED:
* Return an expression representing a parameter with the given name.
*/
public Expression getParameter(String parameterName) {
return new ParameterExpression(parameterName, getBuilder(), null);
}
/**
* ADVANCED:
* Return an expression representing a parameter with the given name.
*/
public Expression getParameter(DatabaseField field) {
return new ParameterExpression(field, getBuilder());
}
/**
* ADVANCED:
* Return an expression representing a property with the given name.
*/
public Expression getProperty(DatabaseField field) {
ParameterExpression paramExpression = new ParameterExpression(field, this);
paramExpression.setIsProperty(true);
return paramExpression;
}
/**
* INTERNAL:
*/
public AbstractSession getSession() {
return getBuilder().getSession();
}
/**
* ADVANCED: Return an expression representing a table in a data-level query.
* This is used internally in EclipseLink, or to construct queries involving
* fields and/or tables that are not mapped.
* <p> Example:
* <blockquote><pre>
* builder.getTable("PROJ_EMP").getField("TYPE").equal("S");
* </pre></blockquote>
*/
public Expression getTable(String tableName) {
DatabaseTable table = new DatabaseTable(tableName);
return getTable(table);
}
/**
* ADVANCED: Return an expression representing a table in a data-level query.
* This is used internally in EclipseLink, or to construct queries involving
* fields and/or tables that are not mapped.
* <p> Example:
* <blockquote><pre>
* builder.getTable(linkTable).getField("TYPE").equal("S");
* </pre></blockquote>
*/
public Expression getTable(DatabaseTable table) {
throw QueryException.illegalUseOfGetTable(table);
}
/**
* ADVANCED: Return an expression representing a sub-select in the from clause.
* <p> Example:
* <blockquote><pre>
* builder.getAlias(builder.subQuery(reportQuery)).get("type").equal("S");
* </pre></blockquote>
*/
public Expression getAlias(Expression subSelect) {
throw QueryException.illegalUseOfGetTable(subSelect);
}
/**
* INTERNAL:
* Return the aliases used. By default, return null, since we don't have tables.
*/
public TableAliasLookup getTableAliases() {
return null;
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is equal to the other value.
* This is equivalent to the SQL "=" operator and Java "equals" method.
*/
public Expression greaterThan(byte theValue) {
return greaterThan(Byte.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is equal to the other value.
* This is equivalent to the SQL "=" operator and Java "equals" method.
*/
public Expression greaterThan(char theChar) {
return greaterThan(Character.valueOf(theChar));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is equal to the other value.
* This is equivalent to the SQL "=" operator and Java "equals" method.
*/
public Expression greaterThan(double theValue) {
return greaterThan(Double.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is equal to the other value.
* This is equivalent to the SQL "=" operator and Java "equals" method.
*/
public Expression greaterThan(float theValue) {
return greaterThan(Float.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is equal to the other value.
* This is equivalent to the SQL "=" operator and Java "equals" method.
*/
public Expression greaterThan(int theValue) {
return greaterThan(Integer.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is equal to the other value.
* This is equivalent to the SQL "=" operator and Java "equals" method.
*/
public Expression greaterThan(long theValue) {
return greaterThan(Long.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receiver's value is greater than the other value.
* This is equivalent to the SQL {@literal ">"} operator.
*/
public Expression greaterThan(Object theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.GreaterThan);
return anOperator.expressionFor(this, theValue);
}
public Expression greaterThan(Expression theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.GreaterThan);
return anOperator.expressionFor(this, theValue);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is equal to the other value.
* This is equivalent to the SQL "=" operator and Java "equals" method.
*/
public Expression greaterThan(short theValue) {
return greaterThan(Short.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is equal to the other value.
* This is equivalent to the SQL "=" operator and Java "equals" method.
*/
public Expression greaterThan(boolean theBoolean) {
return greaterThan(Boolean.valueOf(theBoolean));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is greater and equal to the other value.
* This is equivalent to the SQL {@literal ">="} operator.
*/
public Expression greaterThanEqual(byte theValue) {
return greaterThanEqual(Byte.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is greater and equal to the other value.
* This is equivalent to the SQL {@literal ">="} operator.
*/
public Expression greaterThanEqual(char theChar) {
return greaterThanEqual(Character.valueOf(theChar));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is greater and equal to the other value.
* This is equivalent to the SQL {@literal ">="} operator.
*/
public Expression greaterThanEqual(double theValue) {
return greaterThanEqual(Double.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is greater and equal to the other value.
* This is equivalent to the SQL {@literal ">="} operator.
*/
public Expression greaterThanEqual(float theValue) {
return greaterThanEqual(Float.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is greater and equal to the other value.
* This is equivalent to the SQL {@literal ">="} operator.
*/
public Expression greaterThanEqual(int theValue) {
return greaterThanEqual(Integer.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is greater and equal to the other value.
* This is equivalent to the SQL {@literal ">="} operator.
*/
public Expression greaterThanEqual(long theValue) {
return greaterThanEqual(Long.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is greater and equal to the other value.
* This is equivalent to the SQL {@literal ">="} operator.
*/
public Expression greaterThanEqual(Object theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.GreaterThanEqual);
return anOperator.expressionFor(this, theValue);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is greater and equal to the other value.
* This is equivalent to the SQL {@literal ">="} operator.
*/
public Expression greaterThanEqual(Expression theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.GreaterThanEqual);
return anOperator.expressionFor(this, theValue);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is greater and equal to the other value.
* This is equivalent to the SQL {@literal ">="} operator.
*/
public Expression greaterThanEqual(short theValue) {
return greaterThanEqual(Short.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is greater and equal to the other value.
* This is equivalent to the SQL {@literal ">="} operator.
*/
public Expression greaterThanEqual(boolean theBoolean) {
return greaterThanEqual(Boolean.valueOf(theBoolean));
}
/**
* ADVANCED:
* Answers true if <code>this</code> is to be queried as of a past time.
* @return false from <code>asOf(null); hasAsOfClause()</code>.
* @see #getAsOfClause
*/
public boolean hasAsOfClause() {
return false;
}
/**
* INTERNAL:
* Answers if the database tables associated with this expression have been
* aliased. This insures the same tables are not aliased twice.
*/
public boolean hasBeenAliased() {
return false;
}
/**
* PUBLIC:
* Function, returns binary array value for the hex string.
*/
public Expression hexToRaw() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.HexToRaw);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Function return a specific value if item returned from the
* query is null. Equivalent of the oracle NVL function
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("name").ifNull("no-name")
* Java: NA
* SQL: NVL(name, 'no-name')
* </pre></blockquote>
*/
public Expression ifNull(Object nullValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Nvl);
return anOperator.expressionFor(this, nullValue);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression in(byte[] theBytes) {
List values = new ArrayList(theBytes.length);
for (int index = 0; index < theBytes.length; index++) {
values.add(theBytes[index]);
}
return in(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression in(char[] theChars) {
List values = new ArrayList(theChars.length);
for (int index = 0; index < theChars.length; index++) {
values.add(theChars[index]);
}
return in(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression in(double[] theDoubles) {
List values = new ArrayList(theDoubles.length);
for (int index = 0; index < theDoubles.length; index++) {
values.add(theDoubles[index]);
}
return in(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression in(float[] theFloats) {
List values = new ArrayList(theFloats.length);
for (int index = 0; index < theFloats.length; index++) {
values.add(theFloats[index]);
}
return in(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression in(int[] theInts) {
List values = new ArrayList(theInts.length);
for (int index = 0; index < theInts.length; index++) {
values.add(theInts[index]);
}
return in(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression in(long[] theLongs) {
List values = new ArrayList(theLongs.length);
for (int index = 0; index < theLongs.length; index++) {
values.add(theLongs[index]);
}
return in(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression in(Object[] theObjects) {
List values = new ArrayList(theObjects.length);
for (int index = 0; index < theObjects.length; index++) {
values.add(theObjects[index]);
}
return in(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression in(short[] theShorts) {
List values = new ArrayList(theShorts.length);
for (int index = 0; index < theShorts.length; index++) {
values.add(theShorts[index]);
}
return in(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression in(boolean[] theBooleans) {
List values = new ArrayList(theBooleans.length);
for (int index = 0; index < theBooleans.length; index++) {
values.add(theBooleans[index]);
}
return in(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("age").in(ages)
* Java: ages.contains(employee.getAge())
* SQL: AGE IN (55, 18, 30)
* </pre></blockquote>
*/
public Expression in(Collection theObjects) {
return in(new CollectionExpression(theObjects, this));
}
public Expression in(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.In);
return anOperator.expressionFor(this, arguments);
}
public Expression in(ReportQuery subQuery) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.InSubQuery);
return anOperator.expressionFor(this, subQuery);
}
/*
* PUBLIC:
* Index method could be applied to QueryKeyExpression corresponding to CollectionMapping
* that has non-null listOrderField (the field holding the index values).
* <p>Example:
* <blockquote><pre>
* ReportQuery query = new ReportQuery();
* query.setReferenceClass(Employee.class);
* ExpressionBuilder builder = query.getExpressionBuilder();
* Expression firstNameJohn = builder.get("firstName").equal("John");
* Expression anyOfProjects = builder.anyOf("projects");
* Expression exp = firstNameJohn.and(anyOfProjects.index().between(2, 4));
* query.setSelectionCriteria(exp);
* query.addAttribute("projects", anyOfProjects);
*
* SELECT DISTINCT t0.PROJ_ID, t0.PROJ_TYPE, t0.DESCRIP, t0.PROJ_NAME, t0.LEADER_ID, t0.VERSION, t1.PROJ_ID, t1.BUDGET, t1.MILESTONE
* FROM OL_PROJ_EMP t4, OL_SALARY t3, OL_EMPLOYEE t2, OL_LPROJECT t1, OL_PROJECT t0
* WHERE ((((t2.F_NAME = 'John') AND (t4.PROJ_ORDER BETWEEN 2 AND 4)) AND (t3.OWNER_EMP_ID = t2.EMP_ID)) AND
* (((t4.EMP_ID = t2.EMP_ID) AND (t0.PROJ_ID = t4.PROJ_ID)) AND (t1.PROJ_ID (+) = t0.PROJ_ID)))
* </pre></blockquote>
*/
public Expression index() {
throw QueryException.indexRequiresQueryKeyExpression(this);
}
/**
* PUBLIC:
* Function, returns the integer index of the substring within the source string.
*/
public Expression indexOf(Object substring) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Instring);
return anOperator.expressionFor(this, substring);
}
/**
* INTERNAL:
*/
public boolean isClassTypeExpression(){
return false;
}
/**
* INTERNAL:
*/
public boolean isCompoundExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isConstantExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isDataExpression() {
return false;
}
/**
* PUBLIC: A logical expression for the collection <code>attributeName</code>
* being empty.
* Equivalent to <code>size(attributeName).equal(0)</code>
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.isEmpty("phoneNumbers")
* Java: employee.getPhoneNumbers().size() == 0
* SQL: SELECT ... FROM EMP t0 WHERE (
* (SELECT COUNT(*) FROM PHONE t1 WHERE (t0.EMP_ID = t1.EMP_ID)) = 0)
* </pre></blockquote>
* This is a case where a fast operation in java does not translate to an
* equally fast operation in SQL, requiring a correlated subselect.
* @see #size(java.lang.String)
*/
public Expression isEmpty(String attributeName) {
return size(attributeName).equal(0);
}
/**
* INTERNAL:
*/
public boolean isExpressionBuilder() {
return false;
}
/**
* INTERNAL:
*/
public boolean isFieldExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isFunctionExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isLiteralExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isLogicalExpression() {
return false;
}
/**
* PUBLIC:
* Compare to null.
*/
public Expression isNull() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.IsNull);
return anOperator.expressionFor(this);
}
/**
* INTERNAL:
*/
public boolean isObjectExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isParameterExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isQueryKeyExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isRelationExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isSubSelectExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isTableExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isTreatExpression() {
return false;
}
/**
* INTERNAL:
*/
public boolean isMapEntryExpression(){
return false;
}
/**
* INTERNAL:
* Subclasses implement (isParameterExpression() || isConstantExpression())
*/
public boolean isValueExpression() {
return false;
}
/**
* INTERNAL:
* For iterating using an inner class
*/
public void iterateOn(ExpressionIterator iterator) {
iterator.iterate(this);
}
/**
* PUBLIC:
* Function, returns the date with the last date in the months of this source date.
*/
public Expression lastDay() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.LastDay);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Function, returns the string padded with the substring to the size.
*/
public Expression leftPad(int size, Object substring) {
return leftPad(Integer.valueOf(size), substring);
}
/**
* PUBLIC:
* Function, returns the string padded with the substring to the size.
*/
public Expression leftPad(Object size, Object substring) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.LeftPad);
List args = new ArrayList(2);
args.add(size);
args.add(substring);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Function, returns the string left trimmed for white space.
*/
public Expression leftTrim() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.LeftTrim);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Function, returns the string with the substring trimed from the left.
*/
public Expression leftTrim(Object substring) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.LeftTrim2);
return anOperator.expressionFor(this, substring);
}
/**
* PUBLIC:
* Function, returns the size of the string.
*/
public Expression length() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Length);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than the other value.
* This is equivalent to the SQL {@literal "<"} operator.
*/
public Expression lessThan(byte theValue) {
return lessThan(Byte.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than the other value.
* This is equivalent to the SQL {@literal "<"} operator.
*/
public Expression lessThan(char theChar) {
return lessThan(Character.valueOf(theChar));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than the other value.
* This is equivalent to the SQL {@literal "<"} operator.
*/
public Expression lessThan(double theValue) {
return lessThan(Double.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than the other value.
* This is equivalent to the SQL {@literal "<"} operator.
*/
public Expression lessThan(float theValue) {
return lessThan(Float.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than the other value.
* This is equivalent to the SQL {@literal "<"} operator.
*/
public Expression lessThan(int theValue) {
return lessThan(Integer.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than the other value.
* This is equivalent to the SQL {@literal "<"} operator.
*/
public Expression lessThan(long theValue) {
return lessThan(Long.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than the other value.
* This is equivalent to the SQL {@literal "<"} operator.
*/
public Expression lessThan(Object theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.LessThan);
return anOperator.expressionFor(this, theValue);
}
public Expression lessThan(Expression theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.LessThan);
return anOperator.expressionFor(this, theValue);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than the other value.
* This is equivalent to the SQL {@literal "<"} operator.
*/
public Expression lessThan(short theValue) {
return lessThan(Short.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than the other value.
* This is equivalent to the SQL {@literal "<"} operator.
*/
public Expression lessThan(boolean theBoolean) {
return lessThan(Boolean.valueOf(theBoolean));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than and equal to the other value.
* This is equivalent to the SQL {@literal "<="} operator.
*/
public Expression lessThanEqual(byte theValue) {
return lessThanEqual(Byte.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than and equal to the other value.
* This is equivalent to the SQL {@literal "<="} operator.
*/
public Expression lessThanEqual(char theChar) {
return lessThanEqual(Character.valueOf(theChar));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than and equal to the other value.
* This is equivalent to the SQL {@literal "<="} operator.
*/
public Expression lessThanEqual(double theValue) {
return lessThanEqual(Double.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than and equal to the other value.
* This is equivalent to the SQL {@literal "<="} operator.
*/
public Expression lessThanEqual(float theValue) {
return lessThanEqual(Float.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than and equal to the other value.
* This is equivalent to the SQL {@literal "<="} operator.
*/
public Expression lessThanEqual(int theValue) {
return lessThanEqual(Integer.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than and equal to the other value.
* This is equivalent to the SQL {@literal "<="} operator.
*/
public Expression lessThanEqual(long theValue) {
return lessThanEqual(Long.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than and equal to the other value.
* This is equivalent to the SQL {@literal "<="} operator.
*/
public Expression lessThanEqual(Object theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.LessThanEqual);
return anOperator.expressionFor(this, theValue);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than and equal to the other value.
* This is equivalent to the SQL {@literal "<="} operator.
*/
public Expression lessThanEqual(Expression theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.LessThanEqual);
return anOperator.expressionFor(this, theValue);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than and equal to the other value.
* This is equivalent to the SQL {@literal "<="} operator.
*/
public Expression lessThanEqual(short theValue) {
return lessThanEqual(Short.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is less than and equal to the other value.
* This is equivalent to the SQL {@literal "<="} operator.
*/
public Expression lessThanEqual(boolean theBoolean) {
return lessThanEqual(Boolean.valueOf(theBoolean));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is like other value.
* This is equivalent to the SQL "LIKE" operator that except wildcards.
* The character "%" means any sequence of characters and the character "_" mean any character.
* i.e. "B%" == "Bob", "B_B" == "BOB"
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").like("B%")
* Java: NA
* SQL: F_NAME LIKE 'B%'
* </pre></blockquote>
*/
public Expression like(String value) {
return like(new ConstantExpression(value, this));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is like other value.
* This is equivalent to the SQL "LIKE ESCAPE" operator that except wildcards.
* The character "%" means any sequence of characters and the character "_" mean any character.
* i.e. "B%" == "Bob", "B_B" == "BOB"
* The escape sequence specifies a set of characters the may be used to indicate that
* an one of the wildcard characters should be interpreted literally.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").like("B\_SMITH", "\")
* Java: NA
* SQL: F_NAME LIKE 'B\_SMITH ESCAPE '\''
* </pre></blockquote>
*/
public Expression like(String value, String escapeSequence) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.LikeEscape);
List args = new ArrayList(2);
args.add(value);
args.add(escapeSequence);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is like other value.
* This is equivalent to the SQL "LIKE" operator that except wildcards.
* The character "%" means any sequence of characters and the character "_" mean any character.
* i.e. "B%" == "Bob", "B_B" == "BOB"
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").like("B%")
* Java: NA
* SQL: F_NAME LIKE 'B%'
* </pre></blockquote>
*/
public Expression like(Expression argument) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Like);
return anOperator.expressionFor(this, argument);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value matches the regular expression.
* This uses the databases support for regular expression.
* Regular expressions are similar to LIKE except support a much larger scope of comparisons.
* i.e. "^B.*" == "Bob", "^B.B$" == "BOB"
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").regexp("^B.*")
* Java: Pattern.compile("^B.*").matcher(employee.getFirstName()).matches()
* SQL: F_NAME REGEXP '^B.*'
* </pre></blockquote>
*/
public Expression regexp(String regexp) {
return regexp(new ConstantExpression(regexp, this));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value matches the regular expression.
* This uses the databases support for regular expression.
* Regular expressions are similar to LIKE except support a much larger scope of comparisons.
* i.e. "^B.*" == "Bob", "^B.B$" == "BOB"
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").regexp("^B.*")
* Java: Pattern.compile("^B.*").matcher(employee.getFirstName()).matches()
* SQL: F_NAME REGEXP '^B.*'
* </pre></blockquote>
*/
public Expression regexp(Expression regexp) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Regexp);
return anOperator.expressionFor(this, regexp);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is like other value.
* This is equivalent to the SQL "LIKE ESCAPE" operator that except wildcards.
* The character "%" means any sequence of characters and the character "_" mean any character.
* i.e. "B%" == "Bob", "B_B" == "BOB"
* The escape sequence specifies a set of characters the may be used to indicate that
* an one of the wildcard characters should be interpreted literally.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").like("B\_SMITH", "\")
* Java: NA
* SQL: F_NAME LIKE 'B\_SMITH ESCAPE '\''
* </pre></blockquote>
*/
public Expression like(Expression value, Expression escapeSequence) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.LikeEscape);
List args = new ArrayList(2);
args.add(value);
args.add(escapeSequence);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is like the other value, ignoring case.
* This is a case in-sensitive like.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").likeIgnoreCase("%Bob%")
* Java: none
* SQL: UPPER(F_NAME) LIKE 'BOB'
* </pre></blockquote>
*/
public Expression likeIgnoreCase(String theValue) {
if (shouldUseUpperCaseForIgnoreCase) {
return toUpperCase().like(theValue.toUpperCase());
} else {
return toLowerCase().like(theValue.toLowerCase());
}
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is like the other value, ignoring case.
* This is a case in-sensitive like.
*/
public Expression likeIgnoreCase(Expression theValue) {
if (shouldUseUpperCaseForIgnoreCase) {
return toUpperCase().like(theValue.toUpperCase());
} else {
return toLowerCase().like(theValue.toLowerCase());
}
}
/**
* PUBLIC:
* Function, returns the position of <code>str</code> in <code>this</code>
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").locate("ob")
* Java: employee.getFirstName().indexOf("ob") + 1
* SQL: LOCATE('ob', t0.F_NAME)
* </pre></blockquote>
* <p>
* Note that while in String.locate(str) -1 is returned if not found, and the
* index starting at 0 if found, in SQL it is 0 if not found, and the index
* starting at 1 if found.
*/
public Expression locate(Object str) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Locate);
List args = new ArrayList(1);
args.add(str);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Function, returns the position of <code>str</code> in <code>this</code>,
* starting the search at <code>fromIndex</code>.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").locate("ob", 1)
* Java: employee.getFirstName().indexOf("ob", 1) + 1
* SQL: LOCATE('ob', t0.F_NAME, 1)
* </pre></blockquote>
* <p>
* Note that while in String.locate(str) -1 is returned if not found, and the
* index starting at 0 if found, in SQL it is 0 if not found, and the index
* starting at 1 if found.
*/
public Expression locate(String str, int fromIndex) {
return locate(str, Integer.valueOf(fromIndex));
}
/**
* PUBLIC:
* Function, returns the position of <code>str</code> in <code>this</code>,
* starting the search at <code>fromIndex</code>.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").locate("ob", 1)
* Java: employee.getFirstName().indexOf("ob", 1) + 1
* SQL: LOCATE('ob', t0.F_NAME, 1)
* </pre></blockquote>
* <p>
* Note that while in String.locate(str) -1 is returned if not found, and the
* index starting at 0 if found, in SQL it is 0 if not found, and the index
* starting at 1 if found.
*/
public Expression locate(Object str, Object fromIndex) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Locate2);
List args = new ArrayList(2);
args.add(str);
args.add(fromIndex);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* This represents the aggregate function Maximum. Can be used only within Report Queries.
*/
public Expression maximum() {
return getFunction(ExpressionOperator.Maximum);
}
/**
* PUBLIC:
* This represents the aggregate function Minimum. Can be used only within Report Queries.
*/
public Expression minimum() {
return getFunction(ExpressionOperator.Minimum);
}
/**
* PUBLIC:
* Function, returns the decimal number of months between the two dates.
*/
public Expression monthsBetween(Object otherDate) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.MonthsBetween);
return anOperator.expressionFor(this, otherDate);
}
/**
* PUBLIC:
* Return a Map.Entry containing the key and the value from a mapping that maps to a java.util.Map
* This expression can only be used as a return value in a ReportQuery and cannot be used as part of
* the WHERE clause in any query
*
* EclipseLink: eb.get("mapAttribute").mapEntry()
*/
public Expression mapEntry(){
MapEntryExpression expression = new MapEntryExpression(this);
expression.returnMapEntry();
return expression;
}
/**
* PUBLIC:
* Return the key from a mapping that maps to a java.util.Map
* This expression can be used either in as a return value in a ReportQuery or in the WHERE clause in a query
*
* EclipseLink: eb.get("mapAttribute").mapKey()
*/
public Expression mapKey(){
return new MapEntryExpression(this);
}
/**
* PUBLIC:
* funcation return a date converted to a new timezone. Equivalent of the Oracle NEW_TIME function
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("date").newTime("EST", "PST")
* Java: NA
* SQL: NEW_TIME(date, 'EST', 'PST')
* </pre></blockquote>
*/
public Expression newTime(String timeZoneFrom, String timeZoneTo) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NewTime);
List args = new ArrayList(2);
args.add(timeZoneFrom);
args.add(timeZoneTo);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Function, returns the date with the next day from the source date as the day name given.
*/
public Expression nextDay(Object dayName) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NextDay);
return anOperator.expressionFor(this, dayName);
}
/**
* PUBLIC: Returns an expression equivalent to none of <code>attributeName</code>
* holding true for <code>criteria</code>.
* <p>
* For every expression with an anyOf, its negation has either an allOf or a
* noneOf. The following two examples will illustrate as the second is the
* negation of the first:
* <p>
* AnyOf Example: Employees with a '613' area code phone number.
* <blockquote><pre>
* ReadAllQuery query = new ReadAllQuery(Employee.class);
* ExpressionBuilder employee = new ExpressionBuilder();
* Expression exp = employee.anyOf("phoneNumbers").get("areaCode").equal("613");
* </pre></blockquote>
* <p>
* NoneOf Example: Employees with no '613' area code phone numbers.
* <blockquote><pre>
* ExpressionBuilder employee = new ExpressionBuilder();
* ExpressionBuilder phones = new ExpressionBuilder();
* Expression exp = employee.noneOf("phoneNumbers", phones.get("areaCode").equal("613"));
* SQL:
* SELECT ... EMPLOYEE t0 WHERE NOT EXISTS (SELECT ... PHONE t1 WHERE
* (t0.EMP_ID = t1.EMP_ID) AND (t1.AREACODE = '613'))
* </pre></blockquote>
* <p>
* noneOf is the universal counterpart to the existential anyOf. To have the
* condition evaluated for each instance it must be put inside of a subquery,
* which can be expressed as not exists (any of attributeName some condition).
* (All x such that !y = !Exist x such that y).
* <p>Likewise the syntax employee.noneOf("phoneNumbers").get("areaCode").equal("613")
* is not supported for the <code>equal</code> must go inside a subQuery.
* <p>
* This method saves you from writing the sub query yourself. The above is
* equivalent to the following expression:
* <blockquote><pre>
* ExpressionBuilder employee = new ExpressionBuilder();
* ExpressionBuilder phone = new ExpressionBuilder();
* ReportQuery subQuery = new ReportQuery(Phone.class, phone);
* subQuery.retreivePrimaryKeys();
* subQuery.setSelectionCriteria(phone.equal(employee.anyOf("phoneNumbers").and(
* phone.get("areaCode").equal("613")));
* Expression exp = employee.notExists(subQuery);
* </pre></blockquote>
* @param criteria must have its own builder, as it will become the
* separate selection criteria of a subQuery.
* @return a notExists subQuery expression
*/
public Expression noneOf(String attributeName, Expression criteria) {
ReportQuery subQuery = new ReportQuery();
subQuery.setShouldRetrieveFirstPrimaryKey(true);
Expression builder = criteria.getBuilder();
criteria = builder.equal(anyOf(attributeName)).and(criteria);
subQuery.setSelectionCriteria(criteria);
return notExists(subQuery);
}
/**
* INTERNAL:
* Normalize into a structure that is printable.
* Also compute printing information such as outer joins.
*/
public Expression normalize(ExpressionNormalizer normalizer) {
//This class has no validation but we should still make the method call for consistency
//bug # 2956674
//validation is moved into normalize to ensure that expressions are valid before we attempt to work with them
validateNode();
return this;
}
/**
* PUBLIC:
* Return an expression that is the boolean logical negation of the expression.
* This is equivalent to the SQL "NOT" operator and the Java "!" operator.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("age").equal(24).not()
* Java: (! (employee.getAge() == 24))
* SQL: NOT (AGE = 24)
* </pre></blockquote>
*/
public Expression not() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Not);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not between two other values.
* Equivalent to between negated.
* @see #between(Object, Object)
*/
public Expression notBetween(byte leftValue, byte rightValue) {
return notBetween(Byte.valueOf(leftValue), Byte.valueOf(rightValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not between two other values.
* Equivalent to between negated.
* @see #between(Object, Object)
*/
public Expression notBetween(char leftChar, char rightChar) {
return notBetween(Character.valueOf(leftChar), Character.valueOf(rightChar));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not between two other values.
* Equivalent to between negated.
* @see #between(Object, Object)
*/
public Expression notBetween(double leftValue, double rightValue) {
return notBetween(Double.valueOf(leftValue), Double.valueOf(rightValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not between two other values.
* Equivalent to between negated.
* @see #between(Object, Object)
*/
public Expression notBetween(float leftValue, float rightValue) {
return notBetween(Float.valueOf(leftValue), Float.valueOf(rightValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not between two other values.
* Equivalent to between negated.
* @see #between(Object, Object)
*/
public Expression notBetween(int leftValue, int rightValue) {
return notBetween(Integer.valueOf(leftValue), Integer.valueOf(rightValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not between two other values.
* Equivalent to between negated.
* @see #between(Object, Object)
*/
public Expression notBetween(long leftValue, long rightValue) {
return notBetween(Long.valueOf(leftValue), Long.valueOf(rightValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not between two other values.
* Equivalent to between negated.
* @see #between(Object, Object)
*/
public Expression notBetween(Object leftValue, Object rightValue) {
return between(leftValue, rightValue).not();
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not between two other values.
* Equivalent to between negated.
* @see #between(Object, Object)
*/
public Expression notBetween(Expression leftExpression, Expression rightExpression) {
return between(leftExpression, rightExpression).not();
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not between two other values.
* Equivalent to between negated.
* @see #between(Object, Object)
*/
public Expression notBetween(short leftValue, short rightValue) {
return notBetween(Short.valueOf(leftValue), Short.valueOf(rightValue));
}
/**
* PUBLIC: A logical expression for the collection <code>attributeName</code>
* not being empty.
* Equivalent to <code>size(attributeName).greaterThan(0)</code>
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.notEmpty("phoneNumbers")
* Java: employee.getPhoneNumbers().size() {@literal >} 0
* SQL: SELECT ... FROM EMP t0 WHERE (
* (SELECT COUNT(*) FROM PHONE t1 WHERE (t0.EMP_ID = t1.EMP_ID)) {@literal >} 0)
* </pre></blockquote>
* This is a case where a fast operation in java does not translate to an
* equally fast operation in SQL, requiring a correlated subselect.
* @see #size(java.lang.String)
*/
public Expression notEmpty(String attributeName) {
return size(attributeName).greaterThan(0);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not equal to the other value.
* This is equivalent to the SQL {@literal "<>"} operator
*
* @see #equal(Object)
*/
public Expression notEqual(byte theValue) {
return notEqual(Byte.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not equal to the other value.
* This is equivalent to the SQL {@literal "<>"} operator
*
* @see #equal(Object)
*/
public Expression notEqual(char theChar) {
return notEqual(Character.valueOf(theChar));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not equal to the other value.
* This is equivalent to the SQL {@literal "<>"} operator
*
* @see #equal(Object)
*/
public Expression notEqual(double theValue) {
return notEqual(Double.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not equal to the other value.
* This is equivalent to the SQL {@literal "<>"} operator
*
* @see #equal(Object)
*/
public Expression notEqual(float theValue) {
return notEqual(Float.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not equal to the other value.
* This is equivalent to the SQL {@literal "<>"} operator
*
* @see #equal(Object)
*/
public Expression notEqual(int theValue) {
return notEqual(Integer.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not equal to the other value.
* This is equivalent to the SQL {@literal "<>"} operator
*
* @see #equal(Object)
*/
public Expression notEqual(long theValue) {
return notEqual(Long.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not equal to the other value.
* This is equivalent to the SQL {@literal "<>"} operator
*
* @see #equal(Object)
*/
public Expression notEqual(Object theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NotEqual);
return anOperator.expressionFor(this, theValue);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not equal to the other value.
* This is equivalent to the SQL {@literal "<>"} operator
*
* @see #equal(Object)
*/
public Expression notEqual(Expression theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NotEqual);
return anOperator.expressionFor(this, theValue);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not equal to the other value.
* This is equivalent to the SQL {@literal "<>"} operator
*
* @see #equal(Object)
*/
public Expression notEqual(short theValue) {
return notEqual(Short.valueOf(theValue));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not equal to the other value.
* This is equivalent to the SQL {@literal "<>"} operator
*
* @see #equal(Object)
*/
public Expression notEqual(boolean theBoolean) {
return notEqual(Boolean.valueOf(theBoolean));
}
/**
* PUBLIC:
* Return a sub query expression.
* A sub query using a report query to define a subselect within another queries expression or select's where clause.
* The sub query (the report query) will use its own expression builder be can reference expressions from the base expression builder.
* <p>Example:
* <blockquote><pre>
* ExpressionBuilder builder = new ExpressionBuilder();
* ReportQuery subQuery = new ReportQuery(Employee.class, new ExpressionBuilder());
* subQuery.setSelectionCriteria(subQuery.getExpressionBuilder().get("name").equal(builder.get("name")));
* builder.notExists(subQuery);
* </pre></blockquote>
*/
public Expression notExists(ReportQuery subQuery) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NotExists);
return anOperator.expressionFor(subQuery(subQuery));
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression notIn(byte[] theBytes) {
List values = new ArrayList(theBytes.length);
for (int index = 0; index < theBytes.length; index++) {
values.add(theBytes[index]);
}
return notIn(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression notIn(char[] theChars) {
List values = new ArrayList(theChars.length);
for (int index = 0; index < theChars.length; index++) {
values.add(theChars[index]);
}
return notIn(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression notIn(double[] theDoubles) {
List values = new ArrayList(theDoubles.length);
for (int index = 0; index < theDoubles.length; index++) {
values.add(theDoubles[index]);
}
return notIn(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression notIn(float[] theFloats) {
List values = new ArrayList(theFloats.length);
for (int index = 0; index < theFloats.length; index++) {
values.add(theFloats[index]);
}
return notIn(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression notIn(int[] theInts) {
List values = new ArrayList(theInts.length);
for (int index = 0; index < theInts.length; index++) {
values.add(theInts[index]);
}
return notIn(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression notIn(long[] theLongs) {
List values = new ArrayList(theLongs.length);
for (int index = 0; index < theLongs.length; index++) {
values.add(theLongs[index]);
}
return notIn(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression notIn(Object[] theObjects) {
List values = new ArrayList(theObjects.length);
for (int index = 0; index < theObjects.length; index++) {
values.add(theObjects[index]);
}
return notIn(values);
}
public Expression notIn(ReportQuery subQuery) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NotInSubQuery);
return anOperator.expressionFor(this, subQuery);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression notIn(short[] theShorts) {
List values = new ArrayList(theShorts.length);
for (int index = 0; index < theShorts.length; index++) {
values.add(theShorts[index]);
}
return notIn(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression notIn(boolean[] theBooleans) {
List values = new ArrayList(theBooleans.length);
for (int index = 0; index < theBooleans.length; index++) {
values.add(theBooleans[index]);
}
return notIn(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* The collection can be a collection of constants or expressions.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("age").in(ages)
* Java: ages.contains(employee.getAge())
* SQL: AGE IN (55, 18, 30)
* </pre></blockquote>
*/
public Expression notIn(Collection theObjects) {
return notIn(new CollectionExpression(theObjects, this));
}
public Expression notIn(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NotIn);
return anOperator.expressionFor(this, arguments);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not like the other value.
* Equivalent to like negated.
* @see #like(String)
*/
public Expression notLike(String aString) {
return notLike(new ConstantExpression(aString, this));
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not like the other value.
* Equivalent to like negated.
* @see #like(String)
*/
public Expression notLike(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NotLike);
return anOperator.expressionFor(this, arguments);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not like the other value.
* Equivalent to like negated.
* @param value string to compare
* @param escapeSequence the escape character to use
* @see #like(String)
*/
public Expression notLike(String value, String escapeSequence) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NotLikeEscape);
List args = new ArrayList(2);
args.add(value);
args.add(escapeSequence);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Return an expression that compares if the receivers value is not like the other value.
* Equivalent to like negated.
* @param value string to compare
* @param escapeSequence the escape character to use
* @see #like(String)
*/
public Expression notLike(Expression value, Expression escapeSequence) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NotLikeEscape);
List args = new ArrayList(2);
args.add(value);
args.add(escapeSequence);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Return an expression representing a comparison to null
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("age").notNull()
* Java: employee.getAge() != null
* SQL: AGE IS NOT NULL
* </pre></blockquote>
*/
public Expression notNull() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.NotNull);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Return an expression that is the boolean logical combination of both expressions.
* This is equivalent to the SQL "OR" operator and the Java "||" operator.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").equal("Bob").OR(employee.get("lastName").equal("Smith"))
* Java: (employee.getFirstName().equals("Bob")) || (employee.getLastName().equals("Smith"))
* SQL: F_NAME = 'Bob' OR L_NAME = 'Smith'
* </pre></blockquote>
*/
public Expression or(Expression theExpression) {
// Allow ands with null.
if (theExpression == null) {
return this;
}
ExpressionBuilder base = getBuilder();
Expression expressionToUse = theExpression;
// Ensure the same builder, unless a parralel query is used.
if ((theExpression.getBuilder() != base) && (theExpression.getBuilder().getQueryClass() == null)) {
expressionToUse = theExpression.rebuildOn(base);
}
if (base == this) {// Allow and to be sent to the builder.
return expressionToUse;
}
ExpressionOperator anOperator = getOperator(ExpressionOperator.Or);
return anOperator.expressionFor(this, expressionToUse);
}
/**
* INTERNAL:
*/
public Expression performOperator(ExpressionOperator anOperator, List args) {
return anOperator.expressionForArguments(this, args);
}
protected void postCopyIn(Map alreadyDone) {
}
/**
* ADVANCED:
* Inserts the SQL as is directly into the expression.
* The sql will be printed immediately after (postfixed to) the sql for
* <b>this</b>.
* Warning: Allowing an unverified SQL string to be passed into this
* method makes your application vulnerable to SQL injection attacks.
*/
public Expression postfixSQL(String sqlString) {
ExpressionOperator anOperator = new ExpressionOperator();
anOperator.setType(ExpressionOperator.FunctionOperator);
List<String> v = new ArrayList<>(1);
v.add(sqlString);
anOperator.printsAs(v);
anOperator.bePostfix();
anOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
return anOperator.expressionFor(this);
}
/**
* ADVANCED:
* Insert the SQL as is directly into the expression.
* The sql will be printed immediately before (prefixed to) the sql for
* <b>this</b>.
* Warning: Allowing an unverified SQL string to be passed into this
* method makes your application vulnerable to SQL injection attacks.
*/
public Expression prefixSQL(String sqlString) {
ExpressionOperator anOperator = new ExpressionOperator();
anOperator.setType(ExpressionOperator.FunctionOperator);
List<String> v = new ArrayList<>(1);
v.add(sqlString);
anOperator.printsAs(v);
anOperator.bePrefix();
anOperator.setNodeClass(ClassConstants.FunctionExpression_Class);
return anOperator.expressionFor(this);
}
/**
* INTERNAL:
* Print SQL
*/
public abstract void printSQL(ExpressionSQLPrinter printer);
/**
* INTERNAL:
* Print java for project class generation
*/
public void printJava(ExpressionJavaPrinter printer) {
//do nothing
}
/**
* INTERNAL:
* This expression is built on a different base than the one we want. Rebuild it and
* return the root of the new tree
* If receiver is a complex expression, use cloneUsing(newBase) instead.
* @see #cloneUsing(Expression newBase)
*/
public abstract Expression rebuildOn(Expression newBase);
/**
* INTERNAL:
* Search the tree for any expressions (like SubSelectExpressions) that have been
* built using a builder that is not attached to the query. This happens in case of an Exists
* call using a new ExpressionBuilder(). This builder needs to be replaced with one from the query.
*/
public abstract void resetPlaceHolderBuilder(ExpressionBuilder queryBuilder);
/**
* ADVANCED:
* For Object-relational support.
*/
public Expression ref() {
return getFunction(ExpressionOperator.Ref);
}
protected Expression registerIn(Map alreadyDone) {
Expression copy = shallowClone();
alreadyDone.put(this, copy);
copy.postCopyIn(alreadyDone);
return copy;
}
/**
* PUBLIC:
* Function, returns the string with occurances of the first substring replaced with the second substring.
*/
public Expression replace(Object stringToReplace, Object stringToReplaceWith) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Replace);
List args = new ArrayList(2);
args.add(stringToReplace);
args.add(stringToReplaceWith);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* return the result of this query repeated a given number of times.
* Equivalent of the Sybase REPLICATE function
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("name").replicate(2)
* Java: NA
* SQL: REPLICATE(name, 2)
* </pre></blockquote>
*/
public Expression replicate(int constant) {
return replicate(Integer.valueOf(constant));
}
/**
* PUBLIC:
* return the result of this query repeated a given number of times.
* Equivalent of the Sybase REPLICATE function
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("name").replicate(2)
* Java: NA
* SQL: REPLICATE(name, 2)
* </pre></blockquote>
*/
public Expression replicate(Object theValue) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Replicate);
return anOperator.expressionFor(this, theValue);
}
/**
* Reset cached information here so that we can be sure we're accurate.
*/
protected void resetCache() {
}
/**
* PUBLIC:
* Function return the reverse of the query result. Equivalent of the
* Sybase REVERSE function
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("name").reverse()
* Java: NA
* SQL: REVERSE(name)
* </pre></blockquote>
*/
public Expression reverse() {
return getFunction(ExpressionOperator.Reverse);
}
/**
* PUBLIC:
* Function return a given number of characters starting at the
* right of a string. Equivalent to the Sybase RIGHT function
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("name").right(2)
* Java: NA
* SQL: RIGHT(name, 2)
* </pre></blockquote>
*/
public Expression right(int characters) {
return right(Integer.valueOf(characters));
}
/**
* PUBLIC:
* Function return a given number of characters starting at the
* right of a string. Equivalent to the Sybase RIGHT function
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("name").right(2)
* Java: NA
* SQL: RIGHT(name, 2)
* </pre></blockquote>
*/
public Expression right(Object characters) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Right);
return anOperator.expressionFor(this, characters);
}
/**
* PUBLIC:
* Function, returns the string padded with the substring to the size.
*/
public Expression rightPad(int size, Object substring) {
return rightPad(Integer.valueOf(size), substring);
}
/**
* PUBLIC:
* Function, returns the string padded with the substring to the size.
*/
public Expression rightPad(Object size, Object substring) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.RightPad);
List args = new ArrayList(2);
args.add(size);
args.add(substring);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Function, returns the string right trimmed for white space.
*/
public Expression rightTrim() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.RightTrim);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Function, returns the string with the substring trimed from the right.
*/
public Expression rightTrim(Object substring) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.RightTrim2);
return anOperator.expressionFor(this, substring);
}
/**
* PUBLIC:
* Function, returns the date rounded to the year, month or day.
*/
public Expression roundDate(Object yearOrMonthOrDayRoundToken) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.RoundDate);
return anOperator.expressionFor(this, yearOrMonthOrDayRoundToken);
}
/**
* PUBLIC:
* Return whether this expression should be included in the SELECT clause if it is used
* in an ORDER BY clause
*/
public boolean selectIfOrderedBy() {
return selectIfOrderedBy;
}
/**
* INTERNAL:
* Set the local base expression, ie the one on the other side of the operator
* Most types will ignore this, since they don't need it.
*/
public void setLocalBase(Expression exp) {
}
/**
* PUBLIC:
* Set whether this expression should be included in the SELECT clause of a query
* that uses it in the ORDER BY clause.
*
*/
public void setSelectIfOrderedBy(boolean selectIfOrderedBy) {
this.selectIfOrderedBy = selectIfOrderedBy;
}
/**
* INTERNAL:
*/
public Expression shallowClone() {
Expression result = null;
try {
result = (Expression)super.clone();
} catch (CloneNotSupportedException exception) {
throw new InternalError(exception.toString());
}
return result;
}
/**
* PUBLIC: A logical expression for the size of collection <code>attributeName</code>.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.size("phoneNumbers")
* Java: employee.getPhoneNumbers().size()
* SQL: SELECT ... FROM EMP t0 WHERE ...
* (SELECT COUNT(*) FROM PHONE t1 WHERE (t0.EMP_ID = t1.EMP_ID))
* </pre></blockquote>
* This is a case where a fast operation in java does not translate to an
* equally fast operation in SQL, requiring a correlated subselect.
*/
public Expression size(String attributeName) {
return SubSelectExpression.createSubSelectExpressionForCount(this, this, attributeName, null);
}
/**
* PUBLIC: A logical expression for the size of collection expression.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.size(Class returnType)
* Java: employee.getPhoneNumbers().size()
* SQL: SELECT ... FROM EMP t0 WHERE ...
* (SELECT COUNT(*) FROM PHONE t1 WHERE (t0.EMP_ID = t1.EMP_ID))
* </pre></blockquote>
* This is a case where a fast operation in java does not translate to an
* equally fast operation in SQL, requiring a correlated subselect.
*/
public Expression size(Class returnType) {
if (((BaseExpression)this).getBaseExpression() == null){
return SubSelectExpression.createSubSelectExpressionForCount(this, this, null, returnType);
}
return SubSelectExpression.createSubSelectExpressionForCount(((BaseExpression)this).getBaseExpression(), this, null, returnType);
}
/**
* PUBLIC:
* This represents the aggregate function StandardDeviation. Can be used only within Report Queries.
*/
public Expression standardDeviation() {
return getFunction(ExpressionOperator.StandardDeviation);
}
/**
* PUBLIC:
* Return a sub query expression.
* A sub query using a report query to define a subselect within another queries expression or select's where clause.
* The sub query (the report query) will use its own expression builder be can reference expressions from the base expression builder.
* <p>Example:
* <blockquote><pre>
* ExpressionBuilder builder = new ExpressionBuilder();
* ReportQuery subQuery = new ReportQuery(Employee.class, new ExpressionBuilder());
* subQuery.addMaximum("salary");
* builder.get("salary").equal(builder.subQuery(subQuery));
* </pre></blockquote>
*/
public Expression subQuery(ReportQuery subQuery) {
return new SubSelectExpression(subQuery, this);
}
/**
* PUBLIC:
* Function, returns the substring from the source string.
* EclipseLink: employee.get("firstName").substring(1, 2)
* Java: NA
* SQL: SUBSTR(FIRST_NAME, 1, 2)
*/
public Expression substring(int startPosition, int size) {
return substring(Integer.valueOf(startPosition), Integer.valueOf(size));
}
/**
* PUBLIC:
* Function, returns the substring from the source string.
* EclipseLink: employee.get("firstName").substring(1, 2)
* Java: NA
* SQL: SUBSTR(FIRST_NAME, 1, 2)
*/
public Expression substring(Object startPosition, Object size) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Substring);
List args = new ArrayList(2);
args.add(startPosition);
args.add(size);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Function, returns the substring from the source string.
* EclipseLink: employee.get("firstName").substring(1)
* Java: NA
* SQL: SUBSTR(FIRST_NAME, 1)
*/
public Expression substring(int startPosition) {
return substring(Integer.valueOf(startPosition));
}
/**
* PUBLIC:
* Function, returns the substring from the source string.
* EclipseLink: employee.get("firstName").substring(1)
* Java: NA
* SQL: SUBSTR(FIRST_NAME, 1)
*/
public Expression substring(Object startPosition) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.SubstringSingleArg);
List args = new ArrayList(1);
args.add(startPosition);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* This represents the aggregate function Sum. Can be used only within Report Queries.
*/
public Expression sum() {
return getFunction(ExpressionOperator.Sum);
}
/**
* PUBLIC:
* Function, returns the single character string with the ascii or character set value.
*/
public Expression toCharacter() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Chr);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Function, returns date from the string using the default format.
*/
public Expression toDate() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.ToDate);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Return an expression that represents the receiver value converted to a character string.
* This is equivalent to the SQL "TO_CHAR" operator and Java "toString" method.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("salary").toChar().equal("100000")
* Java: employee.getSalary().toString().equals("100000")
* SQL: TO_CHAR(SALARY) = '100000'
* </pre></blockquote>
*/
public Expression toChar() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.ToChar);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Return an expression that represents the receiver value converted to a character string,
* with the database formating options (i.e. 'year', 'yyyy', 'day', etc.).
* This is equivalent to the SQL "TO_CHAR" operator and Java Date API.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("startDate").toChar("day").equal("monday")
* Java: employee.getStartDate().getDay().equals("monday")
* SQL: TO_CHAR(START_DATE, 'day') = 'monday'
* </pre></blockquote>
*/
public Expression toChar(String format) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.ToCharWithFormat);
return anOperator.expressionFor(this, format);
}
/**
* PUBLIC:
* Return an expression that represents the receiver value converted to lower case.
* This is equivalent to the SQL "LOWER" operator and Java "toLowerCase" method.
* This is only allowed for String attribute values.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").toLowerCase().equal("bob")
* Java: employee.getFirstName().toLowerCase().equals("bob")
* SQL: LOWER(F_NAME) = 'bob'
* </pre></blockquote>
*/
public Expression toLowerCase() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.ToLowerCase);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Function, returns the number converted from the string.
*/
public Expression toNumber() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.ToNumber);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Print a debug form of the expression tree.
*/
@Override
public String toString() {
try {
StringWriter innerWriter = new StringWriter();
BufferedWriter outerWriter = new BufferedWriter(innerWriter);
toString(outerWriter, 0);
outerWriter.flush();
return innerWriter.toString();
} catch (IOException e) {
return ToStringLocalization.buildMessage("error_printing_expression", null);
}
}
/**
* INTERNAL:
* Print a debug form of the expression tree.
*/
public void toString(BufferedWriter writer, int indent) throws IOException {
writer.newLine();
for (int i = 0; i < indent; i++) {
writer.write(" ");
}
writer.write(descriptionOfNodeType());
writer.write(" ");
writeDescriptionOn(writer);
writeSubexpressionsTo(writer, indent + 1);
}
/**
* PUBLIC:
* Return an expression that represents the receiver value converted to upper case.
* This is equivalent to the SQL "UPPER" operator and Java "toUpperCase" method.
* This is only allowed for String attribute values.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("firstName").toUpperCase().equal("BOB")
* Java: employee.getFirstName().toUpperCase().equals("BOB")
* SQL: UPPER(F_NAME) = 'BOB'
* </pre></blockquote>
*/
public Expression toUpperCase() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.ToUpperCase);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Function, returns the string with the first letter of each word capitalized.
*/
public Expression toUppercaseCasedWords() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Initcap);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Function, returns the string with each char from the from string converted to the char in the to string.
*/
public Expression translate(Object fromString, Object toString) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Translate);
List args = new ArrayList(2);
args.add(fromString);
args.add(toString);
return anOperator.expressionForArguments(this, args);
}
/**
* PUBLIC:
* Function, returns the string trimmed for white space.
*/
public Expression trim() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Trim);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Function, returns the string right and left trimmed for the substring.
*/
public Expression trim(Object substring) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Trim2);
return anOperator.expressionFor(this, substring);
}
/**
* PUBLIC:
* XMLType Function, extracts a secton of XML from a larget XML document
* @param xpath XPath expression representing the node to be returned
*/
public Expression extractXml(String xpath) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.ExtractXml);
return anOperator.expressionFor(this, xpath);
}
/**
* PUBLIC:
* Extract the date part from the date/time value.
* EXTRACT is part of the SQL standard, so should be supported by most databases.
* @param part is the date part to extract, "YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND", "TIMEZONE_HOUR", "TIMEZONE_MINUTE".
*/
public Expression extract(String part) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Extract);
return anOperator.expressionFor(this, literal(part));
}
/**
* PUBLIC:
* Cast the value to the database type.
* CAST is part of the SQL standard, so should be supported by most databases.
* @param type is the database type name, this is database specific but should include, "CHAR", "VARCHAR", "NUMERIC", "INTEGER", "DATE", "TIME", "TIMESTAMP",
* the type may include a size and scale.
*/
public Expression cast(String type) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Cast);
return anOperator.expressionFor(this, literal(type));
}
/**
* PUBLIC:
* XMLType Function, extracts a value from an XMLType field
* @param xpath XPath expression
*/
public Expression extractValue(String xpath) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.ExtractValue);
return anOperator.expressionFor(this, xpath);
}
/**
* PUBLIC:
* XMLType Function, gets the number of nodes returned by the given xpath expression
* returns 0 if there are none
* @param xpath Xpath expression
*/
public Expression existsNode(String xpath) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.ExistsNode);
return anOperator.expressionFor(this, xpath);
}
/**
* PUBLIC:
* XMLType Function - evaluates to 0 if the xml is a well formed document and 1 if the document
* is a fragment
*/
public Expression isFragment() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.IsFragment);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* XMLType Function - gets a string value from an XMLType
*/
public Expression getStringVal() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.GetStringVal);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* XMLType Function - gets a number value from an XMLType
*/
public Expression getNumberVal() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.GetNumberVal);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* return the date truncated to the indicated datePart. Equivalent
* to the Sybase TRUNC function for dates
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("date").truncDate(year)
* Java: NA
* SQL: TRUNC(date, year)
* </pre></blockquote>
*/
public Expression truncateDate(String datePart) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.TruncateDate);
return anOperator.expressionFor(this, datePart);
}
/**
* INTERNAL:
* We are given an expression that comes from a different context than the one in which this was built,
* e.g. it is the selection criteria of a mapping, or the criteria on which multiple tables are joined in a descriptor.
* We need to transform it so it refers to the objects we are dealing with, and AND it into the rest of our expression.
*
* We want to replace the original base expression with (newBase), and any parameters will be given values based
* on the context which (this) provides.
*
* For example, suppose that the main expression is
* emp.address.streetName = 'something'
* and we are trying to twist the selection criteria for the mapping 'address' in Employee. Because that mapping
* selects addresses, we will use the 'address' node as the base. Values for any parameters will come from the 'emp' node,
* which was the base of the original expression. Note that the values need not be constants, they can be fields.
*
* We do this by taking the tree we're trying to merge and traverse it more or less re-executing it
* it with the appropriate initial receiver and context.
* Return the root of the new expression tree. This will probably need to be AND'ed with the root of the old tree.
*/
public Expression twist(Expression expression, Expression newBase) {
if (expression == null) {
return null;
}
return expression.twistedForBaseAndContext(newBase, this, null);
}
/**
* INTERNAL:
* Rebuild myself against the base, with the values of parameters supplied by the context
* expression. This is used for transforming a standalone expression (e.g. the join criteria of a mapping)
* into part of some larger expression. You normally would not call this directly, instead calling twist
* See the comment there for more details"
*/
public Expression twistedForBaseAndContext(Expression newBase, Expression context, Expression oldBase) {
// Will be overridden by subclasses
return this;
}
/**
* INTERNAL:
* Do any required validation for this node. Throw an exception for any incorrect constructs.
*/
public void validateNode() {
}
/**
* PUBLIC:
* Function, this represents the value function, used in nestedtable
*/
public Expression value() {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Value);
return anOperator.expressionFor(this);
}
/**
* PUBLIC:
* Return an expression on the constant.
* <p>Example:
* <blockquote><pre>
* reportQuery.addItem("a constant", builder.value("a constant"));
* </pre></blockquote>
*/
public Expression value(byte constant) {
return value(Byte.valueOf(constant));
}
/**
* PUBLIC:
* Return an expression on the constant.
* <p>Example:
* <blockquote><pre>
* reportQuery.addItem("a constant", builder.value("a constant"));
* </pre></blockquote>
*/
public Expression value(char constant) {
return value(Character.valueOf(constant));
}
/**
* PUBLIC:
* Return an expression on the constant.
* <p>Example:
* <blockquote><pre>
* reportQuery.addItem("a constant", builder.value("a constant"));
* </pre></blockquote>
*/
public Expression value(double constant) {
return value(Double.valueOf(constant));
}
/**
* PUBLIC:
* Return an expression on the constant.
* <p>Example:
* <blockquote><pre>
* reportQuery.addItem("a constant", builder.value("a constant"));
* </pre></blockquote>
*/
public Expression value(float constant) {
return value(Float.valueOf(constant));
}
/**
* PUBLIC:
* Return an expression on the constant.
* <p>Example:
* <blockquote><pre>
* reportQuery.addItem("a constant", builder.value("a constant"));
* </pre></blockquote>
*/
public Expression value(int constant) {
return value(Integer.valueOf(constant));
}
/**
* PUBLIC:
* Return an expression on the constant.
* <p>Example:
* <blockquote><pre>
* reportQuery.addItem("a constant", builder.value("a constant"));
* </pre></blockquote>
*/
public Expression value(long constant) {
return value(Long.valueOf(constant));
}
/**
* PUBLIC:
* Return an expression on the constant.
* <p>Example:
* <blockquote><pre>
* reportQuery.addItem("a constant", builder.value("a constant"));
* </pre></blockquote>
*/
public Expression value(Object constant) {
return new ConstantExpression(constant, this);
}
/**
* PUBLIC:
* Return an expression on the constant.
* <p>Example:
* <blockquote><pre>
* reportQuery.addItem("a constant", builder.value("a constant"));
* </pre></blockquote>
*/
public Expression value(short constant) {
return value(Short.valueOf(constant));
}
/**
* PUBLIC:
* Return an expression on the constant.
* <p>Example:
* <blockquote><pre>
* reportQuery.addItem("a constant", builder.value("a constant"));
* </pre></blockquote>
*/
public Expression value(boolean constant) {
return value(Boolean.valueOf(constant));
}
/**
* ADVANCED:
* Return an expression on the literal.
* A literal is a specific SQL syntax string that will be printed as is without quotes in the SQL.
* It can be useful for printing database key words or global variables.
* <p>Example:
* <blockquote><pre>
* reportQuery.addItem("currentTime", builder.literal("SYSDATE"));
* </pre></blockquote>
*/
public Expression literal(String literal) {
return new LiteralExpression(literal, this);
}
/**
* ADVANCED:
* Return an expression for the alias.
* This allows an alias used in the select clause to be used in other clauses.
*/
public Expression alias(String alias) {
return literal(alias);
}
/**
* INTERNAL:
* Return the value for in memory comparison.
* This is only valid for valueable expressions.
* New parameter added for feature 2612601
* @param isObjectUnregistered true if object possibly not a clone, but is being
* conformed against the unit of work cache.
*/
public Object valueFromObject(Object object, AbstractSession session, AbstractRecord translationRow, int valueHolderPolicy, boolean isObjectUnregistered) {
throw QueryException.cannotConformExpression();
}
/**
* INTERNAL:
* Return the value for in memory comparison.
* This is only valid for valueable expressions.
*/
public Object valueFromObject(Object object, AbstractSession session, AbstractRecord translationRow, int valueHolderPolicy) {
return valueFromObject(object, session, translationRow, valueHolderPolicy, false);
}
/**
* PUBLIC:
* Function, this represents the aggregate function Variance. Can be used only within Report Queries.
*/
public Expression variance() {
return getFunction(ExpressionOperator.Variance);
}
/**
* INTERNAL:
* Used to print a debug form of the expression tree.
*/
public void writeDescriptionOn(BufferedWriter writer) throws IOException {
writer.write("some expression");
}
/**
* INTERNAL:
* Append the field name to the writer. Should be overridden for special operators such as functions.
*/
protected void writeField(ExpressionSQLPrinter printer, DatabaseField field, SQLSelectStatement statement) {
//print ", " before each selected field except the first one
if (printer.isFirstElementPrinted()) {
printer.printString(", ");
} else {
printer.setIsFirstElementPrinted(true);
}
if (statement.requiresAliases()) {
if (field.getTable() != lastTable) {
lastTable = field.getTable();
currentAlias = aliasForTable(lastTable);
}
printer.printString(currentAlias.getQualifiedNameDelimited(printer.getPlatform()));
printer.printString(".");
}
printer.printString(field.getNameDelimited(printer.getPlatform()));
//bug6070214: unique field aliases need to be generated when required.
if (statement.getUseUniqueFieldAliases()){
printer.printString(" AS " + statement.generatedAlias(field.getNameDelimited(printer.getPlatform())));
}
}
/**
* INTERNAL:
* Append the field's alias to the writer.
* This is used for pessimistic locking.
*/
protected void writeAlias(ExpressionSQLPrinter printer, DatabaseField field, SQLSelectStatement statement) {
//print ", " before each selected field except the first one
if (printer.isFirstElementPrinted()) {
printer.printString(", ");
} else {
printer.setIsFirstElementPrinted(true);
}
if (statement.requiresAliases()) {
if (field.getTable() != this.lastTable) {
this.lastTable = field.getTable();
this.currentAlias = aliasForTable(this.lastTable);
}
printer.printString(this.currentAlias.getQualifiedNameDelimited(printer.getPlatform()));
} else {
printer.printString(field.getTable().getQualifiedNameDelimited(printer.getPlatform()));
}
}
/**
* INTERNAL:
* called from SQLSelectStatement.writeFieldsFromExpression(...)
*/
public void writeFields(ExpressionSQLPrinter printer, List<DatabaseField> newFields, SQLSelectStatement statement) {
for (DatabaseField field : getSelectionFields(statement.getQuery())) {
newFields.add(field);
writeField(printer, field, statement);
}
}
/**
* INTERNAL:
* Used in SQL printing.
*/
public void writeSubexpressionsTo(BufferedWriter writer, int indent) throws IOException {
// In general, there are no sub-expressions
}
/**
*
* PUBLIC:
* Return an expression that is used with a comparison expression.
* The ANY keyword denotes that the search condition is TRUE if the comparison is TRUE
* for at least one of the values that is returned. If the subquery returns no value,
* the search condition is FALSE
*/
public Expression any(byte[] theBytes) {
List values = new ArrayList(theBytes.length);
for (int index = 0; index < theBytes.length; index++) {
values.add(theBytes[index]);
}
return any(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression any(char[] theChars) {
List values = new ArrayList(theChars.length);
for (int index = 0; index < theChars.length; index++) {
values.add(theChars[index]);
}
return any(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression any(double[] theDoubles) {
List values = new ArrayList(theDoubles.length);
for (int index = 0; index < theDoubles.length; index++) {
values.add(theDoubles[index]);
}
return any(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression any(float[] theFloats) {
List values = new ArrayList(theFloats.length);
for (int index = 0; index < theFloats.length; index++) {
values.add(theFloats[index]);
}
return any(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression any(int[] theInts) {
List values = new ArrayList(theInts.length);
for (int index = 0; index < theInts.length; index++) {
values.add(theInts[index]);
}
return any(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression any(long[] theLongs) {
List values = new ArrayList(theLongs.length);
for (int index = 0; index < theLongs.length; index++) {
values.add(theLongs[index]);
}
return any(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression any(Object[] theObjects) {
List values = new ArrayList(theObjects.length);
for (int index = 0; index < theObjects.length; index++) {
values.add(theObjects[index]);
}
return any(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression any(short[] theShorts) {
List values = new ArrayList(theShorts.length);
for (int index = 0; index < theShorts.length; index++) {
values.add(theShorts[index]);
}
return any(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression any(boolean[] theBooleans) {
List values = new ArrayList(theBooleans.length);
for (int index = 0; index < theBooleans.length; index++) {
values.add(theBooleans[index]);
}
return any(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("age").in(ages)
* Java: ages.contains(employee.getAge())
* SQL: AGE IN (55, 18, 30)
* </pre></blockquote>
*/
public Expression any(List theObjects) {
return any(new ConstantExpression(theObjects, this));
}
public Expression any(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Any);
return anOperator.expressionFor(this, arguments);
}
/**
* PUBLIC:
* Return a union expression with the subquery.
*/
public Expression union(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Union);
return anOperator.expressionFor(this, arguments);
}
/**
* PUBLIC:
* Return a intersect expression with the subquery.
*/
public Expression intersect(ReportQuery query) {
return intersect(subQuery(query));
}
/**
* PUBLIC:
* Return a intersect all expression with the subquery.
*/
public Expression intersectAll(ReportQuery query) {
return intersectAll(subQuery(query));
}
/**
* PUBLIC:
* Return a intersect expression with the subquery.
*/
public Expression intersect(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Intersect);
return anOperator.expressionFor(this, arguments);
}
/**
* PUBLIC:
* Return a except expression with the subquery.
*/
public Expression except(ReportQuery query) {
return except(subQuery(query));
}
/**
* PUBLIC:
* Return a except all expression with the subquery.
*/
public Expression exceptAll(ReportQuery query) {
return exceptAll(subQuery(query));
}
/**
* PUBLIC:
* Return a except expression with the subquery.
*/
public Expression except(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Except);
return anOperator.expressionFor(this, arguments);
}
/**
* PUBLIC:
* Return a union expression with the subquery.
*/
public Expression union(ReportQuery query) {
return union(subQuery(query));
}
/**
* PUBLIC:
* Return a union all expression with the subquery.
*/
public Expression unionAll(ReportQuery query) {
return unionAll(subQuery(query));
}
/**
* PUBLIC:
* Return a union all expression with the subquery.
*/
public Expression unionAll(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.UnionAll);
return anOperator.expressionFor(this, arguments);
}
/**
* PUBLIC:
* Return a intersect all expression with the subquery.
*/
public Expression intersectAll(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.IntersectAll);
return anOperator.expressionFor(this, arguments);
}
/**
* PUBLIC:
* Return a except all expression with the subquery.
*/
public Expression exceptAll(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.ExceptAll);
return anOperator.expressionFor(this, arguments);
}
public Expression any(ReportQuery subQuery) {
return any(subQuery(subQuery));
}
/**
* PUBLIC:
* Return an expression that is used with a comparison expression.
* The SOME keyword denotes that the search condition is TRUE if the comparison is TRUE
* for at least one of the values that is returned. If the subquery returns no value,
* the search condition is FALSE
*/
public Expression some(byte[] theBytes) {
List values = new ArrayList(theBytes.length);
for (int index = 0; index < theBytes.length; index++) {
values.add(theBytes[index]);
}
return some(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression some(char[] theChars) {
List values = new ArrayList(theChars.length);
for (int index = 0; index < theChars.length; index++) {
values.add(theChars[index]);
}
return some(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression some(double[] theDoubles) {
List values = new ArrayList(theDoubles.length);
for (int index = 0; index < theDoubles.length; index++) {
values.add(theDoubles[index]);
}
return some(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression some(float[] theFloats) {
List values = new ArrayList(theFloats.length);
for (int index = 0; index < theFloats.length; index++) {
values.add(theFloats[index]);
}
return some(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression some(int[] theInts) {
List values = new ArrayList(theInts.length);
for (int index = 0; index < theInts.length; index++) {
values.add(theInts[index]);
}
return some(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression some(long[] theLongs) {
List values = new ArrayList(theLongs.length);
for (int index = 0; index < theLongs.length; index++) {
values.add(theLongs[index]);
}
return some(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression some(Object[] theObjects) {
List values = new ArrayList(theObjects.length);
for (int index = 0; index < theObjects.length; index++) {
values.add(theObjects[index]);
}
return some(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression some(short[] theShorts) {
List values = new ArrayList(theShorts.length);
for (int index = 0; index < theShorts.length; index++) {
values.add(theShorts[index]);
}
return some(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression some(boolean[] theBooleans) {
List values = new ArrayList(theBooleans.length);
for (int index = 0; index < theBooleans.length; index++) {
values.add(theBooleans[index]);
}
return some(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("age").in(ages)
* Java: ages.contains(employee.getAge())
* SQL: AGE IN (55, 18, 30)
* </pre></blockquote>
*/
public Expression some(List theObjects) {
return some(new ConstantExpression(theObjects, this));
}
public Expression some(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.Some);
return anOperator.expressionFor(this, arguments);
}
public Expression some(ReportQuery subQuery) {
return some(subQuery(subQuery));
}
/**
*
* PUBLIC:
* Return an expression that is used with a comparison expression.
* The SOME keyword denotes that the search condition is TRUE if the comparison is TRUE
* for at least one of the values that is returned. If the subquery returns no value,
* the search condition is FALSE
*/
public Expression all(byte[] theBytes) {
List values = new ArrayList(theBytes.length);
for (int index = 0; index < theBytes.length; index++) {
values.add(theBytes[index]);
}
return all(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression all(char[] theChars) {
List values = new ArrayList(theChars.length);
for (int index = 0; index < theChars.length; index++) {
values.add(theChars[index]);
}
return all(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression all(double[] theDoubles) {
List values = new ArrayList(theDoubles.length);
for (int index = 0; index < theDoubles.length; index++) {
values.add(theDoubles[index]);
}
return all(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression all(float[] theFloats) {
List values = new ArrayList(theFloats.length);
for (int index = 0; index < theFloats.length; index++) {
values.add(theFloats[index]);
}
return all(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression all(int[] theInts) {
List values = new ArrayList(theInts.length);
for (int index = 0; index < theInts.length; index++) {
values.add(theInts[index]);
}
return all(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression all(long[] theLongs) {
List values = new ArrayList(theLongs.length);
for (int index = 0; index < theLongs.length; index++) {
values.add(theLongs[index]);
}
return all(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression all(Object[] theObjects) {
List values = new ArrayList(theObjects.length);
for (int index = 0; index < theObjects.length; index++) {
values.add(theObjects[index]);
}
return all(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression all(short[] theShorts) {
List values = new ArrayList(theShorts.length);
for (int index = 0; index < theShorts.length; index++) {
values.add(theShorts[index]);
}
return all(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
*/
public Expression all(boolean[] theBooleans) {
List values = new ArrayList(theBooleans.length);
for (int index = 0; index < theBooleans.length; index++) {
values.add(theBooleans[index]);
}
return all(values);
}
/**
* PUBLIC:
* Return an expression that checks if the receivers value is contained in the collection.
* This is equivalent to the SQL "IN" operator and Java "contains" operator.
* <p>Example:
* <blockquote><pre>
* EclipseLink: employee.get("age").in(ages)
* Java: ages.contains(employee.getAge())
* SQL: AGE IN (55, 18, 30)
* </pre></blockquote>
*/
public Expression all(List theObjects) {
return all(new ConstantExpression(theObjects, this));
}
public Expression all(Expression arguments) {
ExpressionOperator anOperator = getOperator(ExpressionOperator.All);
return anOperator.expressionFor(this, arguments);
}
public Expression all(ReportQuery subQuery) {
return all(subQuery(subQuery));
}
/**
* INTERNAL:
* Lookup the descriptor for this item by traversing its expression recursively.
*/
public ClassDescriptor getLeafDescriptor(DatabaseQuery query, ClassDescriptor rootDescriptor, AbstractSession session) {
return null;
}
/**
* INTERNAL:
* Lookup the mapping for this item by traversing its expression recursively.
* If an aggregate of foreign mapping is found it is traversed.
*/
public DatabaseMapping getLeafMapping(DatabaseQuery query, ClassDescriptor rootDescriptor, AbstractSession session) {
return null;
}
}