Class Expression

  • All Implemented Interfaces:
    java.io.Serializable, java.lang.Cloneable

    public final class Expression
    extends java.lang.Object
    implements java.io.Serializable, java.lang.Cloneable
    An expression that can be evaluated in a statement. This is used as a more complete and flexible version of 'Condition' as well as representing column and aggregate functions.

    This class can represent constant expressions (expressions that have no variable input), as well as variable expressions. Optimizations may be possible when evaluating constant expressions.

    Some examples of constant expressions;

       ( 9 + 3 ) * 90
       ( ? * 9 ) / 1
       lower("CaPS MUMma")
       40 & 0x0FF != 39
     
    Some examples of variable expressions;

       upper(Part.description)
       Part.id >= 50
       VendorMakesPart.part_id == Part.id
       Part.value_of <= Part.cost_of / 4
     

    NOTE: the expression is stored in postfix orientation. eg. "8 + 9 * 3" becomes "8,9,3,*,+"

    NOTE: This class is NOT thread safe. Do not use an expression instance between threads.

    See Also:
    Serialized Form
    • Field Summary

      Fields 
      Modifier and Type Field Description
      private java.util.ArrayList elements
      The list of elements followed by operators in our expression.
      private java.util.ArrayList eval_stack
      The evaluation stack for when the expression is evaluated.
      private static SQL expression_parser
      A static expression parser.
      (package private) static long serialVersionUID
      Serialization UID.
      private java.lang.StringBuffer text
      The expression as a plain human readable string.
    • Constructor Summary

      Constructors 
      Constructor Description
      Expression()
      Constructs a new Expression.
      Expression​(Expression exp)
      Constructs a copy of the given Expression.
      Expression​(Expression exp1, Operator op, Expression exp2)
      Constructs a new Expression from the concatination of expression1 and expression2 and the operator for them.
      Expression​(java.lang.Object ob)
      Constructs a new Expression with a single object element.
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void addElement​(java.lang.Object ob)
      Adds a new element into the expression.
      void addOperator​(Operator op)
      Adds a new operator into the expression.
      java.util.List allElements()
      Returns a complete list of all element objects that are in this expression and in the parameters of the functions of this expression.
      java.util.List allVariables()
      Returns a complete List of Variable objects in this expression not including correlated variables.
      java.util.ArrayList breakByOperator​(java.util.ArrayList list, java.lang.String logical_op)
      Breaks this expression into a list of sub-expressions that are split by the given operator.
      java.lang.Object clone()
      Performs a deep clone of this object, calling 'clone' on any elements that are mutable or shallow copying immutable members.
      Expression concat​(Expression expr)
      Merges an expression with this expression.
      boolean containsNotOperator()
      Returns true if the expression contains a NOT operator somewhere in it.
      void copyTextFrom​(Expression e)
      Copies the text from the given expression.
      java.util.ArrayList discoverCorrelatedVariables​(int level, java.util.ArrayList list)
      Discovers all the correlated variables in this expression.
      java.util.ArrayList discoverTableNames​(java.util.ArrayList list)
      Discovers all the tables in the sub-queries of this expression.
      java.lang.Object elementAt​(int n)
      Returns the element at the given position in the postfix list.
      private java.lang.Object elementToObject​(int n, GroupResolver group, VariableResolver resolver, QueryContext context)
      Returns the element at the given position in the expression list.
      TObject evaluate​(GroupResolver group, VariableResolver resolver, QueryContext context)
      Evaluates this expression and returns an Object that represents the result of the evaluation.
      TObject evaluate​(VariableResolver resolver, QueryContext context)
      Evaluation without a grouping table.
      Expression getEndExpression()
      Returns the end Expression of this expression.
      QueryPlanNode getQueryPlanNode()
      Returns the QueryPlanNode object in this expression if it evaluates to a single QueryPlanNode, otherwise returns null.
      Variable getVariable()
      Returns the Variable if this expression evaluates to a single variable, otherwise returns null.
      boolean hasAggregateFunction​(QueryContext context)
      Cascades through the expression and if any aggregate functions are found returns true, otherwise returns false.
      boolean hasSubQuery()
      Returns true if the expression has a subquery (eg 'in ( select ...
      boolean isConstant()
      Returns true if the expression doesn't include any variables or non constant functions (is constant).
      java.lang.Object last()
      Returns the element at the end of the postfix list (the last element).
      static Expression parse​(java.lang.String expression)
      Static method that parses the given string which contains an expression into an Expression object.
      private java.lang.Object pop()
      Pops an element from the evaluation stack.
      void prepare​(ExpressionPreparer preparer)
      A general prepare that cascades through the expression and its parents and substitutes an elements that the preparer wants to substitute.
      private void push​(java.lang.Object ob)
      Pushes an element onto the evaluation stack.
      private void readObject​(java.io.ObjectInputStream in)
      Reads the state of this object from the object stream.
      TType returnTType​(VariableResolver resolver, QueryContext context)
      Determines the type of object this expression evaluates to.
      void setElementAt​(int n, java.lang.Object ob)
      Sets the element at the given position in the postfix list.
      static Expression simple​(java.lang.Object ob1, Operator op, java.lang.Object ob2)
      Generates a simple expression from two objects and an operator.
      int size()
      Returns the number of elements and operators that are in this postfix list.
      Expression[] split()
      Returns an array of two Expression objects that represent the left hand and right and side of the last operator in the post fix notation.
      java.lang.StringBuffer text()
      Returns the StringBuffer that we can use to append plain text representation as we are parsing the expression.
      java.lang.String toString()
      Returns a string representation of this object for diagnostic purposes.
      private void writeObject​(java.io.ObjectOutputStream out)
      Writes the state of this object to the object stream.
      • Methods inherited from class java.lang.Object

        equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Field Detail

      • serialVersionUID

        static final long serialVersionUID
        Serialization UID.
        See Also:
        Constant Field Values
      • elements

        private java.util.ArrayList elements
        The list of elements followed by operators in our expression. The expression elements may be of any type represented by the database (see 'addElement' method for the accepted objects). The expression operators may be '+', '-', '*', '*', '/', '=', '>=', '<>', etc (as an Operator object (see the Operator class for details)).

        This list is stored in postfix order.

      • eval_stack

        private transient java.util.ArrayList eval_stack
        The evaluation stack for when the expression is evaluated.
      • text

        private java.lang.StringBuffer text
        The expression as a plain human readable string. This is in a form that can be readily parsed to an Expression object.
      • expression_parser

        private static final SQL expression_parser
        A static expression parser. To use this we must first synchronize over the object.
    • Constructor Detail

      • Expression

        public Expression()
        Constructs a new Expression.
      • Expression

        public Expression​(java.lang.Object ob)
        Constructs a new Expression with a single object element.
      • Expression

        public Expression​(Expression exp)
        Constructs a copy of the given Expression.
      • Expression

        public Expression​(Expression exp1,
                          Operator op,
                          Expression exp2)
        Constructs a new Expression from the concatination of expression1 and expression2 and the operator for them.
    • Method Detail

      • text

        public java.lang.StringBuffer text()
        Returns the StringBuffer that we can use to append plain text representation as we are parsing the expression.
      • copyTextFrom

        public void copyTextFrom​(Expression e)
        Copies the text from the given expression.
      • parse

        public static Expression parse​(java.lang.String expression)
        Static method that parses the given string which contains an expression into an Expression object. For example, this will parse strings such as '(a + 9) * 2 = b' or 'upper(concat('12', '56', id))'.

        Care should be taken to not use this method inside an inner loop because it creates a lot of objects.

      • simple

        public static Expression simple​(java.lang.Object ob1,
                                        Operator op,
                                        java.lang.Object ob2)
        Generates a simple expression from two objects and an operator.
      • addElement

        public void addElement​(java.lang.Object ob)
        Adds a new element into the expression. String, BigNumber, Boolean and Variable are the types of elements allowed.

        Must be added in postfix order.

      • concat

        public Expression concat​(Expression expr)
        Merges an expression with this expression. For example, given the expression 'ab', if the expression 'abc+-' was added the expression would become 'ababc+-'.

        This method is useful when copying parts of other expressions when forming an expression.

        This always returns this expression. This does not change 'text()'.

      • addOperator

        public void addOperator​(Operator op)
        Adds a new operator into the expression. Operators are represented as an Operator (eg. ">", "+", "<<", "!=" )

        Must be added in postfix order.

      • size

        public int size()
        Returns the number of elements and operators that are in this postfix list.
      • elementAt

        public java.lang.Object elementAt​(int n)
        Returns the element at the given position in the postfix list. Note, this can return Operator's.
      • last

        public java.lang.Object last()
        Returns the element at the end of the postfix list (the last element).
      • setElementAt

        public void setElementAt​(int n,
                                 java.lang.Object ob)
        Sets the element at the given position in the postfix list. This should be called after the expression has been setup to alter variable alias names, etc.
      • push

        private final void push​(java.lang.Object ob)
        Pushes an element onto the evaluation stack.
      • pop

        private final java.lang.Object pop()
        Pops an element from the evaluation stack.
      • allVariables

        public java.util.List allVariables()
        Returns a complete List of Variable objects in this expression not including correlated variables.
      • allElements

        public java.util.List allElements()
        Returns a complete list of all element objects that are in this expression and in the parameters of the functions of this expression.
      • prepare

        public void prepare​(ExpressionPreparer preparer)
                     throws DatabaseException
        A general prepare that cascades through the expression and its parents and substitutes an elements that the preparer wants to substitute.

        NOTE: This will not cascade through to the parameters of Function objects however it will cascade through FunctionDef parameters. For this reason you MUST call 'prepareFunctions' after this method.

        Throws:
        DatabaseException
      • isConstant

        public boolean isConstant()
        Returns true if the expression doesn't include any variables or non constant functions (is constant). Note that a correlated variable is considered a constant.
      • hasSubQuery

        public boolean hasSubQuery()
        Returns true if the expression has a subquery (eg 'in ( select ... )') somewhere in it (this cascades through function parameters also).
      • containsNotOperator

        public boolean containsNotOperator()
        Returns true if the expression contains a NOT operator somewhere in it.
      • discoverCorrelatedVariables

        public java.util.ArrayList discoverCorrelatedVariables​(int level,
                                                               java.util.ArrayList list)
        Discovers all the correlated variables in this expression. If this expression contains a sub-query plan, we ask the plan to find the list of correlated variables. The discovery process increments the 'level' variable for each sub-plan.
      • discoverTableNames

        public java.util.ArrayList discoverTableNames​(java.util.ArrayList list)
        Discovers all the tables in the sub-queries of this expression. This is used for determining all the tables that a query plan touches.
      • getQueryPlanNode

        public QueryPlanNode getQueryPlanNode()
        Returns the QueryPlanNode object in this expression if it evaluates to a single QueryPlanNode, otherwise returns null.
      • getVariable

        public Variable getVariable()
        Returns the Variable if this expression evaluates to a single variable, otherwise returns null. A correlated variable will not be returned.
      • split

        public Expression[] split()
        Returns an array of two Expression objects that represent the left hand and right and side of the last operator in the post fix notation. For example, (a + b) - (c + d) will return { (a + b), (c + d) }. Or more a more useful example is;

           id + 3 > part_id - 2 will return ( id + 3, part_id - 2 }
         
      • getEndExpression

        public Expression getEndExpression()
        Returns the end Expression of this expression. For example, an expression of 'ab' has an end expression of 'b'. The expression 'abc+=' has an end expression of 'abc+='.

        This is a useful method to call in the middle of an Expression object being formed. It allows for the last complete expression to be returned.

        If this is called when an expression is completely formed it will always return the complete expression.

      • breakByOperator

        public java.util.ArrayList breakByOperator​(java.util.ArrayList list,
                                                   java.lang.String logical_op)
        Breaks this expression into a list of sub-expressions that are split by the given operator. For example, given the expression;

           (a = b AND b = c AND (a = 2 OR c = 1))
         

        Calling this method with logical_op = "and" will return a list of the three expressions.

        This is a common function used to split up an expressions into logical components for processing.

      • evaluate

        public TObject evaluate​(GroupResolver group,
                                VariableResolver resolver,
                                QueryContext context)
        Evaluates this expression and returns an Object that represents the result of the evaluation. The passed VariableResolver object is used to resolve the variable name to a value. The GroupResolver object is used if there are any aggregate functions in the evaluation - this can be null if evaluating an expression without grouping aggregates. The query context object contains contextual information about the environment of the query.

        NOTE: This method is gonna be called a lot, so we need it to be optimal.

        NOTE: This method is not thread safe! The reason it's not safe is because of the evaluation stack.

      • elementToObject

        private java.lang.Object elementToObject​(int n,
                                                 GroupResolver group,
                                                 VariableResolver resolver,
                                                 QueryContext context)
        Returns the element at the given position in the expression list. If the element is a variable then it is resolved on the VariableResolver. If the element is a function then it is evaluated and the result is returned.
      • hasAggregateFunction

        public boolean hasAggregateFunction​(QueryContext context)
        Cascades through the expression and if any aggregate functions are found returns true, otherwise returns false.
      • returnTType

        public TType returnTType​(VariableResolver resolver,
                                 QueryContext context)
        Determines the type of object this expression evaluates to. We determine this by looking at the last element of the expression. If the last element is a TType object, it returns the type. If the last element is a Function, Operator or Variable then it returns the type that these objects have set as their result type.
      • clone

        public java.lang.Object clone()
                               throws java.lang.CloneNotSupportedException
        Performs a deep clone of this object, calling 'clone' on any elements that are mutable or shallow copying immutable members.
        Overrides:
        clone in class java.lang.Object
        Throws:
        java.lang.CloneNotSupportedException
      • toString

        public java.lang.String toString()
        Returns a string representation of this object for diagnostic purposes.
        Overrides:
        toString in class java.lang.Object
      • writeObject

        private void writeObject​(java.io.ObjectOutputStream out)
                          throws java.io.IOException
        Writes the state of this object to the object stream. This method is implemented because GCJ doesn't like it if you implement readObject without writeObject.
        Throws:
        java.io.IOException
      • readObject

        private void readObject​(java.io.ObjectInputStream in)
                         throws java.io.IOException,
                                java.lang.ClassNotFoundException
        Reads the state of this object from the object stream.
        Throws:
        java.io.IOException
        java.lang.ClassNotFoundException