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