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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2