1 karl 1.15 //%2006////////////////////////////////////////////////////////////////////////
|
2 chuck 1.2 //
|
3 karl 1.9 // 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 chuck 1.2 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.9 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.15 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 chuck 1.2 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
|
20 karl 1.15 //
|
21 chuck 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 // Authors: David Rosckes (rosckes@us.ibm.com)
33 // Bert Rivero (hurivero@us.ibm.com)
34 // Chuck Carmack (carmack@us.ibm.com)
35 // Brian Lucier (lucier@us.ibm.com)
36 //
|
37 david.dillard 1.11 // Modified By: David Dillard, VERITAS Software Corp.
38 // (david.dillard@veritas.com)
|
39 chuck 1.2 //
40 //%/////////////////////////////////////////////////////////////////////////////
41
42 #include "CQLSelectStatement.h"
43 #include "CQLSelectStatementRep.h"
44
45 #include <Pegasus/Common/CIMValue.h>
46 #include <Pegasus/Common/CIMInstance.h>
47 #include <Pegasus/Common/CIMProperty.h>
48 #include <Pegasus/Query/QueryCommon/QueryException.h>
49 #include <Pegasus/Query/QueryCommon/QueryIdentifier.h>
50 #include <Pegasus/Query/QueryCommon/QueryChainedIdentifier.h>
|
51 chuck 1.3 #include <Pegasus/Common/Tracer.h>
|
52 chuck 1.2 #include <Pegasus/Common/InternalException.h>
53 #include <Pegasus/Common/CIMStatusCode.h>
54 #include <Pegasus/Common/AutoPtr.h>
55 #include "CQLValue.h"
56 #include "CQLIdentifier.h"
57 #include "CQLChainedIdentifier.h"
58 #include "Cql2Dnf.h"
59
|
60 david.dillard 1.11 // ATTN: TODOs -
|
61 chuck 1.2 // optimize
62 // documentation
63
64 PEGASUS_NAMESPACE_BEGIN
65
66 struct PropertyNode
67 {
68 CIMName name; // property name
69 CIMName scope; // class the property is on
|
70 david.dillard 1.11 Boolean wildcard; // true if this property is wildcarded
|
71 chuck 1.3 Boolean endpoint; // true if this property is an endpoint
72 // of a chained identifier
|
73 chuck 1.2 AutoPtr<PropertyNode> sibling;
74 AutoPtr<PropertyNode> firstChild;
75
|
76 chuck 1.8 PropertyNode()
77 : wildcard(false),
78 endpoint(false),
79 sibling(NULL),
80 firstChild(NULL)
81 {}
82
83 ~PropertyNode() {}
|
84 chuck 1.2 };
85
86
87 CQLSelectStatementRep::CQLSelectStatementRep()
88 :SelectStatementRep(),
89 _hasWhereClause(false),
90 _contextApplied(false)
91 {
|
92 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep()");
|
93 chuck 1.8 PEG_METHOD_EXIT();
|
94 chuck 1.2 }
95
96 CQLSelectStatementRep::CQLSelectStatementRep(String& inQlang,
97 String& inQuery,
98 QueryContext& inCtx)
99 :SelectStatementRep(inQlang, inQuery, inCtx),
100 _hasWhereClause(false),
101 _contextApplied(false)
102 {
|
103 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep(inQlang,inQuery,inCtx)");
|
104 chuck 1.8 PEG_METHOD_EXIT();
|
105 chuck 1.2 }
106
107 CQLSelectStatementRep::CQLSelectStatementRep(String& inQlang,
108 String& inQuery)
|
109 david.dillard 1.11
|
110 chuck 1.2 :SelectStatementRep(inQlang, inQuery),
111 _hasWhereClause(false),
112 _contextApplied(false)
113 {
|
114 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep(inQlang,inQuery)");
|
115 chuck 1.8 PEG_METHOD_EXIT();
|
116 chuck 1.2 }
117
118 CQLSelectStatementRep::CQLSelectStatementRep(const CQLSelectStatementRep& rep)
119 :SelectStatementRep(rep),
120 _selectIdentifiers(rep._selectIdentifiers),
121 _hasWhereClause(rep._hasWhereClause),
122 _predicate(rep._predicate),
123 _contextApplied(rep._contextApplied)
124 {
|
125 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep(rep)");
|
126 chuck 1.8 PEG_METHOD_EXIT();
|
127 chuck 1.2 }
128
129 CQLSelectStatementRep::~CQLSelectStatementRep()
130 {
|
131 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "~CQLSelectStatementRep()");
|
132 chuck 1.8 PEG_METHOD_EXIT();
|
133 chuck 1.2 }
134
135 CQLSelectStatementRep& CQLSelectStatementRep::operator=(const CQLSelectStatementRep& rhs)
136 {
|
137 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::operator=");
138
|
139 chuck 1.2 if (this == &rhs)
|
140 chuck 1.3 {
141 PEG_METHOD_EXIT();
|
142 chuck 1.2 return *this;
|
143 chuck 1.3 }
|
144 chuck 1.2
145 SelectStatementRep::operator=(rhs);
146
147 _selectIdentifiers = rhs._selectIdentifiers;
148 _predicate = rhs._predicate;
149 _contextApplied = rhs._contextApplied;
150 _hasWhereClause = rhs._hasWhereClause;
151
|
152 chuck 1.3 PEG_METHOD_EXIT();
|
153 chuck 1.2 return *this;
154 }
155
|
156 chuck 1.3 Boolean CQLSelectStatementRep::evaluate(const CIMInstance& inCI)
|
157 chuck 1.2 {
|
158 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::evaluate");
|
159 chuck 1.2
|
160 chuck 1.3 if(_ctx == NULL)
161 {
162 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"QC not set");
163 PEG_METHOD_EXIT();
|
164 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
165 "Trying to process a query with a NULL Query Context.");
166 throw CQLRuntimeException(parms);
167 }
|
168 chuck 1.3
|
169 chuck 1.7 // Apply to class contexts to the identifiers.
170 // This will check for a well-formed statement.
171 if (!_contextApplied)
172 applyContext();
173
174 // Make sure the type of instance passed in is the FROM class,
175 // or a subclass of the FROM class.
176 if (!isFromChild(inCI.getClassName()))
177 {
|
178 chuck 1.8 PEG_METHOD_EXIT();
|
179 chuck 1.7 return false;
180 }
181
|
182 chuck 1.2 if (!hasWhereClause())
183 {
|
184 chuck 1.3 PEG_METHOD_EXIT();
|
185 chuck 1.2 return true;
186 }
187 else
188 {
189 try
190 {
|
191 chuck 1.3 PEG_METHOD_EXIT();
|
192 chuck 1.2 return _predicate.evaluate(inCI, *_ctx);
193 }
194 catch (CQLNullContagionException& )
195 {
196 // The null contagion rule.
|
197 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null contagion");
198 PEG_METHOD_EXIT();
|
199 chuck 1.2 return false;
200 }
201 }
|
202 chuck 1.3
|
203 carson.hovey 1.10 PEGASUS_UNREACHABLE( PEGASUS_ASSERT(false); )
204 PEGASUS_UNREACHABLE( PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"should not get here in evaluate"); )
205 PEGASUS_UNREACHABLE( return true; ) //should never get here
|
206 chuck 1.2 }
207
|
208 carolann.graves 1.12 void CQLSelectStatementRep::applyProjection(CIMInstance& inCI,
|
209 david.dillard 1.13 Boolean allowMissing)
|
210 chuck 1.2 {
|
211 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::applyProjection(inCI)");
212
213 if(_ctx == NULL)
214 {
215 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"QC not set");
216 PEG_METHOD_EXIT();
|
217 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
218 "Trying to process a query with a NULL Query Context.");
219 throw CQLRuntimeException(parms);
220 }
221
|
222 chuck 1.7 // Apply to class contexts to the identifiers.
223 // This will check for a well-formed statement.
|
224 chuck 1.2 if (!_contextApplied)
225 applyContext();
226
227 //
228 // Build a tree to represent the projected properties from the select list
|
229 david.dillard 1.11 // of chained identifiers. This is needed because embedded instances below
|
230 chuck 1.2 // the FROM class form a tree structure when projected.
231 //
|
232 david.dillard 1.11 // The design of the tree is to gather all the required properties for
233 // an instance at a node as child nodes. The root node
234 // of the tree represents the instance passed in to this function. Below the
235 // root there can be nodes that are required embedded instance properties.
|
236 chuck 1.2 // The child nodes of these embedded instance nodes represent the required
237 // properties on the embedded instance (which may themselves be embedded instances).
238 //
|
239 david.dillard 1.11 // Each node has a name, which is in 2 parts -- the property name and the
|
240 chuck 1.2 // scope (ie. the class the property is on). This allows the scoping
241 // operator to be handled correctly, so that the parent instance can be
242 // checked to see if it is the right class to provide the property.
243 // Note that the scoping is a base class; ie. the parent instance of a node
244 // may be a subclass of the scope.
245 //
246
247 // Set up the root node of the tree. This represents the instance
248 // passed in.
249 AutoPtr<PropertyNode> rootNode(new PropertyNode);
250 Array<QueryIdentifier> fromList = _ctx->getFromList();
251 rootNode->name = fromList[0].getName(); // not doing joins
252 rootNode->scope = fromList[0].getName(); // not used on root, just to fill in the var
253 rootNode->wildcard = false;
|
254 david.dillard 1.11
|
255 chuck 1.2 // Build the tree below the root.
256 for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
257 {
|
258 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"select chained id = " +
259 _selectIdentifiers[i].toString());
260
|
261 chuck 1.2 // Get the chain elements
262 Array<CQLIdentifier> ids = _selectIdentifiers[i].getSubIdentifiers();
263
264 PEGASUS_ASSERT(ids.size() > 1);
265
266 PropertyNode * curNode = rootNode.get();
267 PropertyNode * curChild = curNode->firstChild.get();
268
269 // Loop through the identifiers in the chain.
270 // NOTE: this starts at the position *after* the FROM class
271 // So, the loop index is always one position after the current node,
272 // ie. it will become a child node of the current node.
273 for (Uint32 j = 1; j < ids.size(); j++)
274 {
|
275 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"curNode = " + curNode->name.getString());
276 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"id = " + ids[j].toString());
277
|
278 chuck 1.2 // If the child is wildcarded, then every property exposed by the
279 // class of the instance at the current node is required.
280 // Mark the current node as wildcarded.
281 if (ids[j].isWildcard())
282 {
|
283 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"id is wildcard");
|
284 chuck 1.2 curNode->wildcard = true;
285 break;
286 }
287
288 // Determine if this identifier is already a child node of
289 // the current node.
290 Boolean found = false;
291 while (curChild != NULL && !found)
292 {
293 // The scoping class is either the scope of the identifier
294 // or the FROM class if the identifier is not scoped.
295 String scope = fromList[0].getName().getString();
296 if (ids[j].isScoped())
297 {
298 scope = ids[j].getScope();
299 }
300
|
301 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"scope to compare = " + scope);
302
|
303 chuck 1.2 if (curChild->name == ids[j].getName() &&
304 String::equalNoCase(curChild->scope.getString(), scope))
305 {
|
306 chuck 1.3 // Name and scope match. The identifier is already child node.
307 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"id is already a child node");
|
308 chuck 1.2 found = true;
309 }
310 else
311 {
312 curChild = curChild->sibling.get();
313 }
314 }
315
316 if (!found)
317 {
|
318 david.dillard 1.11 // The identifier is not already a child node.
|
319 chuck 1.2 // Create a node and add it as a child to the current node.
|
320 david.dillard 1.11 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"new child" +
|
321 chuck 1.3 ids[j].getName().getString());
|
322 chuck 1.2 curChild = new PropertyNode;
|
323 chuck 1.6 curChild->sibling.reset(curNode->firstChild.release());
|
324 chuck 1.2 curChild->name = ids[j].getName();
325 curChild->wildcard = false;
|
326 chuck 1.3 curChild->endpoint = false;
|
327 chuck 1.2 curNode->firstChild.reset(curChild); // safer than using the = operator
328 }
329
330 // Set the scope for the child node
331 if (ids[j].isScoped())
332 {
333 // Child node has a scoping class
334 PEGASUS_ASSERT(ids[j].getScope().size() > 0);
|
335 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"child set with scoping class: " +
336 ids[j].getScope());
|
337 chuck 1.2 curChild->scope = CIMName(ids[j].getScope());
338 }
339 else
340 {
341 // Not scoped. The scope is the FROM class.
342 PEGASUS_ASSERT(j == 1);
343 PEGASUS_ASSERT(fromList[0].getName().getString().size() > 0);
|
344 david.dillard 1.11 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"child set with scoping class: " +
|
345 chuck 1.3 fromList[0].getName().getString());
|
346 chuck 1.2 curChild->scope = fromList[0].getName();
347 }
348
|
349 david.dillard 1.11 // If the identifier is the last element of the chain,
|
350 chuck 1.3 // then mark it as an endpoint
351 if ((ids.size() - 1) == j)
352 {
353 curChild->endpoint = true;
354 }
355
|
356 chuck 1.2 curNode = curChild;
357 curChild = curNode->firstChild.get();
358 }
359 }
360
361 //
362 // Do the projection.
363 //
364
365 Array<CIMName> requiredProps;
366 Boolean allPropsRequired = rootNode->wildcard;
367
368 // Loop through the children of the root node.
369 // The root node represents the FROM class,
370 // and the child nodes are the required properties on the FROM class.
371 PropertyNode* childNode = rootNode->firstChild.get();
372 while (childNode != NULL)
373 {
|
374 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"project childNode = " + childNode->name.getString());
375
|
376 chuck 1.2 // Determine if the instance passed in meets the class scoping
377 // rules for the current child node.
378 Boolean filterable = isFilterable(inCI, childNode);
379
|
380 chuck 1.3 // Indicates if the child node is still required after the recursive call.
381 Boolean childRequired = true;
382
|
383 chuck 1.2 // If the instance is filterable, and the child node has children,
384 // or is wildcarded, then the child is assumed to be an embedded instance,
385 // and we need to recurse to apply the projection on the embedded instance.
386 // (the check for embedded instance is done in the recursive call)
|
387 david.dillard 1.11 if (filterable &&
|
388 chuck 1.2 (childNode->firstChild.get() != NULL || childNode->wildcard))
389 {
390 // We need to project on an embedded instance property. The steps are to
391 // remove the embedded instance property from the instance passed in,
|
392 david.dillard 1.11 // project on that embedded instance property, and then add the projected
|
393 chuck 1.2 // embedded instance property back to the instance passed in.
|
394 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"about to recurse: " + childNode->name.getString());
|
395 chuck 1.2 Uint32 index = inCI.findProperty(childNode->name);
396 if (index != PEG_NOT_FOUND)
397 {
|
398 chuck 1.3 // The instance passed in has the required embedded instance property.
399 // Note: embedded instance property missing is caught below.
400
401 // Remove the embedded instance property
|
402 chuck 1.2 CIMProperty childProp = inCI.getProperty(index);
403 inCI.removeProperty(index);
|
404 chuck 1.3
|
405 david.dillard 1.11 // Project onto the embedded instance property.
|
406 chuck 1.3 // If the last parameter is true, then the childNode
407 // will not remove properties when filtering the embedded instance.
408 // This call returns whether the embedded instance property
409 // should be added to the required property list.
|
410 carolann.graves 1.12 childRequired = applyProjection(childNode, childProp, allPropsRequired,
411 allowMissing);
|
412 chuck 1.2 inCI.addProperty(childProp);
413 }
414 }
415
|
416 david.dillard 1.11 // If the instance passed in is filterable,
|
417 chuck 1.8 // then add the current child to the list if it is still required.
418 if (filterable && childRequired)
|
419 chuck 1.2 {
|
420 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"add req prop: " + childNode->name.getString());
|
421 chuck 1.2 requiredProps.append(childNode->name);
422 }
423
424 childNode = childNode->sibling.get();
425 }
426
427 // Remove the properties that are not in the projection.
428 // This also checks for missing required properties.
|
429 chuck 1.3 Boolean preserve = false;
430 filterInstance(inCI,
431 allPropsRequired,
432 fromList[0].getName(),
433 requiredProps,
|
434 carolann.graves 1.12 preserve,
435 allowMissing);
|
436 chuck 1.2 }
437
|
438 chuck 1.3 Boolean CQLSelectStatementRep::applyProjection(PropertyNode* node,
439 CIMProperty& nodeProp,
|
440 carolann.graves 1.12 Boolean& preservePropsForParent,
441 Boolean allowMissing)
|
442 chuck 1.2 {
|
443 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::applyProjection(node, nodeProp)");
444
445 PEGASUS_ASSERT(node->firstChild.get() != NULL || node->wildcard);
|
446 chuck 1.2
447 //
448 // The property passed in must be an embedded instance. It is not
449 // allowed to project properties on embedded classes.
450 // Get the embedded instance from the property.
451 //
452
|
453 chuck 1.3 // First check that it is an embedded object
|
454 chuck 1.2 CIMValue nodeVal = nodeProp.getValue();
|
455 a.dunfey 1.16 CIMType nodeValType = nodeVal.getType();
456 if (nodeValType != CIMTYPE_OBJECT
457 #ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
458 && nodeValType != CIMTYPE_INSTANCE
459 #endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT
460 )
|
461 chuck 1.2 {
|
462 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"not emb");
463 PEG_METHOD_EXIT();
|
464 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROP_NOT_EMB",
465 "The property $0 must contain an embedded object.",
466 nodeProp.getName().getString());
467 throw CQLRuntimeException(parms);
468 }
|
469 chuck 1.3
470 if (nodeVal.isNull())
471 {
472 // Since we will be projecting on the embedded object, it cannot be null
473 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"value is null");
474 PEG_METHOD_EXIT();
475 MessageLoaderParms parms("CQL.CQLSelectStatementRep.NULL_EMB_OBJ",
476 "The embedded object property $0 cannot contain a null value.",
477 nodeProp.getName().getString());
478 throw CQLRuntimeException(parms);
479 }
|
480 chuck 1.2
|
481 david.dillard 1.11 if (nodeVal.isArray() &&
|
482 chuck 1.2 (node->firstChild.get() != NULL || node->wildcard))
483 {
484 // NOTE - since we are blocking projection of array elements, we can
485 // assume that if we get here we were told to project a whole array (ie. no index used), as
486 // an embedded object with properties or wildcard.
487 // Examples not allowed: SELECT fromClass.someArrayProp.scope::notAllowedProp FROM fromClass
488 // SELECT fromClass.someArrayProp.* FROM fromClass
|
489 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"array index needed");
490 PEG_METHOD_EXIT();
|
491 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROJ_WHOLE_ARRAY",
|
492 chuck 1.3 "CQL requires that array indexing is used on embedded object property $0.",
493 nodeProp.getName().getString());
494 throw CQLRuntimeException(parms);
495 }
496
497 CIMObject nodeObj; // this starts uninitialized
|
498 a.dunfey 1.16 CIMInstance nodeInst;
499 #ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
500 if(nodeValType == CIMTYPE_OBJECT)
501 {
502 #endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT
|
503 chuck 1.3 nodeVal.get(nodeObj);
504 if (nodeObj.isUninitialized())
505 {
506 // Not allowed to project on an uninitialized object
507 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"is uninitialized");
508 PEG_METHOD_EXIT();
509 MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROJ_UNINIT",
510 "The embedded object property $0 is uninitialized.",
|
511 chuck 1.2 nodeProp.getName().getString());
512 throw CQLRuntimeException(parms);
513 }
514
515 if (!nodeObj.isInstance())
516 {
517 // Not allowed to project on a Class
|
518 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"is a class");
519 PEG_METHOD_EXIT();
|
520 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROJ_CLASS",
521 "CQL does not allow properties to be projected on class $0.",
522 nodeProp.getName().getString());
523 throw CQLRuntimeException(parms);
524 }
|
525 a.dunfey 1.16 nodeInst = CIMInstance(nodeObj);
526 #ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
527 }
|
528 chuck 1.2
|
529 a.dunfey 1.16 else if(nodeValType == CIMTYPE_INSTANCE)
530 {
531 nodeVal.get(nodeInst);
532 if (nodeInst.isUninitialized())
533 {
534 // Not allowed to project on an uninitialized object
535 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"is uninitialized");
536 PEG_METHOD_EXIT();
537 MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROJ_UNINIT",
538 "The embedded object property $0 is uninitialized.",
539 nodeProp.getName().getString());
540 throw CQLRuntimeException(parms);
541 }
542 }
543 #endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT
|
544 chuck 1.2 //
545 // Do the projection.
546 //
547
548 Array<CIMName> requiredProps;
549 Boolean allPropsRequired = node->wildcard;
550
551 // Loop through the children of the node.
552 // The node represents an embedded instance,
553 // and the child nodes are the required properties on the embedded instance.
554 PropertyNode * curChild = node->firstChild.get();
555 while (curChild != NULL)
556 {
|
557 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"project childNode = " + curChild->name.getString());
558
|
559 chuck 1.2 // Determine if the embedded instance meets the class scoping
560 // rules for the current child node
561 Boolean filterable = isFilterable(nodeInst, curChild);
562
|
563 chuck 1.3 // Indicates if the child node is still required after the recursive call.
564 Boolean childRequired = true;
565
|
566 chuck 1.2 // If the embedded instance is filterable, and the child node has children,
567 // or is wildcarded, then the child is assumed to be an embedded instance,
568 // and we need to recurse to apply the projection on the embedded instance.
569 // (the check for embedded instance is done in the recursive call)
|
570 david.dillard 1.11 if (filterable &&
|
571 chuck 1.2 (curChild->firstChild.get() != NULL || curChild->wildcard))
572 {
573 // We need to project on an embedded instance property. The steps are to
574 // remove the embedded instance property from the current instance,
|
575 david.dillard 1.11 // project on that embedded instance property, and then add the projected
|
576 chuck 1.2 // embedded instance property back to the current instance.
|
577 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"about to recurse: " + curChild->name.getString());
|
578 chuck 1.2 Uint32 index = nodeInst.findProperty(curChild->name);
579 if (index != PEG_NOT_FOUND)
580 {
|
581 chuck 1.3 // The current instance has the required embedded instance property.
582 // Note: embedded instance property missing is caught below.
583
584 // Remove the embedded instance property
|
585 david.dillard 1.11 CIMProperty childProp = nodeInst.getProperty(index);
|
586 chuck 1.2 nodeInst.removeProperty(index);
|
587 chuck 1.3
|
588 david.dillard 1.11 // Project onto the embedded instance property.
|
589 chuck 1.3 // If the last parameter is true, then the childNode
590 // will not remove properties when filtering the embedded instance.
591 // This call returns whether the embedded instance property
592 // should be added to the required property list.
|
593 david.dillard 1.11 Boolean preserve =
|
594 chuck 1.3 node->endpoint || allPropsRequired || preservePropsForParent;
|
595 carolann.graves 1.12 childRequired = applyProjection(curChild, childProp, preserve,
596 allowMissing);
|
597 chuck 1.2 nodeInst.addProperty(childProp);
598 }
599 }
600
|
601 david.dillard 1.11 // If the embedded instance is filterable,
|
602 chuck 1.8 // then add the current child to the list if it is still required.
603 if (filterable && childRequired)
|
604 chuck 1.2 {
|
605 david.dillard 1.11 // The instance is filterable, add the property to the required list.
|
606 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"add req prop: " + curChild->name.getString());
607 requiredProps.append(curChild->name);
|
608 chuck 1.2 }
609
610 curChild = curChild->sibling.get();
611 }
612
|
613 chuck 1.3 // Filter the instance.
614 // This removes unneeded properties, unless this
615 // embedded instance node was an endpoint (last element)
616 // in a chained identifier.
617 // This also checks for missing required properties on the instance.
618 Boolean preserveProps = node->endpoint || preservePropsForParent;
|
619 david.dillard 1.11 filterInstance(nodeInst,
|
620 chuck 1.3 allPropsRequired,
621 nodeInst.getClassName(),
622 requiredProps,
|
623 carolann.graves 1.12 preserveProps,
624 allowMissing);
|
625 chuck 1.2
626 // Put the projected instance back into the property.
|
627 a.dunfey 1.16 #ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
628 if(nodeValType == CIMTYPE_INSTANCE)
629 {
630 nodeProp.setValue(nodeInst);
631 }
632 else
633 #endif
634 {
|
635 chuck 1.3 CIMObject newNodeObj(nodeInst);
636 CIMValue newNodeVal(newNodeObj);
637 nodeProp.setValue(newNodeVal);
|
638 a.dunfey 1.16 }
|
639 chuck 1.3
640 // Indicate to the caller whether the projected instance
641 // is still a required property. It is required if it is an endpoint
642 // (ie. the last element of a chained identifier)
643 // OR if it still has properties after being projected
644 if (node->endpoint || nodeInst.getPropertyCount() > 0)
645 {
646 return true;
647 }
648
649 return false;
|
650 david.dillard 1.11 }
|
651 chuck 1.2
652 Boolean CQLSelectStatementRep::isFilterable(const CIMInstance& inst,
653 PropertyNode* node)
654 {
|
655 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::isFilterable");
|
656 david.dillard 1.11 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"instance = " + inst.getClassName().getString());
657 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"scope = " + node->scope.getString());
|
658 chuck 1.3
|
659 chuck 1.2 //
660 // Determine if an instance is filterable for a scoped property (ie. its
661 // type is the scoping class or a subclass of the scoping class where the
662 // property exists)
663 //
664 // Note that an instance that is unfilterable is not considered
665 // an error. In CQL, an instance that is not of the required scope
|
666 david.dillard 1.11 // would cause a NULL to be placed in the result set column for the
|
667 chuck 1.2 // property. However since we are not implementing result set in stage1,
668 // just skip the property. This can lead to an instance having
669 // NO required properties even though it is derived from the FROM class.
670 // This can easily happen if the scoping operator is used.
671 //
672
673 Boolean filterable = false;
674 if (inst.getClassName() == node->scope)
675 {
676 // The instance's class is the same as the required scope
|
677 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"instance matches scope");
|
678 chuck 1.2 filterable = true;
679 }
680 else
681 {
|
682 david.dillard 1.11 try
|
683 chuck 1.2 {
684 if (_ctx->isSubClass(node->scope, inst.getClassName()))
685 {
686 // The instance's class is a subclass of the required scope.
|
687 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"instance is subclass of scope");
|
688 chuck 1.2 filterable = true;
689 }
690 }
|
691 david.dillard 1.11 catch (const CIMException& ce)
|
692 chuck 1.2 {
|
693 david.dillard 1.11 if (ce.getCode() == CIM_ERR_INVALID_CLASS ||
|
694 chuck 1.2 ce.getCode() == CIM_ERR_NOT_FOUND)
695 {
696 // The scoping class was not found in the schema.
697 // Just swallow this error because according to the
698 // spec we should be putting NULL in the result column,
699 // which means skipping the property on the instance.
|
700 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"scope class not in schema");
701 }
702 else
703 {
704 PEG_METHOD_EXIT();
|
705 david.dillard 1.11 throw;
|
706 chuck 1.2 }
707 }
708 }
|
709 david.dillard 1.11
|
710 chuck 1.3 PEG_METHOD_EXIT();
|
711 chuck 1.2 return filterable;
|
712 david.dillard 1.11 }
|
713 chuck 1.2
|
714 david.dillard 1.11 void CQLSelectStatementRep::filterInstance(CIMInstance& inst,
|
715 chuck 1.3 Boolean& allPropsRequired,
716 const CIMName& allPropsClass,
717 Array<CIMName>& requiredProps,
|
718 carolann.graves 1.12 Boolean& preserveProps,
719 Boolean allowMissing)
|
720 chuck 1.3 {
|
721 carolann.graves 1.12 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::filterInstance");
|
722 david.dillard 1.11 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"instance = " + inst.getClassName().getString());
723 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"allPropsClass = " + allPropsClass.getString());
|
724 chuck 1.3
|
725 chuck 1.2 // Implementation note:
726 // Scoping operator before a wildcard is not allowed:
727 // Example:
728 // SELECT fromclass.embobj1.scope1::* FROM fromclass
729 //
730 // However, the following are allowed:
731 // SELECT fromclass.embobj1.* FROM fromclass
732 // (this means that all the properties on the class of instance embobj1
733 // are required)
734 //
735 // SELECT fromclass.* FROM fromclass
736 // (this means that all the properties on class fromclass are required
737 // to be on the instance being projected, not including any
738 // properties on a subclass of fromclass)
739
|
740 david.dillard 1.11 // If all properties are required (ie. wildcarded), then add
|
741 chuck 1.8 // all the properties of allPropsClass to the required list.
742 // The allPropsClass is either the FROM class or the class of an embedded instance.
|
743 chuck 1.2 if (allPropsRequired)
744 {
|
745 david.dillard 1.11 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"all props required");
|
746 chuck 1.2 CIMClass cls = _ctx->getClass(allPropsClass);
747 Array<CIMName> clsProps;
748 for (Uint32 i = 0; i < cls.getPropertyCount(); i++)
749 {
|
750 chuck 1.8 if (!containsProperty(cls.getProperty(i).getName(), requiredProps))
751 {
752 requiredProps.append(cls.getProperty(i).getName());
753 }
|
754 chuck 1.2 }
755 }
756
757 // Find out what properties are on the instance.
758 Array<CIMName> supportedProps;
759 for (Uint32 i = 0; i < inst.getPropertyCount(); i++)
760 {
761 supportedProps.append(inst.getProperty(i).getName());
762 }
|
763 david.dillard 1.11
|
764 chuck 1.2 // Check that all required properties are on the instance.
|
765 carolann.graves 1.12 if (!allowMissing)
|
766 chuck 1.2 {
|
767 carolann.graves 1.12 for (Uint32 i = 0; i < requiredProps.size(); i++)
768 {
769 if (!containsProperty(requiredProps[i], supportedProps))
770 {
771 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"missing:" +
772 requiredProps[i].getString());
773 PEG_METHOD_EXIT();
774 MessageLoaderParms parms
775 ("CQL.CQLSelectStatementRep.PROJ_MISSING_PROP",
776 "The property $0 is missing on the instance of class $1.",
777 requiredProps[i].getString(),
778 inst.getClassName().getString());
779 throw QueryRuntimePropertyException(parms);
780 }
781 }
|
782 chuck 1.2 }
783
|
784 chuck 1.3 // If requested, remove the properties on the instance that are not required.
785 if (!preserveProps)
|
786 chuck 1.2 {
|
787 chuck 1.3 for (Uint32 i = 0; i < supportedProps.size(); i++)
|
788 chuck 1.2 {
|
789 chuck 1.3 if (!containsProperty(supportedProps[i], requiredProps))
790 {
791 Uint32 index = inst.findProperty(supportedProps[i]);
792 PEGASUS_ASSERT(index != PEG_NOT_FOUND);
793 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"removing:" + supportedProps[i].getString());
794 inst.removeProperty(index);
795 }
|
796 chuck 1.2 }
797 }
|
798 chuck 1.3
799 PEG_METHOD_EXIT();
|
800 chuck 1.2 }
801
802 //
803 // Validates that all the chained identifiers in the statement meet
804 // the rules in the CQL spec vs.the class definitions in the repository
805 //
|
806 david.dillard 1.13 void CQLSelectStatementRep::validate()
|
807 chuck 1.2 {
|
808 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::validate");
809
810 if(_ctx == NULL)
811 {
812 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null QC");
813 PEG_METHOD_EXIT();
|
814 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
815 "Trying to process a query with a NULL Query Context.");
|
816 chuck 1.4 throw QueryValidationException(parms);
|
817 chuck 1.2 }
818
819 if (!_contextApplied)
820 applyContext();
821
822 for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
823 {
824 validateProperty(_selectIdentifiers[i]);
825 }
826
827 Array<QueryChainedIdentifier> _whereIdentifiers = _ctx->getWhereList();
828 for (Uint32 i = 0; i < _whereIdentifiers.size(); i++)
829 {
830 validateProperty(_whereIdentifiers[i]);
831 }
|
832 chuck 1.3
833 PEG_METHOD_EXIT();
|
834 chuck 1.2 }
835
836 //
837 // Validates that the chained identifier meets all the rules in the CQL
838 // spec vs.the class definitions in the repository
839 //
840 void CQLSelectStatementRep::validateProperty(QueryChainedIdentifier& chainId)
841 {
|
842 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::validateProperty");
843
|
844 chuck 1.2 // Note: applyContext has been called beforehand
|
845 david.dillard 1.11
|
846 chuck 1.2 Array<QueryIdentifier> ids = chainId.getSubIdentifiers();
847
848 Uint32 startingPos = 0;
849 CIMName curContext;
850 for (Uint32 pos = startingPos; pos < ids.size(); pos++)
851 {
852 // Determine the current class context
853 if (ids[pos].isScoped())
854 {
855 // The chain element is scoped. Use the scoping
|
856 david.dillard 1.11 // class as the current context. Note: this depends
|
857 chuck 1.2 // on applyContext resolving the class aliases before we get here.
858 curContext = CIMName(ids[pos].getScope());
859 }
860 else
861 {
862 // The chain element is not scoped. Assume that we are
863 // before a position that is required to be scoped.
864 // (applyContext validates that the chained identifier
865 // has scoped identifiers in the required positions).
866 // The current context is the name at the first position,
867 // which must be a classname (ie. right side of ISA where
868 // the only element in the chain is a classname, or
869 // cases where the FROM class is the first, and maybe only,
870 // element of the chain).
871 PEGASUS_ASSERT((pos < startingPos + 2) || ids[pos].isWildcard());
872 curContext = ids[0].getName();
873 }
874
|
875 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"current context: " +
876 curContext.getString());
877
|
878 chuck 1.2 // Get the class definition of the current class context
|
879 chuck 1.3 // Note: keep this code here so that class existence is always
880 // checked. Eg. SELECT * FROM fromClass
|
881 chuck 1.2 CIMClass classDef;
|
882 david.dillard 1.11 try
|
883 chuck 1.2 {
884 classDef = _ctx->getClass(curContext);
885 }
|
886 david.dillard 1.11 catch (const CIMException& ce)
|
887 chuck 1.2 {
|
888 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"repository error");
889 PEG_METHOD_EXIT();
|
890 chuck 1.2 if (ce.getCode() == CIM_ERR_NOT_FOUND ||
891 ce.getCode() == CIM_ERR_INVALID_CLASS)
892 {
893 MessageLoaderParms parms("CQL.CQLSelectStatementRep.VAL_CLASS_NOT_EXIST",
894 "The class $0 does not exist.",
895 curContext.getString());
|
896 chuck 1.4 throw QueryValidationException(parms);
|
897 chuck 1.2 }
|
898 chuck 1.3 else
899 {
|
900 david.dillard 1.11 throw;
|
901 chuck 1.3 }
|
902 chuck 1.2 }
903
904 // Now do the checks for properties existing on the current class context
905 // and the class relationship rules in section 5.4.1.
906 // Only do these checks if the chain id has a property.
907 if (pos > startingPos)
908 {
909 if (ids[pos].isWildcard())
910 {
911 // The wildcard is at the end (verified by applyContext), so
912 // no checking is required at this position.
913 continue;
914 }
915
916 // Determine if the property name at the current position
917 // exists on the current class context.
918 Uint32 propertyIndex = classDef.findProperty(ids[pos].getName());
919 if (propertyIndex == PEG_NOT_FOUND)
920 {
|
921 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"prop not on context " +
922 ids[pos].getName().getString());
923 PEG_METHOD_EXIT();
|
924 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.VAL_PROP_NOT_ON_CLASS",
925 "The property $0 does not exist on class $1.",
926 ids[pos].getName().getString(), classDef.getClassName().getString());
|
927 chuck 1.4 throw QueryMissingPropertyException(parms);
|
928 chuck 1.2 }
929
930 // Checking class relationship rules in section 5.4.1.
931 // For validateProperties, this only applies to the first
932 // property in the chain. This is because once we get into
933 // embedded properties we don't know what the class will be
934 // until we have an instance.
935 if ((pos == (startingPos+1)) && !curContext.equal(ids[0].getName()))
936 {
937 // Its the first property, and the class context is not the FROM class.
938 // Check the class relationship between the scoping class and the FROM class.
939 if (_ctx->getClassRelation(ids[0].getName(), curContext) == QueryContext::NOTRELATED)
940 {
|
941 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"scope violation for:"+
942 ids[0].getName().getString());
943 PEG_METHOD_EXIT();
|
944 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.VAL_SCOPE_VIOLATION",
945 "The class $0 is not a superclass, subclass, or the same class as $1.",
946 curContext.getString(), ids[0].getName().getString());
|
947 chuck 1.4 throw QueryValidationException(parms);
|
948 chuck 1.2 }
949 }
950
951 // If the current position implies an embedded object, then
952 // verify that the property is an embedded object
|
953 david.dillard 1.11 if ((pos > startingPos) && (pos < (ids.size() - 1)))
|
954 chuck 1.2 {
955 CIMProperty embObj = classDef.getProperty(propertyIndex);
956 CIMName qual("EmbeddedObject");
957 if (embObj.findQualifier(qual) == PEG_NOT_FOUND)
958 {
|
959 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"prop not emb " +
960 embObj.getName().getString());
961 PEG_METHOD_EXIT();
|
962 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROP_NOT_EMB",
963 "The property $0 must be an embedded object.",
964 embObj.getName().getString());
|
965 chuck 1.4 throw QueryValidationException(parms);
|
966 chuck 1.2 }
967 }
968 }
969 }
|
970 david.dillard 1.11
|
971 chuck 1.3 PEG_METHOD_EXIT();
|
972 chuck 1.2 }
973
974 CIMName CQLSelectStatementRep::lookupFromClass(const String& lookup)
975 {
|
976 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::lookupFromClass");
977
|
978 chuck 1.2 QueryIdentifier id = _ctx->findClass(lookup);
979
|
980 chuck 1.3 PEG_METHOD_EXIT();
981
|
982 chuck 1.2 return id.getName();
983 }
984
985 Array<CIMObjectPath> CQLSelectStatementRep::getClassPathList()
986 {
|
987 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::getClassPathList");
988
|
989 chuck 1.2 if(_ctx == NULL){
|
990 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null QC");
991 PEG_METHOD_EXIT();
|
992 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
993 "Trying to process a query with a NULL Query Context.");
994 throw CQLRuntimeException(parms);
995 }
996
997 Array<QueryIdentifier> ids = _ctx->getFromList();
998 PEGASUS_ASSERT(ids.size() == 1); // no joins yet
999
1000 // No wbem-uri support yet.
1001 CIMObjectPath path(String::EMPTY, _ctx->getNamespace(), ids[0].getName());
1002
1003 Array<CIMObjectPath> paths;
1004 paths.append(path);
1005
|
1006 chuck 1.3 PEG_METHOD_EXIT();
1007
|
1008 chuck 1.2 return paths;
|
1009 chuck 1.3
|
1010 chuck 1.2 }
1011
1012 CIMPropertyList CQLSelectStatementRep::getPropertyList(const CIMObjectPath& inClassName)
1013 {
|
1014 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::getPropertyList");
|
1015 david.dillard 1.11 try
|
1016 chuck 1.5 {
1017 return getPropertyListInternal(inClassName, true, true);
1018 }
|
1019 david.dillard 1.11 catch (const CIMException& ce)
|
1020 chuck 1.5 {
1021 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"cim exception");
1022 PEG_METHOD_EXIT();
1023 if (ce.getCode() == CIM_ERR_NOT_FOUND ||
1024 ce.getCode() == CIM_ERR_INVALID_CLASS)
1025 {
1026 MessageLoaderParms parms("CQL.CQLSelectStatementRep.GPL_CLASS_NOT_EXIST",
1027 "A class required to determine the property list was not found.");
1028 throw CQLRuntimeException(parms);
1029 }
1030 else
1031 {
|
1032 david.dillard 1.11 throw;
|
1033 chuck 1.5 }
1034 }
|
1035 chuck 1.2 }
1036
1037 CIMPropertyList CQLSelectStatementRep::getSelectPropertyList(const CIMObjectPath& inClassName)
1038 {
|
1039 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::getSelectPropertyList");
|
1040 chuck 1.5 try
1041 {
1042 return getPropertyListInternal(inClassName, true, false);
1043 }
|
1044 david.dillard 1.11 catch (const CIMException& ce)
|
1045 chuck 1.5 {
1046 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"cim exception");
1047 PEG_METHOD_EXIT();
1048 if (ce.getCode() == CIM_ERR_NOT_FOUND ||
1049 ce.getCode() == CIM_ERR_INVALID_CLASS)
1050 {
1051 MessageLoaderParms parms("CQL.CQLSelectStatementRep.GPL_CLASS_NOT_EXIST",
1052 "A class required to determine the property list was not found.");
1053 throw CQLRuntimeException(parms);
1054 }
1055 else
1056 {
|
1057 david.dillard 1.11 throw;
|
1058 chuck 1.5 }
1059 }
|
1060 chuck 1.2 }
1061
1062 CIMPropertyList CQLSelectStatementRep::getWherePropertyList(const CIMObjectPath& inClassName)
1063 {
|
1064 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::getWherePropertyList");
|
1065 chuck 1.5 try
1066 {
1067 return getPropertyListInternal(inClassName, false, true);
1068 }
|
1069 david.dillard 1.11 catch (const CIMException& ce)
|
1070 chuck 1.5 {
1071 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"cim exception");
1072 PEG_METHOD_EXIT();
1073 if (ce.getCode() == CIM_ERR_NOT_FOUND ||
1074 ce.getCode() == CIM_ERR_INVALID_CLASS)
1075 {
1076 MessageLoaderParms parms("CQL.CQLSelectStatementRep.GPL_CLASS_NOT_EXIST",
1077 "A class required to determine the property list was not found.");
1078 throw CQLRuntimeException(parms);
1079 }
1080 else
1081 {
|
1082 david.dillard 1.11 throw;
|
1083 chuck 1.5 }
1084 }
|
1085 chuck 1.2 }
1086
1087 CIMPropertyList CQLSelectStatementRep::getPropertyListInternal(const CIMObjectPath& inClassName,
1088 Boolean includeSelect,
1089 Boolean includeWhere)
1090 {
|
1091 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::getPropertyListInternal");
1092
1093 if(_ctx == NULL)
1094 {
1095 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null QC");
1096 PEG_METHOD_EXIT();
|
1097 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
1098 "Trying to process a query with a NULL Query Context.");
1099 throw CQLRuntimeException(parms);
|
1100 david.dillard 1.11 }
|
1101 chuck 1.2
1102 if (!_contextApplied)
1103 applyContext();
1104
|
1105 chuck 1.3 // Get the FROM class.
|
1106 david.dillard 1.11 CIMName fromClass = _ctx->getFromList()[0].getName();
|
1107 chuck 1.3
1108 // Get the classname passed in. Note: since wbem-uri is not supported yet,
|
1109 david.dillard 1.11 // only use the classname part of the path.
|
1110 chuck 1.2 CIMName className = inClassName.getClassName();
1111 if (className.isNull())
1112 {
|
1113 david.dillard 1.11 // If the caller passed in an empty className, then the
|
1114 chuck 1.2 // FROM class is to be used.
|
1115 chuck 1.3 className = fromClass;
1116 }
1117 else
1118 {
1119 // The caller passed in some class name. Verify that it is the FROM
1120 // class or a subclass of the FROM class.
1121 if(!(className == fromClass))
1122 {
1123 // Check if subclass of the FROM class
1124 if(!_ctx->isSubClass(fromClass, className))
1125 {
1126 MessageLoaderParms parms("CQL.CQLSelectStatementRep.CLASS_NOT_FROM_LIST_CLASS",
1127 "Class $0 does not match the FROM class or any of its subclasses.",
1128 className.getString());
|
1129 chuck 1.4 throw CQLRuntimeException(parms);
|
1130 chuck 1.3 }
|
1131 david.dillard 1.11 }
1132 }
1133
|
1134 chuck 1.2 Boolean isWildcard;
1135 Array<CIMName> reqProps;
1136 Array<CIMName> matchedScopes;
1137 Array<CIMName> unmatchedScopes;
1138
1139 // Add required properties from the select list.
1140 if (includeSelect)
1141 {
1142 for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
1143 {
|
1144 david.dillard 1.11 isWildcard = addRequiredProperty(reqProps,
|
1145 chuck 1.2 className,
1146 _selectIdentifiers[i],
1147 matchedScopes,
1148 unmatchedScopes);
|
1149 david.dillard 1.11
|
1150 chuck 1.2 if (isWildcard)
1151 {
|
1152 david.dillard 1.11 // This indicates that a wildcard was found,
|
1153 chuck 1.5 // and the class passed in was the FROM class.
|
1154 chuck 1.2 // Return null property list to indicate all properties required.
1155 return CIMPropertyList();
1156 }
1157 }
1158 }
1159
1160 // Add required properties from the WHERE clause.
1161 if (includeWhere)
1162 {
1163 Array<QueryChainedIdentifier> _whereIdentifiers = _ctx->getWhereList();
1164 for (Uint32 i = 0; i < _whereIdentifiers.size(); i++)
1165 {
1166 isWildcard = addRequiredProperty(reqProps,
1167 className,
1168 _whereIdentifiers[i],
1169 matchedScopes,
|
1170 david.dillard 1.11 unmatchedScopes);
|
1171 chuck 1.2
1172 // Wildcards are not allowed in the WHERE clause
1173 PEGASUS_ASSERT(!isWildcard);
1174 }
1175 }
|
1176 david.dillard 1.11
|
1177 chuck 1.2 // Check if every property on the class is required.
1178 CIMClass theClass = _ctx->getClass(className);
1179 Uint32 propCnt = theClass.getPropertyCount();
1180 Boolean allProps = true;
1181 for (Uint32 i = 0; i < propCnt; i++)
1182 {
1183 if (!containsProperty(theClass.getProperty(i).getName(), reqProps))
1184 {
1185 allProps = false;
1186 break;
1187 }
1188 }
1189
1190 if (allProps)
1191 {
1192 // Return null property list to indicate all properties are required.
|
1193 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"all props req");
1194 PEG_METHOD_EXIT();
|
1195 chuck 1.2 return CIMPropertyList();
1196 }
1197 else
1198 {
1199 // Return the required property list. Note that it is possible to return
1200 // an empty list in the case of no required properties for the classname
1201 // passed in. This can happen when the scoping operator is used.
|
1202 chuck 1.3 PEG_METHOD_EXIT();
|
1203 chuck 1.2 return CIMPropertyList(reqProps);
1204 }
1205 }
1206
1207 Boolean CQLSelectStatementRep::addRequiredProperty(Array<CIMName>& reqProps,
1208 CIMName& className,
1209 QueryChainedIdentifier& chainId,
1210 Array<CIMName>& matchedScopes,
1211 Array<CIMName>& unmatchedScopes)
1212 {
|
1213 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::addRequiredProperty");
1214
|
1215 chuck 1.2 //
|
1216 david.dillard 1.11 // Implementation notes:
|
1217 chuck 1.2 // This function does not look for required properties on embedded objects.
1218 // This function assumes that applyContext has been called.
1219 //
1220
1221 Array<QueryIdentifier> ids = chainId.getSubIdentifiers();
1222
1223 // After applyContext has been called, a single element
1224 // chained identifier refers to either an instance of the
1225 // FROM class, or is the classname on the right side of ISA.
1226 if (ids.size() == 1)
1227 {
1228 // This identifier is not a property name
|
1229 chuck 1.3 PEG_METHOD_EXIT();
|
1230 chuck 1.2 return false;
1231 }
1232
|
1233 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"id[1] = " + ids[1].toString());
1234
|
1235 chuck 1.2 if (ids[1].isSymbolicConstant())
1236 {
1237 // Non-embedded symbolic constants are not properties
1238 // Note that an embedded symbolic constant like this:
1239 // fromclass.embobj.scope::someprop#'ok'
|
1240 david.dillard 1.11 // implies that embobj is a required property, because
|
1241 chuck 1.2 // embobj could be null, and that affects how the
1242 // identifier is evaluated.
|
1243 chuck 1.3 PEG_METHOD_EXIT();
|
1244 chuck 1.2 return false;
1245 }
1246
1247 // Since applyContext has been called, the first chain element
1248 // will be the FROM class, so go to the 2nd chain element.
1249 if (ids[1].isScoped())
1250 {
1251 // The 2nd chain element is a scoped property.
1252 // Eg. fromclass.someclass::someprop
1253
1254 // Determine the class that the property is being scoped to.
1255 // This could be the FROM class, or some other class not in the FROM list
1256 CIMName scopingClass = CIMName(ids[1].getScope());
1257
1258 // Check if the scoping class is the same as the class passed in.
1259 if (scopingClass == className)
1260 {
|
1261 david.dillard 1.11 // The scoping class is the same as the class passed,
|
1262 chuck 1.2 // add the property if not already added
1263 if (!containsProperty(ids[1].getName(), reqProps))
|
1264 david.dillard 1.11 {
|
1265 chuck 1.2 reqProps.append(ids[1].getName());
1266 }
1267 }
1268 else
1269 {
|
1270 david.dillard 1.11 // The scoping class is not the same as the class passed in.
|
1271 chuck 1.2 // Check if we already know that the scoping class is a subclass
1272 // of the class passed in
1273 if (containsProperty(scopingClass, unmatchedScopes))
1274 {
1275 // Scoping class is a subclass.
|
1276 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"scoping class is a subclass");
1277 PEG_METHOD_EXIT();
|
1278 chuck 1.2 return false;
1279 }
|
1280 david.dillard 1.11
|
1281 chuck 1.2 // Check if we already know that the scoping class is a superclass
1282 // of the class passed in
1283 Boolean isSuper = false;
1284 if (containsProperty(scopingClass, matchedScopes))
1285 {
1286 // Scoping class is a superclass.
1287 isSuper = true;
1288 }
1289
1290 // Check if the scoping class is a superclass of the class passed in
1291 if (isSuper || _ctx->isSubClass(scopingClass, className))
1292 {
|
1293 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"scoping class is a superclass");
1294
|
1295 chuck 1.2 // Scoping class is a superclass of the class passed in.
1296 if (!isSuper)
1297 {
1298 // Save this information
1299 matchedScopes.append(scopingClass);
1300 }
1301
1302 // Add to the required property list if not already there.
1303 if (!containsProperty(ids[1].getName(), reqProps))
|
1304 david.dillard 1.11 {
|
1305 chuck 1.2 reqProps.append(ids[1].getName());
1306 }
1307 }
1308 else
1309 {
|
1310 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"scoping class is NOT a superclass");
1311
|
1312 chuck 1.2 // Scoping class is not superclass of class passed in.
1313 // Save this information.
1314 unmatchedScopes.append(scopingClass);
1315 }
1316 } // end else scoping class not == class passed in
1317 } // end if first id is scoped
1318 else
1319 {
1320 // The 2nd chain element is an unscoped property
1321 // Check if it is wildcarded
1322 if (ids[1].isWildcard())
1323 {
1324 // Wildcard.
1325 // If the class passed in is the FROM class, then
1326 // all properties are required on the class passed in.
1327 CIMName fromClassName = _ctx->getFromList()[0].getName();
1328 if (fromClassName == className)
1329 {
|
1330 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"wildcard and = FROM");
1331 PEG_METHOD_EXIT();
|
1332 chuck 1.2 return true;
1333 }
1334
1335 // Add all the properties on the FROM class to
1336 // the required property list.
1337 CIMClass fromClass = _ctx->getClass(fromClassName);
1338 for (Uint32 n = 0; n < fromClass.getPropertyCount(); n++)
1339 {
1340 // Add to the required property list if not already there.
1341 if (!containsProperty(fromClass.getProperty(n).getName(), reqProps))
|
1342 david.dillard 1.11 {
|
1343 chuck 1.2 reqProps.append(fromClass.getProperty(n).getName());
|
1344 david.dillard 1.11 }
|
1345 chuck 1.2 }
1346
|
1347 chuck 1.3 PEG_METHOD_EXIT();
|
1348 chuck 1.2 return false;
1349 }
1350
1351 // Implementation note:
1352 // Since this API assumes that the class passed in
1353 // is the FROM class or a subclass of the FROM class,
1354 // AND validateProperties can be called to check if
|
1355 david.dillard 1.11 // unscoped properties are on the FROM class,
|
1356 chuck 1.2 // we can just add the required property because
1357 // it is assumed to be on the FROM class.
1358
1359 // Add to the required property list if not already there.
1360 if (!containsProperty(ids[1].getName(), reqProps))
|
1361 david.dillard 1.11 {
|
1362 chuck 1.2 reqProps.append(ids[1].getName());
1363 }
1364 }
|
1365 david.dillard 1.11
|
1366 chuck 1.2 // Indicate the required property is not a wildcard
|
1367 chuck 1.3 PEG_METHOD_EXIT();
|
1368 chuck 1.2 return false;
1369 }
1370
1371 Array<CQLChainedIdentifier> CQLSelectStatementRep::getSelectChainedIdentifiers()
1372 {
|
1373 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::getSelectChainedIdentifiers");
1374
|
1375 chuck 1.2 if (!_contextApplied)
1376 applyContext();
1377
|
1378 chuck 1.3 PEG_METHOD_EXIT();
1379
|
1380 chuck 1.2 return _selectIdentifiers;
1381 }
1382
1383 Array<CQLChainedIdentifier> CQLSelectStatementRep::getWhereChainedIdentifiers()
1384 {
|
1385 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::getWhereChainedIdentifiers");
1386
1387 if(_ctx == NULL)
1388 {
1389 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null QC");
1390 PEG_METHOD_EXIT();
|
1391 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
1392 "Trying to process a query with a NULL Query Context.");
1393 throw CQLRuntimeException(parms);
1394 }
1395
1396 if (!_contextApplied)
1397 applyContext();
1398
1399 Array<QueryChainedIdentifier> qChainIds = _ctx->getWhereList();
1400 Array<CQLChainedIdentifier> cqlChainIds;
1401 for (Uint32 i = 0; i < qChainIds.size(); i++)
1402 {
1403 Array<QueryIdentifier> qSubs = qChainIds[i].getSubIdentifiers();
1404 CQLChainedIdentifier cqlChainId;
1405 for (Uint32 j = 0; j < qSubs.size(); j++)
1406 {
1407 cqlChainId.append(qSubs[j]);
1408 }
1409
1410 cqlChainIds.append(cqlChainId);
1411 }
1412 chuck 1.2
|
1413 chuck 1.3 PEG_METHOD_EXIT();
1414
|
1415 chuck 1.2 return cqlChainIds;
1416 }
1417
1418 Boolean CQLSelectStatementRep::containsProperty(const CIMName& name,
|
1419 david.dillard 1.11 const Array<CIMName>& props)
|
1420 chuck 1.2 {
|
1421 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::containsProperty");
1422
|
1423 chuck 1.2 for (Uint32 i = 0; i < props.size(); i++)
1424 {
1425 if (props[i] == name)
1426 {
|
1427 chuck 1.3 PEG_METHOD_EXIT();
|
1428 chuck 1.2 return true;
1429 }
1430 }
1431
|
1432 chuck 1.3 PEG_METHOD_EXIT();
|
1433 chuck 1.2 return false;
1434 }
1435
|
1436 chuck 1.7 //
1437 // Checks if the classname passed in is the FROM class, or
1438 // a subclass of the FROM class
1439 //
1440 Boolean CQLSelectStatementRep::isFromChild(const CIMName& className)
1441 {
|
1442 chuck 1.8 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::isFromChild");
1443
|
1444 david.dillard 1.11 QueryContext::ClassRelation rel =
|
1445 chuck 1.7 _ctx->getClassRelation(_ctx->getFromList()[0].getName(), className);
1446
|
1447 chuck 1.8 PEG_METHOD_EXIT();
|
1448 chuck 1.7 return (rel == QueryContext::SAMECLASS || rel == QueryContext::SUBCLASS) ? true : false;
1449 }
1450
|
1451 chuck 1.2 void CQLSelectStatementRep::appendClassPath(const CQLIdentifier& inIdentifier)
1452 {
|
1453 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::appendClassPath");
1454
1455 if(_ctx == NULL)
1456 {
1457 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null QC");
1458 PEG_METHOD_EXIT();
|
1459 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
1460 "Trying to process a query with a NULL Query Context.");
|
1461 chuck 1.4 throw QueryValidationException(parms);
|
1462 chuck 1.2 }
1463 _ctx->insertClassPath(inIdentifier);
|
1464 chuck 1.3
1465 PEG_METHOD_EXIT();
|
1466 chuck 1.2 }
1467
1468 void CQLSelectStatementRep::setPredicate(const CQLPredicate& inPredicate)
1469 {
|
1470 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::setPredicate");
|
1471 chuck 1.2 _predicate = inPredicate;
|
1472 chuck 1.3 PEG_METHOD_EXIT();
|
1473 chuck 1.2 }
1474
1475 CQLPredicate CQLSelectStatementRep::getPredicate() const
1476 {
|
1477 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::getPredicate");
|
1478 chuck 1.2 return _predicate;
1479 }
1480
1481 void CQLSelectStatementRep::insertClassPathAlias(const CQLIdentifier& inIdentifier,
1482 String inAlias)
1483 {
|
1484 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::insertClassPathAlias");
1485
1486 if(_ctx == NULL)
1487 {
1488 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null QC");
1489 PEG_METHOD_EXIT();
|
1490 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
1491 "Trying to process a query with a NULL Query Context.");
|
1492 chuck 1.4 throw QueryValidationException(parms);
|
1493 chuck 1.2 }
1494 _ctx->insertClassPath(inIdentifier,inAlias);
|
1495 chuck 1.3
1496 PEG_METHOD_EXIT();
|
1497 chuck 1.2 }
1498
1499 void CQLSelectStatementRep::appendSelectIdentifier(const CQLChainedIdentifier& x)
1500 {
|
1501 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::appendSelectIdentifier");
|
1502 chuck 1.2 _selectIdentifiers.append(x);
|
1503 david.dillard 1.11 PEG_METHOD_EXIT();
|
1504 chuck 1.2 }
1505
1506 void CQLSelectStatementRep::applyContext()
1507 {
|
1508 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::applyContext");
1509
1510 if(_ctx == NULL)
1511 {
1512 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null QC");
1513 PEG_METHOD_EXIT();
|
1514 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
1515 "Trying to process a query with a NULL Query Context.");
|
1516 chuck 1.4 // throw syntax error to be consistent
1517 throw CQLSyntaxErrorException(parms);
|
1518 chuck 1.2 }
1519
1520 for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
1521 {
1522 _selectIdentifiers[i].applyContext(*_ctx);
1523 checkWellFormedIdentifier(_selectIdentifiers[i], true);
1524 }
1525
1526 if (hasWhereClause())
1527 {
1528 _predicate.applyContext(*_ctx);
1529
1530 // Note: must be after call to predicate's applyContext
1531 Array<QueryChainedIdentifier> _whereIdentifiers = _ctx->getWhereList();
1532 for (Uint32 i = 0; i < _whereIdentifiers.size(); i++)
1533 {
1534 checkWellFormedIdentifier(_whereIdentifiers[i], false);
1535 }
1536 }
1537
1538 _contextApplied = true;
|
1539 chuck 1.3 PEG_METHOD_EXIT();
|
1540 chuck 1.2 }
1541
1542 void CQLSelectStatementRep::checkWellFormedIdentifier(const QueryChainedIdentifier& chainId,
1543 Boolean isSelectListId)
1544 {
|
1545 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::checkWellFormedIdentifier");
1546
|
1547 chuck 1.2 // This function assumes that applyContext has been called.
1548 Array<QueryIdentifier> ids = chainId.getSubIdentifiers();
1549
1550 if (ids.size() == 0)
1551 {
|
1552 chuck 1.3 PEG_METHOD_EXIT();
|
1553 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.EMPTY_CHAIN",
1554 "An empty chained identifier was found.");
1555 throw CQLSyntaxErrorException(parms);
1556 }
1557
|
1558 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"chain =" + chainId.toString());
1559
|
1560 chuck 1.2 if (ids.size() == 1 && isSelectListId)
1561 {
1562 // Single element chain ids are not allow in the select list.
1563 // The select list can only have properties.
|
1564 chuck 1.3 PEG_METHOD_EXIT();
|
1565 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.SINGLE_CHID_IN_SELECT",
1566 "A property on the FROM class must be selected.");
1567 throw CQLSyntaxErrorException(parms);
1568 }
1569
1570 if (ids[0].isScoped()
1571 || ids[0].isWildcard()
|
1572 david.dillard 1.11 || ids[0].isSymbolicConstant()
|
1573 chuck 1.2 || ids[0].isArray())
1574 {
1575 // The first identifier must be a classname (it could be the FROM class, or
1576 // some other class for the right side of ISA)
|
1577 chuck 1.3 PEG_METHOD_EXIT();
|
1578 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.FIRST_ID_ILLEGAL",
1579 "The chained identifier $0 is illegal.",
1580 chainId.toString());
1581 throw CQLSyntaxErrorException(parms);
1582 }
|
1583 david.dillard 1.11
|
1584 chuck 1.2 Uint32 startingPos = 1;
1585 for (Uint32 pos = startingPos; pos < ids.size(); pos++)
|
1586 david.dillard 1.11 {
|
1587 chuck 1.2 if (ids[pos].isArray() && isSelectListId)
1588 {
|
1589 chuck 1.3 PEG_METHOD_EXIT();
|
1590 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.ARRAY_IN_SELECT",
1591 "The identifier $0 of $1 in the SELECT list cannot use an array index.",
1592 ids[pos].toString(), chainId.toString());
1593 throw CQLSyntaxErrorException(parms);
1594 }
1595
1596 if (ids[pos].isSymbolicConstant() && isSelectListId)
1597 {
|
1598 chuck 1.3 PEG_METHOD_EXIT();
|
1599 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.SYMCONST_IN_SELECT",
1600 "The identifier $0 of $1 in the SELECT list cannot use a symbolic constant.",
1601 ids[pos].toString(), chainId.toString());
1602 throw CQLSyntaxErrorException(parms);
1603 }
1604
1605 if (ids[pos].isSymbolicConstant() && pos != (ids.size() -1))
1606 {
|
1607 chuck 1.3 PEG_METHOD_EXIT();
|
1608 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.SYMCONST_NOT_LAST",
1609 "The symbolic constant identifier $0 of $1 must be the last element.",
1610 ids[pos].toString(), chainId.toString());
1611 throw CQLSyntaxErrorException(parms);
1612 }
1613
1614 if (ids[pos].isWildcard())
1615 {
1616 if ( !isSelectListId)
1617 {
|
1618 chuck 1.3 PEG_METHOD_EXIT();
|
1619 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.WILD_IN_WHERE",
1620 "The identifier $0 of $1 in the WHERE list cannot use a wildcard.",
1621 ids[pos].toString(), chainId.toString());
1622 throw CQLSyntaxErrorException(parms);
1623 }
1624
1625 if ( pos != ids.size() - 1)
1626 {
|
1627 chuck 1.3 PEG_METHOD_EXIT();
|
1628 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.WILD_NOT_END",
1629 "The wildcard identifier $0 of $1 must be the last element.",
1630 ids[pos].toString(), chainId.toString());
1631 throw CQLSyntaxErrorException(parms);
1632 }
1633 }
1634
1635 if (pos > startingPos && !ids[pos].isWildcard())
1636 {
1637 if (!ids[pos].isScoped())
1638 {
|
1639 chuck 1.3 PEG_METHOD_EXIT();
|
1640 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.EMB_PROP_NOT_SCOPED",
1641 "The identifier $0 of $1 must use the scope operator.",
1642 ids[pos].toString(), chainId.toString());
1643 throw CQLSyntaxErrorException(parms);
1644 }
1645 }
1646 }
|
1647 chuck 1.3
1648 PEG_METHOD_EXIT();
|
1649 chuck 1.2 }
1650
1651 void CQLSelectStatementRep::normalizeToDOC()
1652 {
|
1653 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::normalizeToDOC");
1654
|
1655 chuck 1.2 if (!_contextApplied)
1656 applyContext();
1657
1658 if(_hasWhereClause){
1659 Cql2Dnf DNFer(_predicate);
|
1660 david.dillard 1.11 _predicate = DNFer.getDnfPredicate();
|
1661 chuck 1.2 }
|
1662 chuck 1.3
1663 PEG_METHOD_EXIT();
|
1664 chuck 1.2 }
1665
1666 String CQLSelectStatementRep::toString()
1667 {
|
1668 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::toString");
1669
1670 if(_ctx == NULL)
1671 {
1672 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null QC");
1673 PEG_METHOD_EXIT();
1674 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
1675 "Trying to process a query with a NULL Query Context.");
1676 throw CQLRuntimeException(parms);
1677 }
1678
1679 String s("SELECT ");
1680 for(Uint32 i = 0; i < _selectIdentifiers.size(); i++){
1681 if((i > 0) && (i < _selectIdentifiers.size()))
1682 {
1683 s.append(",");
1684 }
1685 s.append(_selectIdentifiers[i].toString());
|
1686 david.dillard 1.11 }
|
1687 chuck 1.3
1688 s.append(" ");
1689 s.append(_ctx->getFromString());
1690
1691 if(_hasWhereClause){
1692 s.append(" WHERE ");
1693 s.append(_predicate.toString());
1694 }
|
1695 chuck 1.2
|
1696 chuck 1.3 PEG_METHOD_EXIT();
1697 return s;
|
1698 chuck 1.2 }
1699
1700 void CQLSelectStatementRep::setHasWhereClause()
1701 {
|
1702 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::setHasWhereClause");
1703 _hasWhereClause = true;
1704 PEG_METHOD_EXIT();
|
1705 chuck 1.2 }
1706
1707 Boolean CQLSelectStatementRep::hasWhereClause()
1708 {
|
1709 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::hasWhereClause");
1710 return _hasWhereClause;
|
1711 chuck 1.2 }
1712
1713 void CQLSelectStatementRep::clear()
1714 {
|
1715 chuck 1.3 PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::clear");
1716
|
1717 carolann.graves 1.12 if(_ctx == NULL)
1718 {
|
1719 chuck 1.3 PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null QC");
1720 PEG_METHOD_EXIT();
|
1721 chuck 1.2 MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL",
1722 "Trying to process a query with a NULL Query Context.");
1723 throw CQLRuntimeException(parms);
|
1724 carolann.graves 1.12 }
|
1725 chuck 1.2
1726 _ctx->clear();
1727 _hasWhereClause = false;
1728 _contextApplied = false;
1729 _predicate = CQLPredicate();
1730 _selectIdentifiers.clear();
|
1731 chuck 1.3
1732 PEG_METHOD_EXIT();
|
1733 chuck 1.2 }
1734
1735 PEGASUS_NAMESPACE_END
|