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