(file) Return to Cql2Dnf.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / CQL

Diff for /pegasus/src/Pegasus/CQL/Cql2Dnf.cpp between version 1.1 and 1.2

version 1.1, 2004/11/17 19:25:03 version 1.2, 2004/11/21 12:13:07
Line 0 
Line 1 
   //%2003////////////////////////////////////////////////////////////////////////
   //
   // Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development
   // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
   // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
   // IBM Corp.; EMC Corporation, The Open Group.
   //
   // Permission is hereby granted, free of charge, to any person obtaining a copy
   // of this software and associated documentation files (the "Software"), to
   // deal in the Software without restriction, including without limitation the
   // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   // sell copies of the Software, and to permit persons to whom the Software is
   // furnished to do so, subject to the following conditions:
   //
   // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
   // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
   // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
   // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
   // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
   // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   //
   //==============================================================================
   //
   // Author:      Markus Mueller (sedgewick_de@yahoo.de)
   //
   // Modified By: Adrian Schuur, schuur@de.ibm.com
   //
   //%/////////////////////////////////////////////////////////////////////////////
   
   
   //#include "CMPI_Version.h"
   #include "Cql2Dnf.h"
   #include <Pegasus/Common/Stack.h>
   //#include <Pegasus/WQL/WQLParser.h>
   
   PEGASUS_USING_STD;
   PEGASUS_NAMESPACE_BEGIN
   
   #define PEGASUS_ARRAY_T term_el
   # include <Pegasus/Common/ArrayImpl.h>
   #undef PEGASUS_ARRAY_T
   
   #define PEGASUS_ARRAY_T eval_el
   # include <Pegasus/Common/ArrayImpl.h>
   #undef PEGASUS_ARRAY_T
   
   #define PEGASUS_ARRAY_T stack_el
   # include <Pegasus/Common/ArrayImpl.h>
   #undef PEGASUS_ARRAY_T
   
   //
   // Terminal element methods
   //
   void term_el::negate()
   {
       switch (_simplePredicate.getOperation())
       {
           case EQ: _simplePredicate.setOperation(NE); break;
           case NE: _simplePredicate.setOperation(EQ); break;
           case LT: _simplePredicate.setOperation(GE); break;
           case LE: _simplePredicate.setOperation(GT); break;
           case GT: _simplePredicate.setOperation(LE); break;
           case GE: _simplePredicate.setOperation(LT); break;
           case IS_NULL:
           case IS_NOT_NULL:
           case ISA:
           case LIKE:
           default: break;
       }
   };
   /*
   String opnd2string(const WQLOperand &o) {
       switch (o.getType()) {
       case WQLOperand::PROPERTY_NAME:
          return o.getPropertyName();
       case WQLOperand::STRING_VALUE:
          return o.getStringValue();
       case WQLOperand::INTEGER_VALUE:
          return Formatter::format("$0",o.getIntegerValue());
       case WQLOperand::DOUBLE_VALUE:
          return Formatter::format("$0",o.getDoubleValue());
       case WQLOperand::BOOLEAN_VALUE:
          return Formatter::format("$0",o.getBooleanValue());
       default: ;
      }
      return "NULL_VALUE";
   }
   
   */
   /*
   CMPIPredOp mapOperation(WQLOperation op) {
      static CMPIPredOp ops[]={(CMPIPredOp)0,(CMPIPredOp)0,(CMPIPredOp)0,
         CMPI_PredOp_Equals,
         CMPI_PredOp_NotEquals,
         CMPI_PredOp_LessThan,
         CMPI_PredOp_LessThanOrEquals,
         CMPI_PredOp_GreaterThan,
         CMPI_PredOp_GreaterThanOrEquals,
         (CMPIPredOp)0,(CMPIPredOp)0,(CMPIPredOp)0,(CMPIPredOp)0,(CMPIPredOp)0,(CMPIPredOp)0};
      return ops[(int)op];
   }
   
   CMPIType mapType(WQLOperand::Type typ) {
      switch (typ) {
       case WQLOperand::PROPERTY_NAME:
          return CMPI_nameString;
       case WQLOperand::STRING_VALUE:
          return CMPI_charString;
       case WQLOperand::INTEGER_VALUE:
          return CMPI_integerString;
       case WQLOperand::DOUBLE_VALUE:
          return CMPI_realString;
       case WQLOperand::BOOLEAN_VALUE:
          return CMPI_booleanString;
       case WQLOperand::NULL_VALUE:
          return CMPI_null;
     }
     return CMPI_null;
   }
   
   int term_el::toStrings(CMPIType &typ, CMPIPredOp &opr, String &o1, String &o2) const {
      opr=mapOperation(op);
      o1=opnd2string(opn1);
      o2=opnd2string(opn2);
      if (opn1.getType()==WQLOperand::PROPERTY_NAME) typ=mapType(opn2.getType());
      else typ=mapType(opn1.getType());
      return 0;
   }
   */
   //
   // Evaluation heap element methods
   //
   stack_el eval_el::getFirst()
   {
      return stack_el(opn1, is_terminal1);
   }
   
   stack_el eval_el::getSecond()
   {
      return stack_el(opn2, is_terminal2);
   }
   
   void eval_el::setFirst(const stack_el s)
   {
        opn1 = s.opn;
        is_terminal1 = s.is_terminal;
   }
   
   void eval_el::setSecond(const stack_el s)
   {
       opn2 = s.opn;
       is_terminal2 = s.is_terminal;
   }
   
   void eval_el::assign_unary_to_first(const eval_el & assignee)
   {
       opn1 = assignee.opn1;
       is_terminal1 = assignee.is_terminal1;
   }
   
   void eval_el::assign_unary_to_second(const eval_el & assignee)
   {
       opn2 = assignee.opn1;
       is_terminal2 = assignee.is_terminal1;
   }
   
   // Ordering operators, so that op1 > op2 for all non-terminals
   // and terminals appear in the second operand first
   void eval_el::order(void)
   {
       int k;
       if ((!is_terminal1) && (!is_terminal2))
           if ((k = opn2) > opn1)
           {
               opn2 = opn1;
               opn1 =  k;
           }
       else if ((is_terminal1) && (!is_terminal2))
           if ((k = opn2) > opn1)
           {
               opn2 = opn1;
               opn1 =  k;
               is_terminal1 = false;
               is_terminal2 = true;
           }
   }
   
   //
   // Helper function copied from WQLSelectStatement
   //
   /*
   template<class T>
   inline static Boolean _Compare(const T& x, const T& y, WQLOperation op)
   {
       switch (op)
       {
           case WQL_EQ:
               return x == y;
   
           case WQL_NE:
               return x != y;
   
           case WQL_LT:
               return x < y;
           case WQL_LE:
               return x <= y;
   
           case WQL_GT:
               return x > y;
   
           case WQL_GE:
               return x >= y;
   
           default:
               PEGASUS_ASSERT(0);
       }
   
       return false;
   }
   
   static bool operator==(const WQLOperand& x, const WQLOperand& y)
   {
      if (x.getType()==y.getType()) switch (x.getType()) {
      case WQLOperand::PROPERTY_NAME:
         return x.getPropertyName()==y.getPropertyName();
      case WQLOperand::INTEGER_VALUE:
         return x.getIntegerValue()==y.getIntegerValue();
      case WQLOperand::DOUBLE_VALUE:
         return x.getDoubleValue()==y.getDoubleValue();
      case WQLOperand::BOOLEAN_VALUE:
         return x.getBooleanValue()==y.getBooleanValue();
      case WQLOperand::STRING_VALUE:
         return x.getStringValue()==y.getStringValue();
      case WQLOperand::NULL_VALUE:
         return true;
      }
      return false;
   }
   */
   static bool operator==(const term_el& x, const term_el& y)
   {
           return x._simplePredicate == y._simplePredicate;
   }
   /*
   static void addIfNotExists(TableauRow &tr, const term_el& el)
   {
      for (int i=0,m=tr.size(); i<m; i++) {
         if (tr[i]==el) return;
      }
      tr.append(el);
   }
   */
   /*
   static Boolean _Evaluate(
       const WQLOperand& lhs,
       const WQLOperand& rhs,
       WQLOperation op)
   {
       switch (lhs.getType())
       {
           case WQLOperand::NULL_VALUE:
           {
               // This cannot happen since expressions of the form
               // OPERAND OPERATOR NULL are converted to unary form.
               // For example: "count IS NULL" is treated as a unary
               // operation in which IS_NULL is the unary operation
               // and count is the the unary operand.
   
               PEGASUS_ASSERT(0);
               break;
           }
   
           case WQLOperand::INTEGER_VALUE:
           {
               return _Compare(
                   lhs.getIntegerValue(),
                   rhs.getIntegerValue(),
                   op);
           }
   
           case WQLOperand::DOUBLE_VALUE:
           {
               return _Compare(
                   lhs.getDoubleValue(),
                   rhs.getDoubleValue(),
                   op);
           }
   
           case WQLOperand::BOOLEAN_VALUE:
           {
               return _Compare(
                   lhs.getBooleanValue(),
                   rhs.getBooleanValue(),
                   op);
           }
   
           case WQLOperand::STRING_VALUE:
           {
               return _Compare(
                   lhs.getStringValue(),
                   rhs.getStringValue(),
                   op);
           }
   
           default:
               PEGASUS_ASSERT(0);
       }
   
       return false;
   }
   */
   
   //
   // CQL Compiler methods
   //
   
   /*
   Cql2Dnf::Cql2Dnf(const String condition, const String pref)
   {
       WQLSelectStatement wqs;
       WQLParser::parse(pref+condition,wqs);
       eval_heap.reserveCapacity(16);
       terminal_heap.reserveCapacity(16);
       _tableau.clear();
       compile(&wqs);
   }
   */
   Cql2Dnf::Cql2Dnf()
   {
       eval_heap.reserveCapacity(16);
       terminal_heap.reserveCapacity(16);
       //_tableau.clear();
   }
   
   Cql2Dnf::Cql2Dnf(CQLSelectStatement & cqs)
   {
       eval_heap.reserveCapacity(16);
       terminal_heap.reserveCapacity(16);
       compile(&cqs);
   }
   
   Cql2Dnf::Cql2Dnf(CQLSelectStatement * cqs)
   {
       eval_heap.reserveCapacity(16);
       terminal_heap.reserveCapacity(16);
       compile(cqs);
   }
   
   Cql2Dnf::Cql2Dnf(CQLPredicate& topLevel){
       eval_heap.reserveCapacity(16);
       terminal_heap.reserveCapacity(16);
       compile(topLevel);
   }
   
   Cql2Dnf::~Cql2Dnf() {}
   
   void Cql2Dnf::compile(CQLSelectStatement * cqs){
           CQLPredicate topLevel = cqs->getPredicate();
           compile(topLevel);
   }
   
   void Cql2Dnf::compile(CQLPredicate& topLevel)
   {
       //if (!cqs->hasWhereClause()) return;
   
       _strip_ops_operands(topLevel);
       _buildEvalHeap();
       _pushNOTDown();
       _factoring();
       _construct(); // rebuild the statement
   /*
       Array<stack_el> disj;
       _gatherDisj(disj);
       if (disj.size() == 0)
           if (terminal_heap.size() > 0)
              // point to the remaining terminal element
               disj.append(stack_el(0,true));
   
       for (Uint32 i=0, n =disj.size(); i< n; i++)
       {
           TableauRow tr;
           Array<stack_el> conj;
   
           if (!disj[i].is_terminal)
           {
              _gatherConj(conj, disj[i]);
               for( Uint32 j=0, m = conj.size(); j < m; j++)
                   addIfNotExists(tr,terminal_heap[conj[j].opn]);
   //                tr.append(terminal_heap[conj[j].opn]);
           }
           else
              addIfNotExists(tr,terminal_heap[disj[i].opn]);
   //         tr.append(terminal_heap[disj[i].opn]);
           _tableau.append(tr);
       }
   */
       eval_heap.clear();
   
       //print();
       //printTableau();
       //_sortTableau();
   }
   /*
   Boolean CMPI_Wql2Dnf::evaluate(WQLPropertySource * source) const
   {
      Boolean b = false;
      WQLOperand lhs, rhs;
   
      for(Uint32 i=0,n = _tableau.size(); i < n; i++)
      {
          TableauRow tr = _tableau[i];
          for(Uint32 j=0,m = tr.size(); j < m; j++)
          {
              lhs = tr[j].opn1;
              CMPI_Wql2Dnf::_ResolveProperty(lhs,source);
              rhs = tr[j].opn2;
              CMPI_Wql2Dnf::_ResolveProperty(rhs,source);
   
              if (rhs.getType() != lhs.getType())
                  throw TypeMismatchException();
   
              if (!_Evaluate(lhs, rhs, tr[j].op))
              {
                  b = false;
                  break;
              }
              else
                  b = true;
          }
          if (b) return true;
      }
      return false;
   }
   */
   /*
   void Cql2Dnf::print(void)
   {
   for (Uint32 i=0, n=eval_heap.size();i < n;i++) {
       WQLOperation wop = eval_heap[i].op;
       if (wop == WQL_IS_TRUE) continue;
       cout << "Eval element " << i << ": ";
       if (eval_heap[i].is_terminal1) cout << "T(";
       else cout << "E(";
       cout << eval_heap[i].opn1 << ") ";
       cout << WQLOperationToString(eval_heap[i].op);
       if (eval_heap[i].is_terminal2) cout << " T(";
       else cout << " E(";
       cout << eval_heap[i].opn2 << ")" << endl;
   }
   for (Uint32 i=0, n=terminal_heap.size();i < n;i++) {
       cout << "Terminal expression " << i << ": ";
       cout << terminal_heap[i].opn1.toString() << " ";
       cout << WQLOperationToString(terminal_heap[i].op) << " "
            << terminal_heap[i].opn2.toString() << endl;
   }
   }
   */
   /*
   void CMPI_Wql2Dnf::printTableau(void)
   {
      for(Uint32 i=0,n = _tableau.size(); i < n; i++)
      {
          cout << "Tableau " << i << endl;
          TableauRow tr = _tableau[i];
          for(Uint32 j=0,m = tr.size(); j < m; j++)
          {
              cout << tr[j].opn1.toString() << " ";
              cout << WQLOperationToString(tr[j].op) << " "
                   << tr[j].opn2.toString() << endl;
          }
   
      }
   
   }
   */
   void Cql2Dnf::_buildEvalHeap()
   {
   
       //WQLSelectStatement* that = (WQLSelectStatement*)wqs;
   
       Stack<stack_el> stack;
   
       // Operation conversion variable from OperationType enum to ExpressionOpType enum
       ExpressionOpType expOp;
   
       // Counter for Operands
   
       Uint32 j = 0;
   
       //cerr << "Build eval heap\n";
   
       for (Uint32 i = 0, n = _operations.size(); i < n; i++)
       {
           OperationType op = _operations[i];
   
           switch (op)
           {
               case CQL_OR:
               case CQL_AND:
               {
                   PEGASUS_ASSERT(stack.size() >= 2);
   
                   stack_el op1 = stack.top();
                   stack.pop();
   
                   stack_el op2 = stack.top();
   
                   // generate Eval expression
                   eval_heap.append(eval_el(0, op , op1.opn, op1.is_terminal,
                                    op2.opn , op2.is_terminal));
   
                   stack.top() = stack_el(eval_heap.size()-1, false);
   
                   break;
               }
   
               case CQL_NOT:
               {
                   PEGASUS_ASSERT(stack.size() >= 1);
   
                   stack_el op1 = stack.top();
   
                   // generate Eval expression
                   eval_heap.append(eval_el(0, op , op1.opn, op1.is_terminal,
                                    -1, true));
   
                   stack.top() = stack_el(eval_heap.size()-1, false);
   
                   break;
               }
   
               case CQL_EQ:
               case CQL_NE:
               case CQL_LT:
               case CQL_LE:
               case CQL_GT:
               case CQL_GE:
               {
                   PEGASUS_ASSERT(_operands.size() >= 2);
   
                   CQLExpression lhs = _operands[j++];
   
                   CQLExpression rhs = _operands[j++];
   
                   CQLSimplePredicate sp(lhs,rhs,_convertOpType(op));
   printf("****** pushing simplepredicate on terminal heap %s\n",(const char*)sp.toString().getCString());
                   terminal_heap.push(term_el(false, sp));
   
                   stack.push(stack_el(terminal_heap.size()-1, true));
   
                   break;
               }
   /*
               case WQL_IS_TRUE:
               case WQL_IS_NOT_FALSE:
               {
                   PEGASUS_ASSERT(stack.size() >= 1);
                   break;
               }
   */
               case CQL_IS_NULL:
               {
                   PEGASUS_ASSERT(_operands.size() >= 1);
                   CQLExpression expression = _operands[j++];
                   CQLSimplePredicate dummy(expression,EQ);
                   terminal_heap.push(term_el(false, dummy));
   
                   stack.push(stack_el(terminal_heap.size()-1, true));
   
                   break;
               }
   
               case CQL_IS_NOT_NULL:
               {
                   PEGASUS_ASSERT(_operands.size() >= 1);
                   CQLExpression expression = _operands[j++];
                   CQLSimplePredicate dummy(expression,NE);
                   terminal_heap.push(term_el(false, dummy));
   
                   stack.push(stack_el(terminal_heap.size()-1, true));
   
                   break;
               }
               case CQL_NOOP:
               default: break;
           }
       }
   
       PEGASUS_ASSERT(stack.size() == 1);
   }
   
   void Cql2Dnf::_pushNOTDown()
   {
       for (int i=eval_heap.size()-1; i >= 0; i--)
       {
           Boolean _found = false;
           int k;
   
           // Order all operators, so that op1 > op2 for non-terminals
           // and terminals appear as second operand
   
           eval_heap[i].order();
   
           // First solve the unary NOT operator
   
           if (eval_heap[i].op == CQL_NOT)
          {
               // This serves as the equivalent of an empty operator
               eval_heap[i].op = CQL_NOOP;
   
               // Substitute this expression in all higher order eval statements
               // so that this node becomes disconnected from the tree
   
               for (int j=eval_heap.size()-1; j > i;j--)
               {
                  // Test first operand
                  if ((!eval_heap[j].is_terminal1) && (eval_heap[j].opn1 == i))
   
                      eval_heap[j].assign_unary_to_first(eval_heap[i]);
   
                  // Test second operand
                  if ((!eval_heap[j].is_terminal2) && (eval_heap[j].opn2 == i))
   
                      eval_heap[j].assign_unary_to_second(eval_heap[i]);
               }
   
               // Test: Double NOT created by moving down
   
               if (eval_heap[i].mark)
                  eval_heap[i].mark = false;
               else
                  _found = true;
               // else indicate a pending NOT to be pushed down further
           }
   
           // Simple NOT created by moving down
   
           if (eval_heap[i].mark)
           {
               // Remove the mark, indicate a pending NOT to be pushed down
               // further and switch operators (AND / OR)
   
               eval_heap[i].mark=false;
               if (eval_heap[i].op == CQL_OR) eval_heap[i].op = CQL_AND;
               else if (eval_heap[i].op == CQL_AND) eval_heap[i].op = CQL_OR;
   
               // NOT operator is already ruled out
               _found = true;
           }
   
           // Push a pending NOT further down
           if (_found)
           {
                // First operand
   
                int j = eval_heap[i].opn1;
                if (eval_heap[i].is_terminal1)
                    // Flip NOT mark
                    terminal_heap[j].negate();
                else
                    eval_heap[j].mark = !(eval_heap[j].mark);
   
                //Second operand (if it exists)
   
                if ((j = eval_heap[i].opn2) >= 0)
                {
                    if (eval_heap[i].is_terminal2)
                        // Flip NOT mark
                        terminal_heap[j].negate();
                    else
                        eval_heap[j].mark = !(eval_heap[j].mark);
                }
           }
       }
   }
   
   void Cql2Dnf::_factoring(void)
   {
       int i = 0,n = eval_heap.size();
       //for (int i=eval_heap.size()-1; i >= 0; i--)
       while (i < n)
       {
           int _found = 0;
           int index = 0;
   
           // look for expressions (A | B) & C  ---> A & C | A & B
           if (eval_heap[i].op == CQL_AND)
           {
               if (!eval_heap[i].is_terminal1)
               {
                   index = eval_heap[i].opn1; // remember the index
                   if (eval_heap[index].op == CQL_OR) _found = 1;
               }
   
               if ((_found == 0) && (!eval_heap[i].is_terminal2))
               {
                   index = eval_heap[i].opn2; // remember the index
                   if (eval_heap[index].op == CQL_OR) _found = 2;
               }
   
               if (_found != 0)
               {
                    //int u1,u1_t,u2,u2_t,u3,u3_t;
                    stack_el s;
   
                    if (_found == 1)
                        s = eval_heap[i].getSecond();
                    else
                        s = eval_heap[i].getFirst();
   
                    // insert two new expression before entry i
                    eval_el evl;
   
                    evl = eval_el(false, CQL_OR, i+1, false, i, false);
                    if ((Uint32 )i < eval_heap.size()-1)
                        eval_heap.insert(i+1, evl);
                    else
                        eval_heap.append(evl);
                    eval_heap.insert(i+1, evl);
   
                    for (int j=eval_heap.size()-1; j > i + 2; j--)
                    {
                        //eval_heap[j] = eval_heap[j-2];
   
                        // adjust pointers
   
                        if ((!eval_heap[j].is_terminal1)&&
                            (eval_heap[j].opn1 >= i))
                            eval_heap[j].opn1 += 2;
                        if ((!eval_heap[j].is_terminal2)&&
                            (eval_heap[j].opn2 >= i))
                            eval_heap[j].opn2 += 2;
                    }
   
                    n+=2; // increase size of array
   
                    // generate the new expressions : new OR expression
   
   
                    // first new AND expression
                    eval_heap[i+1].mark = false;
                    eval_heap[i+1].op = CQL_AND;
                    eval_heap[i+1].setFirst(s);
                    eval_heap[i+1].setSecond( eval_heap[index].getFirst());
                    eval_heap[i+1].order();
   
   
                    // second new AND expression
                    eval_heap[i].mark = false;
                    eval_heap[i].op = CQL_AND;
                    eval_heap[i].setFirst(s);
                    eval_heap[i].setSecond( eval_heap[index].getSecond());
                    eval_heap[i].order();
   
                    // mark the indexed expression as inactive
                    //eval_heap[index].op = WQL_IS_TRUE; possible disconnects
                    i--;
   
               } /* endif _found > 0 */
   
           } /* endif found AND operator */
   
           i++; // increase pointer
       }
   }
   /*
   void Cql2Dnf::_gatherDisj(Array<stack_el>& stk)
   {
       _gather(stk, stack_el(0,true), true);
   }
   
   void Cql2Dnf::_gatherConj(Array<stack_el>& stk, stack_el sel)
   {
       _gather(stk, sel, false);
   }
   
   void Cql2Dnf::_gather(Array<stack_el>& stk, stack_el sel, Boolean or_flag)
   {
       Uint32 i = 0;
   
       stk.clear();
       stk.reserveCapacity(16);
   
       if ((i = eval_heap.size()) == 0) return;
   
       while (eval_heap[i-1].op == WQL_IS_TRUE)
       {
           eval_heap.remove(i-1);
           i--;
           if (i == 0) return;
       }
       //if (i == 0) return;
   
       if (or_flag)
           stk.append(stack_el(i-1,false));
       else
       {
          if (sel.is_terminal) return;
          stk.append(sel);
       }
   
       i = 0;
   
       while (i<stk.size())
       {
           int k = stk[i].opn;
   
           if ((k < 0) || (stk[i].is_terminal))
              i++;
           else
           {
               if ( ((eval_heap[k].op != WQL_OR) && (or_flag)) ||
                    ((eval_heap[k].op != WQL_AND) && (!or_flag))  )
                   i++;
               else
               {
                   // replace the element with disjunction
                   stk[i] = eval_heap[k].getSecond();
                   stk.insert(i, eval_heap[k].getFirst());
                   if (or_flag)
                       eval_heap[k].op = WQL_IS_TRUE;
               }
           }
       }
   }
   */
   void Cql2Dnf::_strip_ops_operands(CQLPredicate& topLevel)
   {
           //
           // depth first search for all operations and operands
           // extract operations and operands and store in respective arrays for later processing
           //
           _destruct(topLevel);
   }
   
   OperationType Cql2Dnf::_convertOpType(ExpressionOpType op){
           switch(op){
                   case EQ: return CQL_EQ;
                   case NE: return CQL_NE;
                   case GT: return CQL_GT;
                   case LT: return CQL_LT;
                   case GE: return CQL_GE;
                   case LE: return CQL_LE;
                   case IS_NULL: return CQL_IS_NULL;
                   case IS_NOT_NULL: return CQL_IS_NOT_NULL;
                   case ISA:
                   case LIKE:
                   default: return CQL_NOOP;
           }
   }
   
   ExpressionOpType Cql2Dnf::_convertOpType(OperationType op){
           switch(op){
                   case CQL_EQ: return EQ;
                   case CQL_NE: return NE;
                   case CQL_GT: return GT;
                   case CQL_LT: return LT;
                   case CQL_GE: return GE;
                   case CQL_LE: return LE;
                   case CQL_IS_NULL: return IS_NULL;
                   case CQL_IS_NOT_NULL: return IS_NOT_NULL;
                   default: break;
           }
   }
   
   void Cql2Dnf::_destruct(CQLPredicate& _p){
           if(_p.isSimple()){
                   CQLSimplePredicate _sp = _p.getSimplePredicate();
                   _operations.append(_convertOpType(_sp.getOperation()));
                   _operands.append(_sp.getLeftExpression());
                   _operands.append(_sp.getRightExpression());
           }
           else{
                   Array<CQLPredicate> _preds = _p.getPredicates();
                   Array<BooleanOpType> _boolops = _p.getOperators();
                   for(Uint32 i=0;i<_preds.size();i++){
                           _destruct(_preds[i]);
                           if(_preds[i].getInverted()){
                                   _operations.append(CQL_NOT);
                           }
                           if(i > 0){
                                   if(_boolops[i-1] == AND){
                                           _operations.append(CQL_AND);
                                   }
                                   if(_boolops[i-1] == OR){
                                           _operations.append(CQL_OR);
                                   }
                           }
                   }
           }
   }
   
   void Cql2Dnf::_construct(){
           //
           // Each eval_el on the eval heap contains all the information needed to make a CQLPredicate.
           // We will build a CQLPredicate for every element in the eval heap. So there is a 1 to 1 correspondence
           // between elements in the eval heap and elements in the CQLPredicate array used below.
           // The first eval_el on the eval heap will always contain at least one terminal if the operation is a NOT
           // or two terminals if the operation is AND or OR.  We are guaranteed to build a CQLPredicate from the first
           // position in the eval_heap array.
           //
           // The key to the algorithm is the isterminalX flag.  When set to true, we go to the
           // term_heap and get the CQLSimplePredicate.  When set to false, we go to the _preds array below
           // and get the CQLPredicate.  Since there is a 1 - 1 correspondence, as explained above, the index
           // referred to by eval.opn1 or eval.opn2 is valid into the _preds array.
           //
           // For ANDs and ORs, we need two operands, as explained above, we get those operands
           // from either the term_heap or the _preds array.  For NOTs, we need only 1 operand, and that
           // comes from either the term_heap or the _preds array.
           //
           // When finished, the last element in the _preds array contains the top level CQLPredicate (the rebuilt tree)
           //
           // Example:  a=b^(!c=d v e=f)
           // If the current eval_heap looks like:
           //      0,NOT,1,True,-1,True [index = 0]
           //      0,OR,2,True,0,False  [index = 1]
           //      0,AND,1,False,0,True [index = 2]
           //
           // And the current term_heap looks like:
           //      CQLSimplePredicate(a=b) [index = 0]
           //      CQLSimplePredicate(c=d) [index = 1]
           //      CQLSimplePredicate(e=f) [index = 0]
           //
           // The _preds array at the end would look like:
           //      CQLPredicate(!c==d)        [index = 0]
           //      CQLPredicate(e==f v !c==d) [index = 1]
           //      CQLPredicate((e==f v !c==d) ^ a==b) [index = 2]  (the rebuilt tree)
           //
   
           if(eval_heap.size() > 0){
   printf("**** eval_heap.size = %d\n",eval_heap.size());
   printf("**** terminal_heap.size = %d\n",terminal_heap.size());
              Array<CQLPredicate> _preds;
              for(Uint32 i=0;i<eval_heap.size();i++){
                   eval_el eval = eval_heap[i];
                   if(eval.is_terminal1 && eval.is_terminal2){
                           switch(eval.op){
                                   case CQL_NOT:
                                   {
                                           _preds.append(CQLPredicate(terminal_heap[eval.opn1]._simplePredicate,true));
                                           break;
                                   }
                                   case CQL_NOOP:
                                   {
                                           _preds.append(CQLPredicate(terminal_heap[eval.opn1]._simplePredicate,false));
                                           break;
                                   }
                                   case CQL_AND:
                                   {
                                           CQLPredicate p;
                                           CQLPredicate p1(terminal_heap[eval.opn2]._simplePredicate,false);
                                           p.appendPredicate(p1);
                                           CQLPredicate p2(terminal_heap[eval.opn1]._simplePredicate,false);
                                           p.appendPredicate(p2,AND);
                                           _preds.append(p);
                                           break;
                                   }
                                   case CQL_OR:
                                   {
                                           CQLPredicate p;
                                           CQLPredicate p1(terminal_heap[eval.opn2]._simplePredicate,false);
                                           p.appendPredicate(p1);
                                           CQLPredicate p2(terminal_heap[eval.opn1]._simplePredicate,false);
                                           p.appendPredicate(p2,OR);
                                           _preds.append(p);
                                           break;
                                   }
                                   case CQL_EQ:
                                   case CQL_NE:
                                   case CQL_GT:
                                   case CQL_LT:
                                   case CQL_GE:
                                   case CQL_LE:
                                   case CQL_IS_NULL:
                                   case CQL_IS_NOT_NULL: break;
   
                           }
                   }else if(eval.is_terminal1 && !eval.is_terminal2){
                           switch(eval.op){
                                   case CQL_NOT:
                                   {
                                           _preds.append(CQLPredicate(terminal_heap[eval.opn1]._simplePredicate,true));
                                           break;
                                   }
                                   case CQL_NOOP:
                                   {
                                           _preds.append(CQLPredicate(terminal_heap[eval.opn1]._simplePredicate,false));
                                           break;
                                   }
                                   case CQL_AND:
                                   {
                                           CQLPredicate p;
                                           CQLPredicate p1(terminal_heap[eval.opn1]._simplePredicate,false);
                                           p.appendPredicate(_preds[eval.opn2]);
                                           p.appendPredicate(p1,AND);
                                           _preds.append(p);
                                           break;
                                   }
                                   case CQL_OR:
                                   {
                                           CQLPredicate p;
                                           CQLPredicate p1(terminal_heap[eval.opn1]._simplePredicate,false);
                                           p.appendPredicate(_preds[eval.opn2]);
                                           p.appendPredicate(p1,OR);
                                           _preds.append(p);
                                           break;
                                   }
                                   case CQL_EQ:
                                   case CQL_NE:
                                   case CQL_GT:
                                   case CQL_LT:
                                   case CQL_GE:
                                   case CQL_LE:
                                   case CQL_IS_NULL:
                                   case CQL_IS_NOT_NULL: break;
   
                           }
                   }else if(!eval.is_terminal1 && eval.is_terminal2){
                           switch(eval.op){
                                   case CQL_NOT:
                                   {
                                           CQLPredicate p = _preds[eval.opn1];
                                           p.setInverted();
                                           _preds.append(p);
                                           break;
                                   }
                                   case CQL_NOOP:
                                   {
                                           _preds.append(_preds[eval.opn1]);
                                           break;
                                   }
                                   case CQL_AND:
                                   {
                                           CQLPredicate p;
                                           CQLPredicate p1(terminal_heap[eval.opn2]._simplePredicate,false);
                                           p.appendPredicate(_preds[eval.opn1]);
                                           p.appendPredicate(p1,AND);
                                           _preds.append(p);
                                           break;
                                   }
                                   case CQL_OR:
                                   {
                                           CQLPredicate p;
                                           CQLPredicate p1(terminal_heap[eval.opn2]._simplePredicate,false);
                                           p.appendPredicate(_preds[eval.opn1]);
                                           p.appendPredicate(p1,OR);
                                           _preds.append(p);
                                           break;
                                   }
                                   case CQL_EQ:
                                   case CQL_NE:
                                   case CQL_GT:
                                   case CQL_LT:
                                   case CQL_GE:
                                   case CQL_LE:
                                   case CQL_IS_NULL:
                                   case CQL_IS_NOT_NULL: break;
   
                           }
                   }else{ // !eval.is_terminal1 && !eval.is_terminal2
                           switch(eval.op){
                                   case CQL_NOT:
                                   {
                                           CQLPredicate p = _preds[eval.opn1];
                                           p.setInverted();
                                           _preds.append(p);
                                           break;
                                   }
                                   case CQL_NOOP:
                                   {
                                           _preds.append(_preds[eval.opn1]);
                                           break;
                                   }
                                   case CQL_AND:
                                   {
                                           CQLPredicate p = _preds[eval.opn2];
                                           p.appendPredicate(_preds[eval.opn1],AND);
                                           _preds.append(p);
                                           break;
                                   }
                                   case CQL_OR:
                                   {
                                           CQLPredicate p = _preds[eval.opn2];
                                           p.appendPredicate(_preds[eval.opn1],OR);
                                           _preds.append(p);
                                           break;
                                   }
                                   case CQL_EQ:
                                   case CQL_NE:
                                   case CQL_GT:
                                   case CQL_LT:
                                   case CQL_GE:
                                   case CQL_LE:
                                   case CQL_IS_NULL:
                                   case CQL_IS_NOT_NULL: break;
   
                           }
   
                   }
              } // end for(...)
   
              _dnfPredicate = _preds[_preds.size()-1];
   
           } // end if
           else{ // we just have a CQLSimplePredicate on the terminal_heap
                   PEGASUS_ASSERT(terminal_heap.size() == 1);
                   _dnfPredicate = CQLPredicate(terminal_heap[0]._simplePredicate,false);
           }
   }
   
   CQLPredicate Cql2Dnf::getDnfPredicate(){
           return _dnfPredicate;
   }
   
   PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2