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

   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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2