00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #include "OWBI1_config.h"
00031 #include "OWBI1_StringBuffer.hpp"
00032 #include "OWBI1_WQLSelectStatement.hpp"
00033 #include "OWBI1_WQLCompile.hpp"
00034 #include "OW_Assertion.hpp"
00035 
00036 #include <stack>
00037 #if defined(OWBI1_HAVE_OSTREAM)
00038 #include <ostream>
00039 #else
00040 #include <iostream>
00041 #endif
00042 
00043 namespace OWBI1
00044 {
00045 using namespace OpenWBEM;
00046 
00047 template<class T>
00048 inline static bool _Compare(const T& x, const T& y, WQLOperation op)
00049 {
00050    switch (op)
00051    {
00052       case WQL_EQ: 
00053          return x == y;
00054       case WQL_NE: 
00055          return x != y;
00056       case WQL_LT: 
00057          return x < y;
00058       case WQL_LE: 
00059          return x <= y;
00060       case WQL_GT: 
00061          return x > y;
00062       case WQL_GE: 
00063          return x >= y;
00064       default:
00065          OW_ASSERT(0);
00066    }
00067    return false;
00068 }
00069 static bool _Evaluate(
00070       const WQLOperand& lhs, 
00071       const WQLOperand& rhs, 
00072       WQLOperation op)
00073 {
00074    switch (lhs.getType())
00075    {
00076       case WQLOperand::NULL_VALUE:
00077          {
00078             
00079             
00080             return !(op == WQL_EQ) ^ (rhs.getType() == WQLOperand::NULL_VALUE);
00081             break;
00082          }
00083       case WQLOperand::INTEGER_VALUE:
00084          {
00085             return _Compare(
00086                   lhs.getIntegerValue(),
00087                   rhs.getIntegerValue(),
00088                   op);
00089          }
00090       case WQLOperand::DOUBLE_VALUE:
00091          {
00092             return _Compare(
00093                   lhs.getDoubleValue(),
00094                   rhs.getDoubleValue(),
00095                   op);
00096          }
00097       case WQLOperand::BOOLEAN_VALUE:
00098          {
00099             return _Compare(
00100                   lhs.getBooleanValue(),
00101                   rhs.getBooleanValue(),
00102                   op);
00103          }
00104       case WQLOperand::STRING_VALUE:
00105          {
00106             return _Compare(
00107                   lhs.getStringValue(),
00108                   rhs.getStringValue(),
00109                   op);
00110          }
00111       default:
00112          OW_ASSERT(0);
00113    }
00114    return false;
00115 }
00116 WQLSelectStatement::WQLSelectStatement()
00117 {
00118    _operStack.reserve(32);
00119 }
00120 WQLSelectStatement::~WQLSelectStatement()
00121 {
00122 }
00123 void WQLSelectStatement::clear()
00124 {
00125    _className.erase();
00126    _selectPropertyNames.clear();
00127    _operStack.clear();
00128 }
00129 bool WQLSelectStatement::appendWherePropertyName(const String& x)
00130 {
00131    
00132    
00133    
00134    for (size_t i = 0, n = _wherePropertyNames.size(); i < n; i++)
00135    {
00136       if (_wherePropertyNames[i] == x)
00137       {
00138          return false;
00139       }
00140    }
00141    
00142    
00143    
00144    _wherePropertyNames.append(x);
00145    return true;
00146 }
00147 static inline void _ResolveProperty(
00148       WQLOperand& op,
00149       const WQLPropertySource* source)
00150 {
00151    
00152    
00153    
00154    if (op.getType() == WQLOperand::PROPERTY_NAME)
00155    {
00156       const String& propertyName = op.getPropertyName();
00157       
00158       if (!source->getValue(propertyName, op))
00159       {
00160          OWBI1_THROW(NoSuchPropertyException, propertyName.c_str());
00161       }
00162    }
00163 }
00164 bool WQLSelectStatement::evaluateWhereClause(
00165       const WQLPropertySource* source) const
00166 {
00167    if (!hasWhereClause())
00168    {
00169       return true;
00170    }
00171    std::stack<WQLOperand> stack;
00172    
00173    
00174    
00175    for (UInt32 i = 0, n = _operStack.size(); i < n; i++)
00176    {
00177       const WQLSelectStatement::OperandOrOperation& curItem = _operStack[i];
00178       if (curItem.m_type == WQLSelectStatement::OperandOrOperation::OPERAND)
00179       {
00180          
00181          stack.push(curItem.m_operand);
00182       }
00183       else
00184       {
00185          WQLOperation op = curItem.m_operation;
00186          switch (op)
00187          {
00188             case WQL_OR:
00189                {
00190                   OW_ASSERT(stack.size() >= 2);
00191                   WQLOperand op1 = stack.top();
00192                   stack.pop();
00193                   WQLOperand& op2 = stack.top();
00194                   bool b1 = op1.getBooleanValue();
00195                   bool b2 = op2.getBooleanValue();
00196                   stack.top() = WQLOperand(b1 || b2, WQL_BOOLEAN_VALUE_TAG);
00197                   break;
00198                }
00199             case WQL_AND:
00200                {
00201                   OW_ASSERT(stack.size() >= 2);
00202                   WQLOperand op1 = stack.top();
00203                   stack.pop();
00204                   WQLOperand& op2 = stack.top();
00205                   bool b1 = op1.getBooleanValue();
00206                   bool b2 = op2.getBooleanValue();
00207                   stack.top() = WQLOperand(b1 && b2, WQL_BOOLEAN_VALUE_TAG);
00208                   break;
00209                }
00210             case WQL_NOT:
00211                {
00212                   OW_ASSERT(stack.size() >= 1);
00213                   WQLOperand& op = stack.top();
00214                   bool b1 = op.getBooleanValue();
00215                   stack.top() = WQLOperand(!b1, WQL_BOOLEAN_VALUE_TAG);
00216                   break;
00217                }
00218             case WQL_EQ:
00219             case WQL_NE:
00220             case WQL_LT:
00221             case WQL_LE:
00222             case WQL_GT:
00223             case WQL_GE:
00224                {
00225                   OW_ASSERT(stack.size() >= 2);
00226                   
00227                   
00228                   
00229                   
00230                   WQLOperand lhs = stack.top();
00231                   stack.pop();
00232                   _ResolveProperty(lhs, source);
00233                   
00234                   
00235                   
00236                   
00237                   WQLOperand& rhs = stack.top();
00238                   _ResolveProperty(rhs, source);
00239                   
00240                   
00241                   
00242                   if (rhs.getType() != lhs.getType())
00243                   {
00244                      OWBI1_THROW(TypeMismatchException, "");
00245                   }
00246                   
00247                   
00248                   
00249                   
00250                   stack.top() = WQLOperand(_Evaluate(lhs, rhs, op), WQL_BOOLEAN_VALUE_TAG);
00251                   break;
00252                }
00253             case WQL_ISA:
00254                {
00255                   OW_ASSERT(stack.size() >= 2);
00256                   WQLOperand lhs = stack.top();
00257                   stack.pop();
00258                   if (lhs.getType() != WQLOperand::PROPERTY_NAME)
00259                   {
00260                      OWBI1_THROW(TypeMismatchException, "First argument of ISA must be a property name");
00261                   }
00262                   WQLOperand& rhs = stack.top();
00263                   String className;
00264                   if (rhs.getType() == WQLOperand::PROPERTY_NAME)
00265                   {
00266                      className = rhs.getPropertyName();
00267                   }
00268                   else if (rhs.getType() == WQLOperand::STRING_VALUE)
00269                   {
00270                      className = rhs.getStringValue();
00271                   }
00272                   else
00273                   {
00274                      OWBI1_THROW(TypeMismatchException, "Second argument of ISA must be a property name or string constant");
00275                   }
00276                   stack.top() = WQLOperand(source->evaluateISA(lhs.getPropertyName(), className), WQL_BOOLEAN_VALUE_TAG);
00277                   break;
00278                   break;
00279                }
00280             case WQL_DO_NOTHING:
00281                {
00282                   OW_ASSERT(0); 
00283                   break;
00284                }
00285          }
00286       }
00287    }
00288    OW_ASSERT(stack.size() == 1);
00289    return stack.top().getBooleanValue();
00290 }
00291 void WQLSelectStatement::print(std::ostream& ostr) const
00292 {
00293    ostr << "WQLSelectStatement\n";
00294    ostr << "{\n";
00295    ostr << "   _className: \"" << _className << "\"\n";
00296    for (size_t i = 0; i < _selectPropertyNames.size(); i++)
00297    {
00298       if (i == 0)
00299       {
00300          ostr << '\n';
00301       }
00302       ostr << "   _selectPropertyNames[" << i << "]: ";
00303       ostr << '"' << _selectPropertyNames[i] << '"' << '\n';
00304    }
00305    
00306    for (size_t i = 0; i < _operStack.size(); i++)
00307    {
00308       if (i == 0)
00309       {
00310          ostr << '\n';
00311       }
00312       ostr << "   _operStack[" << i << "]: ";
00313       ostr << '"' << _operStack[i].toString() << '"' << '\n';
00314    }
00315    ostr << "}" << std::endl;
00316 }
00317 String WQLSelectStatement::toString() const
00318 {
00319    StringBuffer buf("select ");
00320    if (_selectPropertyNames.size())
00321    {
00322       for (size_t i = 0; i < _selectPropertyNames.size(); i++)
00323       {
00324          if (i != 0)
00325          {
00326             buf += ", ";
00327          }
00328          buf += _selectPropertyNames[i];
00329       }
00330    }
00331    else
00332    {
00333       
00334       buf += " *";
00335    }
00336    buf += " from ";
00337    buf += _className;
00338    
00339    for (size_t i = 0; i < _operStack.size(); i++)
00340    {
00341       if (i == 0)
00342       {
00343          buf += "\n";
00344       }
00345       buf += " _operStack[" + String(UInt32(i)) + "]: ";
00346       buf += "\"" + _operStack[i].toString() + "\"\n";
00347    }
00348    buf += ")";
00349    return buf.toString();
00350 }
00351 void WQLSelectStatement::compileWhereClause(
00352       const WQLPropertySource* , WQLCompile& wcl)
00353 {
00354    wcl.compile(this);
00355 }
00356 
00357 } 
00358