Return-Path: X-Original-To: apmail-asterixdb-commits-archive@minotaur.apache.org Delivered-To: apmail-asterixdb-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 14EA418F41 for ; Mon, 22 Feb 2016 22:35:07 +0000 (UTC) Received: (qmail 31601 invoked by uid 500); 22 Feb 2016 22:35:07 -0000 Delivered-To: apmail-asterixdb-commits-archive@asterixdb.apache.org Received: (qmail 31564 invoked by uid 500); 22 Feb 2016 22:35:07 -0000 Mailing-List: contact commits-help@asterixdb.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@asterixdb.incubator.apache.org Delivered-To: mailing list commits@asterixdb.incubator.apache.org Received: (qmail 31554 invoked by uid 99); 22 Feb 2016 22:35:06 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 22 Feb 2016 22:35:06 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id 60169C12B3 for ; Mon, 22 Feb 2016 22:35:06 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.021 X-Spam-Level: X-Spam-Status: No, score=-4.021 tagged_above=-999 required=6.31 tests=[KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id B7yFliYPJMDu for ; Mon, 22 Feb 2016 22:35:01 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 7C1275FE0B for ; Mon, 22 Feb 2016 22:34:50 +0000 (UTC) Received: (qmail 29287 invoked by uid 99); 22 Feb 2016 22:34:49 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 22 Feb 2016 22:34:49 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 512EBE04D7; Mon, 22 Feb 2016 22:34:49 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: amoudi@apache.org To: commits@asterixdb.incubator.apache.org Date: Mon, 22 Feb 2016 22:34:59 -0000 Message-Id: <331380cef3b54db3ada1b988a0dfc307@git.apache.org> In-Reply-To: <599702c4f0254acfa2e3eeee75299be2@git.apache.org> References: <599702c4f0254acfa2e3eeee75299be2@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [11/34] incubator-asterixdb git commit: Enabled Feed Tests and Added External Library tests 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(); + } +}