All Implemented Interfaces:
Serializable, Cloneable
Direct Known Subclasses:
ClassTypeExpression, FieldExpression, ObjectExpression, TableExpression

public abstract class DataExpression extends BaseExpression
Superclass for all expression that have a context. i.e. a base expression.
See Also:
  • Field Details

    • derivedTables

      protected List<Expression> derivedTables
    • derivedFields

      protected List<Expression> derivedFields
    • hasBeenNormalized

      protected boolean hasBeenNormalized
    • tableAliases

      protected TableAliasLookup tableAliases
    • asOfClause

      protected AsOfClause asOfClause
  • Constructor Details

    • DataExpression

      protected DataExpression()
      DataExpression constructor comment.
  • Method Details

    • equals

      public boolean equals(Object object)
      INTERNAL: Return if the expression is equal to the other. This is used to allow dynamic expression's SQL to be cached.
      Overrides:
      equals in class Expression
    • addDerivedField

      public void addDerivedField(Expression addThis)
    • addDerivedTable

      public void addDerivedTable(Expression addThis)
    • asOf

      public Expression asOf(AsOfClause clause)
      Description copied from class: Expression
      Sets all tables represented by this expression to be queried as of a past time.

      Example:

        EclipseLink: employee.asOf(new AsOfClause(pastTime))
        Java: None
        SQL (Flashback): SELECT ... FROM EMPLOYEE AS OF TIMESTAMP (pastTime) t0 ...
        SQL (Generic): .. WHERE (t1.START <= pastTime) AND ((t1.END IS NULL) OR t1.END > pastTime)
       

      Set an as of clause at the expression level to still query for current objects while expressing selection criteria like:

      • query objects as of one time that met some condition at another time.
      • query objects that changed a certain way over a certain interval (querying for change).

      Simultaneously querying on two versions of the same object (one past one present) lets you express these advanced selection criteria.

      Example: Querying on past attributes using parallel expressions.

         // 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));
       

      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.

      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.

      Example: Querying on object changes using parallel expressions.

         // 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")));
       

      Example: Querying on object changes using custom query keys

         // 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"));
       

      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.

      Full Reference:

      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.

      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:

      • employee.asOf(pastTime).anyOf("projects"): projects as of past time.
      • expressionBuilder.asOf(pastTime): entire expression as of past time.
      • employee.asOf(pastTime).anyOf("projects").asOf(null): projects as of current time.
      • employee.anyOf("projects").asOf(pastTime): projects only as of past time.

      Watch out for x.asOf(oneTime).get("y").asOf(anotherTime).

      • emp.anyOf("phoneNumbers").asOf(yesterday) = emp.asOf(yesterday).anyOf("phoneNumbers") but:
      • emp.get("address").asOf(yesterday) != emp.asOf(yesterday).get("address").
      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.'
      Overrides:
      asOf in class Expression
      Parameters:
      clause - A read only data object used to represent a past time.
      Returns:
      this
      See Also:
    • aliasForTable

      public DatabaseTable aliasForTable(DatabaseTable table)
      INTERNAL: Find the alias for a given table
      Overrides:
      aliasForTable in class Expression
    • assignAlias

      protected void assignAlias(String name, DatabaseTable table)
      INTERNAL: Alias a particular table within this node
      Overrides:
      assignAlias in class Expression
    • assignAlias

      protected void assignAlias(DatabaseTable alias, DatabaseTable table)
      INTERNAL: Alias a particular table within this node
    • clearAliases

      public void clearAliases()
      INTERNAL:
    • copyCollection

      public List<Expression> copyCollection(List<Expression> in, Map alreadyDone)
    • existingDerivedField

      public Expression existingDerivedField(DatabaseField field)
      INTERNAL:
    • existingDerivedTable

      public Expression existingDerivedTable(DatabaseTable table)
      INTERNAL:
    • getAliasedField

      public DatabaseField getAliasedField()
      INTERNAL: Return the field appropriately aliased
    • getAsOfClause

      public AsOfClause getAsOfClause()
      Description copied from class: Expression
      Answers the past time the expression is explicitly as of.
      Overrides:
      getAsOfClause in class Expression
      Returns:
      An immutable object representation of the past time. null if no clause set, AsOfClause.NO_CLAUSE if clause explicitly set to null.
      See Also:
    • getDescriptor

      public ClassDescriptor getDescriptor()
    • getField

      public DatabaseField getField()
      INTERNAL:
    • getField

      public Expression getField(String fieldName)
      Description copied from class: Expression
      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.

      Example:

        builder.getField("ADDR_ID").greaterThan(100);
        builder.getTable("PROJ_EMP").getField("TYPE").equal("S");
       
      Overrides:
      getField in class Expression
    • getField

      public Expression getField(DatabaseField field)
      Description copied from class: Expression
      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.

      Example:

        builder.getField(aField).greaterThan(100);
       
      Overrides:
      getField in class Expression
    • getContainingDescriptor

      public ClassDescriptor getContainingDescriptor()
      INTERNAL: Return the descriptor which contains this query key.
    • getMapping

      public DatabaseMapping getMapping()
    • getQueryKeyOrNull

      public QueryKey getQueryKeyOrNull()
    • getTable

      public Expression getTable(String tableName)
      Description copied from class: Expression
      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.

      Example:

        builder.getTable("PROJ_EMP").getField("TYPE").equal("S");
       
      Overrides:
      getTable in class Expression
    • getTable

      public Expression getTable(DatabaseTable table)
      Description copied from class: Expression
      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.

      Example:

        builder.getTable(linkTable).getField("TYPE").equal("S");
       
      Overrides:
      getTable in class Expression
    • getTableAliases

      public TableAliasLookup getTableAliases()
      INTERNAL: Return the aliases used. For CR#2456 must never lazily initialize as also used for Expression identity.
      Overrides:
      getTableAliases in class Expression
    • hasBeenNormalized

      public boolean hasBeenNormalized()
      INTERNAL: Did the normalizer already add additional joins to the where clause due to this query key representing a foreign reference mapping? This insures that join criteria (for any query key expression) is not added twice.

      New meaning: DataExpressions are often iterated on multiple times during normalize, but Function/Relation expressions only once. Adding a has been normalized flag improves performance and is required in some applications, such as have temporal query criteria been added.

    • hasAsOfClause

      public boolean hasAsOfClause()
      Description copied from class: Expression
      ADVANCED: Answers true if this is to be queried as of a past time.
      Overrides:
      hasAsOfClause in class Expression
      Returns:
      false from asOf(null); hasAsOfClause().
      See Also:
    • hasBeenAliased

      public boolean hasBeenAliased()
      Description copied from class: Expression
      INTERNAL: Answers if the database tables associated with this expression have been aliased. This insures the same tables are not aliased twice.
      Overrides:
      hasBeenAliased in class Expression
    • hasDerivedFields

      protected boolean hasDerivedFields()
    • hasDerivedTables

      protected boolean hasDerivedTables()
    • isAttribute

      public boolean isAttribute()
      INTERNAL:
    • isDataExpression

      public boolean isDataExpression()
      Description copied from class: Expression
      INTERNAL:
      Overrides:
      isDataExpression in class Expression
    • iterateOn

      public void iterateOn(ExpressionIterator iterator)
      INTERNAL: For iterating using an inner class
      Overrides:
      iterateOn in class Expression
    • newDerivedField

      public Expression newDerivedField(DatabaseField field)
      INTERNAL:
    • newDerivedTable

      public Expression newDerivedTable(DatabaseTable table)
      INTERNAL:
    • getAlias

      public Expression getAlias(Expression subSelect)
      ADVANCED: Return an expression representing a sub-select in the from clause.

      Example:

        builder.getAlias(builder.subQuery(reportQuery)).get("type").equal("S");
       
      Overrides:
      getAlias in class Expression
    • normalize

      public Expression normalize(ExpressionNormalizer normalizer)
      INTERNAL: Normalize the expression into a printable structure. Any joins must be added to form a new root.
      Overrides:
      normalize in class Expression
    • postCopyIn

      protected void postCopyIn(Map alreadyDone)
      INTERNAL: Used for cloning.
      Overrides:
      postCopyIn in class BaseExpression
    • printSQL

      public void printSQL(ExpressionSQLPrinter printer)
      INTERNAL: Print SQL onto the stream, using the ExpressionPrinter for context
      Specified by:
      printSQL in class Expression
    • setHasBeenNormalized

      public void setHasBeenNormalized(boolean value)
    • setTableAliases

      public void setTableAliases(TableAliasLookup tableAliases)
      INTERNAL: For CR#2456, Table identity involves having two tables sharing the same aliasing table.
    • tableAliasesDescription

      public String tableAliasesDescription()
    • writeSubexpressionsTo

      public void writeSubexpressionsTo(BufferedWriter writer, int indent) throws IOException
      Print the base for debuggin purposes.
      Overrides:
      writeSubexpressionsTo in class Expression
      Throws:
      IOException