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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2