(file) Return to CQLSelectStatementRep.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / CQL

   1 chuck 1.1.2.12 //%2003////////////////////////////////////////////////////////////////////////
   2 chuck 1.1.2.3  //
   3                // Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development
   4                // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
   5 chuck 1.1.2.13 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
   6 chuck 1.1.2.3  // 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                // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23                //
  24                //==============================================================================
  25                //
  26                // Authors: David Rosckes (rosckes@us.ibm.com)
  27 chuck 1.1.2.3  //          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.14 #include <iostream>
  39                   
  40 chuck    1.1.2.5  #include <Pegasus/Common/CIMValue.h>
  41                   #include <Pegasus/Common/CIMInstance.h>
  42                   #include <Pegasus/Common/CIMProperty.h>
  43                   #include <Pegasus/Common/InternalException.h>
  44 chuck    1.1.2.6  #include <Pegasus/Common/Exception.h>
  45                   #include <Pegasus/Common/CIMStatusCode.h>
  46 chuck    1.1.2.14 #include <Pegasus/Common/AutoPtr.h>
  47 chuck    1.1.2.5  #include "CQLValue.h"
  48                   #include "CQLIdentifier.h"
  49                   #include "CQLChainedIdentifier.h"
  50                   
  51 chuck    1.1.2.6  // ATTN: TODOs - 
  52                   // spec compliance
  53                   // assertions
  54                   // optimize
  55                   // localized CQL exceptions
  56                   // documentation
  57                   // trace? but this could be used by provider
  58 chuck    1.1.2.5  
  59 humberto 1.1.2.1  PEGASUS_NAMESPACE_BEGIN
  60                   
  61 chuck    1.1.2.6  struct PropertyNode
  62 chuck    1.1.2.5  {
  63 chuck    1.1.2.20   CIMName name;              // property name
  64                     CIMName scope;             // class the property is on
  65                     Boolean wildcard;          // true if this property is a wildcard 
  66 chuck    1.1.2.14   AutoPtr<PropertyNode> sibling;
  67                     AutoPtr<PropertyNode> firstChild;
  68                   
  69                     PropertyNode() {/*PEGASUS_STD(cout) << "new " << this << PEGASUS_STD(endl);*/}
  70                     ~PropertyNode() {/*PEGASUS_STD(cout) << "delete " << this << PEGASUS_STD(endl);*/}
  71 chuck    1.1.2.5  };
  72                   
  73                   
  74 chuck    1.1.2.3  CQLSelectStatementRep::CQLSelectStatementRep()
  75 chuck    1.1.2.9    :SelectStatementRep(),
  76 chuck    1.1.2.16    _hasWhereClause(false),
  77                      _contextApplied(false)
  78 humberto 1.1.2.1  {
  79                   }
  80                   
  81 chuck    1.1.2.16 CQLSelectStatementRep::CQLSelectStatementRep(String& inQlang,
  82 chuck    1.1.2.17                                              String& inQuery,
  83                                                                QueryContext& inCtx)
  84 chuck    1.1.2.9    :SelectStatementRep(inQlang, inQuery, inCtx),
  85 chuck    1.1.2.16    _hasWhereClause(false),
  86                      _contextApplied(false)
  87 chuck    1.1.2.3  {
  88 humberto 1.1.2.2  }
  89                   
  90 chuck    1.1.2.3  CQLSelectStatementRep::CQLSelectStatementRep(const CQLSelectStatementRep& rep)
  91                     :SelectStatementRep(rep),
  92                      _selectIdentifiers(rep._selectIdentifiers),
  93 chuck    1.1.2.9     _hasWhereClause(rep._hasWhereClause),
  94 chuck    1.1.2.16    _predicate(rep._predicate),
  95                      _contextApplied(rep._contextApplied)
  96 humberto 1.1.2.1  {
  97                   }
  98                   
  99 chuck    1.1.2.3  CQLSelectStatementRep::~CQLSelectStatementRep()
 100 humberto 1.1.2.1  {
 101                   }
 102                   
 103 chuck    1.1.2.3  CQLSelectStatementRep& CQLSelectStatementRep::operator=(const CQLSelectStatementRep& rhs)
 104 humberto 1.1.2.1  {
 105 chuck    1.1.2.3    if (this ==  &rhs)
 106                       return *this;
 107                   
 108                     SelectStatementRep::operator=(rhs);
 109                   
 110                     _selectIdentifiers = rhs._selectIdentifiers;
 111                     _predicate = rhs._predicate;
 112 chuck    1.1.2.16   _contextApplied = rhs._contextApplied;
 113                     _hasWhereClause = rhs._hasWhereClause;
 114 chuck    1.1.2.3  
 115                     return *this;
 116                   }
 117                   
 118                   Boolean CQLSelectStatementRep::evaluate(const CIMInstance& inCI)
 119                   {
 120 chuck    1.1.2.4    if (!hasWhereClause())
 121 chuck    1.1.2.16   {
 122 chuck    1.1.2.4      return true;
 123 chuck    1.1.2.16   }
 124 chuck    1.1.2.4    else
 125 chuck    1.1.2.11   {
 126 chuck    1.1.2.16     if (!_contextApplied)
 127                         applyContext();
 128                   
 129 chuck    1.1.2.11     try
 130                       {
 131                         return _predicate.evaluate(inCI, *_ctx);
 132                       }
 133                       catch (UninitializedObjectException& )
 134                       {
 135                         // The null contagion rule.
 136                         // ATTN change this to a specific CQLException
 137                         return false;
 138                       }
 139                     }
 140 chuck    1.1.2.3  }
 141                   
 142                   void CQLSelectStatementRep::applyProjection(CIMInstance& inCI) throw(Exception)
 143                   {
 144 chuck    1.1.2.16   if (!_contextApplied)
 145                       applyContext();
 146 chuck    1.1.2.3  
 147 chuck    1.1.2.20   //
 148                     // Build a tree to represent the projected properties from the select list
 149                     // of chained identifiers.  This is needed because embedded instances below 
 150                     // the FROM class form a tree structure when projected.
 151                     //
 152                     // The design of the tree is to gather all the required properties for 
 153                     // an instance at a node as child nodes.  The root node 
 154                     // of the tree represents the instance passed in to this function.  Below the 
 155                     // root there can be nodes that are required embedded instance properties. 
 156                     // The child nodes of these embedded instance nodes represent the required
 157                     // properties on the embedded instance (which may themselves be embedded instances).
 158                     //
 159                     // Each node has a name, which is in 2 parts -- the property name and the 
 160                     // scope (ie. the class the property is on).  This allows the scoping
 161                     // operator to be handled correctly, so that the parent instance can be
 162                     // checked to see if it is the right class to provide the property.
 163                     // Note that the scoping is a base class; ie. the parent instance of a node
 164                     // may be a subclass of the scope.
 165                     //
 166                   
 167                     // Set up the root node of the tree.  This represents the instance
 168 chuck    1.1.2.20   // passed in.
 169 chuck    1.1.2.14   AutoPtr<PropertyNode> rootNode(new PropertyNode);
 170 chuck    1.1.2.5    Array<CQLIdentifier> fromList = _ctx->getFromList();
 171                     rootNode->name = fromList[0].getName();  // not doing joins
 172 chuck    1.1.2.20   rootNode->scope = fromList[0].getName(); // not used on root, just to fill in the var
 173 chuck    1.1.2.17   rootNode->wildcard = false;
 174 chuck    1.1.2.20  
 175                     // Build the tree below the root.
 176 chuck    1.1.2.5    for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
 177                     {
 178 chuck    1.1.2.20     // Get the chain elements
 179 chuck    1.1.2.16     Array<CQLIdentifier> ids = _selectIdentifiers[i].getSubIdentifiers();
 180 chuck    1.1.2.6  
 181 chuck    1.1.2.20     PEGASUS_ASSERT(ids.size() > 1);
 182 chuck    1.1.2.5  
 183 chuck    1.1.2.14     PropertyNode * curNode = rootNode.get();
 184                       PropertyNode * curChild = curNode->firstChild.get();
 185 chuck    1.1.2.5  
 186 chuck    1.1.2.20     // Loop through the identifiers in the chain.
 187                       // NOTE: this starts at the position *after* the FROM class
 188                       // So, the loop index is always one position after the current node,
 189                       // ie. it will become a child node of the current node.
 190 chuck    1.1.2.5      for (Uint32 j = 1; j < ids.size(); j++)
 191                       {
 192 chuck    1.1.2.20       // If the child is wildcarded, then every property exposed by the
 193                         // class of the instance at the current node is required.
 194                         // Mark the current node as wildcarded.
 195 chuck    1.1.2.5        if (ids[j].isWildcard())
 196                         {
 197 chuck    1.1.2.17         curNode->wildcard = true;
 198                           break;
 199 chuck    1.1.2.5        }
 200                   
 201 chuck    1.1.2.20       // Determine if this identifier is already a child node of
 202                         // the current node.
 203 chuck    1.1.2.5        Boolean found = false;
 204                         while (curChild != NULL && !found)
 205                         {
 206 chuck    1.1.2.20         // The scoping class is either the scope of the identifier
 207                           // or the FROM class if the identifier is not scoped.
 208                           String scope = fromList[0].getName().getString();
 209                           if (ids[j].isScoped())
 210                           {
 211                             scope = ids[j].getScope();
 212                           }
 213                   
 214 chuck    1.1.2.17         if (curChild->name == ids[j].getName() &&
 215 chuck    1.1.2.20             String::equalNoCase(curChild->scope.getString(), scope))
 216 chuck    1.1.2.5          {
 217 chuck    1.1.2.20           // Name and scope match.  The identifier already has a child node.
 218 chuck    1.1.2.17           found = true;
 219                           }
 220                           else
 221 chuck    1.1.2.5          {
 222 chuck    1.1.2.17           curChild = curChild->sibling.get();
 223                           }
 224 chuck    1.1.2.5        }
 225                   
 226                         if (!found)
 227                         {
 228 chuck    1.1.2.20         // The identifier doesn't already have a child node. 
 229                           // Create a node and add it as a child to the current node.
 230 chuck    1.1.2.17         curChild = new PropertyNode;
 231                           curChild->sibling = curNode->firstChild;
 232                           curChild->name = ids[j].getName();
 233                           curChild->wildcard = false;
 234                           curNode->firstChild.reset(curChild);  // safer than using the = operator
 235                         }
 236 chuck    1.1.2.16 
 237 chuck    1.1.2.20       // Set the scope for the child node
 238 chuck    1.1.2.17       if (ids[j].isScoped())
 239                         {
 240 chuck    1.1.2.20         // Child node has a scoping class
 241                           PEGASUS_ASSERT(ids[j].getScope().size() > 0);
 242                           curChild->scope =  CIMName(ids[j].getScope());
 243 chuck    1.1.2.17       }
 244                         else
 245                         {
 246 chuck    1.1.2.20         // Not scoped.  The scope is the FROM class.
 247                           PEGASUS_ASSERT(j == 1);
 248                           PEGASUS_ASSERT(fromList[0].getName().getString().size() > 0);
 249                           curChild->scope = fromList[0].getName();
 250 chuck    1.1.2.5        }
 251                   
 252                         curNode = curChild;
 253 chuck    1.1.2.14       curChild = curNode->firstChild.get();
 254 chuck    1.1.2.5      }
 255                     }
 256                   
 257 chuck    1.1.2.20   //
 258                     // Do the projection.
 259                     //
 260                   
 261 chuck    1.1.2.5    Array<CIMName> requiredProps;
 262 chuck    1.1.2.17   Boolean allPropsRequired = rootNode->wildcard;
 263                   
 264 chuck    1.1.2.20   // Loop through the children of the root node.
 265                     // The root node represents the FROM class,
 266                     // and the child nodes are the required properties on the FROM class.
 267 chuck    1.1.2.15   PropertyNode* childNode = rootNode->firstChild.get();
 268                     while (childNode != NULL)
 269 chuck    1.1.2.5    {
 270 chuck    1.1.2.20     // Determine if the instance passed in meets the class scoping
 271                       // rules for the current child node.
 272                       Boolean filterable = isFilterable(inCI, childNode);
 273                   
 274                       // If the instance is filterable, and the child node has children,
 275                       // then the child is assumed to be an embedded instance, and we
 276                       // need to recurse to apply the projection on the embedded instance.
 277                       // (the check for embedded instance is done in the recursive call)
 278                       if (filterable && childNode->firstChild.get() != NULL)
 279                       {
 280                         // We need to project on an embedded instance property. The steps are to
 281                         // remove the embedded instance property from the instance passed in,
 282                         // project on that embedded instance property, and then add the projected 
 283                         // embedded instance property back to the instance passed in.
 284 chuck    1.1.2.15       Uint32 index = inCI.findProperty(childNode->name);
 285 chuck    1.1.2.20       if (index != PEG_NOT_FOUND)
 286                         {
 287                           // The embedded instance has the required embedded instance property.
 288                           CIMProperty childProp = inCI.getProperty(index);
 289                           inCI.removeProperty(index);
 290                           applyProjection(childNode, childProp);
 291                           inCI.addProperty(childProp);
 292                         }
 293 chuck    1.1.2.5      }
 294                   
 295 chuck    1.1.2.20     // If the node is not wildcarded, and the instance passed in
 296                       // is filterable, then add the current child to the list
 297                       // of required properties on the instance passed in.
 298                       if (!allPropsRequired && filterable)
 299 chuck    1.1.2.16     {
 300 chuck    1.1.2.20       requiredProps.append(childNode->name);
 301 chuck    1.1.2.16     }
 302                   
 303 chuck    1.1.2.17     childNode = childNode->sibling.get();
 304 chuck    1.1.2.16   }
 305                   
 306 chuck    1.1.2.20   // Remove the properties that are not in the projection.
 307                     // This also checks for missing required properties.
 308 chuck    1.1.2.21   removeUnneededProperties(inCI,
 309                                              allPropsRequired,
 310                                              fromList[0].getName(),
 311                                              requiredProps);
 312 chuck    1.1.2.5  }
 313                   
 314 chuck    1.1.2.6  void CQLSelectStatementRep::applyProjection(PropertyNode* node,
 315 chuck    1.1.2.17                                             CIMProperty& nodeProp)
 316 chuck    1.1.2.5  {
 317 chuck    1.1.2.14   PEGASUS_ASSERT(node->firstChild.get() != NULL);
 318 chuck    1.1.2.5  
 319 chuck    1.1.2.20   //
 320                     // The property passed in must be an embedded instance. It is not
 321                     // allowed to project properties on embedded classes.
 322                     //
 323                     // Get the embedded instance from the property.
 324                     //
 325                   
 326 chuck    1.1.2.5    CIMValue nodeVal = nodeProp.getValue();
 327 chuck    1.1.2.20 // ATTN - UNCOMMENT when emb objs are supported 
 328                   /*
 329                     if (nodeVal.getType() != CIMTYPE_OBJECT)
 330                     {
 331                       throw Exception("TEMP MSG: applyProjection - property must be emb obj");
 332                     }
 333                   */
 334                   
 335                     CIMObject nodeObj;
 336                   // ATTN - UNCOMMENT when emb objs are supported 
 337                   // nodeVal.get(nodeObj);
 338                     if (!nodeObj.isInstance())
 339                     {
 340                       throw Exception("TEMP MSG: applyProjection - not allowed to project properties on classes");
 341                     }
 342                   
 343                     CIMInstance nodeInst(nodeObj);  
 344                       
 345                     //
 346                     // Do the projection.
 347                     //
 348 chuck    1.1.2.5  
 349                     Array<CIMName> requiredProps;
 350 chuck    1.1.2.17   Boolean allPropsRequired = node->wildcard;
 351 chuck    1.1.2.5  
 352 chuck    1.1.2.20   // Loop through the children of the node.
 353                     // The node represents an embedded instance,
 354                     // and the child nodes are the required properties on the embedded instance.
 355 chuck    1.1.2.14   PropertyNode * curChild = node->firstChild.get();
 356 chuck    1.1.2.5    while (curChild != NULL)
 357                     {
 358 chuck    1.1.2.20     // Determine if the embedded instance meets the class scoping
 359                       // rules for the current child node
 360                       Boolean filterable = isFilterable(nodeInst, curChild);
 361                   
 362                       // If the embedded instance is filterable, and the child node has children,
 363                       // then the child is assumed to be an embedded instance, and we
 364                       // need to recurse to apply the projection on the child embedded instance.
 365                       // (the check for embedded instance is done in the recursive call)
 366                       if (filterable && curChild->firstChild.get() != NULL)
 367                       {
 368                         // We need to project on an embedded instance property. The steps are to
 369                         // remove the embedded instance property from the current instance,
 370                         // project on that embedded instance property, and then add the projected 
 371                         // embedded instance property back to the current instance.
 372 chuck    1.1.2.5        Uint32 index = nodeInst.findProperty(curChild->name);
 373 chuck    1.1.2.20       if (index != PEG_NOT_FOUND)
 374                         {
 375                           // The embedded instance has the required embedded instance property.
 376                           CIMProperty childProp = nodeInst.getProperty(index); 
 377                           nodeInst.removeProperty(index);
 378                           applyProjection(curChild, childProp);
 379                           nodeInst.addProperty(childProp);
 380                         }
 381 chuck    1.1.2.5      }
 382                   
 383 chuck    1.1.2.20     // If the node is not wildcarded, and the embedded instance
 384                       // is filterable, then add the current child to the list
 385                       // of required properties on the embedded instance.
 386                       if (!allPropsRequired && filterable)
 387 chuck    1.1.2.14     {
 388 chuck    1.1.2.20       // The instance is filterable, add the property to the required list. 
 389                         requiredProps.append(node->name);
 390 chuck    1.1.2.16     }
 391                   
 392 chuck    1.1.2.14     curChild = curChild->sibling.get();
 393 chuck    1.1.2.5    }
 394                   
 395 chuck    1.1.2.20   // Remove the properties that are not in the projection.
 396                     // This also checks for missing required properties.
 397 chuck    1.1.2.21   removeUnneededProperties(nodeInst, 
 398                                              allPropsRequired,
 399                                              nodeInst.getClassName(),
 400                                              requiredProps);
 401 chuck    1.1.2.5  
 402 chuck    1.1.2.20   // Put the projected instance back into the property.
 403 chuck    1.1.2.5  // ATTN - UNCOMMENT when emb objs are supported
 404                   //CIMValue newNodeVal(nodeInst);
 405                   //nodeProp.setValue(newNodeVal);
 406                   } 
 407                   
 408 chuck    1.1.2.20 Boolean CQLSelectStatementRep::isFilterable(const  CIMInstance& inst,
 409                                                               PropertyNode* node)
 410                   {
 411                     //
 412                     // Determine if an instance is filterable for a scoped property (ie. its
 413                     // type is the scoping class or a subclass of the scoping class where the
 414                     // property exists)
 415                     //
 416                     // Note that an instance that is unfilterable is not considered
 417                     // an error.  In CQL, an instance that is not of the required scope
 418                     // would cause a NULL to be placed in the result set column for the 
 419                     // property. However since we are not implementing result set in stage1,
 420                     // just skip the property.  This can lead to an instance having
 421                     // NO required properties even though it is derived from the FROM class.
 422                     // This can easily happen if the scoping operator is used.
 423                     //
 424 chuck    1.1.2.17 
 425                     Boolean filterable = false;
 426                     if (inst.getClassName() == node->scope)
 427                     {
 428 chuck    1.1.2.20     // The instance's class is the same as the required scope
 429 chuck    1.1.2.17     filterable = true;
 430                     }
 431 chuck    1.1.2.20   else
 432 chuck    1.1.2.17   {
 433 chuck    1.1.2.20     try 
 434                       {
 435                         if (_ctx->isSubClass(node->scope, inst.getClassName()))
 436                         {
 437                           // The instance's class is a subclass or of the required scope.
 438                           filterable = true;
 439                         }
 440                       }
 441                       catch (CIMException& ce)
 442                       {
 443                         if (ce.getCode() == CIM_ERR_INVALID_CLASS || 
 444                             ce.getCode() == CIM_ERR_NOT_FOUND)
 445                         {
 446                           // The scoping class was not found in the schema.
 447                           // Just swallow this error because according to the
 448                           // spec we should be putting NULL in the result column,
 449                           // which means skipping the property on the instance.
 450                           ;
 451                         }
 452                       }
 453 chuck    1.1.2.17   }
 454 chuck    1.1.2.20   
 455                     return filterable;
 456 chuck    1.1.2.17 } 
 457                   
 458 chuck    1.1.2.5  void CQLSelectStatementRep::removeUnneededProperties(CIMInstance& inst, 
 459 chuck    1.1.2.21                                                      Boolean& allPropsRequired,
 460                                                                        const CIMName& allPropsClass,
 461 chuck    1.1.2.17                                                      Array<CIMName>& requiredProps)
 462 chuck    1.1.2.5  {
 463 chuck    1.1.2.20   // Implementation note:
 464                     // Scoping operator before a wildcard is not allowed:
 465                     // Example:
 466                     // SELECT fromclass.embobj1.scope1::* FROM fromclass
 467                     //
 468 chuck    1.1.2.21   // However, the following are allowed:
 469                     // SELECT fromclass.embobj1.* FROM fromclass
 470                     // (this means that all the properties on the class of instance embobj1
 471                     //  are required)
 472                     //
 473                     // SELECT fromclass.* FROM fromclass
 474                     // (this that all the properties on class fromclass are required
 475                     //  to be on the instance being projected, not including any
 476                     //  properties on a subclass of fromclass)
 477 chuck    1.1.2.20 
 478                     // If all properties are required (ie. wildcarded), then rebuild the 
 479                     // required property list from all the properties on the FROM class 
 480 chuck    1.1.2.17   if (allPropsRequired)
 481 chuck    1.1.2.16   {
 482 chuck    1.1.2.17     requiredProps.clear();
 483 chuck    1.1.2.21     CIMClass cls = _ctx->getClass(allPropsClass);
 484 chuck    1.1.2.16     Array<CIMName> clsProps;
 485                       for (Uint32 i = 0; i < cls.getPropertyCount(); i++)
 486                       {
 487                         requiredProps.append(cls.getProperty(i).getName());
 488                       }
 489                     }
 490                   
 491 chuck    1.1.2.20   // Find out what properties are on the instance.
 492 chuck    1.1.2.16   Array<CIMName> supportedProps;
 493 chuck    1.1.2.5    for (Uint32 i = 0; i < inst.getPropertyCount(); i++)
 494                     {
 495 chuck    1.1.2.16     supportedProps.append(inst.getProperty(i).getName());
 496                     }
 497                     
 498 chuck    1.1.2.20   // Check that all required properties are on the instance.
 499 chuck    1.1.2.16   for (Uint32 i = 0; i < requiredProps.size(); i++)
 500                     {
 501                       if (!containsProperty(requiredProps[i], supportedProps))
 502 chuck    1.1.2.5      {
 503 chuck    1.1.2.17       throw Exception("TEMP MSG - instance missing required property: " + requiredProps[i].getString());
 504 chuck    1.1.2.5      }
 505 chuck    1.1.2.16   }
 506 chuck    1.1.2.5  
 507 chuck    1.1.2.20   // Remove the properties on the instance that are not required.
 508 chuck    1.1.2.16   for (Uint32 i = 0; i < supportedProps.size(); i++)
 509                     {
 510                       if (!containsProperty(supportedProps[i], requiredProps))
 511 chuck    1.1.2.5      {
 512 chuck    1.1.2.17       Uint32 index = inst.findProperty(supportedProps[i]);
 513                         PEGASUS_ASSERT(index != PEG_NOT_FOUND);
 514                         inst.removeProperty(index);
 515 chuck    1.1.2.5      }
 516                     }
 517 humberto 1.1.2.1  }
 518                   
 519                   void CQLSelectStatementRep::validateClass(const CIMObjectPath& inClassName) throw(Exception)
 520                   {
 521 chuck    1.1.2.5    Array<CQLIdentifier> fromList = _ctx->getFromList();
 522                     PEGASUS_ASSERT(fromList.size() == 1);  // no joins yet
 523                   
 524 chuck    1.1.2.22   // Check if the classname passed in is the FROM class or a subclass
 525                     // of the FROM class.
 526 chuck    1.1.2.5    if (!inClassName.getClassName().equal(fromList[0].getName()))
 527                     {
 528 chuck    1.1.2.22     // Not the FROM class, check if it is a subclass of the FROM
 529                       QueryContext::ClassRelation rel;
 530                       try
 531                       {
 532                         rel = _ctx->getClassRelation(fromList[0].getName(),
 533                                                      inClassName.getClassName());
 534                       }
 535                       catch (CIMException& ce)
 536                       {
 537                         if (ce.getCode() == CIM_ERR_INVALID_CLASS || 
 538                             ce.getCode() == CIM_ERR_NOT_FOUND)
 539                         {
 540                           // Either the FROM or the class passed in does not exist
 541                           // ATTN may just want to throw the CIMException rather than
 542                           // CQL exception
 543                           throw Exception("TEMP MSG - class does not exist: " + ce.getMessage());
 544                         }
 545 chuck    1.1.2.5  
 546 chuck    1.1.2.22       throw;
 547                       }    
 548                     
 549                       if (rel != QueryContext::SUBCLASS)
 550                       {
 551                         throw Exception("TEMP MSG: class is not the FROM class and not a subclass of FROM class");
 552                       }
 553 chuck    1.1.2.5    }
 554 chuck    1.1.2.22   else
 555 chuck    1.1.2.5    {
 556 chuck    1.1.2.22     // Class passed in is the FROM class.  Check if it exists.
 557                       try
 558 chuck    1.1.2.5      {
 559 chuck    1.1.2.22       _ctx->getClass(inClassName.getClassName());
 560                       }
 561                       catch (CIMException& ce)
 562                       {
 563                         if (ce.getCode() == CIM_ERR_INVALID_CLASS || 
 564                             ce.getCode() == CIM_ERR_NOT_FOUND)
 565                         {
 566                           // ATTN may just want to throw the CIMException rather than
 567                           // CQL exception
 568                           throw Exception("TEMP MSG - class does not exist " + ce.getMessage());
 569                         }
 570                         
 571                         throw;
 572 chuck    1.1.2.5      }
 573                     }
 574 humberto 1.1.2.1  }
 575                   
 576 chuck    1.1.2.6  //
 577                   // Validates that all the chained identifiers in the statement meet
 578                   // the rules in the CQL spec vs.the class definitions in the repository
 579                   //
 580 humberto 1.1.2.1  void CQLSelectStatementRep::validateProperties() throw(Exception)
 581                   {
 582 chuck    1.1.2.16   if (!_contextApplied)
 583                       applyContext();
 584 chuck    1.1.2.5  
 585                     for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
 586                     {
 587                       validateProperty(_selectIdentifiers[i]);
 588                     }
 589 chuck    1.1.2.23 
 590                     Array<CQLChainedIdentifier> _whereIdentifiers = _ctx->getWhereList();
 591 chuck    1.1.2.5    for (Uint32 i = 0; i < _whereIdentifiers.size(); i++)
 592                     {
 593                       validateProperty(_whereIdentifiers[i]);
 594                     }
 595                   }
 596                   
 597 chuck    1.1.2.6  //
 598                   // Validates that the chained identifier meets all the rules in the CQL
 599                   // spec vs.the class definitions in the repository
 600                   //
 601 chuck    1.1.2.5  void CQLSelectStatementRep::validateProperty(CQLChainedIdentifier& chainId)
 602                   {
 603 chuck    1.1.2.17   // Note: applyContext has been called beforehand
 604                     
 605 chuck    1.1.2.5    Array<CQLIdentifier> ids = chainId.getSubIdentifiers();
 606                   
 607 chuck    1.1.2.20   Uint32 startingPos = 0;
 608 chuck    1.1.2.16   CIMName curContext;
 609 chuck    1.1.2.5    for (Uint32 pos = startingPos; pos < ids.size(); pos++)
 610                     {
 611 chuck    1.1.2.6      // Determine the current class context
 612 chuck    1.1.2.5      if (ids[pos].isScoped())
 613                       {
 614 chuck    1.1.2.20       // The chain element is scoped.  Use the scoping
 615                         // class as the current context.  Note: this depends 
 616                         // on applyContext resolving the class aliases before we get here.
 617                         curContext = CIMName(ids[pos].getScope());
 618 chuck    1.1.2.5      }
 619                       else
 620                       {
 621 chuck    1.1.2.20       // The chain element is not scoped.  Assume that we are
 622                         // before a position that is required to be scoped.
 623                         // (applyContext validates that the chained identifier
 624                         // has scoped identifiers in the required positions).
 625                         // The current context is the name at the first position,
 626                         // which must be a classname (ie. right side of ISA where
 627                         // the only element in the chain is a classname, or
 628                         // cases where the FROM class is the first, and maybe only,
 629                         // element of the chain).
 630                         PEGASUS_ASSERT((pos < startingPos + 2) || ids[pos].isWildcard());
 631                         curContext = ids[0].getName();
 632 chuck    1.1.2.6      }
 633                   
 634                       // Get the class definition of the current class context
 635                       CIMClass classDef;
 636                       try 
 637                       {
 638                         classDef = _ctx->getClass(curContext);
 639                       }
 640                       catch (CIMException& ce)
 641                       {
 642                         if (ce.getCode() == CIM_ERR_NOT_FOUND ||
 643 chuck    1.1.2.17           ce.getCode() == CIM_ERR_INVALID_CLASS)
 644 chuck    1.1.2.6        {
 645 chuck    1.1.2.17         // ATTN: better to just throw the CIMException rather
 646                           // than the CQL exception?
 647                           throw Exception("TEMP_MSG: class context does not exist: " + curContext.getString());
 648 chuck    1.1.2.6        }
 649 chuck    1.1.2.5      }
 650                   
 651 chuck    1.1.2.20     // Now do the checks for properties existing on the current class context
 652                       // and the class relationship rules in section 5.4.1.
 653                       // Only do these checks if the chain id has a property.
 654                       if (pos > startingPos)
 655 chuck    1.1.2.5      {
 656 chuck    1.1.2.17       if (ids[pos].isWildcard())
 657                         {
 658 chuck    1.1.2.20         // The wildcard is at the end (verified by applyContext), so
 659                           // no checking is required at this position.
 660 chuck    1.1.2.17         continue;
 661                         }
 662 chuck    1.1.2.5  
 663 chuck    1.1.2.17       // Determine if the property name at the current position
 664                         // exists on the current class context.
 665                         Uint32 propertyIndex = classDef.findProperty(ids[pos].getName());
 666                         if (propertyIndex == PEG_NOT_FOUND)
 667                         {
 668 chuck    1.1.2.20         throw Exception("TEMP MSG: prop not on class context: " + ids[pos].getName().getString());
 669 chuck    1.1.2.17       }
 670                   
 671                         // Checking class relationship rules in section 5.4.1.
 672                         // For validateProperties, this only applies to the first
 673 chuck    1.1.2.20       // property in the chain.  This is because once we get into
 674                         // embedded properties we don't know what the class will be
 675                         // until we have an instance.
 676                         if ((pos == (startingPos+1)) && !curContext.equal(ids[0].getName()))
 677                         {
 678                           // Its the first property, and the class context is not the FROM class.
 679                           // Check the class relationship between the scoping class and the FROM class.
 680                           if (_ctx->getClassRelation(ids[0].getName(), curContext) == QueryContext::NOTRELATED)
 681 chuck    1.1.2.17         {
 682                             throw Exception("TEMP MSG: section 5.4.1 violation!");
 683                           }
 684                         }
 685                   
 686                         // If the current position implies an embedded object, then
 687                         // verify that the property is an embedded object
 688 chuck    1.1.2.20       if ((pos > startingPos) && (pos < (ids.size() - 1))) 
 689 chuck    1.1.2.5        {
 690 chuck    1.1.2.17         CIMProperty embObj = classDef.getProperty(propertyIndex);
 691                           CIMName qual("EmbeddedObject");
 692                           if (embObj.findQualifier(qual) == PEG_NOT_FOUND)
 693                           {
 694                             throw Exception("TEMP MSG: property is not an embedded object: " + embObj.getName().getString());
 695                           }
 696 chuck    1.1.2.5        }
 697                       }
 698                     }
 699                   }
 700                   
 701                   CIMName CQLSelectStatementRep::lookupFromClass(const String&  lookup)
 702                   {
 703                     CQLIdentifier id = _ctx->findClass(lookup);
 704                   
 705                     return id.getName();
 706 humberto 1.1.2.1  }
 707                   
 708 chuck    1.1.2.3  Array<CIMObjectPath> CQLSelectStatementRep::getClassPathList()
 709 humberto 1.1.2.1  {
 710 chuck    1.1.2.5    Array<CQLIdentifier> ids = _ctx->getFromList();
 711                     PEGASUS_ASSERT(ids.size() == 1);  // no joins yet
 712                   
 713                     // No wbem-uri support yet.
 714                     CIMObjectPath path(String::EMPTY, _ctx->getNamespace(), ids[0].getName());
 715                   
 716                     Array<CIMObjectPath> paths;
 717                     paths.append(path);
 718                   
 719                     return paths;
 720 humberto 1.1.2.1  }
 721                   
 722                   CIMPropertyList CQLSelectStatementRep::getPropertyList(const CIMObjectPath& inClassName)
 723                   {
 724 chuck    1.1.2.16   if (!_contextApplied)
 725                       applyContext();
 726 chuck    1.1.2.5  
 727 chuck    1.1.2.20   // Get the classname.  Note: since wbem-uri is not supported yet,
 728                     // only use the classname part of the path. 
 729 chuck    1.1.2.5    CIMName className = inClassName.getClassName();
 730 chuck    1.1.2.20   if (className.isNull())
 731                     {
 732                       // If the caller passed in an empty className, then the 
 733                       // FROM class is to be used.
 734                       className = _ctx->getFromList()[0].getName();
 735                     }
 736                     
 737 chuck    1.1.2.5    Boolean isWildcard;
 738                     Array<CIMName> reqProps;
 739 chuck    1.1.2.20   Array<CIMName> matchedScopes;
 740                     Array<CIMName> unmatchedScopes;
 741                   
 742                     // Add required properties from the select list.
 743 chuck    1.1.2.5    for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
 744                     {
 745 chuck    1.1.2.20     isWildcard = addRequiredProperty(reqProps, 
 746                                                        className,
 747                                                        _selectIdentifiers[i],
 748                                                        matchedScopes,
 749                                                        unmatchedScopes);
 750 chuck    1.1.2.5      
 751                       if (isWildcard)
 752                       {
 753 chuck    1.1.2.20       // If any wildcard is found then all properties are required.
 754                         // Return null property list to indicate all properties required.
 755 chuck    1.1.2.5        return CIMPropertyList();
 756                       }
 757                     }
 758                   
 759 chuck    1.1.2.20   // Add required properties from the WHERE clause.
 760 chuck    1.1.2.23   Array<CQLChainedIdentifier> _whereIdentifiers = _ctx->getWhereList();
 761 chuck    1.1.2.5    for (Uint32 i = 0; i < _whereIdentifiers.size(); i++)
 762                     {
 763 chuck    1.1.2.20     isWildcard = addRequiredProperty(reqProps,
 764                                                        className,
 765                                                        _whereIdentifiers[i],
 766                                                        matchedScopes,
 767                                                        unmatchedScopes);                                     
 768 chuck    1.1.2.5  
 769 chuck    1.1.2.20     // Wildcards are not allowed in the WHERE clause
 770 chuck    1.1.2.5      PEGASUS_ASSERT(!isWildcard);
 771                     }
 772                   
 773 chuck    1.1.2.20   // Check if every property on the class is required.
 774                     CIMClass theClass = _ctx->getClass(className);
 775 chuck    1.1.2.5    Uint32 propCnt = theClass.getPropertyCount();
 776                     Boolean allProps = true;
 777                     for (Uint32 i = 0; i < propCnt; i++)
 778                     {
 779                       if (!containsProperty(theClass.getProperty(i).getName(), reqProps))
 780                       {
 781                         allProps = false;
 782                         break;
 783                       }
 784                     }
 785                   
 786                     if (allProps)
 787                     {
 788 chuck    1.1.2.20     // Return null property list to indicate all properties are required.
 789 chuck    1.1.2.5      return CIMPropertyList();
 790                     }
 791                     else
 792                     {
 793 chuck    1.1.2.20     // Return the required property list.  Note that it is possible to return
 794                       // an empty list in the case of no required properties for the classname
 795                       // passed in.  This can happen when the scoping operator is used.
 796 chuck    1.1.2.5      return CIMPropertyList(reqProps);
 797                     }
 798                   }
 799                   
 800                   Boolean CQLSelectStatementRep::addRequiredProperty(Array<CIMName>& reqProps,
 801 chuck    1.1.2.20                                                    CIMName& className,
 802                                                                      CQLChainedIdentifier& chainId,
 803                                                                      Array<CIMName>& matchedScopes,
 804                                                                      Array<CIMName>& unmatchedScopes)
 805                   {
 806                     //
 807                     // Implementation notes:  
 808                     // This function does not look for required properties on embedded objects.
 809                     // This function assumes that applyContext has been called.
 810                     //
 811 chuck    1.1.2.5  
 812                     Array<CQLIdentifier> ids = chainId.getSubIdentifiers();
 813                   
 814 chuck    1.1.2.20   // After applyContext has been called, a single element
 815                     // chained identifier refers to either an instance of the
 816                     // FROM class, or is the classname on the right side of ISA.
 817 chuck    1.1.2.17   if (ids.size() == 1)
 818                     {
 819 chuck    1.1.2.20     // This identifier is not a property name
 820 chuck    1.1.2.17     return false;
 821                     }
 822 chuck    1.1.2.5  
 823 chuck    1.1.2.20   if (ids[1].isSymbolicConstant())
 824 chuck    1.1.2.5    {
 825 chuck    1.1.2.20     // Non-embedded symbolic constants are not properties
 826                       // Note that an embedded symbolic constant like this:
 827                       // fromclass.embobj.scope::someprop#'ok'
 828                       // implies that embobj is a required property, because 
 829                       // embobj could be null, and that affects how the
 830                       // identifier is evaluated.
 831 chuck    1.1.2.17     return false;
 832                     }
 833                   
 834 chuck    1.1.2.20   // Since applyContext has been called, the first chain element
 835                     // will be the FROM class, so go to the 2nd chain element.
 836 chuck    1.1.2.17   if (ids[1].isScoped())
 837                     {
 838 chuck    1.1.2.20     // The 2nd chain element is a scoped property.
 839                       // Eg. fromclass.someclass::someprop
 840 chuck    1.1.2.5  
 841 chuck    1.1.2.20     // Determine the class that the property is being scoped to.
 842                       // This could be the FROM class, or some other class not in the FROM list
 843                       CIMName scopingClass = CIMName(ids[1].getScope());
 844                   
 845                       // Check if the scoping class is the same as the class passed in.
 846                       if (scopingClass == className)
 847 chuck    1.1.2.5      {
 848 chuck    1.1.2.20       // The scoping class is the same as the class passed, 
 849                         // add the property if not already added
 850                         if (!containsProperty(ids[1].getName(), reqProps))
 851                         {  
 852                           reqProps.append(ids[1].getName());
 853                         }
 854                       }
 855                       else
 856                       {
 857                         // The scoping class is not the same as the class passed. 
 858                         // Check if we already know that the scoping class is a subclass
 859                         // of the class passed in
 860                         if (containsProperty(scopingClass, unmatchedScopes))
 861 chuck    1.1.2.5        {
 862 chuck    1.1.2.20         // Scoping class is a subclass.
 863                           return false;
 864                         }
 865                           
 866                         // Check if we already know that the scoping class is a superclass
 867                         // of the class passed in
 868                         Boolean isSuper = false;
 869                         if (containsProperty(scopingClass, matchedScopes))
 870 chuck    1.1.2.5        {
 871 chuck    1.1.2.20         // Scoping class is a superclass.
 872                           isSuper = true;
 873                         }
 874                   
 875                         // Check if the scoping class is a superclass of the class passed in
 876                         if (isSuper || _ctx->isSubClass(scopingClass, className))
 877                         {
 878                           // Scoping class is a superclass of the class passed in.
 879                           if (!isSuper)
 880                           {
 881                             // Save this information
 882                             matchedScopes.append(scopingClass);
 883                           }
 884                   
 885                           // Add to the required property list if not already there.
 886 chuck    1.1.2.17         if (!containsProperty(ids[1].getName(), reqProps))
 887                           {  
 888                             reqProps.append(ids[1].getName());
 889                           }
 890 chuck    1.1.2.5        }
 891 chuck    1.1.2.20       else
 892                         {
 893                           // Scoping class is not superclass of class passed in.
 894                           // Save this information.
 895                           unmatchedScopes.append(scopingClass);
 896                         }
 897                       }  // end else scoping class not == class passed in
 898                     }  // end if first id is scoped
 899 chuck    1.1.2.5    else
 900                     {
 901 chuck    1.1.2.20     // The 2nd chain element is an unscoped property
 902 chuck    1.1.2.23     // Check if it is wildcarded
 903 chuck    1.1.2.5      if (ids[1].isWildcard())
 904                       {
 905 chuck    1.1.2.23       // Wildcard.
 906                         // If the class passed in is the FROM class, then
 907                         // all properties are required on the class passed in.
 908                         CIMName fromClassName = _ctx->getFromList()[0].getName();
 909                         if (fromClassName == className)
 910                         {
 911 chuck    1.1.2.22         return true;
 912 chuck    1.1.2.23       }
 913                   
 914                         // Add all the properties on the FROM class to
 915                         // the required property list.
 916                         CIMClass fromClass = _ctx->getClass(fromClassName);
 917                         for (Uint32 n = 0; n < fromClass.getPropertyCount(); n++)
 918                         {
 919                           // Add to the required property list if not already there.
 920                           if (!containsProperty(fromClass.getProperty(n).getName(), reqProps))
 921                           {  
 922                             reqProps.append(fromClass.getProperty(n).getName());
 923                           }        
 924                         }
 925                   
 926                         return false;
 927 chuck    1.1.2.5      }
 928                   
 929 chuck    1.1.2.20     // Implementation note:
 930                       // Since this API assumes that the class passed in
 931                       // is the FROM class or a subclass of the FROM class,
 932                       // AND validateProperties can be called to check if
 933                       // unscoped properties are on the FROM class, 
 934                       // we can just add the required property because
 935                       // it is assumed to be on the FROM class.
 936                   
 937                       // Add to the required property list if not already there.
 938                       if (!containsProperty(ids[1].getName(), reqProps))
 939                       {  
 940                         reqProps.append(ids[1].getName());
 941 chuck    1.1.2.5      }
 942                     }
 943                     
 944 chuck    1.1.2.20   // Indicate the required property is not a wildcard
 945 chuck    1.1.2.5    return false;
 946                   }
 947                   
 948                   Boolean CQLSelectStatementRep::containsProperty(const CIMName& name,
 949 chuck    1.1.2.17                                                 const Array<CIMName>& props) 
 950 chuck    1.1.2.5  {
 951                     for (Uint32 i = 0; i < props.size(); i++)
 952                     {
 953                       if (props[i] == name)
 954                       {
 955                         return true;
 956                       }
 957                     }
 958                   
 959                     return false;
 960                   }
 961                   
 962 humberto 1.1.2.1  void CQLSelectStatementRep::appendClassPath(const CQLIdentifier& inIdentifier)
 963                   {
 964 chuck    1.1.2.3    _ctx->insertClassPath(inIdentifier);
 965 humberto 1.1.2.1  }
 966                   
 967 humberto 1.1.2.18 void CQLSelectStatementRep::setPredicate(const CQLPredicate& inPredicate)
 968 humberto 1.1.2.1  {
 969 chuck    1.1.2.3    _predicate = inPredicate;
 970 humberto 1.1.2.1  }
 971                   
 972 chuck    1.1.2.16 void CQLSelectStatementRep::insertClassPathAlias(const CQLIdentifier& inIdentifier,
 973 chuck    1.1.2.17                                                  String inAlias)
 974 humberto 1.1.2.1  {
 975 chuck    1.1.2.3    _ctx->insertClassPath(inIdentifier,inAlias);
 976 humberto 1.1.2.1  }
 977                   
 978                   void CQLSelectStatementRep::appendSelectIdentifier(const CQLChainedIdentifier& x)
 979                   {
 980 chuck    1.1.2.3    _selectIdentifiers.append(x);
 981 humberto 1.1.2.1  }
 982                   
 983 chuck    1.1.2.5  void CQLSelectStatementRep::applyContext()
 984                   {
 985                     for (Uint32 i = 0; i < _selectIdentifiers.size(); i++)
 986                     {
 987                       _selectIdentifiers[i].applyContext(*_ctx);
 988 chuck    1.1.2.9      checkWellFormedIdentifier(_selectIdentifiers[i], true);
 989 chuck    1.1.2.5    }
 990                   
 991                     if (hasWhereClause())
 992 chuck    1.1.2.9    {
 993 chuck    1.1.2.5      _predicate.applyContext(*_ctx);
 994 chuck    1.1.2.9  
 995 chuck    1.1.2.23     // Note: must be after call to predicate's applyContext
 996                       Array<CQLChainedIdentifier> _whereIdentifiers = _ctx->getWhereList();
 997                       for (Uint32 i = 0; i < _whereIdentifiers.size(); i++)
 998                       {
 999                         checkWellFormedIdentifier(_whereIdentifiers[i], false);
1000                       }
1001 chuck    1.1.2.17   }
1002 chuck    1.1.2.9  }
1003                   
1004                   void CQLSelectStatementRep::checkWellFormedIdentifier(const CQLChainedIdentifier& chainId,
1005 chuck    1.1.2.17                                                       Boolean isSelectListId)
1006 chuck    1.1.2.9  {
1007 chuck    1.1.2.17   // This function assumes that applyContext has been called.
1008 chuck    1.1.2.9    Array<CQLIdentifier> ids = chainId.getSubIdentifiers();
1009                   
1010 chuck    1.1.2.17   if (ids.size() == 0)
1011                     {
1012                       throw Exception("TEMP MSG: empty chained identifier");
1013                     }
1014 chuck    1.1.2.9  
1015 chuck    1.1.2.17   if (ids.size() == 1 && isSelectListId)
1016 chuck    1.1.2.9    {
1017 chuck    1.1.2.20     // Single element chain ids are not allow in the select list.
1018                       // The select list can only have properties.
1019 chuck    1.1.2.17     throw Exception("TEMP MSG: need to select a property on the FROM class");
1020 chuck    1.1.2.9    }
1021                   
1022 chuck    1.1.2.17   if (ids[0].isScoped()
1023                         || ids[0].isWildcard()
1024                         || ids[0].isSymbolicConstant() 
1025                         || ids[0].isArray())
1026                     {
1027 chuck    1.1.2.20     // The first identifier must be a classname (it could be the FROM class, or
1028                       // some other class for the right side of ISA)
1029 chuck    1.1.2.17     throw Exception("TEMP MSG: first identifier is illegal after applyContext");
1030                     }
1031                      
1032                     Uint32 startingPos = 1;
1033 chuck    1.1.2.9    for (Uint32 pos = startingPos; pos < ids.size(); pos++)
1034                     {  
1035                       if (ids[pos].isArray() && isSelectListId)
1036                       {
1037                         throw Exception("TEMP MSG: array indexing not allowed in basic select");
1038                       }
1039                   
1040                       if (ids[pos].isSymbolicConstant() && isSelectListId)
1041                       {
1042 chuck    1.1.2.17       throw Exception("TEMP MSG: symbolic constant not allowed in basic select");
1043 chuck    1.1.2.9      }
1044                   
1045 chuck    1.1.2.20     if (ids[pos].isSymbolicConstant() && pos != (ids.size() -1))
1046                       {
1047                         throw Exception("TEMP MSG: symbolic constant must be last chain element");
1048                       }
1049                   
1050 chuck    1.1.2.9      if (ids[pos].isWildcard())
1051                       {
1052                         if ( !isSelectListId)
1053                         {
1054 chuck    1.1.2.17         throw Exception("TEMP MSG: wildcard not allowed in WHERE clause");
1055 chuck    1.1.2.9        }
1056                   
1057 chuck    1.1.2.16       if ( pos != ids.size() - 1)
1058 chuck    1.1.2.9        {
1059 chuck    1.1.2.17         throw Exception("TEMP MSG: wildcard must be at the end of select-list property");
1060 chuck    1.1.2.9        }
1061                       }
1062                   
1063                       if (pos > startingPos && !ids[pos].isWildcard())
1064                       {
1065                         if (!ids[pos].isScoped())
1066                         {
1067 chuck    1.1.2.17         throw Exception("TEMP MSG: property on embedded object must be scoped");
1068 chuck    1.1.2.9        }
1069                       }
1070                     }
1071 chuck    1.1.2.5  }
1072                   
1073                   void CQLSelectStatementRep::normalizeToDOC()
1074                   {
1075                   
1076                   }
1077                   
1078                   String CQLSelectStatementRep::toString()
1079                   {
1080 chuck    1.1.2.17         String s("SELECT ");
1081                           for(Uint32 i = 0; i < _selectIdentifiers.size(); i++){
1082                                   if((i > 0) && (i < _selectIdentifiers.size())){
1083                                           s.append(",");
1084                                   }
1085                                   s.append(_selectIdentifiers[i].toString());
1086                           }       
1087                   
1088                           s.append(" ");
1089                           s.append(_ctx->getFromString());
1090                   
1091                           if(_hasWhereClause){
1092 chuck    1.1.2.20                 s.append(" WHERE ");
1093 chuck    1.1.2.17                 s.append(_predicate.toString());
1094                           }
1095                           return s;
1096 chuck    1.1.2.4  }
1097                   
1098 chuck    1.1.2.5  void CQLSelectStatementRep::setHasWhereClause()
1099                   {
1100 chuck    1.1.2.4          _hasWhereClause = true;
1101                   }
1102                   
1103 chuck    1.1.2.5  Boolean CQLSelectStatementRep::hasWhereClause()
1104                   {
1105 chuck    1.1.2.4          return _hasWhereClause;
1106                   }
1107                   
1108 chuck    1.1.2.5  void  CQLSelectStatementRep::clear()
1109                   {
1110 chuck    1.1.2.17         _ctx->clear();
1111                           _hasWhereClause = false;
1112                           _contextApplied = false;
1113                           _predicate = CQLPredicate();
1114                           _selectIdentifiers.clear();
1115 chuck    1.1.2.4  }
1116                   
1117 humberto 1.1.2.1  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2