1 /* Copyright (C) 2014 InfiniDB, Inc.
2 
3    This program is free software; you can redistribute it and/or
4    modify it under the terms of the GNU General Public License
5    as published by the Free Software Foundation; version 2 of
6    the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16    MA 02110-1301, USA. */
17 
18 /***********************************************************************
19 *   $Id: operator.cpp 9210 2013-01-21 14:10:42Z rdempsey $
20 *
21 *
22 ***********************************************************************/
23 #include <iostream>
24 #include <sstream>
25 
26 #include "bytestream.h"
27 #include "operator.h"
28 #include "objectreader.h"
29 
30 using namespace std;
31 
32 namespace
33 {
34 
35 /**@brief util struct for converting string to lower case */
36 struct to_lower
37 {
operator ()__anon70f7450f0111::to_lower38     char operator() (char c) const
39     {
40         return tolower(c);
41     }
42 };
43 
44 //Trim any leading/trailing ws
lrtrim(const string & in)45 const string lrtrim(const string& in)
46 {
47     string::size_type p1;
48     p1 = in.find_first_not_of(" \t\n");
49 
50     if (p1 == string::npos) p1 = 0;
51 
52     string::size_type p2;
53     p2 = in.find_last_not_of(" \t\n");
54 
55     if (p2 == string::npos) p2 = in.size() - 1;
56 
57     return string(in, p1, (p2 - p1 + 1));
58 }
59 
60 }
61 
62 namespace execplan
63 {
64 
65 /**
66  * Constructors/Destructors
67  */
Operator()68 Operator::Operator()
69 {
70 }
71 
Operator(const string & operatorName)72 Operator::Operator(const string& operatorName)
73 {
74     data(operatorName);
75 }
76 
Operator(const Operator & rhs)77 Operator::Operator(const Operator& rhs) :
78     TreeNode(rhs),
79     fOp(rhs.op())
80 {
81     data(rhs.fData);
82 }
83 
~Operator()84 Operator:: ~Operator()
85 {
86 }
87 
88 /**
89  * Operations
90  */
data(const string data)91 void Operator::data(const string data)
92 {
93     fData = lrtrim(data);
94     transform (fData.begin(), fData.end(), fData.begin(), to_lower());
95 
96     if (fData == "+")
97     {
98         fOp = OP_ADD;
99     }
100     else if (fData == "-")
101     {
102         fOp = OP_SUB;
103     }
104     else if (fData == "*")
105     {
106         fOp = OP_MUL;
107     }
108     else if (fData == "/")
109     {
110         fOp = OP_DIV;
111     }
112     else if (fData == "=")
113     {
114         fOp = OP_EQ;
115     }
116     else if (fData == "!=" || fData == "<>")
117     {
118         fOp = OP_NE;
119     }
120     else if (fData == ">")
121     {
122         fOp = OP_GT;
123     }
124     else if (fData == ">=")
125     {
126         fOp = OP_GE;
127     }
128     else if (fData == "<")
129     {
130         fOp = OP_LT;
131     }
132     else if (fData == "<=")
133     {
134         fOp = OP_LE;
135     }
136     else if (fData == "and")
137     {
138         fOp = OP_AND;
139     }
140     else if (fData == "or")
141     {
142         fOp = OP_OR;
143     }
144     else if (fData == "like")
145     {
146         fOp = OP_LIKE;
147     }
148     else if (fData == "not like")
149     {
150         fOp = OP_NOTLIKE;
151         fData = "not like";
152     }
153     else if (fData == "isnull")
154     {
155         fOp = OP_ISNULL;
156         fData = "is null";
157     }
158     else if (fData == "isnotnull")
159     {
160         fOp = OP_ISNOTNULL;
161         fData = "is not null";
162     }
163     else if (fData == "xor")
164     {
165         fOp = OP_XOR;
166     }
167     else
168     {
169         fOp = OP_UNKNOWN;
170     }
171 }
172 
toString() const173 const string Operator::toString() const
174 {
175     ostringstream oss;
176     oss << string("Operator: " + fData) << " fOp=" << fOp;
177     oss << " " << "opType=" << fOperationType.colDataType;
178     return oss.str();
179 }
180 
opposite() const181 Operator* Operator::opposite() const
182 {
183     if (fData.compare(">") == 0)
184         return new Operator("<");
185 
186     if (fData.compare("<") == 0)
187         return new Operator(">");
188 
189     if (fData.compare(">=") == 0)
190         return new Operator("<=");
191 
192     if (fData.compare("<=") == 0)
193         return new Operator(">=");
194 
195     return this->clone();
196 }
197 
198 /**
199  * friend function
200  */
operator <<(ostream & output,const Operator & rhs)201 ostream& operator<<(ostream& output, const Operator& rhs)
202 {
203     output << rhs.toString();
204     return output;
205 }
206 
207 /**
208  * The serialization interface
209  */
serialize(messageqcpp::ByteStream & b) const210 void Operator::serialize(messageqcpp::ByteStream& b) const
211 {
212     b << (ObjectReader::id_t) ObjectReader::OPERATOR;
213     b << fData;
214     fResultType.serialize(b);
215     fOperationType.serialize(b);
216     b << (uint32_t)fOp;
217 }
218 
unserialize(messageqcpp::ByteStream & b)219 void Operator::unserialize(messageqcpp::ByteStream& b)
220 {
221     uint32_t val;
222     ObjectReader::checkType(b, ObjectReader::OPERATOR);
223     b >> fData;
224     fResultType.unserialize(b);
225     fOperationType.unserialize(b);
226 
227     b >> (uint32_t&)val;
228     fOp = (OpType)val;
229 
230     fResult.decimalVal.scale = fResultType.scale;
231     fResult.decimalVal.precision = fResultType.precision;
232 }
233 
operator ==(const Operator & t) const234 bool Operator::operator==(const Operator& t) const
235 {
236     if (fOp == t.fOp)
237         return true;
238 
239     return false;
240 }
241 
operator ==(const TreeNode * t) const242 bool Operator::operator==(const TreeNode* t) const
243 {
244     const Operator* o;
245 
246     o = dynamic_cast<const Operator*>(t);
247 
248     if (o == NULL)
249         return false;
250 
251     return *this == *o;
252 }
253 
operator !=(const Operator & t) const254 bool Operator::operator!=(const Operator& t) const
255 {
256     return (!(*this == t));
257 }
258 
operator !=(const TreeNode * t) const259 bool Operator::operator!=(const TreeNode* t) const
260 {
261     return (!(*this == t));
262 }
263 
reverseOp()264 void Operator::reverseOp()
265 {
266     switch (fOp)
267     {
268         case OP_EQ:
269             fOp = OP_NE;
270             fData = "!=";
271             break;
272 
273         case OP_NE:
274             fOp = OP_EQ;
275             fData = "=";
276             break;
277 
278         case OP_GT:
279             fOp = OP_LT;
280             fData = "<";
281             break;
282 
283         case OP_GE:
284             fOp = OP_LE;
285             fData = "<=";
286             break;
287 
288         case OP_LT:
289             fOp = OP_GT;
290             fData = ">";
291             break;
292 
293         case OP_LE:
294             fOp = OP_GE;
295             fData = ">=";
296             break;
297 
298         case OP_LIKE:
299             fOp = OP_NOTLIKE;
300             fData = "not like";
301             break;
302 
303         case OP_NOTLIKE:
304             fOp = OP_LIKE;
305             fData = "like";
306             break;
307 
308         case OP_ISNULL:
309             fOp = OP_ISNOTNULL;
310             fData = "isnotnull";
311             break;
312 
313         case OP_ISNOTNULL:
314             fOp = OP_ISNULL;
315             fData = "isnull";
316             break;
317 
318         case OP_BETWEEN:
319             fOp = OP_NOTBETWEEN;
320             fData = "not between";
321             break;
322 
323         case OP_NOTBETWEEN:
324             fOp = OP_BETWEEN;
325             fData = "between";
326             break;
327 
328         case OP_IN:
329             fOp = OP_NOTIN;
330             fData = "not in";
331             break;
332 
333         case OP_NOTIN:
334             fOp = OP_IN;
335             fData = "in";
336             break;
337 
338         default:
339             fOp = OP_UNKNOWN;
340             fData = "unknown";
341             break;
342     }
343 }
344 
345 }  // namespace
346