/* Copyright (C) 2014 InfiniDB, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /*********************************************************************** * $Id: operator.cpp 9210 2013-01-21 14:10:42Z rdempsey $ * * ***********************************************************************/ #include #include #include "bytestream.h" #include "operator.h" #include "objectreader.h" using namespace std; namespace { /**@brief util struct for converting string to lower case */ struct to_lower { char operator()(char c) const { return tolower(c); } }; // Trim any leading/trailing ws const string lrtrim(const string& in) { string::size_type p1; p1 = in.find_first_not_of(" \t\n"); if (p1 == string::npos) p1 = 0; string::size_type p2; p2 = in.find_last_not_of(" \t\n"); if (p2 == string::npos) p2 = in.size() - 1; return string(in, p1, (p2 - p1 + 1)); } } // namespace namespace execplan { /** * Constructors/Destructors */ Operator::Operator() { } Operator::Operator(const string& operatorName) { data(operatorName); } Operator::Operator(const Operator& rhs) : TreeNode(rhs), fOp(rhs.op()) { data(rhs.fData); } Operator::~Operator() { } /** * Operations */ void Operator::data(const string data) { fData = lrtrim(data); transform(fData.begin(), fData.end(), fData.begin(), to_lower()); if (fData == "+") { fOp = OP_ADD; } else if (fData == "-") { fOp = OP_SUB; } else if (fData == "*") { fOp = OP_MUL; } else if (fData == "/") { fOp = OP_DIV; } else if (fData == "=") { fOp = OP_EQ; } else if (fData == "!=" || fData == "<>") { fOp = OP_NE; } else if (fData == ">") { fOp = OP_GT; } else if (fData == ">=") { fOp = OP_GE; } else if (fData == "<") { fOp = OP_LT; } else if (fData == "<=") { fOp = OP_LE; } else if (fData == "and") { fOp = OP_AND; } else if (fData == "or") { fOp = OP_OR; } else if (fData == "like") { fOp = OP_LIKE; } else if (fData == "not like") { fOp = OP_NOTLIKE; fData = "not like"; } else if (fData == "isnull") { fOp = OP_ISNULL; fData = "is null"; } else if (fData == "isnotnull") { fOp = OP_ISNOTNULL; fData = "is not null"; } else if (fData == "xor") { fOp = OP_XOR; } else { fOp = OP_UNKNOWN; } } const string Operator::toString() const { ostringstream oss; oss << string("Operator: " + fData) << " fOp=" << fOp; oss << " " << "opType=" << fOperationType.colDataType; return oss.str(); } string Operator::toCppCode(IncludeSet& includes) const { includes.insert("operator.h"); stringstream ss; ss << "Operator(" << std::quoted(fData) << ")"; return ss.str(); } Operator* Operator::opposite() const { if (fData.compare(">") == 0) return new Operator("<"); if (fData.compare("<") == 0) return new Operator(">"); if (fData.compare(">=") == 0) return new Operator("<="); if (fData.compare("<=") == 0) return new Operator(">="); return this->clone(); } /** * friend function */ ostream& operator<<(ostream& output, const Operator& rhs) { output << rhs.toString(); return output; } /** * The serialization interface */ void Operator::serialize(messageqcpp::ByteStream& b) const { b << (ObjectReader::id_t)ObjectReader::OPERATOR; b << fData; fResultType.serialize(b); fOperationType.serialize(b); b << (uint32_t)fOp; } void Operator::unserialize(messageqcpp::ByteStream& b) { uint32_t val; ObjectReader::checkType(b, ObjectReader::OPERATOR); b >> fData; fResultType.unserialize(b); fOperationType.unserialize(b); b >> (uint32_t&)val; fOp = (OpType)val; fResult.decimalVal.scale = fResultType.scale; fResult.decimalVal.precision = fResultType.precision; } bool Operator::operator==(const Operator& t) const { if (fOp == t.fOp) return true; return false; } bool Operator::operator==(const TreeNode* t) const { const Operator* o; o = dynamic_cast(t); if (o == NULL) return false; return *this == *o; } bool Operator::operator!=(const Operator& t) const { return (!(*this == t)); } bool Operator::operator!=(const TreeNode* t) const { return (!(*this == t)); } void Operator::reverseOp() { switch (fOp) { case OP_EQ: fOp = OP_NE; fData = "!="; break; case OP_NE: fOp = OP_EQ; fData = '='; break; case OP_GT: fOp = OP_LT; fData = '<'; break; case OP_GE: fOp = OP_LE; fData = "<="; break; case OP_LT: fOp = OP_GT; fData = '>'; break; case OP_LE: fOp = OP_GE; fData = ">="; break; case OP_LIKE: fOp = OP_NOTLIKE; fData = "not like"; break; case OP_NOTLIKE: fOp = OP_LIKE; fData = "like"; break; case OP_ISNULL: fOp = OP_ISNOTNULL; fData = "isnotnull"; break; case OP_ISNOTNULL: fOp = OP_ISNULL; fData = "isnull"; break; case OP_BETWEEN: fOp = OP_NOTBETWEEN; fData = "not between"; break; case OP_NOTBETWEEN: fOp = OP_BETWEEN; fData = "between"; break; case OP_IN: fOp = OP_NOTIN; fData = "not in"; break; case OP_NOTIN: fOp = OP_IN; fData = "in"; break; default: fOp = OP_UNKNOWN; fData = "unknown"; break; } } } // namespace execplan