1 chuck 1.2 //%2003////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Development
4 // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
16 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
17 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
18 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
19 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 chuck 1.2 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 //==============================================================================
25 //
26 // Authors: David Rosckes (rosckes@us.ibm.com)
27 // Bert Rivero (hurivero@us.ibm.com)
28 // Chuck Carmack (carmack@us.ibm.com)
29 // Brian Lucier (lucier@us.ibm.com)
30 //
31 // Modified By:
32 //
33 //%/////////////////////////////////////////////////////////////////////////////
34
35 #include <Pegasus/Common/InternalException.h>
36 #include "CQLSimplePredicate.h"
37 #include "CQLSimplePredicateRep.h"
38 //#include <Pegasus/CQL/CQLExpression.h>
39 #include <Pegasus/CQL/CQLFactory.h>
40 #include <Pegasus/Query/QueryCommon/QueryContext.h>
41 #include <Pegasus/Query/QueryCommon/QueryException.h>
|
42 humberto 1.4 #include <Pegasus/Common/Tracer.h>
|
43 chuck 1.2
44 PEGASUS_NAMESPACE_BEGIN
45
46 CQLSimplePredicateRep::CQLSimplePredicateRep(){
47 _isSimple = true;
48 }
49
50 CQLSimplePredicateRep::CQLSimplePredicateRep(const CQLExpression& inExpression)
51 {
52 _leftSide = inExpression;
53 _isSimple = true;
54 }
55
56 CQLSimplePredicateRep::CQLSimplePredicateRep(const CQLExpression& inExpression,
57 const ExpressionOpType inOperator)
58 {
59 _leftSide = inExpression;
60 _operator = inOperator;
61 _isSimple = true;
62 }
63
64 chuck 1.2 CQLSimplePredicateRep::CQLSimplePredicateRep(const CQLExpression& leftSideExpression,
65 const CQLExpression& rightSideExpression,
66 ExpressionOpType inOperator)
67 {
68 _leftSide = leftSideExpression;
69 _rightSide = rightSideExpression;
70 _operator = inOperator;
71 _isSimple = false;
72 }
73
74 CQLSimplePredicateRep::CQLSimplePredicateRep(const CQLSimplePredicateRep* rep){
75 _leftSide = rep->_leftSide;
76 _rightSide = rep->_rightSide;
77 _operator = rep->_operator;
78 _isSimple = rep->_isSimple;
79 }
80
81 Boolean CQLSimplePredicateRep::evaluate(CIMInstance CI, QueryContext& QueryCtx)
82 {
|
83 humberto 1.4 PEG_METHOD_ENTER(TRC_CQL, "CQLSimplePredicateRep::evaluate");
|
84 chuck 1.2 // Resolve the value of the left side
85 CQLValue leftVal = _leftSide.resolveValue(CI, QueryCtx);
86
87 // If there isn't a right side then operator must by IS_NULL
88 // or IS_NOT_NULL
89 if (isSimple())
90 {
91 PEGASUS_ASSERT(_operator == IS_NULL || _operator == IS_NOT_NULL);
92
93 return (_operator == IS_NULL) ? leftVal.isNull() : !leftVal.isNull();
94 }
95
96 PEGASUS_ASSERT(_operator != IS_NULL && _operator != IS_NOT_NULL);
97
98 if (leftVal.isNull())
99 {
100 // The null contagion rule. See CQLSelectStatementRep for details.
101 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.NULL_CONTAGION",
102 "The expression evaluates to NULL.");
103 throw CQLNullContagionException(parms);
104 }
105 chuck 1.2
106 if (_operator == ISA)
107 {
108 // Special processing for ISA. The CQLValue on the right side of ISA
109 // has a CQLChainedIdentifier with one element that contains
110 // the class name. We don't want to resolve the right side because
111 // CQLValue would assume that a single element chained identifier
112 // refers to an instance of the FROM class.
113 if (!_rightSide.isSimpleValue())
114 {
115 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.RHS_ISA_NOT_SIMPLE",
|
116 chuck 1.3 "The expression $0 on the right side of the ISA operator must be a simple value.",
117 _rightSide.toString());
|
118 chuck 1.2 throw CQLRuntimeException(parms);
119 }
120
121 CQLValue isaRightVal = _rightSide.getTerms()[0].getFactors()[0].getValue();
122 CQLChainedIdentifier isaRightId = isaRightVal.getChainedIdentifier();
123 return leftVal.isa(isaRightId, QueryCtx);
124 }
125
126 if (_operator == LIKE)
127 {
128 // Special processing for LIKE. The right side expression must be
129 // a simple CQLValue (ie. not nested, and not a function), and
130 // must be a literal. Note that this code will test whether
131 // the right side is a literal, but not whether it is a string
132 // literal.
133 if (!_rightSide.isSimpleValue())
134 {
135 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.RHS_LIKE_NOT_SIMPLE",
|
136 chuck 1.3 "The expression $0 on the right side of the LIKE operator must be a simple value.",
137 _rightSide.toString());
|
138 chuck 1.2 throw CQLRuntimeException(parms);
139 }
140
141 CQLValue likeRightVal = _rightSide.getTerms()[0].getFactors()[0].getValue();
142 if (!likeRightVal.isResolved())
143 {
144 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.RHS_LIKE_NOT_LITERAL",
|
145 chuck 1.3 "The expression $0 on the right side of the LIKE operator must be a literal.",
146 _rightSide.toString());
|
147 chuck 1.2 throw CQLRuntimeException(parms);
148 }
149
150 return leftVal.like(likeRightVal);
151 }
152
153 // No special processing needed.
154 // Resolve the value of the right side
155 CQLValue rightVal = _rightSide.resolveValue(CI, QueryCtx);
156
157 if (rightVal.isNull())
158 {
159 // The null contagion rule. See CQLSelectStatementRep for details.
160 // ATTN - change this to a specific CQLException so that it can
161 // be caught above
162 // The null contagion rule. See CQLSelectStatementRep for details.
163 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.NULL_CONTAGION",
164 "The expression evaluates to NULL.");
165 throw CQLNullContagionException(parms);
166 }
167
168 chuck 1.2 switch(_operator)
169 {
170 case LT:
171 return leftVal < rightVal;
172 break;
173
174 case GT:
175 return leftVal > rightVal;
176 break;
177
178 case LE:
179 return leftVal <= rightVal;
180 break;
181
182 case GE:
183 return leftVal >= rightVal;
184 break;
185
186 case EQ:
187 return leftVal == rightVal;
188 break;
189 chuck 1.2
190 case NE:
191 return leftVal != rightVal;
192 break;
193
194 case LIKE:
195 case ISA:
196 // Never get here due to special processing above.
197 PEGASUS_ASSERT(false);
198 case IS_NULL:
199 case IS_NOT_NULL:
200 // Never get here due to the assert.
201 break;
202 }
|
203 humberto 1.4 PEG_METHOD_EXIT();
|
204 chuck 1.2 return true; // keep the compiler happy
205 }
206
207 CQLExpression CQLSimplePredicateRep::getLeftExpression()const
208 {
209 return _leftSide;
210 }
211
212 CQLExpression CQLSimplePredicateRep::getRightExpression()const
213 {
214 return _rightSide;
215 }
216
217 enum ExpressionOpType CQLSimplePredicateRep::getOperation()const
218 {
219 return _operator;
220 }
221
222 void CQLSimplePredicateRep::applyContext(QueryContext& queryContext)
223 {
|
224 humberto 1.4 PEG_METHOD_ENTER(TRC_CQL, "CQLSimplePredicateRep::applyContext");
|
225 chuck 1.2 CQLIdentifier _id;
226
227 _id = _leftSide.getTerms()[0].getFactors()[0].
228 getValue().getChainedIdentifier().getLastIdentifier();
229
230 if(_leftSide.isSimpleValue() &&
231 _id.isSymbolicConstant() &&
232 _id.getName().getString().size() == 0)
233 {
234 // We have a standalone symbolic constant.
235 if(!isSimple() &&
236 _rightSide.isSimpleValue() &&
237 _rightSide.getTerms()[0].getFactors()[0].
238 getValue().getChainedIdentifier().getLastIdentifier().
239 getName().getString().size() > 0)
240 {
241 _rightSide.applyContext(queryContext);
242
243 // We need to add context to the symbolic constant
244 _leftSide.applyContext(queryContext,
245 _rightSide.getTerms()[0].getFactors()[0].
246 chuck 1.2 getValue().getChainedIdentifier());
247 }
248 else
249 {
250 // There is no valid context for the symbolic constant
251 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.RIGHT_STANDALONE_SYMCONST_ERROR",
|
252 chuck 1.3 "The right side of predicate $0 must be a simple property name because a symbolic constant exists on the left side.",
253 toString());
|
254 chuck 1.2 throw CQLSyntaxErrorException(parms);
255 }
256 }
257 else
258 {
259 _leftSide.applyContext(queryContext);
260 }
261
262 if (!isSimple())
263 {
264 _id = _rightSide.getTerms()[0].getFactors()[0].
265 getValue().getChainedIdentifier().getLastIdentifier();
266
267 if(_rightSide.isSimpleValue() &&
268 _id.isSymbolicConstant() &&
269 _id.getName().getString().size() == 0)
270 {
271 // We have a standalone symbolic constant.
272 if(!isSimple() &&
273 _leftSide.isSimpleValue() &&
274 _leftSide.getTerms()[0].getFactors()[0].
275 chuck 1.2 getValue().getChainedIdentifier().getLastIdentifier().
276 getName().getString().size() > 0)
277 {
278 // We need to add context to the symbolic constant
279 _rightSide.applyContext(queryContext,
280 _leftSide.getTerms()[0].getFactors()[0].
281 getValue().getChainedIdentifier());
282 }
283 else
284 {
285 // There is no valid context for the symbolic constant
286 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.LEFT_STANDALONE_SYMCONST_ERROR",
|
287 chuck 1.3 "The left side of predicate $0 must be a simple property name because a symbolic constant exists on the right side.",
288 toString());
|
289 chuck 1.2 throw CQLSyntaxErrorException(parms);
290 }
291 }
292 else
293 {
294 // Right side is not simple OR it is a not a standalone symbolic constant
295 if (_operator != ISA)
296 {
297 // Not doing an ISA, go ahead and applyContext to right side
298 _rightSide.applyContext(queryContext);
299 }
300 else
301 {
302 // Operation is an ISA.. The right side must be simple.
303 // We don't want to applyContext to the right side because
304 // it could be a classname unrelated to the FROM class.
305 if (!_rightSide.isSimpleValue())
306 {
307 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.APPLY_CTX_RHS_ISA_NOT_SIMPLE",
|
308 chuck 1.3 "The right side expression $0 of the ISA operator must be a simple value.",
309 _rightSide.toString());
|
310 chuck 1.2 throw CQLSyntaxErrorException(parms);
311 }
|
312 chuck 1.3
313 // Add the right side identifier to the list of WHERE
314 // identifiers in the QueryContext
315 QueryChainedIdentifier isaId = _rightSide.getTerms()[0].
316 getFactors()[0].
317 getValue().getChainedIdentifier();
318 queryContext.addWhereIdentifier(isaId);
|
319 chuck 1.2 }
320 }
321 }
|
322 humberto 1.4 PEG_METHOD_EXIT();
|
323 chuck 1.2 }
324
325 String CQLSimplePredicateRep::toString()const
326 {
327 String s = _leftSide.toString();
328 if(!_isSimple){
329 switch(_operator){
330 case LT:
331 s.append(" < ");
332 break;
333 case GT:
334 s.append(" > ");
335 break;
336 case LE:
337 s.append(" <= ");
338 break;
339 case GE:
340 s.append(" >= ");
341 break;
342 case EQ:
343 s.append(" = ");
344 chuck 1.2 break;
345 case NE:
346 s.append(" != ");
347 break;
348 case IS_NULL:
349 s.append(" IS NULL ");
350 break;
351 case IS_NOT_NULL:
352 s.append(" IS NOT NULL ");
353 break;
354 case ISA:
355 s.append(" ISA ");
356 break;
357 case LIKE:
358 s.append(" LIKE ");
359 break;
360 }
361 s.append(_rightSide.toString());
362 }
363 switch(_operator){
364 case IS_NULL:
365 chuck 1.2 s.append(" IS NULL ");
366 break;
367 case IS_NOT_NULL:
368 s.append(" IS NOT NULL ");
369 break;
370 default:
371 break;
372 }
373 return s;
374 }
375 Boolean CQLSimplePredicateRep::isSimple()const{
376 return _isSimple;
377 }
378 Boolean CQLSimplePredicateRep::isSimpleValue()const{
379 return _leftSide.isSimpleValue();
380 }
381
382 void CQLSimplePredicateRep::setOperation(ExpressionOpType op){
383 _operator = op;
384 }
385
386 chuck 1.2 PEGASUS_NAMESPACE_END
|