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