1 /* Copyright (C) 2014 InfiniDB, Inc.
2    Copyright (C) 2019 MariaDB Corporation
3 
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License
6    as published by the Free Software Foundation; version 2 of
7    the License.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17    MA 02110-1301, USA. */
18 
19 /***********************************************************************
20 *   $Id: predicateoperator.cpp 9306 2013-03-12 15:49:11Z rdempsey $
21 *
22 *
23 ***********************************************************************/
24 
25 #include <iostream>
26 
27 #include "bytestream.h"
28 #include "predicateoperator.h"
29 #include "objectreader.h"
30 
31 #include "liboamcpp.h"
32 
33 #include "collation.h"
34 
35 using namespace oam;
36 
37 using namespace std;
38 
39 namespace execplan
40 {
41 
42 /**
43  * Constructors/Destructors
44  */
PredicateOperator()45 PredicateOperator::PredicateOperator() :
46     cs(NULL)
47 {
48 }
49 
PredicateOperator(const string & operatorName)50 PredicateOperator::PredicateOperator(const string& operatorName) :
51     cs(NULL)
52 {
53     data(operatorName);
54 }
55 
PredicateOperator(const PredicateOperator & rhs)56 PredicateOperator::PredicateOperator(const PredicateOperator& rhs) : Operator(rhs)
57 {
58     data(rhs.data());
59     cs = rhs.getCharset();
60 }
61 
~PredicateOperator()62 PredicateOperator:: ~PredicateOperator()
63 {
64 }
65 
66 /**
67  * Operations
68  */
69 
70 /**
71  * friend function
72  */
operator <<(ostream & output,const PredicateOperator & rhs)73 ostream& operator<<(ostream& output, const PredicateOperator& rhs)
74 {
75     output << rhs.toString() << endl;
76     output << "OpType=" << rhs.operationType().colDataType << endl;
77     return output;
78 }
79 
80 /**
81  * The serialization interface
82  */
serialize(messageqcpp::ByteStream & b) const83 void PredicateOperator::serialize(messageqcpp::ByteStream& b) const
84 {
85     b << (ObjectReader::id_t) ObjectReader::PREDICATEOPERATOR;
86     //b << fData;
87     Operator::serialize(b);
88 }
89 
unserialize(messageqcpp::ByteStream & b)90 void PredicateOperator::unserialize(messageqcpp::ByteStream& b)
91 {
92     ObjectReader::checkType(b, ObjectReader::PREDICATEOPERATOR);
93     //b >> fData;
94     Operator::unserialize(b);
95     cs = & datatypes::Charset(fOperationType.charsetNumber).getCharset();
96 }
97 
operator ==(const PredicateOperator & t) const98 bool PredicateOperator::operator==(const PredicateOperator& t) const
99 {
100     if (data() == t.data())
101         return true;
102 
103     return false;
104 }
105 
operator ==(const TreeNode * t) const106 bool PredicateOperator::operator==(const TreeNode* t) const
107 {
108     const PredicateOperator* o;
109 
110     o = dynamic_cast<const PredicateOperator*>(t);
111 
112     if (o == NULL)
113         return false;
114 
115     return *this == *o;
116 }
117 
operator !=(const PredicateOperator & t) const118 bool PredicateOperator::operator!=(const PredicateOperator& t) const
119 {
120     return (!(*this == t));
121 }
122 
operator !=(const TreeNode * t) const123 bool PredicateOperator::operator!=(const TreeNode* t) const
124 {
125     return (!(*this == t));
126 }
127 
128 //FIXME: VARBINARY???
setOpType(Type & l,Type & r)129 void PredicateOperator::setOpType(Type& l, Type& r)
130 {
131     fOperationType = l;  // Default to left side. Modify as needed.
132     if ( l.colDataType == execplan::CalpontSystemCatalog::DATETIME ||
133             l.colDataType == execplan::CalpontSystemCatalog::TIME ||
134             l.colDataType == execplan::CalpontSystemCatalog::TIMESTAMP ||
135             l.colDataType == execplan::CalpontSystemCatalog::DATE )
136     {
137         switch (r.colDataType)
138         {
139             case execplan::CalpontSystemCatalog::CHAR:
140             case execplan::CalpontSystemCatalog::VARCHAR:
141                 fOperationType.charsetNumber = r.charsetNumber;
142                 break;
143 
144             case execplan::CalpontSystemCatalog::DATETIME:
145                 fOperationType.colDataType = execplan::CalpontSystemCatalog::DATETIME;
146                 fOperationType.colWidth = 8;
147                 break;
148 
149             case execplan::CalpontSystemCatalog::TIMESTAMP:
150                 fOperationType.colDataType = execplan::CalpontSystemCatalog::TIMESTAMP;
151                 fOperationType.colWidth = 8;
152                 break;
153 
154             case execplan::CalpontSystemCatalog::TIME:
155                 fOperationType.colDataType = execplan::CalpontSystemCatalog::TIME;
156                 fOperationType.colWidth = 8;
157                 break;
158 
159             case execplan::CalpontSystemCatalog::DATE:
160                 fOperationType = l;
161                 break;
162 
163             default:
164                 fOperationType.colDataType = execplan::CalpontSystemCatalog::DOUBLE;
165                 fOperationType.colWidth = 8;
166                 break;
167         }
168     }
169     else if ( r.colDataType == execplan::CalpontSystemCatalog::DATETIME ||
170               r.colDataType == execplan::CalpontSystemCatalog::TIME ||
171               r.colDataType == execplan::CalpontSystemCatalog::TIMESTAMP ||
172               r.colDataType == execplan::CalpontSystemCatalog::DATE )
173     {
174         switch (l.colDataType)
175         {
176             case execplan::CalpontSystemCatalog::CHAR:
177             case execplan::CalpontSystemCatalog::VARCHAR:
178                 fOperationType.colDataType = execplan::CalpontSystemCatalog::VARCHAR;
179                 fOperationType.colWidth = 255;
180                 break;
181 
182             case execplan::CalpontSystemCatalog::DATETIME:
183                 fOperationType.colDataType = execplan::CalpontSystemCatalog::DATETIME;
184                 fOperationType.colWidth = 8;
185                 break;
186 
187             case execplan::CalpontSystemCatalog::TIMESTAMP:
188                 fOperationType.colDataType = execplan::CalpontSystemCatalog::TIMESTAMP;
189                 fOperationType.colWidth = 8;
190                 break;
191 
192             case execplan::CalpontSystemCatalog::TIME:
193                 fOperationType.colDataType = execplan::CalpontSystemCatalog::TIME;
194                 fOperationType.colWidth = 8;
195                 break;
196 
197             case execplan::CalpontSystemCatalog::DATE:
198                 fOperationType = r;
199                 break;
200 
201             default:
202                 fOperationType.colDataType = execplan::CalpontSystemCatalog::DOUBLE;
203                 fOperationType.colWidth = 8;
204                 break;
205         }
206     }
207     else if (l.colDataType == execplan::CalpontSystemCatalog::DECIMAL ||
208              l.colDataType == execplan::CalpontSystemCatalog::UDECIMAL)
209     {
210         switch (r.colDataType)
211         {
212             case execplan::CalpontSystemCatalog::DECIMAL:
213             case execplan::CalpontSystemCatalog::UDECIMAL:
214             {
215                 // should following the result type that MySQL gives
216                 fOperationType = l;
217                 fOperationType.scale = (l.scale > r.scale ? l.scale : r.scale);
218                 break;
219             }
220 
221             case execplan::CalpontSystemCatalog::INT:
222             case execplan::CalpontSystemCatalog::MEDINT:
223             case execplan::CalpontSystemCatalog::TINYINT:
224             case execplan::CalpontSystemCatalog::BIGINT:
225             case execplan::CalpontSystemCatalog::UINT:
226             case execplan::CalpontSystemCatalog::UMEDINT:
227             case execplan::CalpontSystemCatalog::UTINYINT:
228             case execplan::CalpontSystemCatalog::UBIGINT:
229                 fOperationType.colDataType = execplan::CalpontSystemCatalog::DECIMAL;
230                 fOperationType.scale = l.scale;
231                 fOperationType.colWidth = 8;
232                 break;
233 
234             default:
235                 fOperationType.colDataType = execplan::CalpontSystemCatalog::DOUBLE;
236                 fOperationType.colWidth = 8;
237         }
238     }
239     else if (r.colDataType == execplan::CalpontSystemCatalog::DECIMAL ||
240              r.colDataType == execplan::CalpontSystemCatalog::UDECIMAL)
241     {
242         switch (l.colDataType)
243         {
244             case execplan::CalpontSystemCatalog::DECIMAL:
245             case execplan::CalpontSystemCatalog::UDECIMAL:
246             {
247                 // should following the result type that MySQL gives based on the following logic?
248                 // @NOTE is this trustable?
249                 fOperationType = fResultType;
250                 break;
251             }
252 
253             case execplan::CalpontSystemCatalog::INT:
254             case execplan::CalpontSystemCatalog::MEDINT:
255             case execplan::CalpontSystemCatalog::TINYINT:
256             case execplan::CalpontSystemCatalog::BIGINT:
257             case execplan::CalpontSystemCatalog::UINT:
258             case execplan::CalpontSystemCatalog::UMEDINT:
259             case execplan::CalpontSystemCatalog::UTINYINT:
260             case execplan::CalpontSystemCatalog::UBIGINT:
261                 fOperationType.colDataType = execplan::CalpontSystemCatalog::DECIMAL;
262                 fOperationType.scale = r.scale;
263                 fOperationType.colWidth = 8;
264                 break;
265 
266             case execplan::CalpontSystemCatalog::LONGDOUBLE:
267                 fOperationType.colDataType = execplan::CalpontSystemCatalog::LONGDOUBLE;
268                 fOperationType.colWidth = sizeof(long double);
269                 break;
270             default:
271                 fOperationType.colDataType = execplan::CalpontSystemCatalog::DOUBLE;
272                 fOperationType.colWidth = 8;
273         }
274     }
275     // If both sides are unsigned, use UBIGINT as result type, otherwise
276     // "promote" to BIGINT.
277     else if (isUnsigned(l.colDataType) && isUnsigned(r.colDataType))
278     {
279         fOperationType.colDataType = execplan::CalpontSystemCatalog::UBIGINT;
280         fOperationType.colWidth = 8;
281     }
282     else if ((isSignedInteger(l.colDataType) && isUnsigned(r.colDataType)) ||
283              (isUnsigned(l.colDataType) && isSignedInteger(r.colDataType)) ||
284              (isSignedInteger(l.colDataType) && isSignedInteger(r.colDataType)))
285     {
286         fOperationType.colDataType = execplan::CalpontSystemCatalog::BIGINT;
287         fOperationType.colWidth = 8;
288     }
289     else if ((l.colDataType == execplan::CalpontSystemCatalog::CHAR ||
290               l.colDataType == execplan::CalpontSystemCatalog::VARCHAR ||
291               l.colDataType == execplan::CalpontSystemCatalog::TEXT) &&
292              (r.colDataType == execplan::CalpontSystemCatalog::CHAR ||
293               r.colDataType == execplan::CalpontSystemCatalog::VARCHAR ||
294               r.colDataType == execplan::CalpontSystemCatalog::TEXT))
295     {
296 #if 0
297         // Currently, STRINT isn't properly implemented everywhere
298         // For short strings, we can get a faster execution for charset that fit in one byte.
299         if ( ( (l.colDataType == execplan::CalpontSystemCatalog::CHAR && l.colWidth <= 8) ||
300                 (l.colDataType == execplan::CalpontSystemCatalog::VARCHAR && l.colWidth < 8) ) &&
301                 ( (r.colDataType == execplan::CalpontSystemCatalog::CHAR && r.colWidth <= 8) ||
302                   (r.colDataType == execplan::CalpontSystemCatalog::VARCHAR && r.colWidth < 8) ) )
303         {
304             switch (fOperationType.charsetNumber)
305             {
306                 case 8:  // latin1_swedish_ci
307                 case 9:  // latin2_general_ci
308                 case 11: // ascii_general_ci
309                 case 47: // latin1_bin
310                 case 48: // latin1_general_ci
311                 case 49: // latin1_general_cs
312                 case 65: // ascii_bin
313                 case 77: // latin2_bin
314                     // char[] as network order int for fast comparison.
315                     fOperationType.colDataType = execplan::CalpontSystemCatalog::BIGINT;
316                     fOperationType.scale = 0;
317                     fOperationType.colWidth = 8;
318                     l.colDataType = execplan::CalpontSystemCatalog::STRINT;
319                     r.colDataType = execplan::CalpontSystemCatalog::STRINT;
320                 default:
321                     fOperationType.colDataType = execplan::CalpontSystemCatalog::VARCHAR;
322                     fOperationType.colWidth = 255;
323             }
324         }
325         else
326 #endif
327         {
328             fOperationType.colDataType = execplan::CalpontSystemCatalog::VARCHAR;
329             fOperationType.colWidth = 255;
330         }
331     }
332     else if (l.colDataType == execplan::CalpontSystemCatalog::LONGDOUBLE ||
333              r.colDataType == execplan::CalpontSystemCatalog::LONGDOUBLE)
334     {
335         fOperationType.colDataType = execplan::CalpontSystemCatalog::LONGDOUBLE;
336         fOperationType.colWidth = sizeof(long double);
337     }
338     else
339     {
340         fOperationType.colDataType = execplan::CalpontSystemCatalog::DOUBLE;
341         fOperationType.colWidth = 8;
342     }
343 
344     cs = & datatypes::Charset(fOperationType.charsetNumber).getCharset();
345 }
346 
strTrimCompare(const std::string & op1,const std::string & op2)347 inline bool PredicateOperator::strTrimCompare(const std::string& op1, const std::string& op2)
348 {
349     int r1 =  cs->strnncollsp(op1.c_str(), op1.length(), op2.c_str(), op2.length());
350     switch (fOp)
351     {
352         case OP_EQ:
353             return r1 == 0;
354 
355         case OP_NE:
356             return r1 != 0;
357 
358         case OP_GT:
359             return r1 > 0;
360 
361         case OP_GE:
362             return r1 >= 0;
363 
364         case OP_LT:
365             return r1 < 0;
366 
367         case OP_LE:
368             return r1 <= 0;
369 
370         default:
371         {
372             std::ostringstream oss;
373             oss << "Unsupported predicate operation: " << fOp;
374             throw logging::InvalidOperationExcept(oss.str());
375         }
376     }
377 }
378 
getBoolVal(rowgroup::Row & row,bool & isNull,ReturnedColumn * lop,ReturnedColumn * rop)379 bool PredicateOperator::getBoolVal(rowgroup::Row& row, bool& isNull, ReturnedColumn* lop, ReturnedColumn* rop)
380 {
381     // like operator. both sides are string.
382     if (fOp == OP_LIKE || fOp == OP_NOTLIKE)
383     {
384         const std::string & subject = lop->getStrVal(row, isNull);
385         if (isNull)
386             return false;
387         const std::string & pattern = rop->getStrVal(row, isNull);
388         if (isNull)
389             return false;
390         return datatypes::Charset(cs).like(fOp == OP_NOTLIKE,
391                                            utils::ConstString(subject),
392                                            utils::ConstString(pattern));
393     }
394 
395     // fOpType should have already been set on the connector during parsing
396     switch (fOperationType.colDataType)
397     {
398         case execplan::CalpontSystemCatalog::BIGINT:
399         case execplan::CalpontSystemCatalog::INT:
400         case execplan::CalpontSystemCatalog::MEDINT:
401         case execplan::CalpontSystemCatalog::TINYINT:
402         case execplan::CalpontSystemCatalog::SMALLINT:
403         {
404             if (fOp == OP_ISNULL)
405             {
406                 lop->getIntVal(row, isNull);
407                 bool ret = isNull;
408                 isNull = false;
409                 return ret;
410             }
411 
412             if (fOp == OP_ISNOTNULL)
413             {
414                 lop->getIntVal(row, isNull);
415                 bool ret = isNull;
416                 isNull = false;
417                 return !ret;
418             }
419 
420             if (isNull)
421                 return false;
422 
423             int64_t val1 = lop->getIntVal(row, isNull);
424 
425             if (isNull)
426                 return false;
427 
428             return numericCompare(val1,  rop->getIntVal(row, isNull)) && !isNull;
429         }
430 
431         case execplan::CalpontSystemCatalog::UBIGINT:
432         case execplan::CalpontSystemCatalog::UINT:
433         case execplan::CalpontSystemCatalog::UMEDINT:
434         case execplan::CalpontSystemCatalog::UTINYINT:
435         case execplan::CalpontSystemCatalog::USMALLINT:
436         {
437             if (fOp == OP_ISNULL)
438             {
439                 lop->getUintVal(row, isNull);
440                 bool ret = isNull;
441                 isNull = false;
442                 return ret;
443             }
444 
445             if (fOp == OP_ISNOTNULL)
446             {
447                 lop->getUintVal(row, isNull);
448                 bool ret = isNull;
449                 isNull = false;
450                 return !ret;
451             }
452 
453             if (isNull)
454                 return false;
455 
456             uint64_t val1 = lop->getUintVal(row, isNull);
457 
458             if (isNull)
459                 return false;
460 
461             return numericCompare(val1,  rop->getUintVal(row, isNull)) && !isNull;
462         }
463 
464         case execplan::CalpontSystemCatalog::FLOAT:
465         case execplan::CalpontSystemCatalog::UFLOAT:
466         case execplan::CalpontSystemCatalog::DOUBLE:
467         case execplan::CalpontSystemCatalog::UDOUBLE:
468         {
469             if (fOp == OP_ISNULL)
470             {
471                 lop->getDoubleVal(row, isNull);
472                 bool ret = isNull;
473                 isNull = false;
474                 return ret;
475             }
476 
477             if (fOp == OP_ISNOTNULL)
478             {
479                 lop->getDoubleVal(row, isNull);
480                 bool ret = isNull;
481                 isNull = false;
482                 return !ret;
483             }
484 
485             if (isNull)
486                 return false;
487 
488             double val1 = lop->getDoubleVal(row, isNull);
489 
490             if (isNull)
491                 return false;
492 
493             return numericCompare(val1, rop->getDoubleVal(row, isNull)) && !isNull;
494         }
495 
496         case execplan::CalpontSystemCatalog::LONGDOUBLE:
497         {
498             if (fOp == OP_ISNULL)
499             {
500                 lop->getLongDoubleVal(row, isNull);
501                 bool ret = isNull;
502                 isNull = false;
503                 return ret;
504             }
505 
506             if (fOp == OP_ISNOTNULL)
507             {
508                 lop->getLongDoubleVal(row, isNull);
509                 bool ret = isNull;
510                 isNull = false;
511                 return !ret;
512             }
513 
514             if (isNull)
515                 return false;
516 
517             long double val1 = lop->getLongDoubleVal(row, isNull);
518             if (isNull)
519                 return false;
520 
521             long double val2 = rop->getLongDoubleVal(row, isNull);
522             if (isNull)
523                 return false;
524 
525             // In many case, rounding error will prevent an eq compare to work
526             // In these cases, use the largest scale of the two items.
527             if (fOp == execplan::OP_EQ)
528             {
529                 // In case a val is a representation of a very large integer,
530                 // we won't want to just multiply by scale, as it may move
531                 // significant digits out of scope. So we break them apart
532                 // and compare each separately
533                 int64_t scale = std::max(lop->resultType().scale, rop->resultType().scale);
534                 if (scale)
535                 {
536                     long double intpart1;
537                     long double fract1 = modfl(val1, &intpart1);
538                     long double intpart2;
539                     long double fract2 = modfl(val2, &intpart2);
540                     if (numericCompare(intpart1, intpart2))
541                     {
542                         double factor = pow(10.0, (double)scale);
543                         fract1 = roundl(fract1 * factor);
544                         fract2 = roundl(fract2 * factor);
545                         return numericCompare(fract1, fract2);
546                     }
547                     else
548                     {
549                         return false;
550                     }
551                 }
552             }
553             return numericCompare(val1, val2);
554         }
555 
556         case execplan::CalpontSystemCatalog::DECIMAL:
557         case execplan::CalpontSystemCatalog::UDECIMAL:
558         {
559             if (fOp == OP_ISNULL)
560             {
561                 lop->getDecimalVal(row, isNull);
562                 bool ret = isNull;
563                 isNull = false;
564                 return ret;
565             }
566 
567             if (fOp == OP_ISNOTNULL)
568             {
569                 lop->getDecimalVal(row, isNull);
570                 bool ret = isNull;
571                 isNull = false;
572                 return !ret;
573             }
574 
575             if (isNull)
576                 return false;
577 
578             IDB_Decimal val1 = lop->getDecimalVal(row, isNull);
579 
580             if (isNull)
581                 return false;
582 
583             return numericCompare(val1, rop->getDecimalVal(row, isNull)) && !isNull;
584         }
585 
586         case execplan::CalpontSystemCatalog::DATE:
587         {
588             if (fOp == OP_ISNULL)
589             {
590                 lop->getDateIntVal(row, isNull);
591                 bool ret = isNull;
592                 isNull = false;
593                 return ret;
594             }
595 
596             if (fOp == OP_ISNOTNULL)
597             {
598                 lop->getDateIntVal(row, isNull);
599                 bool ret = isNull;
600                 isNull = false;
601                 return !ret;
602             }
603 
604             if (isNull)
605                 return false;
606 
607             int64_t val1 = lop->getDateIntVal(row, isNull);
608 
609             if (isNull)
610                 return false;
611 
612             return numericCompare(val1, (int64_t)rop->getDateIntVal(row, isNull)) && !isNull;
613         }
614 
615         case execplan::CalpontSystemCatalog::DATETIME:
616         {
617             if (fOp == OP_ISNULL)
618             {
619                 lop->getDatetimeIntVal(row, isNull);
620                 bool ret = isNull;
621                 isNull = false;
622                 return ret;
623             }
624 
625             if (fOp == OP_ISNOTNULL)
626             {
627                 lop->getDatetimeIntVal(row, isNull);
628                 bool ret = isNull;
629                 isNull = false;
630                 return !ret;
631             }
632 
633             if (isNull)
634                 return false;
635 
636             int64_t val1 = lop->getDatetimeIntVal(row, isNull);
637 
638             if (isNull)
639                 return false;
640 
641             return numericCompare(val1, rop->getDatetimeIntVal(row, isNull)) && !isNull;
642         }
643 
644         case execplan::CalpontSystemCatalog::TIMESTAMP:
645         {
646             if (fOp == OP_ISNULL)
647             {
648                 lop->getTimestampIntVal(row, isNull);
649                 bool ret = isNull;
650                 isNull = false;
651                 return ret;
652             }
653 
654             if (fOp == OP_ISNOTNULL)
655             {
656                 lop->getTimestampIntVal(row, isNull);
657                 bool ret = isNull;
658                 isNull = false;
659                 return !ret;
660             }
661 
662             if (isNull)
663                 return false;
664 
665             int64_t val1 = lop->getTimestampIntVal(row, isNull);
666 
667             if (isNull)
668                 return false;
669 
670             return numericCompare(val1, rop->getTimestampIntVal(row, isNull)) && !isNull;
671         }
672 
673         case execplan::CalpontSystemCatalog::TIME:
674         {
675             if (fOp == OP_ISNULL)
676             {
677                 lop->getTimeIntVal(row, isNull);
678                 bool ret = isNull;
679                 isNull = false;
680                 return ret;
681             }
682 
683             if (fOp == OP_ISNOTNULL)
684             {
685                 lop->getTimeIntVal(row, isNull);
686                 bool ret = isNull;
687                 isNull = false;
688                 return !ret;
689             }
690 
691             if (isNull)
692                 return false;
693 
694             int64_t val1 = lop->getTimeIntVal(row, isNull);
695 
696             if (isNull)
697                 return false;
698 
699             return numericCompare(val1, rop->getTimeIntVal(row, isNull)) && !isNull;
700         }
701 
702 
703 
704         case execplan::CalpontSystemCatalog::VARCHAR:
705         case execplan::CalpontSystemCatalog::CHAR:
706         case execplan::CalpontSystemCatalog::TEXT:
707         {
708             if (fOp == OP_ISNULL)
709             {
710                 lop->getStrVal(row, isNull);
711                 bool ret = isNull;
712                 isNull = false;
713                 return ret;
714             }
715 
716             if (fOp == OP_ISNOTNULL)
717             {
718                 lop->getStrVal(row, isNull);
719                 bool ret = isNull;
720                 isNull = false;
721                 return !ret;
722             }
723 
724             if (isNull)
725                 return false;
726 
727             const std::string& val1 = lop->getStrVal(row, isNull);
728             if (isNull)
729                 return false;
730 
731             return strTrimCompare(val1, rop->getStrVal(row, isNull)) && !isNull;
732         }
733 
734         //FIXME: ???
735         case execplan::CalpontSystemCatalog::VARBINARY:
736         case execplan::CalpontSystemCatalog::BLOB:
737             return false;
738             break;
739 
740         default:
741         {
742             std::ostringstream oss;
743             oss << "invalid predicate operation type: " << fOperationType.colDataType;
744             throw logging::InvalidOperationExcept(oss.str());
745         }
746     }
747 
748     return false;
749 }
750 
751 }  // namespace
752