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 david.dillard 1.6 // Modified By: David Dillard, VERITAS Software Corp.
32 // (david.dillard@veritas.com)
|
33 chuck 1.2 //
34 //%/////////////////////////////////////////////////////////////////////////////
35
36 #include <Pegasus/Common/InternalException.h>
37 #include "CQLSimplePredicate.h"
38 #include "CQLSimplePredicateRep.h"
39 //#include <Pegasus/CQL/CQLExpression.h>
40 #include <Pegasus/CQL/CQLFactory.h>
41 #include <Pegasus/Query/QueryCommon/QueryContext.h>
42 #include <Pegasus/Query/QueryCommon/QueryException.h>
|
43 humberto 1.4 #include <Pegasus/Common/Tracer.h>
|
44 chuck 1.2
45 PEGASUS_NAMESPACE_BEGIN
46
47 CQLSimplePredicateRep::CQLSimplePredicateRep(){
48 _isSimple = true;
49 }
50
51 CQLSimplePredicateRep::CQLSimplePredicateRep(const CQLExpression& inExpression)
52 {
53 _leftSide = inExpression;
54 _isSimple = true;
55 }
56
57 CQLSimplePredicateRep::CQLSimplePredicateRep(const CQLExpression& inExpression,
|
58 david.dillard 1.6 ExpressionOpType inOperator)
|
59 chuck 1.2 {
60 _leftSide = inExpression;
61 _operator = inOperator;
62 _isSimple = true;
63 }
64
65 CQLSimplePredicateRep::CQLSimplePredicateRep(const CQLExpression& leftSideExpression,
66 const CQLExpression& rightSideExpression,
67 ExpressionOpType inOperator)
68 {
69 _leftSide = leftSideExpression;
70 _rightSide = rightSideExpression;
71 _operator = inOperator;
72 _isSimple = false;
73 }
74
75 CQLSimplePredicateRep::CQLSimplePredicateRep(const CQLSimplePredicateRep* rep){
76 _leftSide = rep->_leftSide;
77 _rightSide = rep->_rightSide;
78 _operator = rep->_operator;
79 _isSimple = rep->_isSimple;
80 chuck 1.2 }
81
82 Boolean CQLSimplePredicateRep::evaluate(CIMInstance CI, QueryContext& QueryCtx)
83 {
|
84 humberto 1.4 PEG_METHOD_ENTER(TRC_CQL, "CQLSimplePredicateRep::evaluate");
|
85 chuck 1.2 // Resolve the value of the left side
86 CQLValue leftVal = _leftSide.resolveValue(CI, QueryCtx);
87
88 // If there isn't a right side then operator must by IS_NULL
89 // or IS_NOT_NULL
90 if (isSimple())
91 {
92 PEGASUS_ASSERT(_operator == IS_NULL || _operator == IS_NOT_NULL);
93
94 return (_operator == IS_NULL) ? leftVal.isNull() : !leftVal.isNull();
95 }
96
97 PEGASUS_ASSERT(_operator != IS_NULL && _operator != IS_NOT_NULL);
98
99 if (leftVal.isNull())
100 {
101 // The null contagion rule. See CQLSelectStatementRep for details.
102 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.NULL_CONTAGION",
103 "The expression evaluates to NULL.");
104 throw CQLNullContagionException(parms);
105 }
106 chuck 1.2
107 if (_operator == ISA)
108 {
109 // Special processing for ISA. The CQLValue on the right side of ISA
110 // has a CQLChainedIdentifier with one element that contains
111 // the class name. We don't want to resolve the right side because
112 // CQLValue would assume that a single element chained identifier
113 // refers to an instance of the FROM class.
114 if (!_rightSide.isSimpleValue())
115 {
116 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.RHS_ISA_NOT_SIMPLE",
|
117 chuck 1.3 "The expression $0 on the right side of the ISA operator must be a simple value.",
118 _rightSide.toString());
|
119 chuck 1.2 throw CQLRuntimeException(parms);
120 }
121
122 CQLValue isaRightVal = _rightSide.getTerms()[0].getFactors()[0].getValue();
123 CQLChainedIdentifier isaRightId = isaRightVal.getChainedIdentifier();
124 return leftVal.isa(isaRightId, QueryCtx);
125 }
126
127 if (_operator == LIKE)
128 {
129 // Special processing for LIKE. The right side expression must be
130 // a simple CQLValue (ie. not nested, and not a function), and
131 // must be a literal. Note that this code will test whether
132 // the right side is a literal, but not whether it is a string
133 // literal.
134 if (!_rightSide.isSimpleValue())
135 {
136 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.RHS_LIKE_NOT_SIMPLE",
|
137 chuck 1.3 "The expression $0 on the right side of the LIKE operator must be a simple value.",
138 _rightSide.toString());
|
139 chuck 1.2 throw CQLRuntimeException(parms);
140 }
141
142 CQLValue likeRightVal = _rightSide.getTerms()[0].getFactors()[0].getValue();
143 if (!likeRightVal.isResolved())
144 {
145 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.RHS_LIKE_NOT_LITERAL",
|
146 chuck 1.3 "The expression $0 on the right side of the LIKE operator must be a literal.",
147 _rightSide.toString());
|
148 chuck 1.2 throw CQLRuntimeException(parms);
149 }
150
151 return leftVal.like(likeRightVal);
152 }
153
154 // No special processing needed.
155 // Resolve the value of the right side
156 CQLValue rightVal = _rightSide.resolveValue(CI, QueryCtx);
157
|
158 lucier 1.5 // printf("Left Value - %s, Right value - %s\n", (const char *)leftVal.toString().getCString(), (const char *)rightVal.toString().getCString());
159
|
160 chuck 1.2 if (rightVal.isNull())
161 {
162 // The null contagion rule. See CQLSelectStatementRep for details.
163 // ATTN - change this to a specific CQLException so that it can
164 // be caught above
165 // The null contagion rule. See CQLSelectStatementRep for details.
166 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.NULL_CONTAGION",
167 "The expression evaluates to NULL.");
168 throw CQLNullContagionException(parms);
169 }
170
171 switch(_operator)
172 {
173 case LT:
174 return leftVal < rightVal;
175 break;
176
177 case GT:
178 return leftVal > rightVal;
179 break;
180
181 chuck 1.2 case LE:
182 return leftVal <= rightVal;
183 break;
184
185 case GE:
186 return leftVal >= rightVal;
187 break;
188
189 case EQ:
190 return leftVal == rightVal;
191 break;
192
193 case NE:
194 return leftVal != rightVal;
195 break;
196
197 case LIKE:
198 case ISA:
199 // Never get here due to special processing above.
200 PEGASUS_ASSERT(false);
201 case IS_NULL:
202 chuck 1.2 case IS_NOT_NULL:
203 // Never get here due to the assert.
204 break;
205 }
|
206 humberto 1.4 PEG_METHOD_EXIT();
|
207 chuck 1.2 return true; // keep the compiler happy
208 }
209
210 CQLExpression CQLSimplePredicateRep::getLeftExpression()const
211 {
212 return _leftSide;
213 }
214
215 CQLExpression CQLSimplePredicateRep::getRightExpression()const
216 {
217 return _rightSide;
218 }
219
220 enum ExpressionOpType CQLSimplePredicateRep::getOperation()const
221 {
222 return _operator;
223 }
224
225 void CQLSimplePredicateRep::applyContext(QueryContext& queryContext)
226 {
|
227 humberto 1.4 PEG_METHOD_ENTER(TRC_CQL, "CQLSimplePredicateRep::applyContext");
|
228 chuck 1.2 CQLIdentifier _id;
229
230 _id = _leftSide.getTerms()[0].getFactors()[0].
231 getValue().getChainedIdentifier().getLastIdentifier();
232
233 if(_leftSide.isSimpleValue() &&
234 _id.isSymbolicConstant() &&
235 _id.getName().getString().size() == 0)
236 {
237 // We have a standalone symbolic constant.
238 if(!isSimple() &&
239 _rightSide.isSimpleValue() &&
240 _rightSide.getTerms()[0].getFactors()[0].
241 getValue().getChainedIdentifier().getLastIdentifier().
242 getName().getString().size() > 0)
243 {
244 _rightSide.applyContext(queryContext);
245
246 // We need to add context to the symbolic constant
247 _leftSide.applyContext(queryContext,
248 _rightSide.getTerms()[0].getFactors()[0].
249 chuck 1.2 getValue().getChainedIdentifier());
250 }
251 else
252 {
253 // There is no valid context for the symbolic constant
254 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.RIGHT_STANDALONE_SYMCONST_ERROR",
|
255 chuck 1.3 "The right side of predicate $0 must be a simple property name because a symbolic constant exists on the left side.",
256 toString());
|
257 chuck 1.2 throw CQLSyntaxErrorException(parms);
258 }
259 }
260 else
261 {
262 _leftSide.applyContext(queryContext);
263 }
264
265 if (!isSimple())
266 {
267 _id = _rightSide.getTerms()[0].getFactors()[0].
268 getValue().getChainedIdentifier().getLastIdentifier();
269
270 if(_rightSide.isSimpleValue() &&
271 _id.isSymbolicConstant() &&
272 _id.getName().getString().size() == 0)
273 {
274 // We have a standalone symbolic constant.
275 if(!isSimple() &&
276 _leftSide.isSimpleValue() &&
277 _leftSide.getTerms()[0].getFactors()[0].
278 chuck 1.2 getValue().getChainedIdentifier().getLastIdentifier().
279 getName().getString().size() > 0)
280 {
281 // We need to add context to the symbolic constant
282 _rightSide.applyContext(queryContext,
283 _leftSide.getTerms()[0].getFactors()[0].
284 getValue().getChainedIdentifier());
285 }
286 else
287 {
288 // There is no valid context for the symbolic constant
289 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.LEFT_STANDALONE_SYMCONST_ERROR",
|
290 chuck 1.3 "The left side of predicate $0 must be a simple property name because a symbolic constant exists on the right side.",
291 toString());
|
292 chuck 1.2 throw CQLSyntaxErrorException(parms);
293 }
294 }
295 else
296 {
297 // Right side is not simple OR it is a not a standalone symbolic constant
298 if (_operator != ISA)
299 {
300 // Not doing an ISA, go ahead and applyContext to right side
301 _rightSide.applyContext(queryContext);
302 }
303 else
304 {
305 // Operation is an ISA.. The right side must be simple.
306 // We don't want to applyContext to the right side because
307 // it could be a classname unrelated to the FROM class.
308 if (!_rightSide.isSimpleValue())
309 {
310 MessageLoaderParms parms("CQL.CQLSimplePredicateRep.APPLY_CTX_RHS_ISA_NOT_SIMPLE",
|
311 chuck 1.3 "The right side expression $0 of the ISA operator must be a simple value.",
312 _rightSide.toString());
|
313 chuck 1.2 throw CQLSyntaxErrorException(parms);
314 }
|
315 chuck 1.3
316 // Add the right side identifier to the list of WHERE
317 // identifiers in the QueryContext
318 QueryChainedIdentifier isaId = _rightSide.getTerms()[0].
319 getFactors()[0].
320 getValue().getChainedIdentifier();
321 queryContext.addWhereIdentifier(isaId);
|
322 chuck 1.2 }
323 }
324 }
|
325 humberto 1.4 PEG_METHOD_EXIT();
|
326 chuck 1.2 }
327
328 String CQLSimplePredicateRep::toString()const
329 {
330 String s = _leftSide.toString();
331 if(!_isSimple){
332 switch(_operator){
333 case LT:
334 s.append(" < ");
335 break;
336 case GT:
337 s.append(" > ");
338 break;
339 case LE:
340 s.append(" <= ");
341 break;
342 case GE:
343 s.append(" >= ");
344 break;
345 case EQ:
346 s.append(" = ");
347 chuck 1.2 break;
348 case NE:
349 s.append(" != ");
350 break;
351 case IS_NULL:
352 s.append(" IS NULL ");
353 break;
354 case IS_NOT_NULL:
355 s.append(" IS NOT NULL ");
356 break;
357 case ISA:
358 s.append(" ISA ");
359 break;
360 case LIKE:
361 s.append(" LIKE ");
362 break;
363 }
364 s.append(_rightSide.toString());
365 }
366 switch(_operator){
367 case IS_NULL:
368 chuck 1.2 s.append(" IS NULL ");
369 break;
370 case IS_NOT_NULL:
371 s.append(" IS NOT NULL ");
372 break;
373 default:
374 break;
375 }
376 return s;
377 }
378 Boolean CQLSimplePredicateRep::isSimple()const{
379 return _isSimple;
380 }
381 Boolean CQLSimplePredicateRep::isSimpleValue()const{
382 return _leftSide.isSimpleValue();
383 }
384
385 void CQLSimplePredicateRep::setOperation(ExpressionOpType op){
386 _operator = op;
387 }
388
389 chuck 1.2 PEGASUS_NAMESPACE_END
|