1 chuck 1.1.2.3 //%2004////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Development
4 // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
5 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L. P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
16 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
17 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
18 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
19 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 chuck 1.1.2.3 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 //==============================================================================
25 //
26 // Authors: David Rosckes (rosckes@us.ibm.com)
27 // Bert Rivero (hurivero@us.ibm.com)
28 // Chuck Carmack (carmack@us.ibm.com)
29 // Brian Lucier (lucier@us.ibm.com)
30 //
31 // Modified By:
32 //
33 //%/////////////////////////////////////////////////////////////////////////////
34
|
35 humberto 1.1.2.1 #include "CQLSelectStatement.h"
36 #include "CQLSelectStatementRep.h"
37
|
38 chuck 1.1.2.5 #include <Pegasus/Common/CIMValue.h>
39 #include <Pegasus/Common/CIMInstance.h>
40 #include <Pegasus/Common/CIMProperty.h>
41 #include <Pegasus/Common/InternalException.h>
42 #include "CQLValue.h"
43 #include "CQLIdentifier.h"
44 #include "CQLChainedIdentifier.h"
45
46
|
47 humberto 1.1.2.1 PEGASUS_NAMESPACE_BEGIN
48
|
49 chuck 1.1.2.5 struct EmbeddedPropertyNode
50 {
51 CIMName name;
52 Boolean wildcard;
53 EmbeddedPropertyNode * parent;
54 EmbeddedPropertyNode * sibling;
55 EmbeddedPropertyNode * firstChild;
56 };
57
58
|
59 chuck 1.1.2.3 CQLSelectStatementRep::CQLSelectStatementRep()
60 :SelectStatementRep()
|
61 humberto 1.1.2.1 {
62 }
63
|
64 chuck 1.1.2.3 CQLSelectStatementRep::CQLSelectStatementRep(String& inQlang, String& inQuery, QueryContext* inCtx)
65 :SelectStatementRep(inQlang, inQuery, inCtx)
66 {
|
67 humberto 1.1.2.2 }
68
|
69 chuck 1.1.2.3 CQLSelectStatementRep::CQLSelectStatementRep(const CQLSelectStatementRep& rep)
70 :SelectStatementRep(rep),
71 _selectIdentifiers(rep._selectIdentifiers),
72 _whereIdentifiers(rep._whereIdentifiers),
73 _predicate(rep._predicate)
|
74 humberto 1.1.2.1 {
75 }
76
|
77 chuck 1.1.2.3 CQLSelectStatementRep::~CQLSelectStatementRep()
|
78 humberto 1.1.2.1 {
79 }
80
|
81 chuck 1.1.2.3 CQLSelectStatementRep& CQLSelectStatementRep::operator=(const CQLSelectStatementRep& rhs)
|
82 humberto 1.1.2.1 {
|
83 chuck 1.1.2.3 if (this == &rhs)
84 return *this;
85
86 SelectStatementRep::operator=(rhs);
87
88 _whereIdentifiers = rhs._whereIdentifiers;
89 _selectIdentifiers = rhs._selectIdentifiers;
90 _predicate = rhs._predicate;
91
92 return *this;
93 }
94
95 Boolean CQLSelectStatementRep::evaluate(const CIMInstance& inCI)
96 {
|
97 chuck 1.1.2.4 if (!hasWhereClause())
98 return true;
99 else
100 return _predicate.evaluate(inCI, *_ctx);
|
101 chuck 1.1.2.3 }
102
103 void CQLSelectStatementRep::applyProjection(CIMInstance& inCI) throw(Exception)
104 {
|
105 chuck 1.1.2.5 // assumes that applyContext had been called.
|
106 chuck 1.1.2.3
|
107 chuck 1.1.2.5 EmbeddedPropertyNode* rootNode = new EmbeddedPropertyNode;
108 Array<CQLIdentifier> fromList = _ctx->getFromList();
109 rootNode->name = fromList[0].getName(); // not doing joins
110
111 for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
112 {
113 CQLValue val(_selectIdentifiers[i]);
114
115 // ATTN: assuming the CQLValue takes care of class aliasing
116 // ATTN: assumes that the instance's class name is first subId.
117 // ATTN: UNCOMMENT when API is available
118 CQLChainedIdentifier resolvedId; // = val.getResolvedIdentifier(inCI, *_ctx);
119 Array<CQLIdentifier> ids = resolvedId.getSubIdentifiers();
120
121 EmbeddedPropertyNode * curNode = rootNode;
122 EmbeddedPropertyNode * curChild = curNode->firstChild;
123
124 for (Uint32 j = 1; j < ids.size(); j++)
125 {
126 if (ids[j].isWildcard())
127 {
128 chuck 1.1.2.5 curNode->wildcard = true;
129 break;
130 }
131
132 Boolean found = false;
133 while (curChild != NULL && !found)
134 {
135 if (curChild->name == ids[j].getName())
136 {
137 found = true;
138 }
139 else
140 {
141 curChild = curChild->sibling;
142 }
143 }
144
145 if (!found)
146 {
147 curChild = new EmbeddedPropertyNode;
148 curChild->parent = curNode;
149 chuck 1.1.2.5 curChild->sibling = curNode->firstChild;
150 curChild->name = ids[j].getName();
151 curNode->firstChild = curChild;
152 curNode->wildcard = false;
153 }
154
155 curNode = curChild;
156 curChild = curNode->firstChild;
157 }
158 }
159
160 Array<CIMName> requiredProps;
161
162 EmbeddedPropertyNode* projNode = rootNode->firstChild;
163 while (projNode != NULL)
164 {
165 if (!projNode->wildcard && !(projNode->firstChild == NULL))
166 {
167 Uint32 index = inCI.findProperty(projNode->name);
168 CIMProperty projProp = inCI.getProperty(index);
169 inCI.removeProperty(index);
170 chuck 1.1.2.5 applyProjection(projNode, projProp);
171 inCI.addProperty(projProp);
172 }
173
174 // ATTN: what to do about selecting one element of an array. Is this allowed
175 // in basic, and if so, then it would cause a property type change.
176 // Line 461. May need to call CQLValue to figure this out.
177
178 if (!projNode->wildcard)
179 requiredProps.append(projNode->name);
180
181 projNode = projNode->sibling;
182 }
183
184 if (!projNode->wildcard)
185 removeUnneededProperties(inCI, requiredProps);
186
187 // ATTN delete the tree
188
189 }
190
191 chuck 1.1.2.5 // spec compliance
192 // assertions
193 // optimize
194 // Need a func to check well formed identifiers - ie. all emb props are scoped. Or does
195 // applyContext or bison do that?
196
197 void CQLSelectStatementRep::applyProjection(EmbeddedPropertyNode* node,
198 CIMProperty& nodeProp)
199 {
200 if (node->wildcard)
201 return;
202
203 PEGASUS_ASSERT(node->firstChild != NULL);
204
205 CIMInstance nodeInst;
206 CIMValue nodeVal = nodeProp.getValue();
207 // ATTN - UNCOMMENT when emb objs are supported
208 //PEGASUS_ASSERT(nodeVal.getType() == CIMTYPE_INSTANCE);
209 //nodeVal.get(nodeInst);
210
211 Array<CIMName> requiredProps;
212 chuck 1.1.2.5
213 EmbeddedPropertyNode * curChild = node->firstChild;
214 while (curChild != NULL)
215 {
216 if (curChild->firstChild != NULL)
217 {
218 Uint32 index = nodeInst.findProperty(curChild->name);
219 CIMProperty childProp = nodeInst.getProperty(index);
220 nodeInst.removeProperty(index);
221 applyProjection(curChild, childProp);
222 nodeInst.addProperty(childProp);
223 }
224
225 // ATTN: what to do about selecting one element of an array. Is this allowed
226 // in basic, and if so, then it would cause a property type change.
227 // Line 461. May need to call CQLValue to figure this out.
228
229 requiredProps.append(curChild->name);
230
231 curChild = curChild->sibling;
232 }
233 chuck 1.1.2.5
234 removeUnneededProperties(nodeInst, requiredProps);
235
236 // ATTN - UNCOMMENT when emb objs are supported
237 //CIMValue newNodeVal(nodeInst);
238 //nodeProp.setValue(newNodeVal);
239 }
240
241 void CQLSelectStatementRep::removeUnneededProperties(CIMInstance& inst,
242 Array<CIMName>& requiredProps)
243 {
244 for (Uint32 i = 0; i < inst.getPropertyCount(); i++)
245 {
246 Boolean found = false;
247 for (Uint32 j = 0; j < requiredProps.size(); j++)
248 {
249 if (inst.getProperty(i).getName() == requiredProps[j])
250 {
251 found = true;
252 break;
253 }
254 chuck 1.1.2.5 }
255
256 if (!found)
257 {
258 inst.removeProperty(i);
259 }
260 }
|
261 humberto 1.1.2.1 }
262
263 void CQLSelectStatementRep::validateClass(const CIMObjectPath& inClassName) throw(Exception)
264 {
|
265 chuck 1.1.2.5 Array<CQLIdentifier> fromList = _ctx->getFromList();
266 PEGASUS_ASSERT(fromList.size() == 1); // no joins yet
267
268 if (!inClassName.getClassName().equal(fromList[0].getName()))
269 {
270 throw Exception("TEMP MSG: not in the FROM list ");
271 }
272
273 try
274 {
275 _ctx->getClass(inClassName.getClassName());
276 }
277 catch (CIMException& ce)
278 {
279 if (ce.getCode() == CIM_ERR_INVALID_CLASS ||
280 ce.getCode() == CIM_ERR_NOT_FOUND)
281 {
282 // ATTN may just want to throw the CIMException rather than
283 // CQL exception
284 throw Exception("TEMP MSG - class does not exist");
285 }
286 chuck 1.1.2.5 }
|
287 humberto 1.1.2.1 }
288
289 void CQLSelectStatementRep::validateProperties() throw(Exception)
290 {
|
291 chuck 1.1.2.5 // assumes applyContext has been called
292
293 for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
294 {
295 validateProperty(_selectIdentifiers[i]);
296 }
297
298 for (Uint32 i = 0; i < _whereIdentifiers.size(); i++)
299 {
300 validateProperty(_whereIdentifiers[i]);
301 }
302 }
303
304 void CQLSelectStatementRep::validateProperty(CQLChainedIdentifier& chainId)
305 {
306 // assumes that applyContext has been called and all identfiers are well-formed
307
308 Array<CQLIdentifier> ids = chainId.getSubIdentifiers();
309
310 // Normalize to prepend the FROM class
311 // see the description of CQLIdentifier::applyContext
312 chuck 1.1.2.5 CIMName prevContext;
313 Uint32 startingPos = 0;
314 if (ids[0].isScoped())
315 {
316 Array<CQLIdentifier> fromList = _ctx->getFromList();
317 PEGASUS_ASSERT(fromList.size() == 1); // no joins yet
318 prevContext = fromList[0].getName();
319 }
320 else
321 {
322 prevContext = ids[0].getName();
323 startingPos = 1;
324 }
325
326 for (Uint32 pos = startingPos; pos < ids.size(); pos++)
327 {
328 CIMName classContext;
329 if (ids[pos].isScoped())
330 {
331 classContext = lookupFromClass(ids[pos].getScope());
332 if (classContext.getString() == String::EMPTY)
333 chuck 1.1.2.5 {
334 classContext = CIMName(ids[pos].getScope());
335 }
336 }
337 else
338 {
339 PEGASUS_ASSERT(pos == 1);
340 classContext = prevContext;
341 }
342
343 CIMClass classDef = _ctx->getClass(classContext);
344 if (classDef.findProperty(ids[pos].getName()) == PEG_NOT_FOUND)
345 {
346 throw Exception("TEMP MSG: prop not on scoped class");
347 }
348
349 if (!classContext.equal(prevContext))
350 {
351 if (!isSubClass(classContext, prevContext) &&
352 !isSubClass(prevContext, classContext))
353 {
354 chuck 1.1.2.5 throw Exception("TEMP MSG: section 5.4.1 violation!");
355 }
356 }
357
358 prevContext = classContext;
359 }
360 }
361
362 CIMName CQLSelectStatementRep::lookupFromClass(const String& lookup)
363 {
364 CQLIdentifier id = _ctx->findClass(lookup);
365
366 return id.getName();
|
367 humberto 1.1.2.1 }
368
|
369 chuck 1.1.2.3 Array<CIMObjectPath> CQLSelectStatementRep::getClassPathList()
|
370 humberto 1.1.2.1 {
|
371 chuck 1.1.2.5 Array<CQLIdentifier> ids = _ctx->getFromList();
372 PEGASUS_ASSERT(ids.size() == 1); // no joins yet
373
374 // No wbem-uri support yet.
375 CIMObjectPath path(String::EMPTY, _ctx->getNamespace(), ids[0].getName());
376
377 Array<CIMObjectPath> paths;
378 paths.append(path);
379
380 return paths;
|
381 humberto 1.1.2.1 }
382
383 CIMPropertyList CQLSelectStatementRep::getPropertyList(const CIMObjectPath& inClassName)
384 {
|
385 chuck 1.1.2.5 // assumes that applyContext had been called.
386
387 // check if namespace matches default namespace?
388
389 // No wbem-uri support yet
390 CIMName className = inClassName.getClassName();
391 CIMClass theClass = _ctx->getClass(className);
392
393 Boolean isWildcard;
394 Array<CIMName> reqProps;
395 for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
396 {
397 isWildcard = addRequiredProperty(reqProps, theClass, _selectIdentifiers[i]);
398
399 if (isWildcard)
400 {
401 return CIMPropertyList();
402 }
403 }
404
405 for (Uint32 i = 0; i < _whereIdentifiers.size(); i++)
406 chuck 1.1.2.5 {
407 isWildcard = addRequiredProperty(reqProps, theClass, _whereIdentifiers[i]);
408
409 PEGASUS_ASSERT(!isWildcard);
410 }
411
412 Uint32 propCnt = theClass.getPropertyCount();
413 Boolean allProps = true;
414 for (Uint32 i = 0; i < propCnt; i++)
415 {
416 if (!containsProperty(theClass.getProperty(i).getName(), reqProps))
417 {
418 allProps = false;
419 break;
420 }
421 }
422
423 if (allProps)
424 {
425 return CIMPropertyList();
426 }
427 chuck 1.1.2.5 else
428 {
429 return CIMPropertyList(reqProps);
430 }
431 }
432
433 Boolean CQLSelectStatementRep::addRequiredProperty(Array<CIMName>& reqProps,
434 CIMClass& theClass,
435 CQLChainedIdentifier& chainId)
436 {
437 // Assumes that applyContext had been called
438 // Does not look at properties on embedded objects
439
440 Array<CQLIdentifier> ids = chainId.getSubIdentifiers();
441
442 // see the description of CQLIdentifier::applyContext
443
444 if (ids[0].isScoped())
445 {
446 PEGASUS_ASSERT(!ids[0].isWildcard());
447
448 chuck 1.1.2.5 // Check if the scoped property is exposed by the class passed in.
449 if (theClass.findProperty(ids[0].getName()) != PEG_NOT_FOUND)
450 {
451 CIMName scopingClass = lookupFromClass(ids[0].getScope());
452 if (scopingClass.getString() == String::EMPTY)
453 {
454 scopingClass = CIMName(ids[0].getScope());
455 }
456
457 // Check if the scoping class is a subclass of the class passed in
458 Boolean sub = isSubClass(scopingClass, theClass.getClassName());
459
460 // Add to the required properties only if the scoping class
461 // is not a subclass of the class passed in
462 if (!sub)
463 {
464 if (!containsProperty(ids[0].getName(), reqProps))
465 {
466 reqProps.append(ids[0].getName());
467 }
468 }
469 chuck 1.1.2.5 }
470 }
471 else
472 {
473 if (ids[1].isWildcard())
474 {
475 return true;
476 }
477
478 if (theClass.findProperty(ids[1].getName()) != PEG_NOT_FOUND)
479 {
480 if (!containsProperty(ids[1].getName(), reqProps))
481 {
482 reqProps.append(ids[1].getName());
483 }
484 }
485 }
486
487 return false;
488 }
489
490 chuck 1.1.2.5 Boolean CQLSelectStatementRep::containsProperty(const CIMName& name,
491 const Array<CIMName>& props)
492 {
493 for (Uint32 i = 0; i < props.size(); i++)
494 {
495 if (props[i] == name)
496 {
497 return true;
498 }
499 }
500
501 return false;
502 }
503
504 Boolean CQLSelectStatementRep::isSubClass(const CIMName& derived,
505 const CIMName& base)
506 {
507 Array<CIMName> subClasses = _ctx->enumerateClassNames(base);
508 for (Uint32 i = 0; i < subClasses.size(); i++)
509 {
510 if (subClasses[i] == derived)
511 chuck 1.1.2.5 {
512 return true;
513 }
514 }
515
516 return false;
|
517 humberto 1.1.2.1 }
518
519 void CQLSelectStatementRep::appendClassPath(const CQLIdentifier& inIdentifier)
520 {
|
521 chuck 1.1.2.3 _ctx->insertClassPath(inIdentifier);
|
522 humberto 1.1.2.1 }
523
524 void CQLSelectStatementRep::setPredicate(CQLPredicate inPredicate)
525 {
|
526 chuck 1.1.2.3 _predicate = inPredicate;
|
527 humberto 1.1.2.1 }
528
529 void CQLSelectStatementRep::insertClassPathAlias(const CQLIdentifier& inIdentifier, String inAlias)
530 {
|
531 chuck 1.1.2.3 _ctx->insertClassPath(inIdentifier,inAlias);
|
532 humberto 1.1.2.1 }
533
534 void CQLSelectStatementRep::appendSelectIdentifier(const CQLChainedIdentifier& x)
535 {
|
536 chuck 1.1.2.3 _selectIdentifiers.append(x);
|
537 humberto 1.1.2.1 }
538
539 Boolean CQLSelectStatementRep::appendWhereIdentifier(const CQLChainedIdentifier& x)
540 {
|
541 chuck 1.1.2.3 _whereIdentifiers.append(x);
542 return true;
|
543 humberto 1.1.2.1 }
544
|
545 chuck 1.1.2.5 void CQLSelectStatementRep::applyContext()
546 {
547 // ATTN - wait for applyContext API
548 /*
549 for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
550 {
551 _selectIdentifiers[i].applyContext(*_ctx);
552 }
553
554 for (Uint32 i = 0; i < _whereIdentifiers.size(); i++)
555 {
556 _whereIdentifiers[i].applyContext(*_ctx);
557 }
558
559 if (hasWhereClause())
560 _predicate.applyContext(*_ctx);
561 */
562 }
563
564 void CQLSelectStatementRep::normalizeToDOC()
565 {
566 chuck 1.1.2.5
567 }
568
569 String CQLSelectStatementRep::toString()
570 {
|
571 chuck 1.1.2.4 printf("CQLSelectStatementRep::toString()\n");
572 String s("SELECT ");
573 for(Uint32 i = 0; i < _selectIdentifiers.size(); i++){
574 s.append(_selectIdentifiers[i].toString());
575 }
576 s.append(" FROM ");
577 Array<CQLIdentifier> _ids = _ctx->getFromList();
578 for(Uint32 i = 0; i < _ids.size(); i++){
579 s.append(_ids[i].toString());
580 }
581 if(_hasWhereClause){
582 s.append(" WHERE ");
583 s.append(_predicate.toString());
584 }
585 return s;
586 }
587
|
588 chuck 1.1.2.5 void CQLSelectStatementRep::setHasWhereClause()
589 {
|
590 chuck 1.1.2.4 _hasWhereClause = true;
591 }
592
|
593 chuck 1.1.2.5 Boolean CQLSelectStatementRep::hasWhereClause()
594 {
|
595 chuck 1.1.2.4 return _hasWhereClause;
596 }
597
|
598 chuck 1.1.2.5 void CQLSelectStatementRep::clear()
599 {
|
600 chuck 1.1.2.4 _ctx->clear();
601 }
602
|
603 humberto 1.1.2.1 PEGASUS_NAMESPACE_END
|