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