1 karl 1.10 //%2006////////////////////////////////////////////////////////////////////////
|
2 chuck 1.2 //
|
3 karl 1.8 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 chuck 1.2 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.8 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.10 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 chuck 1.2 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
|
20 karl 1.8 //
|
21 chuck 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 // Author: Markus Mueller (sedgewick_de@yahoo.de)
33 //
|
34 humberto 1.3 // Modified By: Humberto Rivero (hurivero@us.ibm.com)
|
35 chuck 1.2 //
36 //%/////////////////////////////////////////////////////////////////////////////
37
38
39 #include "Cql2Dnf.h"
40 #include <Pegasus/Common/Stack.h>
|
41 humberto 1.5 #include <Pegasus/Common/Tracer.h>
|
42 chuck 1.2
43 PEGASUS_USING_STD;
44 PEGASUS_NAMESPACE_BEGIN
45
46 #define PEGASUS_ARRAY_T term_el
47 # include <Pegasus/Common/ArrayImpl.h>
48 #undef PEGASUS_ARRAY_T
49
50 #define PEGASUS_ARRAY_T eval_el
51 # include <Pegasus/Common/ArrayImpl.h>
52 #undef PEGASUS_ARRAY_T
53
54 #define PEGASUS_ARRAY_T stack_el
55 # include <Pegasus/Common/ArrayImpl.h>
56 #undef PEGASUS_ARRAY_T
57
58 //
59 // Terminal element methods
60 //
|
61 humberto 1.6
|
62 chuck 1.2 void term_el::negate()
63 {
|
64 humberto 1.6 NOT = true;
|
65 chuck 1.2 };
|
66 humberto 1.3
|
67 chuck 1.2 //
68 // Evaluation heap element methods
69 //
70 stack_el eval_el::getFirst()
71 {
72 return stack_el(opn1, is_terminal1);
73 }
74
75 stack_el eval_el::getSecond()
76 {
77 return stack_el(opn2, is_terminal2);
78 }
79
80 void eval_el::setFirst(const stack_el s)
81 {
82 opn1 = s.opn;
83 is_terminal1 = s.is_terminal;
84 }
85
86 void eval_el::setSecond(const stack_el s)
87 {
88 chuck 1.2 opn2 = s.opn;
89 is_terminal2 = s.is_terminal;
90 }
91
92 void eval_el::assign_unary_to_first(const eval_el & assignee)
93 {
94 opn1 = assignee.opn1;
95 is_terminal1 = assignee.is_terminal1;
96 }
97
98 void eval_el::assign_unary_to_second(const eval_el & assignee)
99 {
100 opn2 = assignee.opn1;
101 is_terminal2 = assignee.is_terminal1;
102 }
103
104 // Ordering operators, so that op1 > op2 for all non-terminals
105 // and terminals appear in the second operand first
106 void eval_el::order(void)
107 {
108 int k;
109 chuck 1.2 if ((!is_terminal1) && (!is_terminal2))
110 if ((k = opn2) > opn1)
111 {
112 opn2 = opn1;
113 opn1 = k;
114 }
115 else if ((is_terminal1) && (!is_terminal2))
116 if ((k = opn2) > opn1)
117 {
118 opn2 = opn1;
119 opn1 = k;
120 is_terminal1 = false;
121 is_terminal2 = true;
122 }
123 }
|
124 humberto 1.6 /*
|
125 chuck 1.2 static bool operator==(const term_el& x, const term_el& y)
126 {
127 return x._simplePredicate == y._simplePredicate;
128 }
|
129 humberto 1.6 */
|
130 chuck 1.2 //
131 // CQL Compiler methods
132 //
|
133 humberto 1.5 /*
|
134 chuck 1.2 Cql2Dnf::Cql2Dnf()
135 {
136 eval_heap.reserveCapacity(16);
137 terminal_heap.reserveCapacity(16);
138 }
139
140 Cql2Dnf::Cql2Dnf(CQLSelectStatement & cqs)
141 {
142 eval_heap.reserveCapacity(16);
143 terminal_heap.reserveCapacity(16);
144 compile(&cqs);
145 }
146
147 Cql2Dnf::Cql2Dnf(CQLSelectStatement * cqs)
148 {
149 eval_heap.reserveCapacity(16);
150 terminal_heap.reserveCapacity(16);
151 compile(cqs);
152 }
|
153 humberto 1.5 */
|
154 chuck 1.2 Cql2Dnf::Cql2Dnf(CQLPredicate& topLevel){
155 eval_heap.reserveCapacity(16);
156 terminal_heap.reserveCapacity(16);
157 compile(topLevel);
158 }
159
160 Cql2Dnf::~Cql2Dnf() {}
|
161 humberto 1.5 /*
|
162 chuck 1.2 void Cql2Dnf::compile(CQLSelectStatement * cqs){
163 CQLPredicate topLevel = cqs->getPredicate();
164 compile(topLevel);
165 }
|
166 humberto 1.5 */
|
167 chuck 1.2 void Cql2Dnf::compile(CQLPredicate& topLevel)
168 {
|
169 humberto 1.5 PEG_METHOD_ENTER(TRC_CQL, "Cql2Dnf::compile");
170
|
171 chuck 1.2 _strip_ops_operands(topLevel);
172 _buildEvalHeap();
173 _pushNOTDown();
174 _factoring();
|
175 humberto 1.3 _construct();
|
176 chuck 1.2 eval_heap.clear();
|
177 humberto 1.5
178 PEG_METHOD_EXIT();
|
179 chuck 1.2 }
180
181 void Cql2Dnf::_buildEvalHeap()
182 {
|
183 humberto 1.5 PEG_METHOD_ENTER(TRC_CQL, "Cql2Dnf::_buildEvalHeap");
184
|
185 chuck 1.2 Stack<stack_el> stack;
186
187 // Counter for Operands
188 Uint32 j = 0;
189
190 for (Uint32 i = 0, n = _operations.size(); i < n; i++)
191 {
192 OperationType op = _operations[i];
193
194 switch (op)
195 {
196 case CQL_OR:
197 case CQL_AND:
198 {
199 PEGASUS_ASSERT(stack.size() >= 2);
200
201 stack_el op1 = stack.top();
202 stack.pop();
203
204 stack_el op2 = stack.top();
205
206 chuck 1.2 // generate Eval expression
207 eval_heap.append(eval_el(0, op , op1.opn, op1.is_terminal,
208 op2.opn , op2.is_terminal));
209
210 stack.top() = stack_el(eval_heap.size()-1, false);
211
212 break;
213 }
214
215 case CQL_NOT:
216 {
217 PEGASUS_ASSERT(stack.size() >= 1);
218
219 stack_el op1 = stack.top();
220
221 // generate Eval expression
222 eval_heap.append(eval_el(0, op , op1.opn, op1.is_terminal,
223 -1, true));
224
225 stack.top() = stack_el(eval_heap.size()-1, false);
226
227 chuck 1.2 break;
228 }
229
230 case CQL_EQ:
231 case CQL_NE:
232 case CQL_LT:
233 case CQL_LE:
234 case CQL_GT:
235 case CQL_GE:
|
236 humberto 1.6 case CQL_ISA:
237 case CQL_LIKE:
|
238 chuck 1.2 {
239 PEGASUS_ASSERT(_operands.size() >= 2);
240
241 CQLExpression lhs = _operands[j++];
242
243 CQLExpression rhs = _operands[j++];
244
245 CQLSimplePredicate sp(lhs,rhs,_convertOpType(op));
246 terminal_heap.push(term_el(false, sp));
247
248 stack.push(stack_el(terminal_heap.size()-1, true));
249
250 break;
251 }
|
252 humberto 1.3
|
253 chuck 1.2 case CQL_IS_NULL:
254 {
255 PEGASUS_ASSERT(_operands.size() >= 1);
256 CQLExpression expression = _operands[j++];
|
257 humberto 1.6 CQLSimplePredicate dummy(expression,IS_NULL);
|
258 chuck 1.2 terminal_heap.push(term_el(false, dummy));
259
260 stack.push(stack_el(terminal_heap.size()-1, true));
261
262 break;
263 }
264
265 case CQL_IS_NOT_NULL:
266 {
267 PEGASUS_ASSERT(_operands.size() >= 1);
268 CQLExpression expression = _operands[j++];
|
269 humberto 1.6 CQLSimplePredicate dummy(expression,IS_NOT_NULL);
|
270 chuck 1.2 terminal_heap.push(term_el(false, dummy));
271
272 stack.push(stack_el(terminal_heap.size()-1, true));
273
274 break;
275 }
276 case CQL_NOOP:
277 default: break;
278 }
279 }
280
281 PEGASUS_ASSERT(stack.size() == 1);
|
282 humberto 1.5
283 PEG_METHOD_EXIT();
|
284 chuck 1.2 }
285
286 void Cql2Dnf::_pushNOTDown()
287 {
|
288 humberto 1.5 PEG_METHOD_ENTER(TRC_CQL, "Cql2Dnf::_pushNOTDown");
289
|
290 chuck 1.2 for (int i=eval_heap.size()-1; i >= 0; i--)
291 {
292 Boolean _found = false;
293
294 // Order all operators, so that op1 > op2 for non-terminals
295 // and terminals appear as second operand
296
297 eval_heap[i].order();
298
299 // First solve the unary NOT operator
300
301 if (eval_heap[i].op == CQL_NOT)
302 {
303 // This serves as the equivalent of an empty operator
304 eval_heap[i].op = CQL_NOOP;
305
306 // Substitute this expression in all higher order eval statements
307 // so that this node becomes disconnected from the tree
308
309 for (int j=eval_heap.size()-1; j > i;j--)
310 {
311 chuck 1.2 // Test first operand
312 if ((!eval_heap[j].is_terminal1) && (eval_heap[j].opn1 == i))
313
314 eval_heap[j].assign_unary_to_first(eval_heap[i]);
315
316 // Test second operand
317 if ((!eval_heap[j].is_terminal2) && (eval_heap[j].opn2 == i))
318
319 eval_heap[j].assign_unary_to_second(eval_heap[i]);
320 }
321
322 // Test: Double NOT created by moving down
323
324 if (eval_heap[i].mark)
325 eval_heap[i].mark = false;
326 else
327 _found = true;
328 // else indicate a pending NOT to be pushed down further
329 }
330
331 // Simple NOT created by moving down
332 chuck 1.2
333 if (eval_heap[i].mark)
334 {
335 // Remove the mark, indicate a pending NOT to be pushed down
336 // further and switch operators (AND / OR)
337
338 eval_heap[i].mark=false;
339 if (eval_heap[i].op == CQL_OR) eval_heap[i].op = CQL_AND;
340 else if (eval_heap[i].op == CQL_AND) eval_heap[i].op = CQL_OR;
341
342 // NOT operator is already ruled out
343 _found = true;
344 }
345
346 // Push a pending NOT further down
347 if (_found)
348 {
349 // First operand
350
351 int j = eval_heap[i].opn1;
352 if (eval_heap[i].is_terminal1)
353 chuck 1.2 // Flip NOT mark
354 terminal_heap[j].negate();
355 else
356 eval_heap[j].mark = !(eval_heap[j].mark);
357
358 //Second operand (if it exists)
359
360 if ((j = eval_heap[i].opn2) >= 0)
361 {
362 if (eval_heap[i].is_terminal2)
363 // Flip NOT mark
364 terminal_heap[j].negate();
365 else
366 eval_heap[j].mark = !(eval_heap[j].mark);
367 }
368 }
369 }
|
370 humberto 1.5 PEG_METHOD_EXIT();
|
371 chuck 1.2 }
372
373 void Cql2Dnf::_factoring(void)
374 {
|
375 humberto 1.5 PEG_METHOD_ENTER(TRC_CQL, "Cql2Dnf::_factoring");
376
|
377 chuck 1.2 int i = 0,n = eval_heap.size();
378 //for (int i=eval_heap.size()-1; i >= 0; i--)
379 while (i < n)
380 {
381 int _found = 0;
382 int index = 0;
383
384 // look for expressions (A | B) & C ---> A & C | A & B
385 if (eval_heap[i].op == CQL_AND)
386 {
387 if (!eval_heap[i].is_terminal1)
388 {
389 index = eval_heap[i].opn1; // remember the index
390 if (eval_heap[index].op == CQL_OR) _found = 1;
391 }
392
393 if ((_found == 0) && (!eval_heap[i].is_terminal2))
394 {
395 index = eval_heap[i].opn2; // remember the index
396 if (eval_heap[index].op == CQL_OR) _found = 2;
397 }
398 chuck 1.2
399 if (_found != 0)
400 {
401 //int u1,u1_t,u2,u2_t,u3,u3_t;
402 stack_el s;
403
404 if (_found == 1)
405 s = eval_heap[i].getSecond();
406 else
407 s = eval_heap[i].getFirst();
408
409 // insert two new expression before entry i
410 eval_el evl;
411
412 evl = eval_el(false, CQL_OR, i+1, false, i, false);
413 if ((Uint32 )i < eval_heap.size()-1)
414 eval_heap.insert(i+1, evl);
415 else
416 eval_heap.append(evl);
417 eval_heap.insert(i+1, evl);
418
419 chuck 1.2 for (int j=eval_heap.size()-1; j > i + 2; j--)
420 {
421 //eval_heap[j] = eval_heap[j-2];
422
423 // adjust pointers
424
425 if ((!eval_heap[j].is_terminal1)&&
426 (eval_heap[j].opn1 >= i))
427 eval_heap[j].opn1 += 2;
428 if ((!eval_heap[j].is_terminal2)&&
429 (eval_heap[j].opn2 >= i))
430 eval_heap[j].opn2 += 2;
431 }
432
433 n+=2; // increase size of array
434
435 // generate the new expressions : new OR expression
436
437
438 // first new AND expression
439 eval_heap[i+1].mark = false;
440 chuck 1.2 eval_heap[i+1].op = CQL_AND;
441 eval_heap[i+1].setFirst(s);
442 eval_heap[i+1].setSecond( eval_heap[index].getFirst());
443 eval_heap[i+1].order();
444
445
446 // second new AND expression
447 eval_heap[i].mark = false;
448 eval_heap[i].op = CQL_AND;
449 eval_heap[i].setFirst(s);
450 eval_heap[i].setSecond( eval_heap[index].getSecond());
451 eval_heap[i].order();
452
453 // mark the indexed expression as inactive
454 //eval_heap[index].op = WQL_IS_TRUE; possible disconnects
455 i--;
456
457 } /* endif _found > 0 */
458
459 } /* endif found AND operator */
460
461 chuck 1.2 i++; // increase pointer
462 }
|
463 humberto 1.5
464 PEG_METHOD_EXIT();
|
465 chuck 1.2 }
466
467 void Cql2Dnf::_strip_ops_operands(CQLPredicate& topLevel)
468 {
|
469 humberto 1.5 PEG_METHOD_ENTER(TRC_CQL, "Cql2Dnf::_strip_ops_operands");
|
470 chuck 1.2 //
471 // depth first search for all operations and operands
472 // extract operations and operands and store in respective arrays for later processing
473 //
474 _destruct(topLevel);
|
475 humberto 1.3 if(topLevel.getInverted()){
476 _operations.append(CQL_NOT);
477 }
|
478 humberto 1.5 PEG_METHOD_EXIT();
|
479 chuck 1.2 }
480
481 OperationType Cql2Dnf::_convertOpType(ExpressionOpType op){
482 switch(op){
483 case EQ: return CQL_EQ;
484 case NE: return CQL_NE;
485 case GT: return CQL_GT;
486 case LT: return CQL_LT;
487 case GE: return CQL_GE;
488 case LE: return CQL_LE;
489 case IS_NULL: return CQL_IS_NULL;
490 case IS_NOT_NULL: return CQL_IS_NOT_NULL;
|
491 humberto 1.6 case ISA: return CQL_ISA;
492 case LIKE: return CQL_LIKE;
|
493 chuck 1.2 default: return CQL_NOOP;
494 }
495 }
496
497 ExpressionOpType Cql2Dnf::_convertOpType(OperationType op){
498 switch(op){
499 case CQL_EQ: return EQ;
500 case CQL_NE: return NE;
501 case CQL_GT: return GT;
502 case CQL_LT: return LT;
503 case CQL_GE: return GE;
504 case CQL_LE: return LE;
|
505 humberto 1.6 case CQL_IS_NULL: return IS_NULL;
506 case CQL_IS_NOT_NULL: return IS_NOT_NULL;
507 case CQL_ISA: return ISA;
508 case CQL_LIKE: return LIKE;
|
509 humberto 1.3 default: return EQ; // should never get here
|
510 chuck 1.2 }
|
511 gs.keenan 1.9 PEGASUS_UNREACHABLE(return EQ;) // should never get here
|
512 chuck 1.2 }
513
514 void Cql2Dnf::_destruct(CQLPredicate& _p){
515 if(_p.isSimple()){
516 CQLSimplePredicate _sp = _p.getSimplePredicate();
517 _operations.append(_convertOpType(_sp.getOperation()));
518 _operands.append(_sp.getLeftExpression());
|
519 humberto 1.6 if((_operations[_operations.size()-1] != CQL_IS_NULL) && (_operations[_operations.size()-1] != CQL_IS_NOT_NULL))
520 _operands.append(_sp.getRightExpression());
|
521 chuck 1.2 }
522 else{
523 Array<CQLPredicate> _preds = _p.getPredicates();
524 Array<BooleanOpType> _boolops = _p.getOperators();
525 for(Uint32 i=0;i<_preds.size();i++){
526 _destruct(_preds[i]);
527 if(_preds[i].getInverted()){
528 _operations.append(CQL_NOT);
529 }
530 if(i > 0){
531 if(_boolops[i-1] == AND){
532 _operations.append(CQL_AND);
533 }
534 if(_boolops[i-1] == OR){
535 _operations.append(CQL_OR);
536 }
537 }
538 }
539 }
540 }
541
542 chuck 1.2 void Cql2Dnf::_construct(){
|
543 humberto 1.5
544 PEG_METHOD_ENTER(TRC_CQL, "Cql2Dnf::_construct");
|
545 chuck 1.2 //
546 // Each eval_el on the eval heap contains all the information needed to make a CQLPredicate.
547 // We will build a CQLPredicate for every element in the eval heap. So there is a 1 to 1 correspondence
548 // between elements in the eval heap and elements in the CQLPredicate array used below.
549 // The first eval_el on the eval heap will always contain at least one terminal if the operation is a NOT
550 // or two terminals if the operation is AND or OR. We are guaranteed to build a CQLPredicate from the first
551 // position in the eval_heap array.
552 //
553 // The key to the algorithm is the isterminalX flag. When set to true, we go to the
554 // term_heap and get the CQLSimplePredicate. When set to false, we go to the _preds array below
555 // and get the CQLPredicate. Since there is a 1 - 1 correspondence, as explained above, the index
556 // referred to by eval.opn1 or eval.opn2 is valid into the _preds array.
557 //
558 // For ANDs and ORs, we need two operands, as explained above, we get those operands
559 // from either the term_heap or the _preds array. For NOTs, we need only 1 operand, and that
560 // comes from either the term_heap or the _preds array.
561 //
562 // When finished, the last element in the _preds array contains the top level CQLPredicate (the rebuilt tree)
563 //
564 // Example: a=b^(!c=d v e=f)
565 // If the current eval_heap looks like:
566 chuck 1.2 // 0,NOT,1,True,-1,True [index = 0]
567 // 0,OR,2,True,0,False [index = 1]
568 // 0,AND,1,False,0,True [index = 2]
569 //
570 // And the current term_heap looks like:
571 // CQLSimplePredicate(a=b) [index = 0]
572 // CQLSimplePredicate(c=d) [index = 1]
573 // CQLSimplePredicate(e=f) [index = 0]
574 //
575 // The _preds array at the end would look like:
576 // CQLPredicate(!c==d) [index = 0]
577 // CQLPredicate(e==f v !c==d) [index = 1]
578 // CQLPredicate((e==f v !c==d) ^ a==b) [index = 2] (the rebuilt tree)
579 //
580
581 if(eval_heap.size() > 0){
582 Array<CQLPredicate> _preds;
|
583 humberto 1.3 CQLPredicate pred;
|
584 chuck 1.2 for(Uint32 i=0;i<eval_heap.size();i++){
585 eval_el eval = eval_heap[i];
586 if(eval.is_terminal1 && eval.is_terminal2){
587 switch(eval.op){
588 case CQL_NOT:
|
589 humberto 1.7 {
590 _preds.append(CQLPredicate(terminal_heap[eval.opn1]._simplePredicate,true));
|
591 chuck 1.2 break;
|
592 humberto 1.7 }
|
593 chuck 1.2 case CQL_NOOP:
594 {
|
595 humberto 1.7 CQLPredicate p(terminal_heap[eval.opn1]._simplePredicate,false);
596 if(terminal_heap[eval.opn1].NOT == true)
597 p.setInverted(true);
598 _preds.append(p);
|
599 chuck 1.2 break;
600 }
|
601 humberto 1.7 case CQL_AND:
602 {
|
603 chuck 1.2 CQLPredicate p;
604 CQLPredicate p1(terminal_heap[eval.opn2]._simplePredicate,false);
|
605 humberto 1.6 if(terminal_heap[eval.opn2].NOT == true)
|
606 humberto 1.7 p1.setInverted(true);
|
607 chuck 1.2 p.appendPredicate(p1);
608 CQLPredicate p2(terminal_heap[eval.opn1]._simplePredicate,false);
|
609 humberto 1.6 if(terminal_heap[eval.opn1].NOT == true)
|
610 humberto 1.7 p2.setInverted(true);
|
611 chuck 1.2 p.appendPredicate(p2,AND);
612 _preds.append(p);
613 break;
|
614 humberto 1.7 }
615 case CQL_OR:
616 {
617 CQLPredicate p;
618 CQLPredicate p1(terminal_heap[eval.opn2]._simplePredicate,false);
619 if(terminal_heap[eval.opn2].NOT == true)
620 p1.setInverted(true);
621 p.appendPredicate(p1);
622 CQLPredicate p2(terminal_heap[eval.opn1]._simplePredicate,false);
623 if(terminal_heap[eval.opn1].NOT == true)
624 p2.setInverted(true);
625 p.appendPredicate(p2,OR);
626 _preds.append(p);
627 break;
628 }
|
629 chuck 1.2 case CQL_EQ:
630 case CQL_NE:
631 case CQL_GT:
632 case CQL_LT:
633 case CQL_GE:
634 case CQL_LE:
|
635 humberto 1.6 case CQL_ISA:
636 case CQL_LIKE:
|
637 chuck 1.2 case CQL_IS_NULL:
638 case CQL_IS_NOT_NULL: break;
639
640 }
641 }else if(eval.is_terminal1 && !eval.is_terminal2){
642 switch(eval.op){
643 case CQL_NOT:
|
644 humberto 1.7 {
645 _preds.append(CQLPredicate(terminal_heap[eval.opn1]._simplePredicate,true));
|
646 chuck 1.2 break;
|
647 humberto 1.7 }
|
648 chuck 1.2 case CQL_NOOP:
|
649 humberto 1.7 {
650 CQLPredicate p(terminal_heap[eval.opn1]._simplePredicate,false);
651 if(terminal_heap[eval.opn1].NOT == true)
652 p.setInverted(true);
653 _preds.append(p);
654 break;
655 }
656 case CQL_AND:
657 {
658 CQLPredicate p;
659 CQLPredicate p1(terminal_heap[eval.opn1]._simplePredicate,false);
660 if(terminal_heap[eval.opn1].NOT == true)
661 p1.setInverted(true);
662 p = _preds[eval.opn2];
663 p.appendPredicate(p1,AND);
664 _preds.append(p);
665 break;
666 }
667 case CQL_OR:
668 {
669 CQLPredicate p;
670 humberto 1.7 CQLPredicate p1(terminal_heap[eval.opn1]._simplePredicate,false);
671 if(terminal_heap[eval.opn1].NOT == true)
672 p1.setInverted(true);
673 p = _preds[eval.opn2];
674 p.appendPredicate(p1,OR);
675 _preds.append(p);
676 break;
677 }
|
678 chuck 1.2 case CQL_EQ:
679 case CQL_NE:
680 case CQL_GT:
681 case CQL_LT:
682 case CQL_GE:
683 case CQL_LE:
|
684 humberto 1.6 case CQL_ISA:
685 case CQL_LIKE:
|
686 chuck 1.2 case CQL_IS_NULL:
687 case CQL_IS_NOT_NULL: break;
688
689 }
690 }else if(!eval.is_terminal1 && eval.is_terminal2){
|
691 humberto 1.7 switch(eval.op){
692 case CQL_NOT:
693 {
694 CQLPredicate p = _preds[eval.opn1];
695 p.setInverted(true);
696 _preds.append(p);
|
697 chuck 1.2 break;
|
698 humberto 1.7 }
|
699 chuck 1.2 case CQL_NOOP:
|
700 humberto 1.7 {
701 _preds.append(_preds[eval.opn1]);
|
702 chuck 1.2 break;
|
703 humberto 1.7 }
704 case CQL_AND:
705 {
706 CQLPredicate p;
707 CQLPredicate p1(terminal_heap[eval.opn2]._simplePredicate,false);
708 if(terminal_heap[eval.opn2].NOT == true)
709 p1.setInverted(true);
710 p = _preds[eval.opn1];
711 p.appendPredicate(p1,AND);
712 _preds.append(p);
713 break;
714 }
715 case CQL_OR:
716 {
717 CQLPredicate p;
718 CQLPredicate p1(terminal_heap[eval.opn2]._simplePredicate,false);
719 if(terminal_heap[eval.opn2].NOT == true)
720 p1.setInverted(true);
721 p = _preds[eval.opn1];
722 p.appendPredicate(p1,OR);
723 _preds.append(p);
724 humberto 1.7 break;
725 }
|
726 chuck 1.2 case CQL_EQ:
727 case CQL_NE:
728 case CQL_GT:
729 case CQL_LT:
730 case CQL_GE:
731 case CQL_LE:
|
732 humberto 1.6 case CQL_ISA:
733 case CQL_LIKE:
|
734 chuck 1.2 case CQL_IS_NULL:
735 case CQL_IS_NOT_NULL: break;
736
737 }
738 }else{ // !eval.is_terminal1 && !eval.is_terminal2
739 switch(eval.op){
|
740 humberto 1.7 case CQL_NOT:
741 {
|
742 chuck 1.2 CQLPredicate p = _preds[eval.opn1];
|
743 humberto 1.7 p.setInverted(true);
744 _preds.append(p);
|
745 chuck 1.2 break;
|
746 humberto 1.7 }
747 case CQL_NOOP:
748 {
749 _preds.append(_preds[eval.opn1]);
750 break;
751 }
752 case CQL_AND:
753 {
|
754 chuck 1.2 CQLPredicate p = _preds[eval.opn2];
|
755 humberto 1.7 _flattenANDappend(p,AND,_preds[eval.opn1]);
756 _preds.append(p);
757 break;
758 }
759 case CQL_OR:
760 {
|
761 chuck 1.2 CQLPredicate p = _preds[eval.opn2];
|
762 humberto 1.7 _flattenANDappend(p,OR,_preds[eval.opn1]);
763 _preds.append(p);
764 break;
765 }
|
766 chuck 1.2 case CQL_EQ:
767 case CQL_NE:
768 case CQL_GT:
769 case CQL_LT:
770 case CQL_GE:
771 case CQL_LE:
|
772 humberto 1.6 case CQL_ISA:
773 case CQL_LIKE:
|
774 chuck 1.2 case CQL_IS_NULL:
775 case CQL_IS_NOT_NULL: break;
776
777 }
778
779 }
780 } // end for(...)
781
782 _dnfPredicate = _preds[_preds.size()-1];
783
784 } // end if
785 else{ // we just have a CQLSimplePredicate on the terminal_heap
786 PEGASUS_ASSERT(terminal_heap.size() == 1);
787 _dnfPredicate = CQLPredicate(terminal_heap[0]._simplePredicate,false);
788 }
|
789 humberto 1.5
790 PEG_METHOD_EXIT();
|
791 chuck 1.2 }
792
793 CQLPredicate Cql2Dnf::getDnfPredicate(){
794 return _dnfPredicate;
795 }
796
|
797 humberto 1.3 CQLPredicate Cql2Dnf::_flattenANDappend(CQLPredicate& topLevel, BooleanOpType op, CQLPredicate& p){
|
798 humberto 1.5
799 PEG_METHOD_ENTER(TRC_CQL, "Cql2Dnf::_flattenANDappend");
|
800 humberto 1.3 //
801 // this is to prevent appending complex predicates to the top level predicate
802 // the final DNFed predicate must only have simple predicates inside its predicate array
803 //
804 // example:
805 // say P(top level) = A AND B
806 // say P1 = C AND D
807 // say we need to OR them together
808 // we cant call P.appendPredicate(P1,OR) because this creates one more complex predicate layer
809 // instead we would:
810 // -> get P1s predicates (which should all be simple)
811 // -> append its first predicate to P along with the operator passed into us
812 // -> at this point we have P = A AND B OR C
813 // -> then go through P1s remaining predicates and append them and P1s operators to P
814 // -> when finished, we have P = A AND B OR C AND D INSTEAD of having P = A AND B OR P1 where P1 is a complex predicate
815 //
816
817 if(!p.isSimple()){
818 Array<CQLPredicate> preds = p.getPredicates();
819 Array<BooleanOpType> ops = p.getOperators();
820 for(Uint32 i=0;i<preds.size();i++){
821 humberto 1.3 if(i==0) topLevel.appendPredicate(preds[i],op);
822 else topLevel.appendPredicate(preds[i],ops[i-1]);
823 }
824 }else{
825 topLevel.appendPredicate(p,op);
826 }
|
827 humberto 1.5
828 PEG_METHOD_EXIT();
|
829 humberto 1.3 return topLevel;
830 }
831
|
832 chuck 1.2 PEGASUS_NAMESPACE_END
|