Variable* Expression::opPostfix(Variable *&a, TokenType op){ VarNumber* tmp = new VarNumber(); tmp->value = 1; Variable* res = a; res->retain(); switch (op){ case INCREASE : { // ++ Variable* tt = opAdditive(a, TokenType::PLUS, tmp); Variable* tt2 = Variable::assign(&a, tt); tt->release(); tt2->release(); break; } case DECREASE :{ // -- Variable* tt = opAdditive(a, TokenType::MINUS, tmp); Variable* tt2 = Variable::assign(&a, tt); tt->release(); tt2->release(); break; } default : throw ExpressionException(); break; } tmp->release(); return res; }
AbstractExpression *GetMoreSpecialized(ExpressionType c, L *l, R *r) { assert(l); assert(r); switch (c) { case (EXPRESSION_TYPE_COMPARE_EQUAL): return new InlinedComparisonExpression<CmpEq, L, R>(c, l, r); case (EXPRESSION_TYPE_COMPARE_NOTEQUAL): return new InlinedComparisonExpression<CmpNe, L, R>(c, l, r); case (EXPRESSION_TYPE_COMPARE_LESSTHAN): return new InlinedComparisonExpression<CmpLt, L, R>(c, l, r); case (EXPRESSION_TYPE_COMPARE_GREATERTHAN): return new InlinedComparisonExpression<CmpGt, L, R>(c, l, r); case (EXPRESSION_TYPE_COMPARE_LESSTHANOREQUALTO): return new InlinedComparisonExpression<CmpLte, L, R>(c, l, r); case (EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO): return new InlinedComparisonExpression<CmpGte, L, R>(c, l, r); case (EXPRESSION_TYPE_COMPARE_LIKE): return new InlinedComparisonExpression<CmpLike, L, R>( c, l, r); // added by michael case (EXPRESSION_TYPE_COMPARE_IN): return new InlinedComparisonExpression<CmpIn, L, R>( c, l, r); // added by michael default: char message[256]; sprintf(message, "Invalid ExpressionType '%s' called for" " ComparisonExpression", ExpressionTypeToString(c).c_str()); throw ExpressionException(message); } }
// convert the enumerated value type into a concrete c type for the // operator expression templated ctors AbstractExpression *OperatorFactory(ExpressionType et, AbstractExpression *lc, AbstractExpression *rc) { AbstractExpression *ret = nullptr; switch (et) { case (EXPRESSION_TYPE_OPERATOR_PLUS): ret = new OperatorExpression<OpPlus>(et, lc, rc); break; case (EXPRESSION_TYPE_OPERATOR_MINUS): ret = new OperatorExpression<OpMinus>(et, lc, rc); break; case (EXPRESSION_TYPE_OPERATOR_MULTIPLY): ret = new OperatorExpression<OpMultiply>(et, lc, rc); break; case (EXPRESSION_TYPE_OPERATOR_DIVIDE): ret = new OperatorExpression<OpDivide>(et, lc, rc); break; case (EXPRESSION_TYPE_OPERATOR_NOT): ret = new OperatorNotExpression(lc); break; case (EXPRESSION_TYPE_OPERATOR_MOD): throw ExpressionException("Mod operator is not yet supported."); case (EXPRESSION_TYPE_OPERATOR_CONCAT): throw ExpressionException("Concat operator not yet supported."); case (EXPRESSION_TYPE_OPERATOR_CAST): throw ExpressionException("Cast operator not yet supported."); default: throw ExpressionException("operator ctor helper out of sync"); } return ret; }
Variable* Expression::opEqual(Variable *a, TokenType op, Variable*b){ if (op != TokenType::EQUAL && op != TokenType::UNEQUAL) throw ExpressionException(); VarBoolean* res = new VarBoolean(); bool isEqual = false; if (a->type == Variable::BOOLEAN || a->type == Variable::NUMBER //convert to number for comparison || b->type == Variable::BOOLEAN || b->type == Variable::NUMBER){ VarNumber* ta = a->toVarNumber(); VarNumber* tb = b->toVarNumber(); if (ta->numType == VarNumber::NANUMBER || tb->numType == NANUMBER) isEqual = (op != TokenType::EQUAL); else isEqual = (ta->toString() == tb->toString()); ta->release(); tb->release(); } else if (a->type == Variable::OBJECT && ((VarObject*)a)->value != NULL && b->type == Variable::OBJECT && ((VarObject*)b)->value != NULL) isEqual = (a == b); else isEqual = a->toString() == b->toString(); switch (op){ case EQUAL :{ // == res->value = isEqual; break; } case UNEQUAL :{ // != res->value = !isEqual; break; } default: throw ExpressionException(); break; } return res; }
Variable* Expression::opAdditive(Variable *a, TokenType op, Variable *b){ Variable *res = NULL; if ((a->type == Variable::STRING || a->type == Variable::FUNCTION || b->type == Variable::STRING || b->type == Variable::FUNCTION) && op == TokenType::PLUS){ VarString* tmp = new VarString(); tmp->value = a->toString() + b->toString(); res = tmp; } else{ VarNumber* tmp = new VarNumber(); VarNumber* ta = a->toVarNumber(); VarNumber* tb = b->toVarNumber(); if (ta->numType == VarNumber::NANUMBER || tb->numType == VarNumber::NANUMBER){ tmp->numType = VarNumber::NANUMBER; res = tmp; } else { switch (op){ case MINUS : // - if (tb->numType == VarNumber::INF) tb->numType = VarNumber::NEG_INF; else if (tb->numType == VarNumber::NEG_INF) tb->numType = VarNumber::INF; else tb->value = -tb->value; case PLUS : // + if (ta->numType == VarNumber::INF && tb->numType == VarNumber::NEG_INF) tmp->numType = VarNumber::NANUMBER; else if (ta->numType == VarNumber::NEG_INF && tb->numType == VarNumber::INF) tmp->numType = VarNumber::NANUMBER; else if (ta->numType == VarNumber::NEG_INF || tb->numType == VarNumber::NEG_INF) tmp->numType = VarNumber::NEG_INF; else if (ta->numType == VarNumber::INF || tb->numType == VarNumber::INF) tmp->numType = VarNumber::INF; else { tmp->numType = VarNumber::NORMAL; tmp->value = ta->value + tb->value; } res = tmp; break; default : throw ExpressionException(); break; } } ta->release(); tb->release(); } return res; }
Variable* Expression::opUnary(TokenType op, Variable *a){ Variable* res = NULL; switch (op){ case NOT :{ // ! VarBoolean* tmp = new VarBoolean(); tmp->value = !a->toBoolean(); res = tmp; break; } case INCREASE : { // ++ VarNumber* tmp = new VarNumber(); tmp->value = 1; res = opAdditive(a, TokenType::PLUS, tmp); tmp->release(); break; } case DECREASE : { // -- VarNumber* tmp = new VarNumber(); tmp->value = 1; res = opAdditive(a, TokenType::MINUS, tmp); tmp->release(); break; } case REVERSE :{ // ~ break; } case PLUS : { // + VarNumber* tmp = a->toVarNumber(); res = tmp; break; } case MINUS : { // - VarNumber* tmp = new VarNumber(); res = opAdditive(tmp, TokenType::MINUS, a); tmp->release(); break; } default : throw ExpressionException(); break; } return res; }
// convert the enumerated value type into a concrete c type for the // operator expression templated ctors AbstractExpression *ExpressionUtil::OperatorFactory( ExpressionType et, ValueType vt, AbstractExpression *first, AbstractExpression *second, AbstractExpression *third, AbstractExpression *fourth) { AbstractExpression *ret = nullptr; switch (et) { case (EXPRESSION_TYPE_OPERATOR_PLUS): ret = new OperatorExpression<OpPlus>(et, vt, first, second); break; case EXPRESSION_TYPE_OPERATOR_UNARY_MINUS: ret = new OperatorUnaryMinusExpression(first); break; case (EXPRESSION_TYPE_OPERATOR_MINUS): ret = new OperatorExpression<OpMinus>(et, vt, first, second); break; case (EXPRESSION_TYPE_OPERATOR_MULTIPLY): ret = new OperatorExpression<OpMultiply>(et, vt, first, second); break; case (EXPRESSION_TYPE_OPERATOR_DIVIDE): ret = new OperatorExpression<OpDivide>(et, vt, first, second); break; case (EXPRESSION_TYPE_OPERATOR_NOT): ret = new OperatorUnaryNotExpression(first); break; case (EXPRESSION_TYPE_SUBSTR): ret = new SubstringExpression(first, second, third); break; case (EXPRESSION_TYPE_CONCAT): ret = new ConcatExpression(first, second); break; case (EXPRESSION_TYPE_ASCII): ret = new AsciiExpression(first); break; case (EXPRESSION_TYPE_CHAR): ret = new CharExpression(first); break; case (EXPRESSION_TYPE_CHAR_LEN): ret = new CharLengthExpression(first); break; case (EXPRESSION_TYPE_OCTET_LEN): ret = new OctetLengthExpression(first); break; case (EXPRESSION_TYPE_POSITION): ret = new PositionExpression(first, second); break; case (EXPRESSION_TYPE_REPEAT): ret = new RepeatExpression(first, second); break; case (EXPRESSION_TYPE_LEFT): ret = new LeftExpression(first, second); break; case (EXPRESSION_TYPE_RIGHT): ret = new RightExpression(first, second); break; case (EXPRESSION_TYPE_REPLACE): ret = new ReplaceExpression(first, second, third); break; case (EXPRESSION_TYPE_OVERLAY): ret = new OverlayExpression(first, second, third, fourth); break; case (EXPRESSION_TYPE_LTRIM): ret = new LTrimExpression(first, second); break; case (EXPRESSION_TYPE_RTRIM): ret = new RTrimExpression(first, second); break; case (EXPRESSION_TYPE_BTRIM): ret = new BTrimExpression(first, second); break; case (EXPRESSION_TYPE_OPERATOR_MOD): ret = new OperatorExpression<OpMod>(et, vt, first, second); break; case (EXPRESSION_TYPE_EXTRACT): ret = new ExtractExpression(first, second); break; case (EXPRESSION_TYPE_DATE_TO_TIMESTAMP): ret = new DateToTimestampExpression(first); break; case (EXPRESSION_TYPE_OPERATOR_CONCAT): throw ExpressionException("Concat operator not yet supported."); case (EXPRESSION_TYPE_OPERATOR_CAST): throw ExpressionException("Cast operator not yet supported."); default: throw ExpressionException("operator ctor helper out of sync"); } return ret; }
AbstractExpression *AbstractExpression::CreateExpressionTreeRecurse( json_spirit::Object &obj) { // build a tree recursively from the bottom upwards. // when the expression node is instantiated, its type, // value and child types will have been discovered. ExpressionType peek_type = EXPRESSION_TYPE_INVALID; ValueType value_type = VALUE_TYPE_INVALID; AbstractExpression *left_child = nullptr; AbstractExpression *right_child = nullptr; // read the expression type json_spirit::Value expression_type_value = json_spirit::find_value(obj, "TYPE"); if (expression_type_value == json_spirit::Value::null) { throw ExpressionException( "AbstractExpression:: buildExpressionTree_recurse:" "Couldn't find TYPE value"); } assert(StringToExpressionType(expression_type_value.get_str()) != EXPRESSION_TYPE_INVALID); peek_type = StringToExpressionType(expression_type_value.get_str()); // and the value type json_spirit::Value valueTypeValue = json_spirit::find_value(obj, "VALUE_TYPE"); if (valueTypeValue == json_spirit::Value::null) { throw ExpressionException( "AbstractExpression:: buildExpressionTree_recurse:" " Couldn't find VALUE_TYPE value"); } std::string value_type_string = valueTypeValue.get_str(); value_type = StringToValueType(value_type_string); // this should be relatively safe, though it ignores overflow. if ((value_type == VALUE_TYPE_TINYINT) || (value_type == VALUE_TYPE_SMALLINT) || (value_type == VALUE_TYPE_INTEGER)) { value_type = VALUE_TYPE_BIGINT; } assert(value_type != VALUE_TYPE_INVALID); // add the value size json_spirit::Value value_size_value = json_spirit::find_value(obj, "VALUE_SIZE"); if (value_size_value == json_spirit::Value::null) { throw ExpressionException( "AbstractExpression:: buildExpressionTree_recurse:" " Couldn't find VALUE_SIZE value"); } int value_size = value_size_value.get_int(); // recurse to children try { json_spirit::Value leftValue = json_spirit::find_value(obj, "LEFT"); if (!(leftValue == json_spirit::Value::null)) { left_child = AbstractExpression::CreateExpressionTreeRecurse(leftValue.get_obj()); } else { left_child = nullptr; } json_spirit::Value rightValue = json_spirit::find_value(obj, "RIGHT"); if (!(rightValue == json_spirit::Value::null)) { right_child = AbstractExpression::CreateExpressionTreeRecurse(rightValue.get_obj()); } else { right_child = nullptr; } // Invoke the factory. obviously it has to handle null children. // pass it the serialization stream in case a subclass has more // to read. yes, the per-class data really does follow the // child serializations. return ExpressionUtil::ExpressionFactory(obj, peek_type, value_type, value_size, left_child, right_child); } catch (ExpressionException &ex) { // clean up children delete left_child; delete right_child; throw; } }
Variable* Expression::opMultiplicative(Variable *a, TokenType op, Variable *b){ VarNumber* res = new VarNumber(); VarNumber* ta = a->toVarNumber(); VarNumber* tb = b->toVarNumber(); if (ta->numType == VarNumber::NANUMBER || tb->numType == VarNumber::NANUMBER) res->numType = VarNumber::NANUMBER; else { bool nega = ta->numType == VarNumber::NEG_INF || (ta->numType == VarNumber::NORMAL && ta->value < 0); bool negb = tb->numType == VarNumber::NEG_INF || (tb->numType == VarNumber::NORMAL && tb->value < 0); bool negres = nega != negb; switch (op){ case TIMES : // * if (ta->numType == VarNumber::INF && tb->numType == VarNumber::NORMAL && fabs(tb->value) <1e-9) res->numType = VarNumber::NANUMBER; else if (tb->numType == VarNumber::INF && ta->numType == VarNumber::NORMAL && ta->value <1e-9) res->numType = VarNumber::NANUMBER; else { if (ta->numType != VarNumber::NORMAL) res->numType = negres ? VarNumber::NEG_INF : VarNumber::INF; else if (tb->numType != VarNumber::NORMAL) res->numType = negres ? VarNumber::NEG_INF : VarNumber::INF; else { res->numType = VarNumber::NORMAL; res->value = ta->value * tb->value; } } break; case OVER : // / if (ta->numType != VarNumber::NORMAL && tb->numType != VarNumber::NORMAL) res->numType = VarNumber::NANUMBER; else if (ta->numType != VarNumber::NORMAL) res->numType = negres ? VarNumber::NEG_INF : VarNumber::INF; else if (tb->numType != VarNumber::NORMAL){ res->numType = VarNumber::NORMAL; res->value = 0; } else if (fabs(tb->value) < 1e-9) res->numType = VarNumber::NANUMBER; else { res->numType = VarNumber::NORMAL; res->value = ta->value / tb->value; } break; case MOD : // % if (ta->numType != VarNumber::NORMAL && tb->numType != VarNumber::NORMAL) res->numType = VarNumber::NANUMBER; else if (ta->numType != VarNumber::NORMAL || (tb->numType == VarNumber::NORMAL && fabs(tb->value) < 1e-9 || tb->numType == VarNumber::INF)) res->numType = VarNumber::NANUMBER; else if (tb->numType != VarNumber::NORMAL){ res->numType = VarNumber::NORMAL; res->value = ta->value; } else if (ta->value == 0){ res->numType = VarNumber::NORMAL; res->value = 0; } else { res->numType = VarNumber::NORMAL; res->value = (long long)(ta->value) % (long long)(tb->value); } break; default : throw ExpressionException(); break; } } ta->release(); tb->release(); return res; }
Variable* Expression::opAssign(Variable *&a, TokenType op, Variable *b){ Variable* res = NULL; switch (op){ case ASSIGN :{ // = res = Variable::assign(&a, b); break; } case PASSIGN: { // += Variable* tmp = opAdditive(a, TokenType::PLUS, b); res = Variable::assign(&a, tmp); tmp->release(); break; } case MINUSASSIGN :{ // -= Variable* tmp = opAdditive(a, TokenType::MINUS, b); res = Variable::assign(&a, tmp); tmp->release(); break; } case TASSIGN:{ // *= Variable* tmp = opMultiplicative(a, TokenType::TIMES, b); res = Variable::assign(&a, tmp); tmp->release(); break; } case OASSIGN: { // /= Variable* tmp = opMultiplicative(a, TokenType::OVER, b); res = Variable::assign(&a, tmp); tmp->release(); break; } case MODASSIGN :{ // %= Variable* tmp = opMultiplicative(a, TokenType::MOD, b); res = Variable::assign(&a, tmp); tmp->release(); break; } case ORASSIGN : { // |= Variable* tmp = opMultiplicative(a, TokenType::OR, b); res = Variable::assign(&a, tmp); tmp->release(); break; } case XORASSIGN :{ // ^= Variable* tmp = opMultiplicative(a, TokenType::XOR, b); res = Variable::assign(&a, tmp); tmp->release(); break; } case ANDASSIGN :{ // &= Variable * tmp = opLogical(a, TokenType::AND, b); res = Variable::assign(&a, tmp); tmp->release(); break; } default :{ throw ExpressionException(); break; } } return res; }
Variable* Expression::opRelation(Variable *a, TokenType op, Variable *b){ VarBoolean* res = new VarBoolean(); if (a->type == Variable::BOOLEAN || a->type == Variable::NUMBER //convert to number for comparison || b->type == Variable::BOOLEAN || b->type == Variable::NUMBER){ VarNumber* ta = a->toVarNumber(); VarNumber* tb = b->toVarNumber(); if (ta->numType == VarNumber::NANUMBER || tb->numType == VarNumber::NANUMBER) res->value = false; else { switch (op){ case LESS : // < res->value = (ta->type == VarNumber::NEG_INF && tb->type == VarNumber::INF) || (ta->type == VarNumber::NEG_INF && tb->type == VarNumber::NORMAL) || (ta->type == VarNumber::NORMAL && tb->type == VarNumber::INF) || (ta->type == VarNumber::NORMAL && tb->type == VarNumber::NORMAL && ta->toNumber() < tb->toNumber()); break; case GREAT : // > res->value = (ta->type == VarNumber::INF && tb->type == VarNumber::NEG_INF) || (ta->type == VarNumber::INF && tb->type == VarNumber::NORMAL) || (ta->type == VarNumber::NORMAL && tb->type == VarNumber::NEG_INF) || (ta->type == VarNumber::NORMAL && tb->type == VarNumber::NORMAL && ta->toNumber() > tb->toNumber()); break; case LESSEUQAL : // <= res->value = (ta->type == VarNumber::NEG_INF && tb->type == VarNumber::INF) || (ta->type == VarNumber::NEG_INF && tb->type == VarNumber::NORMAL) || (ta->type == VarNumber::NORMAL && tb->type == VarNumber::INF) || (ta->type == VarNumber::INF && tb->type == VarNumber::INF) || (ta->type == VarNumber::NEG_INF && tb->type == VarNumber::NEG_INF) || (ta->type == VarNumber::NORMAL && tb->type == VarNumber::NORMAL && ta->toNumber() <= tb->toNumber()); break; case GREATQUAL : // >= res->value = (ta->type == VarNumber::INF && tb->type == VarNumber::NEG_INF) || (ta->type == VarNumber::INF && tb->type == VarNumber::NORMAL) || (ta->type == VarNumber::NORMAL && tb->type == VarNumber::NEG_INF) || (ta->type == VarNumber::INF && tb->type == VarNumber::INF) || (ta->type == VarNumber::NEG_INF && tb->type == VarNumber::NEG_INF) || (ta->type == VarNumber::NORMAL && tb->type == VarNumber::NORMAL && ta->toNumber() >= tb->toNumber()); break; default : throw ExpressionException(); break; } } ta->release(); tb->release(); } else { switch (op){ case LESS : // < res->value = a->toString() < b->toString(); break; case GREAT : // > res->value = a->toString() > b->toString(); break; case LESSEUQAL : // <= res->value = a->toString() <= b->toString(); break; case GREATQUAL : // >= res->value = a->toString() >= b->toString(); break; default : throw ExpressionException(); break; } } return res; }