asterixdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From amo...@apache.org
Subject [11/34] incubator-asterixdb git commit: Enabled Feed Tests and Added External Library tests
Date Mon, 22 Feb 2016 22:34:59 GMT
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/ac683db0/asterix-external-data/src/test/java/org/apache/asterix/external/classad/Operation.java
----------------------------------------------------------------------
diff --git a/asterix-external-data/src/test/java/org/apache/asterix/external/classad/Operation.java b/asterix-external-data/src/test/java/org/apache/asterix/external/classad/Operation.java
new file mode 100644
index 0000000..ae3c5ef
--- /dev/null
+++ b/asterix-external-data/src/test/java/org/apache/asterix/external/classad/Operation.java
@@ -0,0 +1,1902 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.external.classad;
+
+import org.apache.asterix.external.classad.Value.ValueType;
+import org.apache.asterix.om.base.AMutableDouble;
+import org.apache.asterix.om.base.AMutableInt32;
+import org.apache.asterix.om.base.AMutableInt64;
+import org.apache.commons.lang3.mutable.MutableBoolean;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+/**
+ * Represents a node of the expression tree which is an operation applied to
+ * expression operands, like 3 + 2
+ */
+public class Operation extends ExprTree {
+    enum SigValues {
+        SIG_NONE,
+        SIG_CHLD1,
+        SIG_CHLD2,
+        SIG_DUMMY,
+        SIG_CHLD3
+    };
+
+    /// List of supported operators
+    public static final int OpKind_NO_OP = 0;
+    public static final int OpKind_FIRST_OP = 1;
+    // Comparison
+    public static final int OpKind_COMPARISON_START = OpKind_FIRST_OP;
+    /** @name Strict comparison operators */
+    public static final int OpKind_LESS_THAN_OP = OpKind_COMPARISON_START;
+    public static final int OpKind_LESS_OR_EQUAL_OP = OpKind_LESS_THAN_OP + 1;
+    public static final int OpKind_NOT_EQUAL_OP = OpKind_LESS_OR_EQUAL_OP + 1;
+    public static final int OpKind_EQUAL_OP = OpKind_NOT_EQUAL_OP + 1;
+    public static final int OpKind_GREATER_OR_EQUAL_OP = OpKind_EQUAL_OP + 1;
+    public static final int OpKind_GREATER_THAN_OP = OpKind_GREATER_OR_EQUAL_OP + 1;
+    /** @name Non-strict comparison operators */
+    public static final int OpKind_META_EQUAL_OP = OpKind_GREATER_THAN_OP + 1;
+    public static final int OpKind_IS_OP = OpKind_META_EQUAL_OP;
+    public static final int OpKind_META_NOT_EQUAL_OP = OpKind_IS_OP + 1;
+    public static final int OpKind_ISNT_OP = OpKind_META_NOT_EQUAL_OP;
+    public static final int OpKind_COMPARISON_END = OpKind_ISNT_OP;
+    /** @name Arithmetic operators */
+    public static final int OpKind_ARITHMETIC_START = OpKind_COMPARISON_END + 1;
+    public static final int OpKind_UNARY_PLUS_OP = OpKind_ARITHMETIC_START;
+    public static final int OpKind_UNARY_MINUS_OP = OpKind_UNARY_PLUS_OP + 1;
+    public static final int OpKind_ADDITION_OP = OpKind_UNARY_MINUS_OP + 1;
+    public static final int OpKind_SUBTRACTION_OP = OpKind_ADDITION_OP + 1;
+    public static final int OpKind_MULTIPLICATION_OP = OpKind_SUBTRACTION_OP + 1;
+    public static final int OpKind_DIVISION_OP = OpKind_MULTIPLICATION_OP + 1;
+    public static final int OpKind_MODULUS_OP = OpKind_DIVISION_OP + 1;
+    public static final int OpKind_ARITHMETIC_END = OpKind_MODULUS_OP;
+    /** @name Logical operators */
+    public static final int OpKind_LOGIC_START = OpKind_ARITHMETIC_END + 1;
+    public static final int OpKind_LOGICAL_NOT_OP = OpKind_LOGIC_START;
+    public static final int OpKind_LOGICAL_OR_OP = OpKind_LOGICAL_NOT_OP + 1;
+    public static final int OpKind_LOGICAL_AND_OP = OpKind_LOGICAL_OR_OP + 1;
+    public static final int OpKind_LOGIC_END = OpKind_LOGICAL_AND_OP;
+    /** @name Bitwise operators */
+    public static final int OpKind_BITWISE_START = OpKind_LOGIC_END + 1;
+    public static final int OpKind_BITWISE_NOT_OP = OpKind_BITWISE_START;
+    public static final int OpKind_BITWISE_OR_OP = OpKind_BITWISE_NOT_OP + 1;
+    public static final int OpKind_BITWISE_XOR_OP = OpKind_BITWISE_OR_OP + 1;
+    public static final int OpKind_BITWISE_AND_OP = OpKind_BITWISE_XOR_OP + 1;
+    public static final int OpKind_LEFT_SHIFT_OP = OpKind_BITWISE_AND_OP + 1;
+    public static final int OpKind_RIGHT_SHIFT_OP = OpKind_LEFT_SHIFT_OP + 1;
+    public static final int OpKind_URIGHT_SHIFT_OP = OpKind_RIGHT_SHIFT_OP + 1;
+    public static final int OpKind_BITWISE_END = OpKind_URIGHT_SHIFT_OP;
+    /** @name Miscellaneous operators */
+    public static final int OpKind_MISC_START = OpKind_BITWISE_END + 1;
+    public static final int OpKind_PARENTHESES_OP = OpKind_MISC_START;
+    public static final int OpKind_SUBSCRIPT_OP = OpKind_PARENTHESES_OP + 1;
+    public static final int OpKind_TERNARY_OP = OpKind_SUBSCRIPT_OP + 1;
+    public static final int OpKind_MISC_END = OpKind_TERNARY_OP;
+    public static final int OpKind_LAST_OP = OpKind_MISC_END;
+
+    private int opKind;
+    private ExprTree child1;
+    private ExprTree child2;
+    private ExprTree child3;
+
+    /// node type
+    @Override
+    public NodeKind getKind() {
+        return NodeKind.OP_NODE;
+    }
+
+    public int getOpKind() {
+        return opKind;
+    }
+
+    /**
+     * Factory method to create an operation expression node
+     *
+     * @param kind
+     *            The kind of operation.
+     * @param e1
+     *            The first sub-expression child of the node.
+     * @param e2
+     *            The second sub-expression child of the node (if any).
+     * @param e3
+     *            The third sub-expression child of the node (if any).
+     * @return The constructed operation
+     */
+
+    public static Operation createOperation(int opkind, ExprTree e1, ExprTree e2) {
+        return createOperation(opkind, e1, e2, null);
+    }
+
+    public static Operation createOperation(int opkind, ExprTree e1) {
+        return createOperation(opkind, e1, null, null);
+    }
+
+    // public access to operation function
+    /**
+     * Convenience method which operates on binary operators.
+     *
+     * @param op
+     *            The kind of operation.
+     * @param op1
+     *            The first operand.
+     * @param op2
+     *            The second operand.
+     * @param result
+     *            The result of the operation.
+     * @see OpKind, Value
+     */
+
+    /**
+     * Convenience method which operates on ternary operators.
+     *
+     * @param op
+     *            The kind of operation.
+     * @param op1
+     *            The first operand.
+     * @param op2
+     *            The second operand.
+     * @param op3
+     *            The third operand.
+     * @param result
+     *            The result of the operation.
+     * @see OpKind, Value
+     */
+
+    /**
+     * Predicate which tests if an operator is strict.
+     *
+     * @param op
+     *            The operator to be tested.
+     * @return true if the operator is strict, false otherwise.
+     */
+
+    public Operation() {
+        opKind = OpKind_NO_OP;
+        child1 = null;
+        child2 = null;
+        child3 = null;
+    }
+
+    public Operation(Operation op) throws HyracksDataException {
+        copyFrom(op);
+        return;
+    }
+
+    @Override
+    public ExprTree copy() throws HyracksDataException {
+        Operation newTree = new Operation();
+        newTree.copyFrom(this);
+        return newTree;
+    }
+
+    public boolean copyFrom(Operation op) throws HyracksDataException {
+        boolean success = true;
+        if (op.child1 == null) {
+            child1 = null;
+        } else {
+            if (child1 == null) {
+                child1 = new ExprTreeHolder();
+            }
+            child1.copyFrom(op.child1);
+            child1 = child1.self();
+        }
+        if (op.child2 == null) {
+            child2 = null;
+        } else {
+            if (child2 == null) {
+                child2 = new ExprTreeHolder();
+            }
+            child2.copyFrom(op.child2);
+            child2 = child2.self();
+        }
+        if (op.child3 == null) {
+            child3 = null;
+        } else {
+            if (child3 == null) {
+                child3 = new ExprTreeHolder();
+            }
+            child3.copyFrom(op.child3);
+            child3 = child3.self();
+        }
+        this.opKind = op.opKind;
+        super.copyFrom(op);
+        return success;
+    }
+
+    @Override
+    public boolean sameAs(ExprTree tree) {
+        boolean is_same = false;
+        Operation other_op;
+        ExprTree pSelfTree = tree.self();
+
+        if (pSelfTree.getKind() != NodeKind.OP_NODE) {
+            is_same = false;
+        } else {
+            other_op = (Operation) pSelfTree;
+            if (opKind == other_op.opKind && sameChild(child1, other_op.child1) && sameChild(child2, other_op.child2)
+                    && sameChild(child3, other_op.child3)) {
+                is_same = true;
+            } else {
+                is_same = false;
+            }
+        }
+        return is_same;
+    }
+
+    public boolean sameChild(ExprTree tree1, ExprTree tree2) {
+        boolean is_same = false;
+        if (tree1 == null) {
+            if (tree2 == null) {
+                is_same = true;
+            } else {
+                is_same = false;
+            }
+        } else if (tree2 == null) {
+            is_same = false;
+        } else {
+            is_same = tree1.sameAs(tree2);
+        }
+        return is_same;
+    }
+
+    @Override
+    public void privateSetParentScope(ClassAd parent) {
+        if (child1 != null) {
+            child1.setParentScope(parent);
+        }
+        if (child2 != null) {
+            child2.setParentScope(parent);
+        }
+        if (child3 != null) {
+            child3.setParentScope(parent);
+        }
+    }
+
+    public static void operate(int opKind, Value op1, Value op2, Value result) throws HyracksDataException {
+        Value dummy = new Value();
+        privateDoOperation(opKind, op1, op2, dummy, true, true, false, result, null);
+    }
+
+    public void operate(int op, Value op1, Value op2, Value op3, Value result) throws HyracksDataException {
+        privateDoOperation(op, op1, op2, op3, true, true, true, result, null);
+    }
+
+    public static int privateDoOperation(int op, Value val1, Value val2, Value val3, boolean valid1, boolean valid2,
+            boolean valid3, Value result) throws HyracksDataException {
+        return privateDoOperation(op, val1, val2, val3, valid1, valid2, valid3, result, null);
+    }
+
+    public static int privateDoOperation(int op, Value val1, Value val2, Value val3, boolean valid1, boolean valid2,
+            boolean valid3, Value result, EvalState es) throws HyracksDataException {
+        ValueType vt1;
+        ValueType vt2;
+        ValueType vt3;
+
+        // get the types of the values
+        vt1 = val1.getType();
+        vt2 = val2.getType();
+        vt3 = val3.getType();
+
+        // take care of the easy cases
+        if (op == OpKind_NO_OP || op == OpKind_PARENTHESES_OP) {
+            result.copyFrom(val1);
+            return SigValues.SIG_CHLD1.ordinal();
+        } else if (op == OpKind_UNARY_PLUS_OP) {
+            if (vt1 == ValueType.BOOLEAN_VALUE || vt1 == ValueType.STRING_VALUE || val1.isListValue()
+                    || vt1 == ValueType.CLASSAD_VALUE || vt1 == ValueType.ABSOLUTE_TIME_VALUE) {
+                result.setErrorValue();
+            } else {
+                // applies for ERROR, UNDEFINED and Numbers
+                result.copyFrom(val1);
+            }
+            return SigValues.SIG_CHLD1.ordinal();
+        }
+
+        // test for cases when evaluation is strict
+        if (isStrictOperator(op)) {
+            // check for error values
+            if (vt1 == ValueType.ERROR_VALUE) {
+                result.setErrorValue();
+                return SigValues.SIG_CHLD1.ordinal();
+            }
+            if (valid2 && vt2 == ValueType.ERROR_VALUE) {
+                result.setErrorValue();
+                return SigValues.SIG_CHLD2.ordinal();
+            }
+            if (valid3 && vt3 == ValueType.ERROR_VALUE) {
+                result.setErrorValue();
+                return SigValues.SIG_CHLD3.ordinal();
+            }
+
+            // check for undefined values.  we need to check if the corresponding
+            // tree exists, because these values would be undefined" anyway then.
+            if (valid1 && vt1 == ValueType.UNDEFINED_VALUE) {
+                result.setUndefinedValue();
+                return SigValues.SIG_CHLD1.ordinal();
+            }
+            if (valid2 && vt2 == ValueType.UNDEFINED_VALUE) {
+                result.setUndefinedValue();
+                return SigValues.SIG_CHLD2.ordinal();
+            }
+            if (valid3 && vt3 == ValueType.UNDEFINED_VALUE) {
+                result.setUndefinedValue();
+                return SigValues.SIG_CHLD3.ordinal();
+            }
+        }
+
+        // comparison operations (binary, one unary)
+        if (op >= OpKind_COMPARISON_START && op <= OpKind_COMPARISON_END) {
+            return (doComparison(op, val1, val2, result));
+        }
+
+        // arithmetic operations (binary)
+        if (op >= OpKind_ARITHMETIC_START && op <= OpKind_ARITHMETIC_END) {
+            return (doArithmetic(op, val1, val2, result));
+        }
+
+        // logical operators (binary, one unary)
+        if (op >= OpKind_LOGIC_START && op <= OpKind_LOGIC_END) {
+            return (doLogical(op, val1, val2, result));
+        }
+
+        // bitwise operators (binary, one unary)
+        if (op >= OpKind_BITWISE_START && op <= OpKind_BITWISE_END) {
+            return (doBitwise(op, val1, val2, result));
+        }
+
+        // misc.
+        if (op == OpKind_TERNARY_OP) {
+            // ternary (if-operator)
+            MutableBoolean b = new MutableBoolean(false);
+
+            // if the selector is UNDEFINED, the result is undefined
+            if (vt1 == ValueType.UNDEFINED_VALUE) {
+                result.setUndefinedValue();
+                return SigValues.SIG_CHLD1.ordinal();
+            }
+
+            if (!val1.isBooleanValueEquiv(b)) {
+                result.setErrorValue();
+                return SigValues.SIG_CHLD1.ordinal();
+            } else if (b.booleanValue()) {
+                result.copyFrom(val2);
+                return (SigValues.SIG_CHLD2.ordinal());
+            } else {
+                result.copyFrom(val3);
+                return (SigValues.SIG_CHLD3.ordinal());
+            }
+        } else if (op == OpKind_SUBSCRIPT_OP) {
+            // subscripting from a list (strict)
+
+            if (vt1 == ValueType.CLASSAD_VALUE && vt2 == ValueType.STRING_VALUE) {
+                ClassAd classad = new ClassAd();
+                AMutableCharArrayString index = new AMutableCharArrayString();
+
+                val1.isClassAdValue(classad);
+                val2.isStringValue(index);
+
+                if (classad.lookup(index.toString()) == null) {
+                    result.setErrorValue();
+                    return SigValues.SIG_CHLD2.ordinal();
+                }
+                if (!classad.evaluateAttr(index.toString(), result)) {
+                    result.setErrorValue();
+                    return SigValues.SIG_CHLD2.ordinal();
+                }
+
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            } else if (val1.isListValue() && vt2 == ValueType.INTEGER_VALUE) {
+                AMutableInt64 index = new AMutableInt64(0);
+                ExprList elist = new ExprList();
+
+                val1.isListValue(elist);
+                val2.isIntegerValue(index);
+
+                // check bounds
+                if (index.getLongValue() < 0 || index.getLongValue() >= elist.getExprList().size()) {
+                    result.setErrorValue();
+                    return SigValues.SIG_CHLD2.ordinal();
+                }
+                // get value
+                elist.getValue(result, elist.get((int) index.getLongValue()), es);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+            // should not reach here
+            throw new HyracksDataException("Should not get here");
+        }
+        return -1;
+    }
+
+    @Override
+    public boolean privateEvaluate(EvalState state, Value result) throws HyracksDataException {
+        Value val1 = new Value();
+        Value val2 = new Value();
+        Value val3 = new Value();
+        boolean valid1, valid2, valid3;
+        int rval = 0;
+
+        valid1 = false;
+        valid2 = false;
+        valid3 = false;
+
+        AMutableInt32 operationKind = new AMutableInt32(OpKind_NO_OP);
+        ExprTreeHolder child1 = new ExprTreeHolder();
+        ExprTreeHolder child2 = new ExprTreeHolder();
+        ExprTreeHolder child3 = new ExprTreeHolder();
+        getComponents(operationKind, child1, child2, child3);
+
+        // Evaluate all valid children
+        if (child1.getInnerTree() != null) {
+            if (!child1.publicEvaluate(state, val1)) {
+                result.setErrorValue();
+                return (false);
+            }
+            valid1 = true;
+
+            if (shortCircuit(state, val1, result)) {
+                return true;
+            }
+        }
+
+        if (child2.getInnerTree() != null) {
+            if (!child2.publicEvaluate(state, val2)) {
+                result.setErrorValue();
+                return (false);
+            }
+            valid2 = true;
+        }
+        if (child3.getInnerTree() != null) {
+            if (!child3.publicEvaluate(state, val3)) {
+                result.setErrorValue();
+                return (false);
+            }
+            valid3 = true;
+        }
+
+        rval = privateDoOperation(opKind, val1, val2, val3, valid1, valid2, valid3, result, state);
+
+        return (rval != SigValues.SIG_NONE.ordinal());
+    }
+
+    public boolean shortCircuit(EvalState state, Value arg1, Value result) throws HyracksDataException {
+        MutableBoolean arg1_bool = new MutableBoolean();
+        switch (opKind) {
+            case OpKind_LOGICAL_OR_OP:
+                if (arg1.isBooleanValueEquiv(arg1_bool) && arg1_bool.booleanValue()) {
+                    result.setBooleanValue(true);
+                    return true;
+                }
+                break;
+            case OpKind_LOGICAL_AND_OP:
+                if (arg1.isBooleanValueEquiv(arg1_bool) && !arg1_bool.booleanValue()) {
+                    result.setBooleanValue(false);
+                    return true;
+                }
+                break;
+            case OpKind_TERNARY_OP:
+                if (arg1.isBooleanValueEquiv(arg1_bool)) {
+                    if (arg1_bool.booleanValue()) {
+                        if (child2 != null) {
+                            return child2.publicEvaluate(state, result);
+                        }
+                    } else {
+                        if (child3 != null) {
+                            return child3.publicEvaluate(state, result);
+                        }
+                    }
+                }
+                break;
+            default:
+                // no-op
+                break;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean privateEvaluate(EvalState state, Value result, ExprTreeHolder tree) throws HyracksDataException {
+        int sig;
+        Value val1 = new Value();
+        Value val2 = new Value();
+        Value val3 = new Value();
+        ExprTreeHolder t1 = new ExprTreeHolder();
+        ExprTreeHolder t2 = new ExprTreeHolder();
+        ExprTreeHolder t3 = new ExprTreeHolder();
+        boolean valid1 = false, valid2 = false, valid3 = false;
+        AMutableInt32 opKind = new AMutableInt32(OpKind_NO_OP);
+        ExprTreeHolder child1 = new ExprTreeHolder();
+        ExprTreeHolder child2 = new ExprTreeHolder();
+        ExprTreeHolder child3 = new ExprTreeHolder();
+        getComponents(opKind, child1, child2, child3);
+
+        // Evaluate all valid children
+        tree = new ExprTreeHolder();
+        if (child1.getInnerTree() != null) {
+            if (!child1.publicEvaluate(state, val1, t1)) {
+                result.setErrorValue();
+                return (false);
+            }
+            valid1 = true;
+        }
+
+        if (child2.getInnerTree() != null) {
+            if (!child2.publicEvaluate(state, val2, t2)) {
+                result.setErrorValue();
+                return (false);
+            }
+            valid2 = true;
+        }
+        if (child3.getInnerTree() != null) {
+            if (!child3.publicEvaluate(state, val3, t3)) {
+                result.setErrorValue();
+                return (false);
+            }
+            valid3 = true;
+        }
+
+        // do evaluation
+        sig = privateDoOperation(opKind.getIntegerValue().intValue(), val1, val2, val3, valid1, valid2, valid3, result,
+                state);
+
+        // delete trees which were not significant
+        if (valid1 && 0 != (sig & SigValues.SIG_CHLD1.ordinal())) {
+            t1 = null;
+        }
+        if (valid2 && 0 != (sig & SigValues.SIG_CHLD2.ordinal())) {
+            t2 = null;
+        }
+        if (valid3 && 0 != (sig & SigValues.SIG_CHLD3.ordinal())) {
+            t3 = null;
+        }
+
+        if (sig == SigValues.SIG_NONE.ordinal()) {
+            result.setErrorValue();
+            tree.setInnerTree(null);;
+            return (false);
+        }
+
+        // in case of strict operators, if a subexpression is significant and the
+        // corresponding value is UNDEFINED or ERROR, propagate only that tree
+        if (isStrictOperator(opKind.getIntegerValue().intValue())) {
+            // strict unary operators:  unary -, unary +, !, ~, ()
+            if (opKind.getIntegerValue().intValue() == OpKind_UNARY_MINUS_OP
+                    || opKind.getIntegerValue().intValue() == OpKind_UNARY_PLUS_OP
+                    || opKind.getIntegerValue().intValue() == OpKind_LOGICAL_NOT_OP
+                    || opKind.getIntegerValue().intValue() == OpKind_BITWISE_NOT_OP
+                    || opKind.getIntegerValue().intValue() == OpKind_PARENTHESES_OP) {
+                if (val1.isExceptional()) {
+                    // the operator is only propagating the value;  only the
+                    // subexpression is significant
+                    tree.setInnerTree(t1);
+                } else {
+                    // the node operated on the value; the operator is also
+                    // significant
+                    tree.setInnerTree(createOperation(opKind.getIntegerValue().intValue(), t1));
+                }
+                return (true);
+            } else {
+                // strict binary operators
+                if (val1.isExceptional() || val2.isExceptional()) {
+                    // exceptional values are only being propagated
+                    if (0 != (SigValues.values()[sig].ordinal() & SigValues.SIG_CHLD1.ordinal())) {
+                        tree.setInnerTree(t1);
+                        return (true);
+                    } else if (0 != (SigValues.values()[sig].ordinal() & SigValues.SIG_CHLD2.ordinal())) {
+                        tree.setInnerTree(t2);
+                        return (true);
+                    }
+                    throw new HyracksDataException("Should not reach here");
+                } else {
+                    // the node is also significant
+                    tree.setInnerTree(createOperation(opKind.getIntegerValue().intValue(), t1, t2));
+                    return (true);
+                }
+            }
+        } else {
+            // non-strict operators
+            if (opKind.getIntegerValue().intValue() == OpKind_IS_OP
+                    || opKind.getIntegerValue().intValue() == OpKind_ISNT_OP) {
+                // the operation is *always* significant for IS and ISNT
+                tree.setInnerTree(createOperation(opKind.getIntegerValue().intValue(), t1, t2));
+                return (true);
+            }
+            // other non-strict binary operators
+            if (opKind.getIntegerValue().intValue() == OpKind_LOGICAL_AND_OP
+                    || opKind.getIntegerValue().intValue() == OpKind_LOGICAL_OR_OP) {
+                if ((SigValues.values()[sig].ordinal() & SigValues.SIG_CHLD1.ordinal()) != 0
+                        && (SigValues.values()[sig].ordinal() & SigValues.SIG_CHLD2.ordinal()) != 0) {
+                    tree.setInnerTree(createOperation(opKind.getIntegerValue().intValue(), t1, t2));
+                    return (true);
+                } else if ((SigValues.values()[sig].ordinal() & SigValues.SIG_CHLD1.ordinal()) != 0) {
+                    tree.setInnerTree(t1);
+                    return (true);
+                } else if ((SigValues.values()[sig].ordinal() & SigValues.SIG_CHLD2.ordinal()) != 0) {
+                    tree.setInnerTree(t2);
+                    return (true);
+                } else {
+                    throw new HyracksDataException("Shouldn't reach here");
+                }
+            }
+            // non-strict ternary operator (conditional operator) s ? t : f
+            // selector is always significant (???)
+            if (opKind.getIntegerValue().intValue() == OpKind_TERNARY_OP) {
+                Value tmpVal = new Value();
+                tmpVal.setUndefinedValue();
+                tree.setInnerTree(Literal.createLiteral(tmpVal));
+
+                // "true" consequent taken
+                if ((SigValues.values()[sig].ordinal() & SigValues.SIG_CHLD2.ordinal()) != 0) {
+                    tree.setInnerTree(t2);
+                    return (true);
+                } else if ((SigValues.values()[sig].ordinal() & SigValues.SIG_CHLD3.ordinal()) != 0) {
+                    tree.setInnerTree(t3);
+                    return (true);
+                }
+                // neither consequent; selector was exceptional; return ( s )
+                tree.setInnerTree(t1);
+                return (true);
+            }
+        }
+        throw new HyracksDataException("Should not reach here");
+    }
+
+    @Override
+    public boolean privateFlatten(EvalState state, Value val, ExprTreeHolder tree, AMutableInt32 opPtr)
+            throws HyracksDataException {
+        AMutableInt32 childOp1 = new AMutableInt32(OpKind_NO_OP);
+        AMutableInt32 childOp2 = new AMutableInt32(OpKind_NO_OP);
+        ExprTreeHolder fChild1 = new ExprTreeHolder();
+        ExprTreeHolder fChild2 = new ExprTreeHolder();;
+        Value val1 = new Value();
+        Value val2 = new Value();
+        Value val3 = new Value();
+        AMutableInt32 newOp = new AMutableInt32(opKind);
+        int op = opKind;
+
+        tree.setInnerTree(null);; // Just to be safe...  wenger 2003-12-11.
+
+        // if op is binary, but not associative or commutative, disallow splitting
+        if ((op >= OpKind_COMPARISON_START && op <= OpKind_COMPARISON_END) || op == OpKind_SUBTRACTION_OP
+                || op == OpKind_DIVISION_OP || op == OpKind_MODULUS_OP || op == OpKind_LEFT_SHIFT_OP
+                || op == OpKind_RIGHT_SHIFT_OP || op == OpKind_URIGHT_SHIFT_OP) {
+            if (opPtr != null)
+                opPtr.setValue(OpKind_NO_OP);
+            if (child1.publicFlatten(state, val1, fChild1) && child2.publicFlatten(state, val2, fChild2)) {
+                if (fChild1.getInnerTree() == null && fChild2.getInnerTree() == null) {
+                    privateDoOperation(op, val1, val2, val3, true, true, false, val);
+                    tree.setInnerTree(null);
+                    return true;
+                } else if (fChild1.getInnerTree() != null && fChild2.getInnerTree() != null) {
+                    tree.setInnerTree(Operation.createOperation(op, fChild1, fChild2));
+                    return true;
+                } else if (fChild1.getInnerTree() != null) {
+                    tree.setInnerTree(Operation.createOperation(op, fChild1, val2));
+                    return true;
+                } else if (fChild2.getInnerTree() != null) {
+                    tree.setInnerTree(Operation.createOperation(op, val1, fChild2));
+                    return true;
+                }
+            } else {
+                tree.setInnerTree(null);
+                return false;
+            }
+        } else
+        // now catch all non-binary operators
+        if (op == OpKind_TERNARY_OP || op == OpKind_SUBSCRIPT_OP || op == OpKind_UNARY_PLUS_OP
+                || op == OpKind_UNARY_MINUS_OP || op == OpKind_PARENTHESES_OP || op == OpKind_LOGICAL_NOT_OP
+                || op == OpKind_BITWISE_NOT_OP) {
+            return flattenSpecials(state, val, tree);
+        }
+
+        // any op that got past the above is binary, commutative and associative
+        // Flatten sub expressions
+        if ((child1 != null && !child1.publicFlatten(state, val1, fChild1, childOp1))
+                || (child2 != null && !child2.publicFlatten(state, val2, fChild2, childOp2))) {
+            tree.setInnerTree(null);
+            return false;
+        }
+
+        // NOTE: combine() deletes fChild1 and/or fChild2 if they are not
+        // included in tree
+        if (!combine(newOp, val, tree, childOp1, val1, fChild1, childOp2, val2, fChild2)) {
+            tree.setInnerTree(null);
+            if (opPtr != null) {
+                opPtr.setValue(OpKind_NO_OP);
+            }
+            return false;
+        }
+
+        // if splitting is disallowed, fold the value and tree into a tree
+        if (opPtr == null && newOp.getIntegerValue().intValue() != OpKind_NO_OP) {
+            tree.setInnerTree(Operation.createOperation(newOp.getIntegerValue().intValue(), val, tree));
+            if (tree.getInnerTree() == null) {
+                return false;
+            }
+            return true;
+        } else if (opPtr != null) {
+            opPtr.setValue(newOp.getIntegerValue().intValue());
+        }
+        return true;
+    }
+
+    public boolean combine(AMutableInt32 op, Value val, ExprTreeHolder tree, AMutableInt32 op1, Value val1,
+            ExprTreeHolder tree1, AMutableInt32 op2, Value val2, ExprTreeHolder tree2) throws HyracksDataException {
+        Operation newOp = new Operation();
+        Value dummy = new Value(); // undefined
+
+        // special don't care cases for logical operators with exactly one value
+        if ((tree1.getInnerTree() == null || tree2.getInnerTree() == null)
+                && (tree1.getInnerTree() != null || tree2.getInnerTree() != null)
+                && (op.getIntegerValue() == OpKind_LOGICAL_OR_OP || op.getIntegerValue() == OpKind_LOGICAL_AND_OP)) {
+            privateDoOperation(op.getIntegerValue().intValue(), tree1.getInnerTree() == null ? val1 : dummy,
+                    tree2.getInnerTree() == null ? val2 : dummy, dummy, true, true, false, val);
+            if (val.isBooleanValue()) {
+                tree.setInnerTree(null);
+                op.setValue(OpKind_NO_OP);
+                return true;
+            }
+        }
+
+        if (tree1.getInnerTree() == null && tree2.getInnerTree() == null) {
+            // left and rightsons are only values
+            privateDoOperation(op.getIntegerValue().intValue(), val1, val2, dummy, true, true, false, val);
+            tree.setInnerTree(null);
+            op.setValue(OpKind_NO_OP);
+            return true;
+        } else if (tree1.getInnerTree() == null
+                && (tree2.getInnerTree() != null && op2.getIntegerValue().intValue() == OpKind_NO_OP)) {
+            // leftson is a value, rightson is a tree
+            tree.setInnerTree(tree2.getInnerTree());
+            val.copyFrom(val1);
+            return true;
+        } else if (tree2.getInnerTree() == null
+                && (tree1.getInnerTree() != null && op1.getIntegerValue().intValue() == OpKind_NO_OP)) {
+            // rightson is a value, leftson is a tree
+            tree.setInnerTree(tree1.getInnerTree());
+            val.copyFrom(val2);
+            return true;
+        } else if ((tree1.getInnerTree() != null && op1.getIntegerValue().intValue() == OpKind_NO_OP)
+                && (tree2.getInnerTree() != null && op2.getIntegerValue().intValue() == OpKind_NO_OP)) {
+            // left and rightsons are trees only
+            if (null != (newOp = createOperation(op.getIntegerValue().intValue(), tree1, tree2))) {
+                return false;
+            }
+            tree.setInnerTree(newOp);
+            op.setValue(OpKind_NO_OP);
+            return true;
+        }
+
+        // cannot collapse values due to dissimilar ops
+        if ((op1.getIntegerValue().intValue() != OpKind_NO_OP || op2.getIntegerValue().intValue() != OpKind_NO_OP)
+                && !op.equals(op1) && !op.equals(op1)) {
+            // at least one of them returned a value and a tree, and parent does
+            // not share the same operation with either child
+            ExprTreeHolder newOp1 = new ExprTreeHolder();
+            ExprTreeHolder newOp2 = new ExprTreeHolder();
+
+            if (op1.getIntegerValue().intValue() != OpKind_NO_OP) {
+                newOp1.setInnerTree(Operation.createOperation(op1.getIntegerValue().intValue(), val1, tree1));
+            } else if (tree1.getInnerTree() != null) {
+                newOp1.setInnerTree(tree1.getInnerTree());
+            } else {
+                newOp1.setInnerTree(Literal.createLiteral(val1));
+            }
+
+            if (op2.getIntegerValue().intValue() != OpKind_NO_OP) {
+                newOp2.setInnerTree(Operation.createOperation(op2.getIntegerValue().intValue(), val2, tree2));
+            } else if (tree2.getInnerTree() != null) {
+                newOp2.setInnerTree(tree2);
+            } else {
+                newOp2.setInnerTree(Literal.createLiteral(val2));
+            }
+
+            if (newOp1.getInnerTree() == null || newOp2.getInnerTree() == null) {
+                tree.setInnerTree(null);
+                op.setValue(OpKind_NO_OP);
+                return false;
+            }
+            newOp = createOperation(op.getIntegerValue().intValue(), newOp1, newOp2);
+            if (newOp == null) {
+                tree.setInnerTree(null);
+                op.setValue(OpKind_NO_OP);
+                return false;
+            }
+            op.setValue(OpKind_NO_OP);
+            tree.setInnerTree(newOp);
+            return true;
+        }
+
+        if (op.equals(op1) && op.equals(op2)) {
+            // same operators on both children . since op!=NO_OP, neither are op1,
+            // op2.  so they both make tree and value contributions
+            newOp = createOperation(op.getIntegerValue().intValue(), tree1, tree2);
+            if (newOp == null) {
+                return false;
+            }
+            privateDoOperation(op.getIntegerValue().intValue(), val1, val2, dummy, true, true, false, val);
+            tree.setInnerTree(newOp);
+            return true;
+        } else if (op.equals(op1)) {
+            // leftson makes a tree,value contribution
+            if (tree2.getInnerTree() == null) {
+                // rightson makes a value contribution
+                privateDoOperation(op.getIntegerValue().intValue(), val1, val2, dummy, true, true, false, val);
+                tree.setInnerTree(tree1);
+                return true;
+            } else {
+                // rightson makes a tree contribution
+                Operation local_newOp = createOperation(op.getIntegerValue().intValue(), tree1, tree2);
+                if (local_newOp == null) {
+                    tree.setInnerTree(null);
+                    op.setValue(OpKind_NO_OP);
+                    return false;
+                }
+                val.copyFrom(val1);
+                tree.setInnerTree(local_newOp); // NAC - BUG FIX
+                return true;
+            }
+        } else if (op.equals(op2)) {
+            // rightson makes a tree,value contribution
+            if (tree1.getInnerTree() == null) {
+                // leftson makes a value contribution
+                privateDoOperation(op.getIntegerValue().intValue(), val1, val2, dummy, true, true, false, val);
+                tree.setInnerTree(tree2);
+                return true;
+            } else {
+                // leftson makes a tree contribution
+                Operation local_newOp = createOperation(op.getIntegerValue().intValue(), tree1, tree2);
+                if (local_newOp == null) {
+                    tree.setInnerTree(null);
+                    op.setValue(OpKind_NO_OP);
+                    return false;
+                }
+                tree.setInnerTree(local_newOp); // NAC BUG FIX
+                val.copyFrom(val2);
+                return true;
+            }
+        }
+
+        throw new HyracksDataException("Should not reach here");
+    }
+
+    public static int doComparison(int op, Value v1, Value v2, Value result) throws HyracksDataException {
+        ValueType vt1;
+        ValueType vt2;
+        ValueType coerceResult;
+
+        if (op == OpKind_META_EQUAL_OP || op == OpKind_META_NOT_EQUAL_OP) {
+            // do not do type promotions for the meta operators
+            vt1 = v1.getType();
+            vt2 = v2.getType();
+            coerceResult = vt1;
+        } else {
+            // do numerical type promotions --- other types/values are unchanged
+            coerceResult = coerceToNumber(v1, v2);
+            vt1 = v1.getType();
+            vt2 = v2.getType();
+        }
+
+        // perform comparison for =?= ; true iff same types and same values
+        if (op == OpKind_META_EQUAL_OP) {
+            if (vt1 != vt2) {
+                result.setBooleanValue(false);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+
+            // undefined or error
+            if (vt1 == ValueType.UNDEFINED_VALUE || vt1 == ValueType.ERROR_VALUE) {
+                result.setBooleanValue(true);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+        }
+        // perform comparison for =!= ; negation of =?=
+        if (op == OpKind_META_NOT_EQUAL_OP) {
+            if (vt1 != vt2) {
+                result.setBooleanValue(true);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+
+            // undefined or error
+            if (vt1 == ValueType.UNDEFINED_VALUE || vt1 == ValueType.ERROR_VALUE) {
+                result.setBooleanValue(false);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+        }
+
+        switch (coerceResult) {
+            // at least one of v1, v2 is a string
+            case STRING_VALUE:
+                // check if both are strings
+                if (vt1 != ValueType.STRING_VALUE || vt2 != ValueType.STRING_VALUE) {
+                    // comparison between strings and non-exceptional non-string
+                    // values is error
+                    result.setErrorValue();
+                    return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+                }
+                compareStrings(op, v1, v2, result);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+            case INTEGER_VALUE:
+                compareIntegers(op, v1, v2, result);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+            case REAL_VALUE:
+                compareReals(op, v1, v2, result);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+            case BOOLEAN_VALUE:
+                // check if both are bools
+                if (!v1.isBooleanValue() || !v2.isBooleanValue()) {
+                    result.setErrorValue();
+                    return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+                }
+                compareBools(op, v1, v2, result);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+            case LIST_VALUE:
+            case SLIST_VALUE:
+            case CLASSAD_VALUE:
+                result.setErrorValue();
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+            case ABSOLUTE_TIME_VALUE:
+                if (!v1.isAbsoluteTimeValue() || !v2.isAbsoluteTimeValue()) {
+                    result.setErrorValue();
+                    return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+                }
+                compareAbsoluteTimes(op, v1, v2, result);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+            case RELATIVE_TIME_VALUE:
+                if (!v1.isRelativeTimeValue() || !v2.isRelativeTimeValue()) {
+                    result.setErrorValue();
+                    return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+                }
+                compareRelativeTimes(op, v1, v2, result);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+            default:
+                // should not get here
+                throw new HyracksDataException("Should not get here");
+        }
+    }
+
+    public static int doArithmetic(int op, Value v1, Value v2, Value result) throws HyracksDataException {
+        AMutableInt64 i1 = new AMutableInt64(0);
+        AMutableInt64 i2 = new AMutableInt64(0);
+        ClassAdTime t1 = new ClassAdTime();
+        AMutableDouble r1 = new AMutableDouble(0);
+        MutableBoolean b1 = new MutableBoolean();
+
+        // ensure the operands have arithmetic types
+        if ((!v1.isIntegerValue() && !v1.isRealValue() && !v1.isAbsoluteTimeValue() && !v1.isRelativeTimeValue()
+                && !v1.isBooleanValue())
+                || (op != OpKind_UNARY_MINUS_OP && !v2.isBooleanValue() && !v2.isIntegerValue() && !v2.isRealValue()
+                        && !v2.isAbsoluteTimeValue() && !v2.isRelativeTimeValue())) {
+            result.setErrorValue();
+            return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+        }
+
+        // take care of the unary arithmetic operators
+        if (op == OpKind_UNARY_MINUS_OP) {
+            if (v1.isIntegerValue(i1)) {
+                result.setIntegerValue((-1L) * i1.getLongValue());
+                return SigValues.SIG_CHLD1.ordinal();
+            } else if (v1.isRealValue(r1)) {
+                result.setRealValue((-1) * r1.getDoubleValue());
+                return SigValues.SIG_CHLD1.ordinal();
+            } else if (v1.isRelativeTimeValue(t1)) {
+                t1.setValue((-1) * t1.getTimeInMillis());
+                result.setRelativeTimeValue(t1);
+                return (SigValues.SIG_CHLD1.ordinal());
+            } else if (v1.isBooleanValue(b1)) {
+                result.setBooleanValue(!b1.booleanValue());
+            } else if (v1.isExceptional()) {
+                // undefined or error --- same as operand
+                result.copyFrom(v1);
+                return SigValues.SIG_CHLD1.ordinal();
+            }
+            // unary minus not defined on any other operand type
+            result.setErrorValue();
+            return (SigValues.SIG_CHLD1.ordinal());
+        }
+
+        // perform type promotions and proceed with arithmetic
+        switch (coerceToNumber(v1, v2)) {
+            case INTEGER_VALUE:
+                v1.isIntegerValue(i1);
+                v2.isIntegerValue(i2);
+                switch (op) {
+                    case OpKind_ADDITION_OP:
+                        result.setIntegerValue(i1.getLongValue() + i2.getLongValue());
+                        return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+                    case OpKind_SUBTRACTION_OP:
+                        result.setIntegerValue(i1.getLongValue() - i2.getLongValue());
+                        return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+                    case OpKind_MULTIPLICATION_OP:
+                        result.setIntegerValue(i1.getLongValue() * i2.getLongValue());
+                        return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+                    case OpKind_DIVISION_OP:
+                        if (i2.getLongValue() != 0L) {
+                            result.setIntegerValue(i1.getLongValue() / i2.getLongValue());
+                        } else {
+                            result.setErrorValue();
+                        }
+                        return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+                    case OpKind_MODULUS_OP:
+                        if (i2.getLongValue() != 0) {
+                            result.setIntegerValue(i1.getLongValue() % i2.getLongValue());
+                        } else {
+                            result.setErrorValue();
+                        }
+                        return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+
+                    default:
+                        // should not reach here
+                        throw new HyracksDataException("Should not get here");
+                }
+
+            case REAL_VALUE: {
+                return (doRealArithmetic(op, v1, v2, result));
+            }
+            case ABSOLUTE_TIME_VALUE:
+            case RELATIVE_TIME_VALUE: {
+                return (doTimeArithmetic(op, v1, v2, result));
+            }
+            default:
+                // should not get here
+                throw new HyracksDataException("Should not get here");
+        }
+    }
+
+    public static int doLogical(int op, Value v1, Value v2, Value result) throws HyracksDataException {
+        MutableBoolean b1 = new MutableBoolean();
+        MutableBoolean b2 = new MutableBoolean();
+
+        // first coerece inputs to boolean if they are considered equivalent
+        if (!v1.isBooleanValue(b1) && v1.isBooleanValueEquiv(b1)) {
+            v1.setBooleanValue(b1.booleanValue());
+        }
+        if (!v2.isBooleanValue(b2) && v2.isBooleanValueEquiv(b2)) {
+            v2.setBooleanValue(b2);
+        }
+
+        ValueType vt1 = v1.getType();
+        ValueType vt2 = v2.getType();
+
+        if (vt1 != ValueType.UNDEFINED_VALUE && vt1 != ValueType.ERROR_VALUE && vt1 != ValueType.BOOLEAN_VALUE) {
+            result.setErrorValue();
+            return SigValues.SIG_CHLD1.ordinal();
+        }
+        if (vt2 != ValueType.UNDEFINED_VALUE && vt2 != ValueType.ERROR_VALUE && vt2 != ValueType.BOOLEAN_VALUE) {
+            result.setErrorValue();
+            return SigValues.SIG_CHLD2.ordinal();
+        }
+
+        // handle unary operator
+        if (op == OpKind_LOGICAL_NOT_OP) {
+            if (vt1 == ValueType.BOOLEAN_VALUE) {
+                result.setBooleanValue(!b1.booleanValue());
+            } else {
+                result.copyFrom(v1);
+            }
+            return SigValues.SIG_CHLD1.ordinal();
+        }
+
+        if (op == OpKind_LOGICAL_OR_OP) {
+            if (vt1 == ValueType.BOOLEAN_VALUE && b1.booleanValue()) {
+                result.setBooleanValue(true);
+                return SigValues.SIG_CHLD1.ordinal();
+            } else if (vt1 == ValueType.ERROR_VALUE) {
+                result.setErrorValue();
+                return SigValues.SIG_CHLD1.ordinal();
+            } else if (vt1 == ValueType.BOOLEAN_VALUE && !b1.booleanValue()) {
+                result.copyFrom(v2);
+            } else if (vt2 != ValueType.BOOLEAN_VALUE) {
+                result.copyFrom(v2);
+            } else if (b2.booleanValue()) {
+                result.setBooleanValue(true);
+            } else {
+                result.setUndefinedValue();
+            }
+            return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+        } else if (op == OpKind_LOGICAL_AND_OP) {
+            if (vt1 == ValueType.BOOLEAN_VALUE && !b1.booleanValue()) {
+                result.setBooleanValue(false);
+                return SigValues.SIG_CHLD1.ordinal();
+            } else if (vt1 == ValueType.ERROR_VALUE) {
+                result.setErrorValue();
+                return SigValues.SIG_CHLD1.ordinal();
+            } else if (vt1 == ValueType.BOOLEAN_VALUE && b1.booleanValue()) {
+                result.copyFrom(v2);
+            } else if (vt2 != ValueType.BOOLEAN_VALUE) {
+                result.copyFrom(v2);
+            } else if (!b2.booleanValue()) {
+                result.setBooleanValue(false);
+            } else {
+                result.setUndefinedValue();
+            }
+            return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+        }
+
+        throw new HyracksDataException("Shouldn't reach here");
+    }
+
+    public static int doBitwise(int op, Value v1, Value v2, Value result) throws HyracksDataException {
+        AMutableInt64 i1 = new AMutableInt64(0);
+        AMutableInt64 i2 = new AMutableInt64(0);
+
+        // bitwise operations are defined only on integers
+        if (op == OpKind_BITWISE_NOT_OP) {
+            if (!v1.isIntegerValue(i1)) {
+                result.setErrorValue();
+                return SigValues.SIG_CHLD1.ordinal();
+            }
+        } else if (!v1.isIntegerValue(i1) || !v2.isIntegerValue(i2)) {
+            result.setErrorValue();
+            return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+        }
+
+        switch (op) {
+            case OpKind_BITWISE_NOT_OP:
+                result.setIntegerValue(~(i1.getLongValue()));
+                break;
+            case OpKind_BITWISE_OR_OP:
+                result.setIntegerValue(i1.getLongValue() | i2.getLongValue());
+                break;
+            case OpKind_BITWISE_AND_OP:
+                result.setIntegerValue(i1.getLongValue() & i2.getLongValue());
+                break;
+            case OpKind_BITWISE_XOR_OP:
+                result.setIntegerValue(i1.getLongValue() ^ i2.getLongValue());
+                break;
+            case OpKind_LEFT_SHIFT_OP:
+                result.setIntegerValue(i1.getLongValue() << i2.getLongValue());
+                break;
+
+            case OpKind_URIGHT_SHIFT_OP:
+                //               if (i1 >= 0) {
+                // Could probably just use >>>
+                // sign bit is not on;  >> will work fine
+                result.setIntegerValue(i1.getLongValue() >>> i2.getLongValue());
+                break;
+            //               } else {
+            // sign bit is on
+            //                  val.setValue(i1 >> 1);      // shift right 1; the sign bit *may* be on
+            //                  val.setValue(val.getLongValue() & (~signMask)); // Clear the sign bit for sure
+            //                  val.setValue(val.getLongValue() >>(i2.getLongValue() - 1));   // shift remaining Number of positions
+            //                  result.SetIntegerValue (val.getLongValue());
+            //                  break;
+            //               }
+
+            case OpKind_RIGHT_SHIFT_OP:
+                // sign bit is off;  >> will work fine
+                result.setIntegerValue(i1.getLongValue() >> i2.getLongValue());
+                break;
+
+            default:
+                // should not get here
+                throw new HyracksDataException("Should not get here");
+        }
+
+        if (op == OpKind_BITWISE_NOT_OP) {
+            return SigValues.SIG_CHLD1.ordinal();
+        }
+
+        return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+    }
+
+    //out of domain value
+    public static final int EDOM = 33;
+
+    public static int doRealArithmetic(int op, Value v1, Value v2, Value result) throws HyracksDataException {
+        AMutableDouble r1 = new AMutableDouble(0);
+        AMutableDouble r2 = new AMutableDouble(0);
+        double comp = 0;
+
+        // we want to prevent FPE and set the ERROR value on the result; on Unix
+        // trap sigfpe and set the ClassAdExprFPE flag to true; on NT check the
+        // result against HUGE_VAL.  check errno for EDOM and ERANGE for kicks.
+
+        v1.isRealValue(r1);
+        v2.isRealValue(r2);
+        int errno = 0;
+        switch (op) {
+            case OpKind_ADDITION_OP:
+                comp = r1.getDoubleValue() + r2.getDoubleValue();
+                break;
+            case OpKind_SUBTRACTION_OP:
+                comp = r1.getDoubleValue() - r2.getDoubleValue();
+                break;
+            case OpKind_MULTIPLICATION_OP:
+                comp = r1.getDoubleValue() * r2.getDoubleValue();
+                break;
+            case OpKind_DIVISION_OP:
+                comp = r1.getDoubleValue() / r2.getDoubleValue();
+                break;
+            case OpKind_MODULUS_OP:
+                errno = EDOM;
+                break;
+            default:
+                // should not reach here
+                throw new HyracksDataException("Should not get here");
+        }
+
+        // check if anything bad happened
+        if (errno == EDOM) {
+            result.setErrorValue();
+        } else {
+            result.setRealValue(comp);
+        }
+        return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+    }
+
+    public static int doTimeArithmetic(int op, Value v1, Value v2, Value result) {
+        ClassAdTime asecs1 = new ClassAdTime();
+        ClassAdTime asecs2 = new ClassAdTime();
+        ValueType vt1 = v1.getType();
+        ValueType vt2 = v2.getType();
+
+        // addition
+        if (op == OpKind_ADDITION_OP) {
+            if (vt1 == ValueType.ABSOLUTE_TIME_VALUE && vt2 == ValueType.RELATIVE_TIME_VALUE) {
+                v1.isAbsoluteTimeValue(asecs1);
+                v2.isRelativeTimeValue(asecs2);
+                asecs1.setValue(asecs1.getTimeInMillis() + asecs2.getTimeInMillis());
+                result.setAbsoluteTimeValue(asecs1);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+
+            if (vt1 == ValueType.RELATIVE_TIME_VALUE && vt2 == ValueType.ABSOLUTE_TIME_VALUE) {
+                v1.isRelativeTimeValue(asecs1);
+                v2.isAbsoluteTimeValue(asecs2);
+                asecs2.setValue(asecs1.getTimeInMillis() + asecs2.getTimeInMillis());
+                result.setAbsoluteTimeValue(asecs2);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+
+            if (vt1 == ValueType.RELATIVE_TIME_VALUE && vt2 == ValueType.RELATIVE_TIME_VALUE) {
+                v1.isRelativeTimeValue(asecs1);
+                v2.isRelativeTimeValue(asecs2);
+                result.setRelativeTimeValue(asecs1.plus(asecs2.getRelativeTime(), false));
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+        }
+
+        if (op == OpKind_SUBTRACTION_OP) {
+            if (vt1 == ValueType.ABSOLUTE_TIME_VALUE && vt2 == ValueType.ABSOLUTE_TIME_VALUE) {
+                v1.isAbsoluteTimeValue(asecs1);
+                v2.isAbsoluteTimeValue(asecs2);
+                result.setRelativeTimeValue(asecs1.subtract(asecs2, false));
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+
+            if (vt1 == ValueType.ABSOLUTE_TIME_VALUE && vt2 == ValueType.RELATIVE_TIME_VALUE) {
+                v1.isAbsoluteTimeValue(asecs1);
+                v2.isRelativeTimeValue(asecs2);
+                asecs1.setValue(asecs1.getTimeInMillis() - asecs2.getRelativeTime());
+                result.setAbsoluteTimeValue(asecs1);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+
+            if (vt1 == ValueType.RELATIVE_TIME_VALUE && vt2 == ValueType.RELATIVE_TIME_VALUE) {
+                v1.isRelativeTimeValue(asecs1);
+                v2.isRelativeTimeValue(asecs2);
+                result.setRelativeTimeValue(asecs1.subtract(asecs2));
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+        }
+
+        if (op == OpKind_MULTIPLICATION_OP || op == OpKind_DIVISION_OP) {
+            if (vt1 == ValueType.RELATIVE_TIME_VALUE && vt2 == ValueType.INTEGER_VALUE) {
+                AMutableInt64 num = new AMutableInt64(0);
+                ClassAdTime msecs = new ClassAdTime();
+                v1.isRelativeTimeValue(asecs1);
+                v2.isIntegerValue(num);
+                if (op == OpKind_MULTIPLICATION_OP) {
+                    msecs.setValue(asecs1.multiply(num.getLongValue(), false));
+                } else {
+                    msecs.setValue(asecs1.divide(num.getLongValue(), false));
+                }
+                result.setRelativeTimeValue(msecs);
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+
+            if (vt1 == ValueType.RELATIVE_TIME_VALUE && vt2 == ValueType.REAL_VALUE) {
+                AMutableDouble num = new AMutableDouble(0);
+                AMutableDouble msecs = new AMutableDouble(0);
+                v1.isRelativeTimeValue(asecs1);
+                v2.isRealValue(num);
+                if (op == OpKind_MULTIPLICATION_OP) {
+                    msecs.setValue(asecs1.getRelativeTime() * num.getDoubleValue());
+                } else {
+                    msecs.setValue(asecs1.getRelativeTime() * num.getDoubleValue());
+                }
+                result.setRelativeTimeValue(new ClassAdTime(1000L * ((long) msecs.getDoubleValue()), false));
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+
+            if (vt1 == ValueType.INTEGER_VALUE && vt2 == ValueType.RELATIVE_TIME_VALUE
+                    && op == OpKind_MULTIPLICATION_OP) {
+                AMutableInt64 num = new AMutableInt64(0);
+                v1.isIntegerValue(num);
+                v2.isRelativeTimeValue(asecs1);
+                result.setRelativeTimeValue(new ClassAdTime(num.getLongValue() * asecs1.getRelativeTime(), false));
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+
+            if (vt2 == ValueType.RELATIVE_TIME_VALUE && vt1 == ValueType.REAL_VALUE && op == OpKind_MULTIPLICATION_OP) {
+                AMutableDouble num = new AMutableDouble(0);
+                v1.isRelativeTimeValue(asecs1);
+                v2.isRealValue(num);
+                result.setRelativeTimeValue(
+                        new ClassAdTime((long) (asecs1.getRelativeTime() * num.getDoubleValue()), false));
+                return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+            }
+        }
+        // no other operations are supported on times
+        result.setErrorValue();
+        return (SigValues.SIG_CHLD1.ordinal() | SigValues.SIG_CHLD2.ordinal());
+    }
+
+    public static void compareStrings(int op, Value v1, Value v2, Value result) {
+        AMutableCharArrayString s1 = new AMutableCharArrayString();
+        AMutableCharArrayString s2 = new AMutableCharArrayString();
+        int cmp;
+        v1.isStringValue(s1);
+        v2.isStringValue(s2);
+        result.setBooleanValue(false);
+        if (op == OpKind_META_EQUAL_OP || op == OpKind_META_NOT_EQUAL_OP) {
+            cmp = s1.compareTo(s2);
+        } else {
+            cmp = s1.compareToIgnoreCase(s2);
+        }
+        if (cmp < 0) {
+            // s1 < s2
+            if (op == OpKind_LESS_THAN_OP || op == OpKind_LESS_OR_EQUAL_OP || op == OpKind_META_NOT_EQUAL_OP
+                    || op == OpKind_NOT_EQUAL_OP) {
+                result.setBooleanValue(true);
+            }
+        } else if (cmp == 0) {
+            // s1 == s2
+            if (op == OpKind_LESS_OR_EQUAL_OP || op == OpKind_META_EQUAL_OP || op == OpKind_EQUAL_OP
+                    || op == OpKind_GREATER_OR_EQUAL_OP) {
+                result.setBooleanValue(true);
+            }
+        } else {
+            // s1 > s2
+            if (op == OpKind_GREATER_THAN_OP || op == OpKind_GREATER_OR_EQUAL_OP || op == OpKind_META_NOT_EQUAL_OP
+                    || op == OpKind_NOT_EQUAL_OP) {
+                result.setBooleanValue(true);
+            }
+        }
+    }
+
+    public static void compareAbsoluteTimes(int op, Value v1, Value v2, Value result) throws HyracksDataException {
+        ClassAdTime asecs1 = new ClassAdTime();
+        ClassAdTime asecs2 = new ClassAdTime();
+        boolean compResult = false;
+        v1.isAbsoluteTimeValue(asecs1);
+        v2.isAbsoluteTimeValue(asecs2);
+        switch (op) {
+            case OpKind_LESS_THAN_OP:
+                compResult = (asecs1.getTimeInMillis() < asecs2.getTimeInMillis());
+                break;
+            case OpKind_LESS_OR_EQUAL_OP:
+                compResult = (asecs1.getTime() <= asecs2.getTime());
+                break;
+            case OpKind_EQUAL_OP:
+                compResult = (asecs1.getTime() == asecs2.getTime());
+                break;
+            case OpKind_META_EQUAL_OP:
+                compResult = (asecs1.getTime() == asecs2.getTime()) && (asecs1.getOffset() == asecs2.getOffset());
+                break;
+            case OpKind_NOT_EQUAL_OP:
+                compResult = (asecs1.getTime() != asecs2.getTime());
+                break;
+            case OpKind_META_NOT_EQUAL_OP:
+                compResult = (asecs1.getTime() != asecs2.getTime()) || (asecs1.getOffset() != asecs2.getOffset());
+                break;
+            case OpKind_GREATER_THAN_OP:
+                compResult = (asecs1.getTime() > asecs2.getTime());
+                break;
+            case OpKind_GREATER_OR_EQUAL_OP:
+                compResult = (asecs1.getTime() >= asecs2.getTime());
+                break;
+            default:
+                // should not get here
+                throw new HyracksDataException("Should not get here");
+        }
+        result.setBooleanValue(compResult);
+    }
+
+    public static void compareRelativeTimes(int op, Value v1, Value v2, Value result) throws HyracksDataException {
+        ClassAdTime rsecs1 = new ClassAdTime();
+        ClassAdTime rsecs2 = new ClassAdTime();
+        boolean compResult = false;
+
+        v1.isRelativeTimeValue(rsecs1);
+        v2.isRelativeTimeValue(rsecs2);
+
+        switch (op) {
+            case OpKind_LESS_THAN_OP:
+                compResult = (rsecs1.getRelativeTime() < rsecs2.getRelativeTime());
+                break;
+
+            case OpKind_LESS_OR_EQUAL_OP:
+                compResult = (rsecs1.getRelativeTime() <= rsecs2.getRelativeTime());
+                break;
+
+            case OpKind_EQUAL_OP:
+            case OpKind_META_EQUAL_OP:
+                compResult = (rsecs1.getRelativeTime() == rsecs2.getRelativeTime());
+                break;
+
+            case OpKind_NOT_EQUAL_OP:
+            case OpKind_META_NOT_EQUAL_OP:
+                compResult = (rsecs1.getRelativeTime() != rsecs2.getRelativeTime());
+                break;
+
+            case OpKind_GREATER_THAN_OP:
+                compResult = (rsecs1.getRelativeTime() > rsecs2.getRelativeTime());
+                break;
+
+            case OpKind_GREATER_OR_EQUAL_OP:
+                compResult = (rsecs1.getRelativeTime() >= rsecs2.getRelativeTime());
+                break;
+
+            default:
+                // should not get here
+                throw new HyracksDataException("Should not get here");
+        }
+        result.setBooleanValue(compResult);
+    }
+
+    public static void compareBools(int op, Value v1, Value v2, Value result) throws HyracksDataException {
+        MutableBoolean b1 = new MutableBoolean();
+        MutableBoolean b2 = new MutableBoolean();
+        boolean compResult = false;
+        v1.isBooleanValue(b1);
+        v2.isBooleanValue(b2);
+
+        switch (op) {
+            case OpKind_LESS_THAN_OP:
+                compResult = (b1.compareTo(b2) < 0);
+                break;
+            case OpKind_LESS_OR_EQUAL_OP:
+                compResult = (b1.compareTo(b2) <= 0);
+                break;
+            case OpKind_EQUAL_OP:
+                compResult = (b1.booleanValue() == b2.booleanValue());
+                break;
+            case OpKind_META_EQUAL_OP:
+                compResult = (b1.booleanValue() == b2.booleanValue());
+                break;
+            case OpKind_NOT_EQUAL_OP:
+                compResult = (b1.booleanValue() != b2.booleanValue());
+                break;
+            case OpKind_META_NOT_EQUAL_OP:
+                compResult = (b1.booleanValue() != b2.booleanValue());
+                break;
+            case OpKind_GREATER_THAN_OP:
+                compResult = (b1.compareTo(b2) > 0);
+                break;
+            case OpKind_GREATER_OR_EQUAL_OP:
+                compResult = (b1.compareTo(b2) >= 0);
+                break;
+            default:
+                // should not get here
+                throw new HyracksDataException("Should not get here");
+        }
+        result.setBooleanValue(compResult);
+    }
+
+    public static void compareIntegers(int op, Value v1, Value v2, Value result) throws HyracksDataException {
+        AMutableInt64 i1 = new AMutableInt64(0);
+        AMutableInt64 i2 = new AMutableInt64(0);
+        boolean compResult = false;
+        v1.isIntegerValue(i1);
+        v2.isIntegerValue(i2);
+        switch (op) {
+            case OpKind_LESS_THAN_OP:
+                compResult = (i1.getLongValue() < i2.getLongValue());
+                break;
+            case OpKind_LESS_OR_EQUAL_OP:
+                compResult = (i1.getLongValue() <= i2.getLongValue());
+                break;
+            case OpKind_EQUAL_OP:
+                compResult = (i1.getLongValue() == i2.getLongValue());
+                break;
+            case OpKind_META_EQUAL_OP:
+                compResult = (i1.getLongValue() == i2.getLongValue());
+                break;
+            case OpKind_NOT_EQUAL_OP:
+                compResult = (i1.getLongValue() != i2.getLongValue());
+                break;
+            case OpKind_META_NOT_EQUAL_OP:
+                compResult = (i1.getLongValue() != i2.getLongValue());
+                break;
+            case OpKind_GREATER_THAN_OP:
+                compResult = (i1.getLongValue() > i2.getLongValue());
+                break;
+            case OpKind_GREATER_OR_EQUAL_OP:
+                compResult = (i1.getLongValue() >= i2.getLongValue());
+                break;
+            default:
+                // should not get here
+                throw new HyracksDataException("Should not get here");
+        }
+        result.setBooleanValue(compResult);
+    }
+
+    public static void compareReals(int op, Value v1, Value v2, Value result) throws HyracksDataException {
+        AMutableDouble r1 = new AMutableDouble(0);
+        AMutableDouble r2 = new AMutableDouble(0);
+        boolean compResult = false;
+
+        v1.isRealValue(r1);
+        v2.isRealValue(r2);
+
+        switch (op) {
+            case OpKind_LESS_THAN_OP:
+                compResult = (r1.getDoubleValue() < r2.getDoubleValue());
+                break;
+            case OpKind_LESS_OR_EQUAL_OP:
+                compResult = (r1.getDoubleValue() <= r2.getDoubleValue());
+                break;
+            case OpKind_EQUAL_OP:
+                compResult = (r1.getDoubleValue() == r2.getDoubleValue());
+                break;
+            case OpKind_META_EQUAL_OP:
+                compResult = (r1.getDoubleValue() == r2.getDoubleValue());
+                break;
+            case OpKind_NOT_EQUAL_OP:
+                compResult = (r1.getDoubleValue() != r2.getDoubleValue());
+                break;
+            case OpKind_META_NOT_EQUAL_OP:
+                compResult = (r1.getDoubleValue() != r2.getDoubleValue());
+                break;
+            case OpKind_GREATER_THAN_OP:
+                compResult = (r1.getDoubleValue() > r2.getDoubleValue());
+                break;
+            case OpKind_GREATER_OR_EQUAL_OP:
+                compResult = (r1.getDoubleValue() >= r2.getDoubleValue());
+                break;
+            default:
+                // should not get here
+                throw new HyracksDataException("Should not get here");
+        }
+        result.setBooleanValue(compResult);
+    }
+
+    // This function performs type promotions so that both v1 and v2 are of the
+    // same numerical type: (v1 and v2 are not ERROR or UNDEFINED)
+    //  + if both v1 and v2 are Numbers and of the same type, return type
+    //  + if v1 is an int and v2 is a real, convert v1 to real; return REAL_VALUE
+    //  + if v1 is a real and v2 is an int, convert v2 to real; return REAL_VALUE
+    public static ValueType coerceToNumber(Value v1, Value v2) {
+        AMutableInt64 i = new AMutableInt64(0);
+        AMutableDouble r = new AMutableDouble(0);
+        MutableBoolean b = new MutableBoolean();
+
+        // either of v1, v2 not numerical?
+        if (v1.isClassAdValue() || v2.isClassAdValue())
+            return ValueType.CLASSAD_VALUE;
+        if (v1.isListValue() || v2.isListValue())
+            return ValueType.LIST_VALUE;
+        if (v1.isStringValue() || v2.isStringValue())
+            return ValueType.STRING_VALUE;
+        if (v1.isUndefinedValue() || v2.isUndefinedValue())
+            return ValueType.UNDEFINED_VALUE;
+        if (v1.isErrorValue() || v2.isErrorValue())
+            return ValueType.ERROR_VALUE;
+        if (v1.isAbsoluteTimeValue() || v2.isAbsoluteTimeValue())
+            return ValueType.ABSOLUTE_TIME_VALUE;
+        if (v1.isRelativeTimeValue() || v2.isRelativeTimeValue())
+            return ValueType.RELATIVE_TIME_VALUE;
+
+        // promote booleans to integers
+        if (v1.isBooleanValue(b)) {
+            if (b.booleanValue()) {
+                v1.setIntegerValue(1);
+            } else {
+                v1.setIntegerValue(0);
+            }
+        }
+
+        if (v2.isBooleanValue(b)) {
+            if (b.booleanValue()) {
+                v2.setIntegerValue(1);
+            } else {
+                v2.setIntegerValue(0);
+            }
+        }
+
+        // both v1 and v2 of same numerical type
+        if (v1.isIntegerValue(i) && v2.isIntegerValue(i))
+            return ValueType.INTEGER_VALUE;
+        if (v1.isRealValue(r) && v2.isRealValue(r))
+            return ValueType.REAL_VALUE;
+
+        // type promotions required
+        if (v1.isIntegerValue(i) && v2.isRealValue(r))
+            v1.setRealValue(i.getLongValue());
+        else if (v1.isRealValue(r) && v2.isIntegerValue(i))
+            v2.setRealValue(i.getLongValue());
+
+        return ValueType.REAL_VALUE;
+    }
+
+    public Operation(int op, ExprTreeHolder e1, ExprTreeHolder e2, ExprTreeHolder e3) {
+        this.opKind = op;
+        this.child1 = e1 == null ? null : e1.self();
+        this.child2 = e2 == null ? null : e2.self();
+        this.child3 = e3 == null ? null : e3.self();
+    }
+
+    public static Operation createOperation(int op, ExprTree e1, ExprTree e2, ExprTree e3) {
+        Operation opnode = new Operation();
+        opnode.opKind = op;
+        opnode.child1 = e1 == null ? null : e1.self();
+        opnode.child2 = e2 == null ? null : e2.self();
+        opnode.child3 = e3 == null ? null : e3.self();
+        return opnode;
+    }
+
+    public static void createOperation(int op, ExprTree e1, ExprTree e2, ExprTree e3, Operation opnode) {
+        opnode.opKind = op;
+        opnode.child1 = e1 == null ? null : e1.self();
+        opnode.child2 = e2 == null ? null : e2.self();
+        opnode.child3 = e3 == null ? null : e3.self();
+    }
+
+    public void getComponents(AMutableInt32 op, ExprTreeHolder e1, ExprTreeHolder e2, ExprTreeHolder e3) {
+        op.setValue(opKind);
+        e1.setInnerTree(child1);
+        e2.setInnerTree(child2);
+        e3.setInnerTree(child3);
+    }
+
+    public static Operation createOperation(int op, Value val, ExprTreeHolder tree) throws HyracksDataException {
+        if (tree.getInnerTree() == null) {
+            return null;
+        }
+        Literal lit = Literal.createLiteral(val);
+        if (lit == null) {
+            return null;
+        }
+        Operation newOp = createOperation(op, lit, tree);
+        return newOp;
+    }
+
+    public static Operation createOperation(int op, ExprTreeHolder tree, Value val) throws HyracksDataException {
+        if (tree.getInnerTree() == null) {
+            return null;
+        }
+        Literal lit = Literal.createLiteral(val);
+        if (lit == null) {
+            return null;
+        }
+        Operation newOp = createOperation(op, lit, tree);
+        return newOp;
+    }
+
+    public boolean flattenSpecials(EvalState state, Value val, ExprTreeHolder tree) throws HyracksDataException {
+        ExprTreeHolder fChild1 = new ExprTreeHolder();
+        ExprTreeHolder fChild2 = new ExprTreeHolder();
+        ExprTreeHolder fChild3 = new ExprTreeHolder();
+        Value eval1 = new Value();
+        Value eval2 = new Value();
+        Value eval3 = new Value();
+
+        switch (opKind) {
+            case OpKind_UNARY_PLUS_OP:
+            case OpKind_UNARY_MINUS_OP:
+            case OpKind_PARENTHESES_OP:
+            case OpKind_LOGICAL_NOT_OP:
+            case OpKind_BITWISE_NOT_OP:
+                if (!child1.publicFlatten(state, eval1, fChild1)) {
+                    tree.setInnerTree(null);
+                    return false;
+                }
+                if (fChild1.getInnerTree() != null) {
+                    tree.setInnerTree(Operation.createOperation(opKind, fChild1));
+                    return (tree.getInnerTree() != null);
+                } else {
+                    privateDoOperation(opKind, eval1, null, null, true, false, false, val);
+                    tree.setInnerTree(null);
+                    eval1.clear();
+                    return true;
+                }
+            case OpKind_TERNARY_OP:
+                // Flatten the selector expression
+                if (!child1.publicFlatten(state, eval1, fChild1)) {
+                    tree.setInnerTree(null);
+                    return false;
+                }
+
+                // check if selector expression collapsed to a non-undefined value
+                if (fChild1.getInnerTree() == null && !eval1.isUndefinedValue()) {
+                    MutableBoolean b = new MutableBoolean();
+                    // if the selector is not boolean-equivalent, propagate error
+                    if (!eval1.isBooleanValueEquiv(b)) {
+                        val.setErrorValue();
+                        eval1.clear();
+                        tree.setInnerTree(null);
+                        return true;
+                    }
+
+                    // eval1 is either a real or an integer
+                    if (b.booleanValue()) {
+                        return child2.publicFlatten(state, val, tree);
+                    } else {
+                        return child3.publicFlatten(state, val, tree);
+                    }
+                } else {
+                    // Flatten arms of the if expression
+                    if (!child2.publicFlatten(state, eval2, fChild2) || !child3.publicFlatten(state, eval3, fChild3)) {
+                        // clean up
+                        tree.setInnerTree(null);
+                        return false;
+                    }
+
+                    // if any arm collapsed into a value, make it a Literal
+                    if (fChild2.getInnerTree() == null)
+                        fChild2.setInnerTree(Literal.createLiteral(eval2));
+                    if (fChild3.getInnerTree() == null)
+                        fChild3.setInnerTree(Literal.createLiteral(eval3));
+                    if (fChild2.getInnerTree() == null || fChild3.getInnerTree() == null) {
+                        tree.setInnerTree(null);;
+                        return false;
+                    }
+
+                    // fChild1 may be NULL if child1 Flattened to UNDEFINED
+                    if (fChild1.getInnerTree() == null) {
+                        fChild1.setInnerTree(child1.copy());
+                    }
+
+                    tree.setInnerTree(Operation.createOperation(opKind, fChild1, fChild2, fChild3));
+                    if (tree.getInnerTree() == null) {
+                        return false;
+                    }
+                    return true;
+                }
+            case OpKind_SUBSCRIPT_OP:
+                // Flatten both arguments
+                if (!child1.publicFlatten(state, eval1, fChild1) || !child2.publicFlatten(state, eval2, fChild2)) {
+                    tree.setInnerTree(null);
+                    return false;
+                }
+
+                // if both arguments Flattened to values, Evaluate now
+                if (fChild1.getInnerTree() == null && fChild2.getInnerTree() == null) {
+                    privateDoOperation(opKind, eval1, eval2, null, true, true, false, val);
+                    tree.setInnerTree(null);
+                    return true;
+                }
+
+                // otherwise convert Flattened values into literals
+                if (fChild1.getInnerTree() == null)
+                    fChild1.setInnerTree(Literal.createLiteral(eval1));
+                if (fChild2.getInnerTree() == null)
+                    fChild2.setInnerTree(Literal.createLiteral(eval2));
+                if (fChild1.getInnerTree() == null || fChild2.getInnerTree() == null) {
+                    tree.setInnerTree(null);
+                    return false;
+                }
+
+                tree.setInnerTree(Operation.createOperation(opKind, fChild1, fChild2));
+                if (tree.getInnerTree() == null) {
+                    return false;
+                }
+                return true;
+
+            default:
+                throw new HyracksDataException("Should not get here");
+        }
+    }
+
+    public static boolean isStrictOperator(int op) {
+        switch (op) {
+            case OpKind_META_EQUAL_OP:
+            case OpKind_META_NOT_EQUAL_OP:
+            case OpKind_LOGICAL_AND_OP:
+            case OpKind_LOGICAL_OR_OP:
+            case OpKind_TERNARY_OP:
+                return false;
+            default:
+                return true;
+        }
+    }
+
+    // get precedence levels for operators (see K&R p.53 )
+    public static int precedenceLevel(int op) {
+        switch (op) {
+            case OpKind_SUBSCRIPT_OP:
+                return (12);
+
+            case OpKind_LOGICAL_NOT_OP:
+            case OpKind_BITWISE_NOT_OP:
+            case OpKind_UNARY_PLUS_OP:
+            case OpKind_UNARY_MINUS_OP:
+                return (11);
+
+            case OpKind_MULTIPLICATION_OP:
+            case OpKind_DIVISION_OP:
+            case OpKind_MODULUS_OP:
+                return (10);
+
+            case OpKind_ADDITION_OP:
+            case OpKind_SUBTRACTION_OP:
+                return (9);
+
+            case OpKind_LEFT_SHIFT_OP:
+            case OpKind_RIGHT_SHIFT_OP:
+            case OpKind_URIGHT_SHIFT_OP:
+                return (8);
+
+            case OpKind_LESS_THAN_OP:
+            case OpKind_LESS_OR_EQUAL_OP:
+            case OpKind_GREATER_OR_EQUAL_OP:
+            case OpKind_GREATER_THAN_OP:
+                return (7);
+
+            case OpKind_NOT_EQUAL_OP:
+            case OpKind_EQUAL_OP:
+            case OpKind_IS_OP:
+            case OpKind_ISNT_OP:
+                return (6);
+
+            case OpKind_BITWISE_AND_OP:
+                return (5);
+
+            case OpKind_BITWISE_XOR_OP:
+                return (4);
+
+            case OpKind_BITWISE_OR_OP:
+                return (3);
+
+            case OpKind_LOGICAL_AND_OP:
+                return (2);
+
+            case OpKind_LOGICAL_OR_OP:
+                return (1);
+
+            case OpKind_TERNARY_OP:
+                return (0);
+            default:
+                return (-1);
+        }
+    }
+
+    @Override
+    public void reset() {
+        opKind = OpKind_NO_OP;
+        if (child1 != null)
+            child1.reset();
+        if (child2 != null)
+            child2.reset();
+        if (child3 != null)
+            child3.reset();
+    }
+}


Mime
View raw message