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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2