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