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