1 mike 1.2 //%/////////////////////////////////////////////////////////////////////////////
2 //
|
3 kumpf 1.3 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
|
4 mike 1.2 // The Open Group, Tivoli Systems
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 kumpf 1.3 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
10 mike 1.2 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
|
13 kumpf 1.3 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
14 mike 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
16 kumpf 1.3 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
19 mike 1.2 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 //==============================================================================
23 //
24 // Author: Mike Brasher (mbrasher@bmc.com)
25 //
26 // Modified By:
27 //
28 //%/////////////////////////////////////////////////////////////////////////////
29
30 #include <iostream>
31 #include <Pegasus/Common/Stack.h>
32 #include "WQLSelectStatement.h"
33
34 PEGASUS_USING_STD;
35
36 PEGASUS_NAMESPACE_BEGIN
37
38 template<class T>
39 inline static Boolean _Compare(const T& x, const T& y, WQLOperation op)
40 mike 1.2 {
41 switch (op)
42 {
43 case WQL_EQ:
44 return x == y;
45
46 case WQL_NE:
47 return x != y;
48
49 case WQL_LT:
50 return x < y;
51 case WQL_LE:
52 return x <= y;
53
54 case WQL_GT:
55 return x > y;
56
57 case WQL_GE:
58 return x >= y;
59
60 default:
61 mike 1.2 PEGASUS_ASSERT(0);
62 }
63
64 return false;
65 }
66
67 static Boolean _Evaluate(
68 const WQLOperand& lhs,
69 const WQLOperand& rhs,
70 WQLOperation op)
71 {
72 switch (lhs.getType())
73 {
74 case WQLOperand::NULL_VALUE:
75 {
76 // This cannot happen since expressions of the form
77 // OPERAND OPERATOR NULL are converted to unary form.
78 // For example: "count IS NULL" is treated as a unary
79 // operation in which IS_NULL is the unary operation
80 // and count is the the unary operand.
81
82 mike 1.2 PEGASUS_ASSERT(0);
83 break;
84 }
85
86 case WQLOperand::INTEGER_VALUE:
87 {
88 return _Compare(
89 lhs.getIntegerValue(),
90 rhs.getIntegerValue(),
91 op);
92 }
93
94 case WQLOperand::DOUBLE_VALUE:
95 {
96 return _Compare(
97 lhs.getDoubleValue(),
98 rhs.getDoubleValue(),
99 op);
100 }
101
102 case WQLOperand::BOOLEAN_VALUE:
103 mike 1.2 {
104 return _Compare(
105 lhs.getBooleanValue(),
106 rhs.getBooleanValue(),
107 op);
108 }
109
110 case WQLOperand::STRING_VALUE:
111 {
112 return _Compare(
113 lhs.getStringValue(),
114 rhs.getStringValue(),
115 op);
116 }
117
118 default:
119 PEGASUS_ASSERT(0);
120 }
121
122 return false;
123 }
124 mike 1.2
125 WQLSelectStatement::WQLSelectStatement()
126 {
127 //
128 // Reserve space for a where clause with up to sixteen terms.
129 //
130
|
131 kumpf 1.4 _operations.reserveCapacity(16);
132 _operands.reserveCapacity(16);
|
133 mike 1.2 }
134
135 WQLSelectStatement::~WQLSelectStatement()
136 {
137
138 }
139
140 void WQLSelectStatement::clear()
141 {
142 _className.clear();
143 _selectPropertyNames.clear();
144 _operations.clear();
145 _operands.clear();
146 }
147
148 Boolean WQLSelectStatement::appendWherePropertyName(const String& x)
149 {
150 //
151 // Reject duplicate property names by returning false.
152 //
153
154 mike 1.2 for (Uint32 i = 0, n = _wherePropertyNames.size(); i < n; i++)
155 {
156 if (_wherePropertyNames[i] == x)
157 return false;
158 }
159
160 //
161 // Append the new property.
162 //
163
164 _wherePropertyNames.append(x);
165 return true;
166 }
167
168 static inline void _ResolveProperty(
169 WQLOperand& op,
170 const WQLPropertySource* source)
171 {
172 //
173 // Resolve the operand: if it's a property name, look up its value:
174 //
175 mike 1.2
176 if (op.getType() == WQLOperand::PROPERTY_NAME)
177 {
178 const String& propertyName = op.getPropertyName();
179
180 if (!source->getValue(propertyName, op))
181 throw NoSuchProperty(propertyName);
182 }
183 }
184
185 Boolean WQLSelectStatement::evaluateWhereClause(
186 const WQLPropertySource* source) const
187 {
188 if (!hasWhereClause())
189 return true;
190
191 WQLSelectStatement* that = (WQLSelectStatement*)this;
192 Stack<Boolean> stack;
|
193 kumpf 1.4 stack.reserveCapacity(16);
|
194 mike 1.2
195 //
196 // Counter for operands:
197 //
198
199 Uint32 j = 0;
200
201 //
202 // Process each of the operations:
203 //
204
205 for (Uint32 i = 0, n = _operations.size(); i < n; i++)
206 {
207 WQLOperation op = _operations[i];
208
209 switch (op)
210 {
211 case WQL_OR:
212 {
213 PEGASUS_ASSERT(stack.size() >= 2);
214
215 mike 1.2 Boolean op1 = stack.top();
216 stack.pop();
217
218 Boolean op2 = stack.top();
219
220 stack.top() = op1 || op2;
221 break;
222 }
223
224 case WQL_AND:
225 {
226 PEGASUS_ASSERT(stack.size() >= 2);
227
228 Boolean op1 = stack.top();
229 stack.pop();
230
231 Boolean op2 = stack.top();
232
233 stack.top() = op1 && op2;
234 break;
235 }
236 mike 1.2
237 case WQL_NOT:
238 {
239 PEGASUS_ASSERT(stack.size() >= 1);
240
241 Boolean op = stack.top();
242 stack.top() = !op;
243 break;
244 }
245
246 case WQL_EQ:
247 case WQL_NE:
248 case WQL_LT:
249 case WQL_LE:
250 case WQL_GT:
251 case WQL_GE:
252 {
253 PEGASUS_ASSERT(_operands.size() >= 2);
254
255 //
256 // Resolve the left-hand-side to a value (if not already
257 mike 1.2 // a value).
258 //
259
260 WQLOperand& lhs = that->_operands[j++];
261 _ResolveProperty(lhs, source);
262
263 //
264 // Resolve the right-hand-side to a value (if not already
265 // a value).
266 //
267
268 WQLOperand& rhs = that->_operands[j++];
269 _ResolveProperty(rhs, source);
270
271 //
272 // Check for a type mismatch:
273 //
274
275 // PEGASUS_OUT(lhs.toString());
276 // PEGASUS_OUT(rhs.toString());
277
278 mike 1.2 if (rhs.getType() != lhs.getType())
279 throw TypeMismatch();
280
281 //
282 // Now that the types are known to be alike, apply the
283 // operation:
284 //
285
286 stack.push(_Evaluate(lhs, rhs, op));
287 break;
288 }
289
290 case WQL_IS_TRUE:
291 case WQL_IS_NOT_FALSE:
292 {
293 PEGASUS_ASSERT(stack.size() >= 1);
294 break;
295 }
296
297 case WQL_IS_FALSE:
298 case WQL_IS_NOT_TRUE:
299 mike 1.2 {
300 PEGASUS_ASSERT(stack.size() >= 1);
301 stack.top() = !stack.top();
302 break;
303 }
304
305 case WQL_IS_NULL:
306 {
307 PEGASUS_ASSERT(_operands.size() >= 1);
308 WQLOperand& op = that->_operands[j++];
309 _ResolveProperty(op, source);
310 stack.push(op.getType() == WQLOperand::NULL_VALUE);
311 break;
312 }
313
314 case WQL_IS_NOT_NULL:
315 {
316 PEGASUS_ASSERT(_operands.size() >= 1);
317 WQLOperand& op = that->_operands[j++];
318 _ResolveProperty(op, source);
319 stack.push(op.getType() != WQLOperand::NULL_VALUE);
320 mike 1.2 break;
321 }
322 }
323 }
324
325 PEGASUS_ASSERT(stack.size() == 1);
326 return stack.top();
327 }
328
329 void WQLSelectStatement::print() const
330 {
331 //
332 // Print the header:
333 //
334
335 cout << "WQLSelectStatement" << endl;
336 cout << "{" << endl;
337
338 //
339 // Print the class name:
340 //
341 mike 1.2
342 cout << " _className: \"" << _className << '"' << endl;
343
344 //
345 // Print the property:
346 //
347
348 for (Uint32 i = 0; i < _selectPropertyNames.size(); i++)
349 {
350 if (i == 0)
351 cout << endl;
352
353 cout << " _selectPropertyNames[" << i << "]: ";
354 cout << '"' << _selectPropertyNames[i] << '"' << endl;
355 }
356
357 //
358 // Print the operations:
359 //
360
361 for (Uint32 i = 0; i < _operations.size(); i++)
362 mike 1.2 {
363 if (i == 0)
364 cout << endl;
365
366 cout << " _operations[" << i << "]: ";
367 cout << '"' << WQLOperationToString(_operations[i]) << '"' << endl;
368 }
369
370 //
371 // Print the operands:
372 //
373
374 for (Uint32 i = 0; i < _operands.size(); i++)
375 {
376 if (i == 0)
377 cout << endl;
378
379 cout << " _operands[" << i << "]: ";
380 cout << '"' << _operands[i].toString() << '"' << endl;
381 }
382
383 mike 1.2 //
384 // Print the trailer:
385 //
386
387 cout << "}" << endl;
388 }
389
390 PEGASUS_NAMESPACE_END
|