00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00026 #include "OW_config.h"
00027 #include "OW_Assertion.hpp"
00028 #include "OW_WQLOperation.hpp"
00029 #include "OW_WQLOperand.hpp"
00030 #include "OW_WQLCompile.hpp"
00031 #include "OW_Format.hpp"
00032 #include "OW_Stack.hpp"
00033 #ifdef OW_HAVE_OSTREAM
00034 #include <ostream>
00035 #else
00036 #include <iostream>
00037 #endif
00038 #include <algorithm>
00039
00040 namespace OW_NAMESPACE
00041 {
00042
00043
00044
00045
00046 void WQLCompile::term_el::negate()
00047 {
00048 switch (op)
00049 {
00050 case WQL_EQ: op = WQL_NE; break;
00051 case WQL_NE: op = WQL_EQ; break;
00052 case WQL_LT: op = WQL_GE; break;
00053 case WQL_LE: op = WQL_GT; break;
00054 case WQL_GT: op = WQL_LE; break;
00055 case WQL_GE: op = WQL_LT; break;
00056 default: break;
00057 }
00058 };
00059 bool operator==(const WQLCompile::term_el& x, const WQLCompile::term_el& y)
00060 {
00061 return x.op == y.op && x.opn1 == y.opn1 && x.opn2 == y.opn2;
00062 }
00063 bool operator!=(const WQLCompile::term_el& x, const WQLCompile::term_el& y)
00064 {
00065 return !(x == y);
00066 }
00067
00068
00069
00070 WQLCompile::stack_el
00071 WQLCompile::eval_el::getFirst()
00072 {
00073 return stack_el(opn1, is_terminal1);
00074 }
00075 WQLCompile::stack_el
00076 WQLCompile::eval_el::getSecond()
00077 {
00078 return stack_el(opn2, is_terminal2);
00079 }
00080 void WQLCompile::eval_el::setFirst(const WQLCompile::stack_el s)
00081 {
00082 opn1 = s.opn;
00083 is_terminal1 = s.type;
00084 }
00085 void WQLCompile::eval_el::setSecond(const WQLCompile::stack_el s)
00086 {
00087 opn2 = s.opn;
00088 is_terminal2 = s.type;
00089 }
00090 void WQLCompile::eval_el::assign_unary_to_first(const WQLCompile::eval_el & assignee)
00091 {
00092 opn1 = assignee.opn1;
00093 is_terminal1 = assignee.is_terminal1;
00094 }
00095 void WQLCompile::eval_el::assign_unary_to_second(const WQLCompile::eval_el & assignee)
00096 {
00097 opn2 = assignee.opn1;
00098 is_terminal2 = assignee.is_terminal1;
00099 }
00100
00101
00102 void WQLCompile::eval_el::order()
00103 {
00104 if ((is_terminal1 == EVAL_HEAP) && (is_terminal2 == EVAL_HEAP))
00105 {
00106 if (opn2 > opn1)
00107 {
00108 std::swap(opn1, opn2);
00109 }
00110 }
00111 else if ((is_terminal1 != EVAL_HEAP) && (is_terminal2 == EVAL_HEAP))
00112 {
00113 if (opn2 > opn1)
00114 {
00115 std::swap(opn1, opn2);
00116 std::swap(is_terminal1, is_terminal2);
00117 }
00118 }
00119 }
00120
00121
00122
00123 template<class T>
00124 inline static bool _Compare(const T& x, const T& y, WQLOperation op)
00125 {
00126 switch (op)
00127 {
00128 case WQL_EQ:
00129 return x == y;
00130 case WQL_NE:
00131 return x != y;
00132 case WQL_LT:
00133 return x < y;
00134 case WQL_LE:
00135 return x <= y;
00136 case WQL_GT:
00137 return x > y;
00138 case WQL_GE:
00139 return x >= y;
00140 default:
00141 OW_ASSERT(0);
00142 }
00143 return false;
00144 }
00145 static bool _Evaluate(
00146 const WQLOperand& lhs,
00147 const WQLOperand& rhs,
00148 WQLOperation op)
00149 {
00150 switch (lhs.getType())
00151 {
00152 case WQLOperand::NULL_VALUE:
00153 {
00154
00155
00156 return !(op == WQL_EQ) ^ (rhs.getType() == WQLOperand::NULL_VALUE);
00157 break;
00158 }
00159 case WQLOperand::INTEGER_VALUE:
00160 {
00161 return _Compare(
00162 lhs.getIntegerValue(),
00163 rhs.getIntegerValue(),
00164 op);
00165 }
00166 case WQLOperand::DOUBLE_VALUE:
00167 {
00168 return _Compare(
00169 lhs.getDoubleValue(),
00170 rhs.getDoubleValue(),
00171 op);
00172 }
00173 case WQLOperand::BOOLEAN_VALUE:
00174 {
00175 return _Compare(
00176 lhs.getBooleanValue(),
00177 rhs.getBooleanValue(),
00178 op);
00179 }
00180 case WQLOperand::STRING_VALUE:
00181 {
00182 return _Compare(
00183 lhs.getStringValue(),
00184 rhs.getStringValue(),
00185 op);
00186 }
00187 default:
00188 OW_ASSERT(0);
00189 }
00190 return false;
00191 }
00192
00193
00194
00195 WQLCompile::WQLCompile()
00196 {
00197 }
00198 WQLCompile::WQLCompile(const WQLSelectStatement & wqs)
00199 {
00200 compile(&wqs);
00201 }
00202 WQLCompile::~WQLCompile()
00203 {
00204 }
00205 void WQLCompile::compile(const WQLSelectStatement * wqs)
00206 {
00207 if (!wqs->hasWhereClause())
00208 {
00209 return;
00210 }
00211 _tableau.clear();
00212 _buildEvalHeap(wqs);
00213 _pushNOTDown();
00214 _factoring();
00215 Array<stack_el> disj;
00216 _gatherDisj(disj);
00217 if (disj.size() == 0)
00218 {
00219 if (terminal_heap.size() > 0)
00220 {
00221
00222 disj.append(stack_el(0, TERMINAL_HEAP));
00223 }
00224 }
00225
00226 for (UInt32 i=0, n =disj.size(); i< n; i++)
00227 {
00228 TableauRow tr;
00229 Array<stack_el> conj;
00230 if (disj[i].type == EVAL_HEAP)
00231 {
00232 _gatherConj(conj, disj[i]);
00233 for ( UInt32 j=0, m = conj.size(); j < m; j++)
00234 {
00235 tr.append(terminal_heap[conj[j].opn]);
00236 }
00237 }
00238 else
00239 {
00240 tr.append(terminal_heap[disj[i].opn]);
00241 }
00242 _tableau.append(tr);
00243 }
00244 eval_heap.clear();
00245
00246 _sortTableau();
00247 }
00248 bool WQLCompile::evaluate(const WQLPropertySource& source) const
00249 {
00250 WQLOperand lhs, rhs;
00251 UInt32 tableauSize = _tableau.size();
00252 if (tableauSize == 0)
00253 {
00254 return true;
00255 }
00256 for (UInt32 i = 0; i < tableauSize; i++)
00257 {
00258 TableauRow tr = _tableau[i];
00259 bool b = true;
00260 for (UInt32 j=0,m = tr.size(); b && j < m; j++)
00261 {
00262 if (tr[j].op == WQL_ISA)
00263 {
00264 String propertyName = tr[j].opn1.getPropertyName();
00265 String className;
00266 if (tr[j].opn2.getType() == WQLOperand::PROPERTY_NAME)
00267 {
00268 className = tr[j].opn2.getPropertyName();
00269 }
00270 else
00271 {
00272 className = tr[j].opn2.getStringValue();
00273 }
00274 b = source.evaluateISA(propertyName, className);
00275 }
00276 else
00277 {
00278 lhs = tr[j].opn1;
00279 WQLCompile::_ResolveProperty(lhs,source);
00280 rhs = tr[j].opn2;
00281 WQLCompile::_ResolveProperty(rhs,source);
00282 if (rhs.getType() != lhs.getType())
00283 {
00284 OW_THROW(TypeMismatchException, Format("Type mismatch: lhs: %1 rhs: %2", lhs.toString(), rhs.toString()).c_str());
00285 }
00286 b = _Evaluate(lhs, rhs, tr[j].op);
00287 }
00288 }
00289
00290 if (b)
00291 {
00292 return true;
00293 }
00294 }
00295 return false;
00296 }
00297 void WQLCompile::print(std::ostream& ostr)
00298 {
00299 for (UInt32 i=0, n=eval_heap.size();i < n;i++)
00300 {
00301 WQLOperation wop = eval_heap[i].op;
00302 if (wop == WQL_DO_NOTHING)
00303 {
00304 continue;
00305 }
00306 ostr << "Eval element " << i << ": ";
00307 if (eval_heap[i].is_terminal1 == TERMINAL_HEAP)
00308 {
00309 ostr << "T(";
00310 }
00311 else if (eval_heap[i].is_terminal1 == EVAL_HEAP)
00312 {
00313 ostr << "E(";
00314 }
00315 else
00316 {
00317 ostr << "O(";
00318 }
00319 ostr << eval_heap[i].opn1 << ") ";
00320 ostr << WQLOperationToString(eval_heap[i].op);
00321 if (eval_heap[i].is_terminal2 == TERMINAL_HEAP)
00322 {
00323 ostr << " T(";
00324 }
00325 else if (eval_heap[i].is_terminal2 == EVAL_HEAP)
00326 {
00327 ostr << "E(";
00328 }
00329 else
00330 {
00331 ostr << "O(";
00332 }
00333 ostr << eval_heap[i].opn2 << ")" << std::endl;
00334 }
00335 for (UInt32 i=0, n=terminal_heap.size();i < n;i++)
00336 {
00337 ostr << "Terminal expression " << i << ": ";
00338 ostr << terminal_heap[i].opn1.toString() << " ";
00339 ostr << WQLOperationToString(terminal_heap[i].op) << " "
00340 << terminal_heap[i].opn2.toString() << std::endl;
00341 }
00342 }
00343 void WQLCompile::printTableau(std::ostream& ostr)
00344 {
00345 for (UInt32 i=0, n = _tableau.size(); i < n; i++)
00346 {
00347 ostr << "Tableau " << i << std::endl;
00348 TableauRow tr = _tableau[i];
00349 for (UInt32 j=0, m = tr.size(); j < m; j++)
00350 {
00351 ostr << tr[j].opn1.toString() << " ";
00352 ostr << WQLOperationToString(tr[j].op) << " "
00353 << tr[j].opn2.toString() << std::endl;
00354 }
00355 }
00356 }
00357 void WQLCompile::_buildEvalHeap(const WQLSelectStatement * wqs)
00358 {
00359 Stack<stack_el> stack;
00360 for (UInt32 i = 0, n = wqs->_operStack.size(); i < n; i++)
00361 {
00362 const WQLSelectStatement::OperandOrOperation& curItem = wqs->_operStack[i];
00363 if (curItem.m_type == WQLSelectStatement::OperandOrOperation::OPERAND)
00364 {
00365
00366 stack.push(stack_el(i, OPERAND));
00367 }
00368 else
00369 {
00370 WQLOperation op = curItem.m_operation;
00371
00372 switch (op)
00373 {
00374
00375 case WQL_NOT:
00376 {
00377 OW_ASSERT(stack.size() >= 1);
00378
00379 stack_el op1 = stack.top();
00380
00381
00382 eval_heap.append(eval_el(false, op, op1.opn, op1.type,
00383 -1, TERMINAL_HEAP));
00384
00385 stack.top() = stack_el(eval_heap.size()-1, EVAL_HEAP);
00386
00387 break;
00388 }
00389
00390
00391 case WQL_OR:
00392 case WQL_AND:
00393 case WQL_EQ:
00394 case WQL_NE:
00395 case WQL_LT:
00396 case WQL_LE:
00397 case WQL_GT:
00398 case WQL_GE:
00399 case WQL_ISA:
00400 {
00401 OW_ASSERT(stack.size() >= 2);
00402
00403 stack_el op2 = stack.top();
00404 stack.pop();
00405
00406 stack_el op1 = stack.top();
00407 if (op1.type == OPERAND && op2.type == OPERAND)
00408 {
00409 OW_ASSERT(op1.type == OPERAND);
00410 OW_ASSERT(wqs->_operStack[op1.opn].m_type == WQLSelectStatement::OperandOrOperation::OPERAND);
00411 WQLOperand lhs = wqs->_operStack[op1.opn].m_operand;
00412 OW_ASSERT(op2.type == OPERAND);
00413 OW_ASSERT(wqs->_operStack[op2.opn].m_type == WQLSelectStatement::OperandOrOperation::OPERAND);
00414 WQLOperand rhs = wqs->_operStack[op2.opn].m_operand;
00415 terminal_heap.push_back(term_el(false, op, lhs, rhs));
00416 stack.top() = stack_el(terminal_heap.size()-1, TERMINAL_HEAP);
00417 }
00418 else
00419 {
00420
00421 eval_heap.append(eval_el(false, op, op1.opn, op1.type,
00422 op2.opn , op2.type));
00423 stack.top() = stack_el(eval_heap.size()-1, EVAL_HEAP);
00424 }
00425
00426 break;
00427 }
00428 case WQL_DO_NOTHING:
00429 {
00430 OW_ASSERT(0);
00431 break;
00432 }
00433 }
00434 }
00435 }
00436 OW_ASSERT(stack.size() == 1);
00437 }
00438 void WQLCompile::_pushNOTDown()
00439 {
00440 for (Int32 i=eval_heap.size()-1; i >= 0; i--)
00441 {
00442 bool _found = false;
00443
00444
00445 eval_heap[i].order();
00446
00447 if (eval_heap[i].op == WQL_NOT)
00448 {
00449
00450 eval_heap[i].op = WQL_DO_NOTHING;
00451
00452
00453 for (Int32 j=eval_heap.size()-1; j > i;j--)
00454 {
00455
00456 if ((eval_heap[j].is_terminal1 == EVAL_HEAP) && (eval_heap[j].opn1 == i))
00457 {
00458 eval_heap[j].assign_unary_to_first(eval_heap[i]);
00459 }
00460
00461 if ((eval_heap[j].is_terminal2 == EVAL_HEAP) && (eval_heap[j].opn2 == i))
00462 {
00463 eval_heap[j].assign_unary_to_second(eval_heap[i]);
00464 }
00465 }
00466
00467 if (eval_heap[i].mark)
00468 {
00469 eval_heap[i].mark = false;
00470 }
00471 else
00472 {
00473 _found = true;
00474 }
00475
00476 }
00477
00478 if (eval_heap[i].mark)
00479 {
00480
00481
00482 eval_heap[i].mark=false;
00483 if (eval_heap[i].op == WQL_OR)
00484 {
00485 eval_heap[i].op = WQL_AND;
00486 }
00487 else if (eval_heap[i].op == WQL_AND)
00488 {
00489 eval_heap[i].op = WQL_OR;
00490 }
00491
00492 _found = true;
00493 }
00494
00495 if (_found)
00496 {
00497
00498 int j = eval_heap[i].opn1;
00499 if (eval_heap[i].is_terminal1 == TERMINAL_HEAP)
00500 {
00501
00502 terminal_heap[j].negate();
00503 }
00504 else if (eval_heap[i].is_terminal1 == EVAL_HEAP)
00505 {
00506 eval_heap[j].mark = !(eval_heap[j].mark);
00507 }
00508
00509 if ((j = eval_heap[i].opn2) >= 0)
00510 {
00511 if (eval_heap[i].is_terminal2 == TERMINAL_HEAP)
00512 {
00513
00514 terminal_heap[j].negate();
00515 }
00516 else if (eval_heap[i].is_terminal2 == EVAL_HEAP)
00517 {
00518 eval_heap[j].mark = !(eval_heap[j].mark);
00519 }
00520 }
00521 }
00522 }
00523 }
00524 void WQLCompile::_factoring()
00525 {
00526 int i = 0,n = eval_heap.size();
00527
00528 while (i < n)
00529 {
00530 int _found = 0;
00531 int index = 0;
00532
00533 if (eval_heap[i].op == WQL_AND)
00534 {
00535 if (eval_heap[i].is_terminal1 == EVAL_HEAP)
00536 {
00537 index = eval_heap[i].opn1;
00538 if (eval_heap[index].op == WQL_OR)
00539 {
00540 _found = 1;
00541 }
00542 }
00543 if ((_found == 0) && (eval_heap[i].is_terminal2 == EVAL_HEAP))
00544 {
00545 index = eval_heap[i].opn2;
00546 if (eval_heap[index].op == WQL_OR)
00547 {
00548 _found = 2;
00549 }
00550 }
00551 if (_found != 0)
00552 {
00553 stack_el s;
00554 if (_found == 1)
00555 {
00556 s = eval_heap[i].getSecond();
00557 }
00558 else
00559 {
00560 s = eval_heap[i].getFirst();
00561 }
00562
00563 eval_el evl(false, WQL_OR, i+1, EVAL_HEAP, i, EVAL_HEAP);
00564 if (i < static_cast<int>(eval_heap.size())-1)
00565 {
00566 eval_heap.insert(i+1, evl);
00567 }
00568 else
00569 {
00570 eval_heap.append(evl);
00571 }
00572 eval_heap.insert(i+1, evl);
00573 for (int j=eval_heap.size()-1; j > i + 2; j--)
00574 {
00575
00576
00577 if ((eval_heap[j].is_terminal1 == EVAL_HEAP) &&
00578 (eval_heap[j].opn1 >= i))
00579 {
00580 eval_heap[j].opn1 += 2;
00581 }
00582 if ((eval_heap[j].is_terminal2 == EVAL_HEAP) &&
00583 (eval_heap[j].opn2 >= i))
00584 {
00585 eval_heap[j].opn2 += 2;
00586 }
00587 }
00588 n+=2;
00589
00590
00591 eval_heap[i+1].mark = false;
00592 eval_heap[i+1].op = WQL_AND;
00593 eval_heap[i+1].setFirst(s);
00594 eval_heap[i+1].setSecond( eval_heap[index].getFirst());
00595 eval_heap[i+1].order();
00596
00597 eval_heap[i].mark = false;
00598 eval_heap[i].op = WQL_AND;
00599 eval_heap[i].setFirst(s);
00600 eval_heap[i].setSecond( eval_heap[index].getSecond());
00601 eval_heap[i].order();
00602
00603
00604 i--;
00605 }
00606 }
00607 i++;
00608 }
00609 }
00610 void WQLCompile::_gatherDisj(Array<stack_el>& stk)
00611 {
00612 _gather(stk, stack_el(0, TERMINAL_HEAP), true);
00613 }
00614 void WQLCompile::_gatherConj(Array<stack_el>& stk, stack_el sel)
00615 {
00616 _gather(stk, sel, false);
00617 }
00618 void WQLCompile::_gather(Array<stack_el>& stk, stack_el sel, bool or_flag)
00619 {
00620 UInt32 i = 0;
00621 stk.empty();
00622 if ((i = eval_heap.size()) == 0)
00623 {
00624 return;
00625 }
00626 while (eval_heap[i-1].op == WQL_DO_NOTHING)
00627 {
00628 eval_heap.remove(i-1);
00629 i--;
00630 if (i == 0)
00631 {
00632 return;
00633 }
00634 }
00635 if (or_flag)
00636 {
00637 stk.append(stack_el(i-1, EVAL_HEAP));
00638 }
00639 else
00640 {
00641 if (sel.type != EVAL_HEAP)
00642 {
00643 return;
00644 }
00645 stk.append(sel);
00646 }
00647 i = 0;
00648 while (i<stk.size())
00649 {
00650 int k = stk[i].opn;
00651 if ((k < 0) || (stk[i].type != EVAL_HEAP))
00652 {
00653 i++;
00654 }
00655 else
00656 {
00657 if ( ((eval_heap[k].op != WQL_OR) && (or_flag)) ||
00658 ((eval_heap[k].op != WQL_AND) && (!or_flag)) )
00659 {
00660 i++;
00661 }
00662 else
00663 {
00664
00665 stk[i] = eval_heap[k].getSecond();
00666 stk.insert(i, eval_heap[k].getFirst());
00667 if (or_flag)
00668 {
00669 eval_heap[k].op = WQL_DO_NOTHING;
00670 }
00671 }
00672 }
00673 }
00674 }
00675 void WQLCompile::_sortTableau()
00676 {
00677
00678
00679 for (UInt32 i = 0, n = _tableau.size(); i < n; i++)
00680 {
00681 TableauRow tr = _tableau[i];
00682 WQLOperand wop;
00683 WQLOperation wopt;
00684
00685
00686 for (UInt32 j = 0, m = tr.size(); j < m; j++)
00687 {
00688 if (tr[j].opn2.getType() == WQLOperand::PROPERTY_NAME)
00689 {
00690 if (tr[j].opn1.getType() != WQLOperand::PROPERTY_NAME)
00691 {
00692 wop = tr[j].opn1;
00693 tr[j].opn1 = tr[j].opn2;
00694 tr[j].opn2 = wop;
00695
00696 switch (tr[j].op)
00697 {
00698 case WQL_LT: tr[j].op = WQL_GT; break;
00699 case WQL_GT: tr[j].op = WQL_LT; break;
00700 case WQL_LE: tr[j].op = WQL_GE; break;
00701 case WQL_GE: tr[j].op = WQL_LE; break;
00702 default: break;
00703 }
00704 }
00705 }
00706 }
00707 String key1, key2;
00708
00709 for (UInt32 j = 0, m = tr.size(); j < m; j++)
00710 {
00711 if ((tr[j].opn1.getType() == WQLOperand::PROPERTY_NAME)
00712 && (tr[j].opn2.getType() != WQLOperand::PROPERTY_NAME))
00713 {
00714 key1 = tr[j].opn1.getPropertyName();
00715 }
00716 else
00717 {
00718 key1.erase();
00719 }
00720 for (UInt32 k = j; k < m; k++)
00721 {
00722 if ((tr[k].opn1.getType() == WQLOperand::PROPERTY_NAME)
00723 && (tr[k].opn2.getType() != WQLOperand::PROPERTY_NAME))
00724 {
00725 key2 = tr[k].opn1.getPropertyName();
00726 }
00727 else
00728 {
00729 key2.erase();
00730 }
00731 if (key1 > key2)
00732 {
00733 wop = tr[j].opn1;
00734 tr[j].opn1 = tr[k].opn1;
00735 tr[k].opn1 = wop;
00736 wop = tr[j].opn2;
00737 tr[j].opn2 = tr[k].opn2;
00738 tr[k].opn2 = wop;
00739 wopt = tr[j].op;
00740 tr[j].op = tr[k].op;
00741 tr[k].op = wopt;
00742 }
00743 }
00744 }
00745
00746 tr.erase(std::unique(tr.begin(), tr.end()), tr.end());
00747
00748 _tableau[i] = tr;
00749 }
00750 }
00751
00752 }
00753