1 /*
2    Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include "API.hpp"
26 #include <NdbScanFilter.hpp>
27 #include <Vector.hpp>
28 #include <NdbOut.hpp>
29 #include <Interpreter.hpp>
30 #include <signaldata/AttrInfo.hpp>
31 
32 #ifdef VM_TRACE
33 #include <NdbEnv.h>
34 #define INT_DEBUG(x) \
35   { const char* tmp = NdbEnv_GetEnv("INT_DEBUG", (char*)0, 0); \
36   if (tmp != 0 && strlen(tmp) != 0) { ndbout << "INT:"; ndbout_c x; } }
37 #else
38 #define INT_DEBUG(x)
39 #endif
40 
41 class NdbScanFilterImpl {
42 public:
NdbScanFilterImpl()43   NdbScanFilterImpl() {}
44   struct State {
45     NdbScanFilter::Group m_group;
46     Uint32 m_popCount;
47     Uint32 m_ownLabel;
48     Uint32 m_trueLabel;
49     Uint32 m_falseLabel;
50   };
51 
52   int m_label;
53   State m_current;
54   Uint32 m_negative;    //used for translating NAND/NOR to AND/OR, equal 0 or 1
55   Vector<State> m_stack;
56   Vector<Uint32> m_stack2;    //to store info of m_negative
57   NdbInterpretedCode * m_code;
58   NdbError m_error;
59 
60   /* Members for supporting old Api */
61   NdbScanOperation *m_associated_op;
62 
63   int cond_col(Interpreter::UnaryCondition, Uint32 attrId);
64 
65   int cond_col_const(Interpreter::BinaryCondition, Uint32 attrId,
66 		     const void * value, Uint32 len);
67 
68   /* Method to initialise the members */
init(NdbInterpretedCode * code)69   void init (NdbInterpretedCode *code)
70   {
71     m_current.m_group = (NdbScanFilter::Group)0;
72     m_current.m_popCount = 0;
73     m_current.m_ownLabel = 0;
74     m_current.m_trueLabel = ~0;
75     m_current.m_falseLabel = ~0;
76     m_label = 0;
77     m_negative = 0;
78     m_code= code;
79     m_associated_op= NULL;
80 
81     if (code == NULL)
82       /* NdbInterpretedCode not supported for operation type */
83       m_error.code = 4539;
84     else
85       m_error.code = 0;
86   };
87 
88   /* This method propagates an error code from NdbInterpretedCode
89    * back to the NdbScanFilter object
90    */
propagateErrorFromCode()91   int propagateErrorFromCode()
92   {
93     NdbError codeError= m_code->getNdbError();
94 
95     /* Map interpreted code's 'Too many instructions in
96      * interpreted program' to FilterTooLarge error for
97      * NdbScanFilter
98      */
99     if (codeError.code == 4518)
100       m_error.code = NdbScanFilter::FilterTooLarge;
101     else
102       m_error.code = codeError.code;
103 
104     return -1;
105   };
106 
107   /* This method performs any steps required once the
108    * filter definition is complete
109    */
handleFilterDefined()110   int handleFilterDefined()
111   {
112     /* Finalise the interpreted program */
113     if (m_code->finalise() != 0)
114       return propagateErrorFromCode();
115 
116     /* For old Api support, we set the passed-in operation's
117      * interpreted code to be the code generated by the
118      * scanfilter
119      */
120     if (m_associated_op != NULL)
121     {
122       m_associated_op->setInterpretedCode(m_code);
123     }
124 
125     return 0;
126   }
127 
128 };
129 
130 const Uint32 LabelExit = ~0;
131 
132 
NdbScanFilter(NdbInterpretedCode * code)133 NdbScanFilter::NdbScanFilter(NdbInterpretedCode* code) :
134   m_impl(* new NdbScanFilterImpl())
135 {
136   DBUG_ENTER("NdbScanFilter::NdbScanFilter(NdbInterpretedCode)");
137   m_impl.init(code);
138   DBUG_VOID_RETURN;
139 }
140 
NdbScanFilter(class NdbOperation * op)141 NdbScanFilter::NdbScanFilter(class NdbOperation * op) :
142   m_impl(* new NdbScanFilterImpl())
143 {
144   DBUG_ENTER("NdbScanFilter::NdbScanFilter(NdbOperation)");
145 
146   NdbInterpretedCode* code= NULL;
147   NdbOperation::Type opType= op->getType();
148 
149   /* If the operation is not of the correct type then
150    * m_impl.init() will set an error on the scan filter
151    */
152   if (likely((opType == NdbOperation::TableScan) ||
153              (opType == NdbOperation::OrderedIndexScan)))
154   {
155     /* We ask the NdbScanOperation to allocate an InterpretedCode
156      * object for us.  It will look after freeing it when
157      * necessary.  This allows the InterpretedCode object to
158      * survive after the NdbScanFilter has gone out of scope
159      */
160     code= ((NdbScanOperation *)op)->allocInterpretedCodeOldApi();
161   }
162 
163   m_impl.init(code);
164 
165   m_impl.m_associated_op= (NdbScanOperation*) op;
166 
167   DBUG_VOID_RETURN;
168 }
169 
~NdbScanFilter()170 NdbScanFilter::~NdbScanFilter()
171 {
172   delete &m_impl;
173 }
174 
175 int
begin(Group group)176 NdbScanFilter::begin(Group group){
177   if (m_impl.m_error.code != 0) return -1;
178 
179   if (m_impl.m_stack2.push_back(m_impl.m_negative))
180   {
181     /* Memory allocation problem */
182     m_impl.m_error.code= 4000;
183     return -1;
184   }
185   switch(group){
186   case NdbScanFilter::AND:
187     INT_DEBUG(("Begin(AND)"));
188     if(m_impl.m_negative == 1){
189       group = NdbScanFilter::OR;
190     }
191     break;
192   case NdbScanFilter::OR:
193     INT_DEBUG(("Begin(OR)"));
194     if(m_impl.m_negative == 1){
195       group = NdbScanFilter::AND;
196     }
197     break;
198   case NdbScanFilter::NAND:
199     INT_DEBUG(("Begin(NAND)"));
200     if(m_impl.m_negative == 0){
201       group = NdbScanFilter::OR;
202       m_impl.m_negative = 1;
203     }else{
204       group = NdbScanFilter::AND;
205       m_impl.m_negative = 0;
206     }
207     break;
208   case NdbScanFilter::NOR:
209     INT_DEBUG(("Begin(NOR)"));
210     if(m_impl.m_negative == 0){
211       group = NdbScanFilter::AND;
212       m_impl.m_negative = 1;
213     }else{
214       group = NdbScanFilter::OR;
215       m_impl.m_negative = 0;
216     }
217     break;
218   }
219 
220   if(group == m_impl.m_current.m_group){
221     switch(group){
222     case NdbScanFilter::AND:
223     case NdbScanFilter::OR:
224       m_impl.m_current.m_popCount++;
225       return 0;
226     case NdbScanFilter::NOR:
227     case NdbScanFilter::NAND:
228       break;
229     }
230   }
231 
232   NdbScanFilterImpl::State tmp = m_impl.m_current;
233   if (m_impl.m_stack.push_back(m_impl.m_current))
234   {
235     /* Memory allocation problem */
236     m_impl.m_error.code= 4000;
237     return -1;
238   }
239   m_impl.m_current.m_group = group;
240   m_impl.m_current.m_ownLabel = m_impl.m_label++;
241   m_impl.m_current.m_popCount = 0;
242 
243   switch(group){
244   case NdbScanFilter::AND:
245   case NdbScanFilter::NAND:
246     m_impl.m_current.m_falseLabel = m_impl.m_current.m_ownLabel;
247     m_impl.m_current.m_trueLabel = tmp.m_trueLabel;
248     break;
249   case NdbScanFilter::OR:
250   case NdbScanFilter::NOR:
251     m_impl.m_current.m_falseLabel = tmp.m_falseLabel;
252     m_impl.m_current.m_trueLabel = m_impl.m_current.m_ownLabel;
253     break;
254   default:
255     /* Operator is not defined in NdbScanFilter::Group  */
256     m_impl.m_error.code= 4260;
257     return -1;
258   }
259 
260   return 0;
261 }
262 
263 int
end()264 NdbScanFilter::end(){
265   if (m_impl.m_error.code != 0) return -1;
266 
267   if(m_impl.m_stack2.size() == 0){
268     /* Invalid set of range scan bounds */
269     m_impl.m_error.code= 4259;
270     return -1;
271   }
272   m_impl.m_negative = m_impl.m_stack2.back();
273   m_impl.m_stack2.erase(m_impl.m_stack2.size() - 1);
274 
275   switch(m_impl.m_current.m_group){
276   case NdbScanFilter::AND:
277     INT_DEBUG(("End(AND pc=%d)", m_impl.m_current.m_popCount));
278     break;
279   case NdbScanFilter::OR:
280     INT_DEBUG(("End(OR pc=%d)", m_impl.m_current.m_popCount));
281     break;
282   case NdbScanFilter::NAND:
283     INT_DEBUG(("End(NAND pc=%d)", m_impl.m_current.m_popCount));
284     break;
285   case NdbScanFilter::NOR:
286     INT_DEBUG(("End(NOR pc=%d)", m_impl.m_current.m_popCount));
287     break;
288   }
289 
290   if(m_impl.m_current.m_popCount > 0){
291     m_impl.m_current.m_popCount--;
292     return 0;
293   }
294 
295   NdbScanFilterImpl::State tmp = m_impl.m_current;
296   if(m_impl.m_stack.size() == 0){
297     /* Invalid set of range scan bounds */
298     m_impl.m_error.code= 4259;
299     return -1;
300   }
301   m_impl.m_current = m_impl.m_stack.back();
302   m_impl.m_stack.erase(m_impl.m_stack.size() - 1);
303 
304   switch(tmp.m_group){
305   case NdbScanFilter::AND:
306     if(tmp.m_trueLabel == (Uint32)~0){
307       if (m_impl.m_code->interpret_exit_ok() == -1)
308         return m_impl.propagateErrorFromCode();
309     } else {
310       if (m_impl.m_code->branch_label(tmp.m_trueLabel) == -1)
311         return m_impl.propagateErrorFromCode();
312     }
313     break;
314   case NdbScanFilter::NAND:
315     if(tmp.m_trueLabel == (Uint32)~0){
316       if (m_impl.m_code->interpret_exit_nok() == -1)
317         return m_impl.propagateErrorFromCode();
318     } else {
319       if (m_impl.m_code->branch_label(tmp.m_falseLabel) == -1)
320         return m_impl.propagateErrorFromCode();
321     }
322     break;
323   case NdbScanFilter::OR:
324     if(tmp.m_falseLabel == (Uint32)~0){
325       if (m_impl.m_code->interpret_exit_nok() == -1)
326         return m_impl.propagateErrorFromCode();
327     } else {
328       if (m_impl.m_code->branch_label(tmp.m_falseLabel) == -1)
329         return m_impl.propagateErrorFromCode();
330     }
331     break;
332   case NdbScanFilter::NOR:
333     if(tmp.m_falseLabel == (Uint32)~0){
334       if (m_impl.m_code->interpret_exit_ok() == -1)
335         return m_impl.propagateErrorFromCode();
336     } else {
337       if (m_impl.m_code->branch_label(tmp.m_trueLabel) == -1)
338         return m_impl.propagateErrorFromCode();
339     }
340     break;
341   default:
342     /* Operator is not defined in NdbScanFilter::Group */
343     m_impl.m_error.code= 4260;
344     return -1;
345   }
346 
347   if (m_impl.m_code->def_label(tmp.m_ownLabel) == -1)
348     return m_impl.propagateErrorFromCode();
349 
350   if(m_impl.m_stack.size() == 0){
351     switch(tmp.m_group){
352     case NdbScanFilter::AND:
353     case NdbScanFilter::NOR:
354       if (m_impl.m_code->interpret_exit_nok() == -1)
355         return m_impl.propagateErrorFromCode();
356       break;
357     case NdbScanFilter::OR:
358     case NdbScanFilter::NAND:
359       if (m_impl.m_code->interpret_exit_ok() == -1)
360         return m_impl.propagateErrorFromCode();
361       break;
362     default:
363       /* Operator is not defined in NdbScanFilter::Group */
364       m_impl.m_error.code= 4260;
365       return -1;
366     }
367 
368     /* Handle the completion of the filter definition */
369     return m_impl.handleFilterDefined();
370   }
371   return 0;
372 }
373 
374 int
istrue()375 NdbScanFilter::istrue(){
376   if(m_impl.m_error.code != 0) return -1;
377 
378   if(m_impl.m_current.m_group < NdbScanFilter::AND ||
379      m_impl.m_current.m_group > NdbScanFilter::NOR){
380     /* Operator is not defined in NdbScanFilter::Group */
381     m_impl.m_error.code= 4260;
382     return -1;
383   }
384 
385   if(m_impl.m_current.m_trueLabel == (Uint32)~0){
386     if (m_impl.m_code->interpret_exit_ok() == -1)
387       return m_impl.propagateErrorFromCode();
388   } else {
389     if (m_impl.m_code->branch_label(m_impl.m_current.m_trueLabel) == -1)
390       return m_impl.propagateErrorFromCode();
391   }
392 
393   return 0;
394 }
395 
396 int
isfalse()397 NdbScanFilter::isfalse(){
398   if (m_impl.m_error.code != 0) return -1;
399   if(m_impl.m_current.m_group < NdbScanFilter::AND ||
400      m_impl.m_current.m_group > NdbScanFilter::NOR){
401     /* Operator is not defined in NdbScanFilter::Group */
402     m_impl.m_error.code= 4260;
403     return -1;
404   }
405 
406   if(m_impl.m_current.m_falseLabel == (Uint32)~0){
407     if (m_impl.m_code->interpret_exit_nok() == -1)
408       return m_impl.propagateErrorFromCode();
409   } else {
410     if (m_impl.m_code->branch_label(m_impl.m_current.m_falseLabel) == -1)
411       return m_impl.propagateErrorFromCode();
412   }
413 
414   return 0;
415 }
416 
417 #define action(x, y, z)
418 
419 /* One argument branch definition method signature */
420 typedef int (NdbInterpretedCode:: * Branch1)(Uint32, Uint32 label);
421 /* Two argument branch definition method signature */
422 typedef int (NdbInterpretedCode:: * StrBranch2)(const void*, Uint32, Uint32,  Uint32);
423 
424 /* Table of unary branch methods for each group type */
425 struct tab2 {
426   Branch1 m_branches[5];
427 };
428 
429 /* Table of correct branch method to use for group types
430  * and condition type.
431  * In general, AND branches to fail (short circuits) if the
432  * condition is not satisfied, and OR branches to success
433  * (short circuits) if it is satisfied.
434  * NAND is the same as AND, with the branch condition inverted.
435  * NOR is the same as OR, with the branch condition inverted
436  */
437 static const tab2 table2[] = {
438   /**
439    * IS NULL
440    */
441   { { 0,
442       &NdbInterpretedCode::branch_col_ne_null,      // AND
443       &NdbInterpretedCode::branch_col_eq_null,      // OR
444       &NdbInterpretedCode::branch_col_eq_null,      // NAND
445       &NdbInterpretedCode::branch_col_ne_null } }   // NOR
446 
447   /**
448    * IS NOT NULL
449    */
450   ,{ { 0,
451        &NdbInterpretedCode::branch_col_eq_null,     // AND
452        &NdbInterpretedCode::branch_col_ne_null,     // OR
453        &NdbInterpretedCode::branch_col_ne_null,     // NAND
454        &NdbInterpretedCode::branch_col_eq_null } }  // NOR
455 };
456 
457 const int tab2_sz = sizeof(table2)/sizeof(table2[0]);
458 
459 int
cond_col(Interpreter::UnaryCondition op,Uint32 AttrId)460 NdbScanFilterImpl::cond_col(Interpreter::UnaryCondition op, Uint32 AttrId){
461 
462   if (m_error.code != 0) return -1;
463 
464   if(op < 0 || op >= tab2_sz){
465     /* Condition is out of bounds */
466     m_error.code= 4262;
467     return -1;
468   }
469 
470   if(m_current.m_group < NdbScanFilter::AND ||
471      m_current.m_group > NdbScanFilter::NOR){
472     /* Operator is not defined in NdbScanFilter::Group */
473     m_error.code= 4260;
474     return -1;
475   }
476 
477   Branch1 branch = table2[op].m_branches[m_current.m_group];
478   if ((m_code->* branch)(AttrId, m_current.m_ownLabel) == -1)
479     return propagateErrorFromCode();
480 
481   return 0;
482 }
483 
484 int
isnull(int AttrId)485 NdbScanFilter::isnull(int AttrId){
486   if (m_impl.m_error.code != 0) return -1;
487 
488   if(m_impl.m_negative == 1)
489     return m_impl.cond_col(Interpreter::IS_NOT_NULL, AttrId);
490   else
491     return m_impl.cond_col(Interpreter::IS_NULL, AttrId);
492 }
493 
494 int
isnotnull(int AttrId)495 NdbScanFilter::isnotnull(int AttrId){
496   if (m_impl.m_error.code != 0) return -1;
497 
498   if(m_impl.m_negative == 1)
499     return m_impl.cond_col(Interpreter::IS_NULL, AttrId);
500   else
501     return m_impl.cond_col(Interpreter::IS_NOT_NULL, AttrId);
502 }
503 
504 /* NdbInterpretedCode two-arg branch method to use for
505  * given logical group type
506  */
507 struct tab3 {
508   StrBranch2 m_branches[5];
509 };
510 
511 /* Table of branch methds to use for each combination of
512  * logical group type (AND, OR, NAND, NOR) and comparison
513  * type.
514  * Generally, AND short circuits by branching to the failure
515  * label when the condition fails, and OR short circuits by
516  * branching to the success label when the condition passes.
517  * NAND and NOR invert these by inverting the 'sense' of the
518  * branch
519  */
520 static const tab3 table3[] = {
521   /**
522    * EQ (AND, OR, NAND, NOR)
523    */
524   { { 0,
525       &NdbInterpretedCode::branch_col_ne,
526       &NdbInterpretedCode::branch_col_eq,
527       &NdbInterpretedCode::branch_col_ne,
528       &NdbInterpretedCode::branch_col_eq } }
529 
530   /**
531    * NEQ
532    */
533   ,{ { 0,
534        &NdbInterpretedCode::branch_col_eq,
535        &NdbInterpretedCode::branch_col_ne,
536        &NdbInterpretedCode::branch_col_eq,
537        &NdbInterpretedCode::branch_col_ne } }
538 
539   /**
540    * LT
541    */
542   ,{ { 0,
543        &NdbInterpretedCode::branch_col_le,
544        &NdbInterpretedCode::branch_col_gt,
545        &NdbInterpretedCode::branch_col_le,
546        &NdbInterpretedCode::branch_col_gt } }
547 
548   /**
549    * LE
550    */
551   ,{ { 0,
552        &NdbInterpretedCode::branch_col_lt,
553        &NdbInterpretedCode::branch_col_ge,
554        &NdbInterpretedCode::branch_col_lt,
555        &NdbInterpretedCode::branch_col_ge } }
556 
557   /**
558    * GT
559    */
560   ,{ { 0,
561        &NdbInterpretedCode::branch_col_ge,
562        &NdbInterpretedCode::branch_col_lt,
563        &NdbInterpretedCode::branch_col_ge,
564        &NdbInterpretedCode::branch_col_lt } }
565 
566   /**
567    * GE
568    */
569   ,{ { 0,
570        &NdbInterpretedCode::branch_col_gt,
571        &NdbInterpretedCode::branch_col_le,
572        &NdbInterpretedCode::branch_col_gt,
573        &NdbInterpretedCode::branch_col_le } }
574 
575   /**
576    * LIKE
577    */
578   ,{ { 0,
579        &NdbInterpretedCode::branch_col_notlike,
580        &NdbInterpretedCode::branch_col_like,
581        &NdbInterpretedCode::branch_col_notlike,
582        &NdbInterpretedCode::branch_col_like } }
583 
584   /**
585    * NOT LIKE
586    */
587   ,{ { 0,
588        &NdbInterpretedCode::branch_col_like,
589        &NdbInterpretedCode::branch_col_notlike,
590        &NdbInterpretedCode::branch_col_like,
591        &NdbInterpretedCode::branch_col_notlike } }
592 
593   /**
594    * AND EQ MASK
595    */
596   ,{ { 0,
597        &NdbInterpretedCode::branch_col_and_mask_ne_mask,
598        &NdbInterpretedCode::branch_col_and_mask_eq_mask,
599        &NdbInterpretedCode::branch_col_and_mask_ne_mask,
600        &NdbInterpretedCode::branch_col_and_mask_eq_mask } }
601 
602   /**
603    * AND NE MASK
604    */
605   ,{ { 0,
606        &NdbInterpretedCode::branch_col_and_mask_eq_mask,
607        &NdbInterpretedCode::branch_col_and_mask_ne_mask,
608        &NdbInterpretedCode::branch_col_and_mask_eq_mask,
609        &NdbInterpretedCode::branch_col_and_mask_ne_mask } }
610 
611   /**
612    * AND EQ ZERO
613    */
614   ,{ { 0,
615        &NdbInterpretedCode::branch_col_and_mask_ne_zero,
616        &NdbInterpretedCode::branch_col_and_mask_eq_zero,
617        &NdbInterpretedCode::branch_col_and_mask_ne_zero,
618        &NdbInterpretedCode::branch_col_and_mask_eq_zero } }
619 
620   /**
621    * AND NE ZERO
622    */
623   ,{ { 0,
624        &NdbInterpretedCode::branch_col_and_mask_eq_zero,
625        &NdbInterpretedCode::branch_col_and_mask_ne_zero,
626        &NdbInterpretedCode::branch_col_and_mask_eq_zero,
627        &NdbInterpretedCode::branch_col_and_mask_ne_zero } }
628 };
629 
630 const int tab3_sz = sizeof(table3)/sizeof(table3[0]);
631 
632 int
cond_col_const(Interpreter::BinaryCondition op,Uint32 AttrId,const void * value,Uint32 len)633 NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op,
634 				  Uint32 AttrId,
635 				  const void * value, Uint32 len){
636   if (m_error.code != 0) return -1;
637 
638   if(op < 0 || op >= tab3_sz){
639     /* Condition is out of bounds */
640     m_error.code= 4262;
641     return -1;
642   }
643 
644   if(m_current.m_group < NdbScanFilter::AND ||
645      m_current.m_group > NdbScanFilter::NOR){
646     /* Operator is not defined in NdbScanFilter::Group */
647     m_error.code= 4260;
648     return -1;
649   }
650 
651   StrBranch2 branch;
652   if(m_negative == 1){  //change NdbOperation to its negative
653     if(m_current.m_group == NdbScanFilter::AND)
654       branch = table3[op].m_branches[NdbScanFilter::OR];
655     else if(m_current.m_group == NdbScanFilter::OR)
656       branch = table3[op].m_branches[NdbScanFilter::AND];
657     else
658     {
659       /**
660        * This is not possible, as NAND/NOR is converted to negative OR/AND in
661        * begin().
662        * But silence the compiler warning about uninitialised variable `branch`
663        */
664       assert(FALSE);
665       m_error.code= 4260;
666       return -1;
667     }
668   }else{
669     branch = table3[op].m_branches[(Uint32)(m_current.m_group)];
670   }
671 
672   const NdbDictionary::Table * table = m_code->getTable();
673 
674   if (table == NULL)
675   {
676     /* NdbInterpretedCode instruction requires that table is set */
677     m_error.code=4538;
678     return -1;
679   }
680 
681   const NdbDictionary::Column * col =
682     table->getColumn(AttrId);
683 
684   if(col == 0){
685     /* Column is NULL */
686     m_error.code= 4261;
687     return -1;
688   }
689 
690   if ((m_code->* branch)(value, len, AttrId, m_current.m_ownLabel) == -1)
691     return propagateErrorFromCode();
692 
693   return 0;
694 }
695 
696 int
cmp(BinaryCondition cond,int ColId,const void * val,Uint32 len)697 NdbScanFilter::cmp(BinaryCondition cond, int ColId,
698 		   const void *val, Uint32 len)
699 {
700   switch(cond){
701   case COND_LE:
702     return m_impl.cond_col_const(Interpreter::LE, ColId, val, len);
703   case COND_LT:
704     return m_impl.cond_col_const(Interpreter::LT, ColId, val, len);
705   case COND_GE:
706     return m_impl.cond_col_const(Interpreter::GE, ColId, val, len);
707   case COND_GT:
708     return m_impl.cond_col_const(Interpreter::GT, ColId, val, len);
709   case COND_EQ:
710     return m_impl.cond_col_const(Interpreter::EQ, ColId, val, len);
711   case COND_NE:
712     return m_impl.cond_col_const(Interpreter::NE, ColId, val, len);
713   case COND_LIKE:
714     return m_impl.cond_col_const(Interpreter::LIKE, ColId, val, len);
715   case COND_NOT_LIKE:
716     return m_impl.cond_col_const(Interpreter::NOT_LIKE, ColId, val, len);
717   case COND_AND_EQ_MASK:
718     return m_impl.cond_col_const(Interpreter::AND_EQ_MASK, ColId, val, len);
719   case COND_AND_NE_MASK:
720     return m_impl.cond_col_const(Interpreter::AND_NE_MASK, ColId, val, len);
721   case COND_AND_EQ_ZERO:
722     return m_impl.cond_col_const(Interpreter::AND_EQ_ZERO, ColId, val, len);
723   case COND_AND_NE_ZERO:
724     return m_impl.cond_col_const(Interpreter::AND_NE_ZERO, ColId, val, len);
725   }
726   return -1;
727 }
728 
729 static void
update(const NdbError & _err)730 update(const NdbError & _err){
731   NdbError & error = (NdbError &) _err;
732   ndberror_struct ndberror = (ndberror_struct)error;
733   ndberror_update(&ndberror);
734   error = NdbError(ndberror);
735 }
736 
737 const NdbError &
getNdbError() const738 NdbScanFilter::getNdbError() const
739 {
740   update(m_impl.m_error);
741   return m_impl.m_error;
742 }
743 
744 const NdbInterpretedCode*
getInterpretedCode() const745 NdbScanFilter::getInterpretedCode() const
746 {
747   /* Return nothing if this is an old-style
748    * ScanFilter as the InterpretedCode is
749    * entirely encapsulated
750    */
751   if (m_impl.m_associated_op != NULL)
752     return NULL;
753 
754   return m_impl.m_code;
755 }
756 
757 NdbOperation*
getNdbOperation() const758 NdbScanFilter::getNdbOperation() const
759 {
760   /* Return associated NdbOperation (or NULL
761    * if we don't have one)
762    */
763   return m_impl.m_associated_op;
764 }
765 
766 #if 0
767 int
768 main(void){
769   if(0)
770   {
771     ndbout << "a > 7 AND b < 9 AND c = 4" << endl;
772     NdbScanFilter f(0);
773     f.begin(NdbScanFilter::AND);
774     f.gt(0, 7);
775     f.lt(1, 9);
776     f.eq(2, 4);
777     f.end();
778     ndbout << endl;
779   }
780 
781   if(0)
782   {
783     ndbout << "a > 7 OR b < 9 OR c = 4" << endl;
784     NdbScanFilter f(0);
785     f.begin(NdbScanFilter::OR);
786     f.gt(0, 7);
787     f.lt(1, 9);
788     f.eq(2, 4);
789     f.end();
790     ndbout << endl;
791   }
792 
793   if(0)
794   {
795     ndbout << "a > 7 AND (b < 9 OR c = 4)" << endl;
796     NdbScanFilter f(0);
797     f.begin(NdbScanFilter::AND);
798     f.gt(0, 7);
799     f.begin(NdbScanFilter::OR);
800     f.lt(1, 9);
801     f.eq(2, 4);
802     f.end();
803     f.end();
804     ndbout << endl;
805   }
806 
807   if(0)
808   {
809     ndbout << "a > 7 AND (b < 9 AND c = 4)" << endl;
810     NdbScanFilter f(0);
811     f.begin(NdbScanFilter::AND);
812     f.gt(0, 7);
813     f.begin(NdbScanFilter::AND);
814     f.lt(1, 9);
815     f.eq(2, 4);
816     f.end();
817     f.end();
818     ndbout << endl;
819   }
820 
821   if(0)
822   {
823     ndbout << "(a > 7 AND b < 9) AND c = 4" << endl;
824     NdbScanFilter f(0);
825     f.begin(NdbScanFilter::AND);
826     f.begin(NdbScanFilter::AND);
827     f.gt(0, 7);
828     f.lt(1, 9);
829     f.end();
830     f.eq(2, 4);
831     f.end();
832     ndbout << endl;
833   }
834 
835   if(1)
836   {
837     ndbout << "(a > 7 OR b < 9) AND (c = 4 OR c = 5)" << endl;
838     NdbScanFilter f(0);
839     f.begin(NdbScanFilter::AND);
840     f.begin(NdbScanFilter::OR);
841     f.gt(0, 7);
842     f.lt(1, 9);
843     f.end();
844     f.begin(NdbScanFilter::OR);
845     f.eq(2, 4);
846     f.eq(2, 5);
847     f.end();
848     f.end();
849     ndbout << endl;
850   }
851 
852   if(1)
853   {
854     ndbout << "(a > 7 AND b < 9) OR (c = 4 AND c = 5)" << endl;
855     NdbScanFilter f(0);
856     f.begin(NdbScanFilter::OR);
857     f.begin(NdbScanFilter::AND);
858     f.gt(0, 7);
859     f.lt(1, 9);
860     f.end();
861     f.begin(NdbScanFilter::AND);
862     f.eq(2, 4);
863     f.eq(2, 5);
864     f.end();
865     f.end();
866     ndbout << endl;
867   }
868 
869   if(1)
870   {
871     ndbout <<
872       "((a > 7 AND b < 9) OR (c = 4 AND d = 5)) AND "
873       "((e > 6 AND f < 8) OR (g = 2 AND h = 3)) "  << endl;
874     NdbScanFilter f(0);
875     f.begin(NdbScanFilter::AND);
876     f.begin(NdbScanFilter::OR);
877     f.begin(NdbScanFilter::AND);
878     f.gt(0, 7);
879     f.lt(1, 9);
880     f.end();
881     f.begin(NdbScanFilter::AND);
882     f.eq(2, 4);
883     f.eq(3, 5);
884     f.end();
885     f.end();
886 
887     f.begin(NdbScanFilter::OR);
888     f.begin(NdbScanFilter::AND);
889     f.gt(4, 6);
890     f.lt(5, 8);
891     f.end();
892     f.begin(NdbScanFilter::AND);
893     f.eq(6, 2);
894     f.eq(7, 3);
895     f.end();
896     f.end();
897     f.end();
898   }
899 
900   return 0;
901 }
902 #endif
903 
904 template class Vector<NdbScanFilterImpl::State>;
905 
906