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