📄 cqlselectstatementrep.cpp
字号:
allowMissing);}Boolean CQLSelectStatementRep::applyProjection(PropertyNode* node, CIMProperty& nodeProp, Boolean& preservePropsForParent, Boolean allowMissing){ PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::applyProjection(node, nodeProp)"); PEGASUS_ASSERT(node->firstChild.get() != NULL || node->wildcard); // // The property passed in must be an embedded instance. It is not // allowed to project properties on embedded classes. // Get the embedded instance from the property. // // First check that it is an embedded object CIMValue nodeVal = nodeProp.getValue(); CIMType nodeValType = nodeVal.getType(); if (nodeValType != CIMTYPE_OBJECT#ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT && nodeValType != CIMTYPE_INSTANCE#endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT ) { PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"not emb"); PEG_METHOD_EXIT(); MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROP_NOT_EMB", "The property $0 must contain an embedded object.", nodeProp.getName().getString()); throw CQLRuntimeException(parms); } if (nodeVal.isNull()) { // Since we will be projecting on the embedded object, it cannot be null PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"value is null"); PEG_METHOD_EXIT(); MessageLoaderParms parms("CQL.CQLSelectStatementRep.NULL_EMB_OBJ", "The embedded object property $0 cannot contain a null value.", nodeProp.getName().getString()); throw CQLRuntimeException(parms); } if (nodeVal.isArray() && (node->firstChild.get() != NULL || node->wildcard)) { // NOTE - since we are blocking projection of array elements, we can // assume that if we get here we were told to project a whole array (ie. no index used), as // an embedded object with properties or wildcard. // Examples not allowed: SELECT fromClass.someArrayProp.scope::notAllowedProp FROM fromClass // SELECT fromClass.someArrayProp.* FROM fromClass PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"array index needed"); PEG_METHOD_EXIT(); MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROJ_WHOLE_ARRAY", "CQL requires that array indexing is used on embedded object property $0.", nodeProp.getName().getString()); throw CQLRuntimeException(parms); } CIMObject nodeObj; // this starts uninitialized CIMInstance nodeInst;#ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT if(nodeValType == CIMTYPE_OBJECT) {#endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT nodeVal.get(nodeObj); if (nodeObj.isUninitialized()) { // Not allowed to project on an uninitialized object PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"is uninitialized"); PEG_METHOD_EXIT(); MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROJ_UNINIT", "The embedded object property $0 is uninitialized.", nodeProp.getName().getString()); throw CQLRuntimeException(parms); } if (!nodeObj.isInstance()) { // Not allowed to project on a Class PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"is a class"); PEG_METHOD_EXIT(); MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROJ_CLASS", "CQL does not allow properties to be projected on class $0.", nodeProp.getName().getString()); throw CQLRuntimeException(parms); } nodeInst = CIMInstance(nodeObj);#ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT } else if(nodeValType == CIMTYPE_INSTANCE) { nodeVal.get(nodeInst); if (nodeInst.isUninitialized()) { // Not allowed to project on an uninitialized object PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"is uninitialized"); PEG_METHOD_EXIT(); MessageLoaderParms parms("CQL.CQLSelectStatementRep.PROJ_UNINIT", "The embedded object property $0 is uninitialized.", nodeProp.getName().getString()); throw CQLRuntimeException(parms); } }#endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT // // Do the projection. // Array<CIMName> requiredProps; Boolean allPropsRequired = node->wildcard; // Loop through the children of the node. // The node represents an embedded instance, // and the child nodes are the required properties on the embedded instance. PropertyNode * curChild = node->firstChild.get(); while (curChild != NULL) { PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"project childNode = " + curChild->name.getString()); // Determine if the embedded instance meets the class scoping // rules for the current child node Boolean filterable = isFilterable(nodeInst, curChild); // Indicates if the child node is still required after the recursive call. Boolean childRequired = true; // If the embedded instance is filterable, and the child node has children, // or is wildcarded, then the child is assumed to be an embedded instance, // and we need to recurse to apply the projection on the embedded instance. // (the check for embedded instance is done in the recursive call) if (filterable && (curChild->firstChild.get() != NULL || curChild->wildcard)) { // We need to project on an embedded instance property. The steps are to // remove the embedded instance property from the current instance, // project on that embedded instance property, and then add the projected // embedded instance property back to the current instance. PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"about to recurse: " + curChild->name.getString()); Uint32 index = nodeInst.findProperty(curChild->name); if (index != PEG_NOT_FOUND) { // The current instance has the required embedded instance property. // Note: embedded instance property missing is caught below. // Remove the embedded instance property CIMProperty childProp = nodeInst.getProperty(index); nodeInst.removeProperty(index); // Project onto the embedded instance property. // If the last parameter is true, then the childNode // will not remove properties when filtering the embedded instance. // This call returns whether the embedded instance property // should be added to the required property list. Boolean preserve = node->endpoint || allPropsRequired || preservePropsForParent; childRequired = applyProjection(curChild, childProp, preserve, allowMissing); nodeInst.addProperty(childProp); } } // If the embedded instance is filterable, // then add the current child to the list if it is still required. if (filterable && childRequired) { // The instance is filterable, add the property to the required list. PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"add req prop: " + curChild->name.getString()); requiredProps.append(curChild->name); } curChild = curChild->sibling.get(); } // Filter the instance. // This removes unneeded properties, unless this // embedded instance node was an endpoint (last element) // in a chained identifier. // This also checks for missing required properties on the instance. Boolean preserveProps = node->endpoint || preservePropsForParent; filterInstance(nodeInst, allPropsRequired, nodeInst.getClassName(), requiredProps, preserveProps, allowMissing); // Put the projected instance back into the property.#ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT if(nodeValType == CIMTYPE_INSTANCE) { nodeProp.setValue(nodeInst); } else#endif { CIMObject newNodeObj(nodeInst); CIMValue newNodeVal(newNodeObj); nodeProp.setValue(newNodeVal); } // Indicate to the caller whether the projected instance // is still a required property. It is required if it is an endpoint // (ie. the last element of a chained identifier) // OR if it still has properties after being projected if (node->endpoint || nodeInst.getPropertyCount() > 0) { return true; } return false;}Boolean CQLSelectStatementRep::isFilterable(const CIMInstance& inst, PropertyNode* node){ PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::isFilterable"); PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"instance = " + inst.getClassName().getString()); PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"scope = " + node->scope.getString()); // // Determine if an instance is filterable for a scoped property (ie. its // type is the scoping class or a subclass of the scoping class where the // property exists) // // Note that an instance that is unfilterable is not considered // an error. In CQL, an instance that is not of the required scope // would cause a NULL to be placed in the result set column for the // property. However since we are not implementing result set in stage1, // just skip the property. This can lead to an instance having // NO required properties even though it is derived from the FROM class. // This can easily happen if the scoping operator is used. // Boolean filterable = false; if (inst.getClassName() == node->scope) { // The instance's class is the same as the required scope PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"instance matches scope"); filterable = true; } else { try { if (_ctx->isSubClass(node->scope, inst.getClassName())) { // The instance's class is a subclass of the required scope. PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"instance is subclass of scope"); filterable = true; } } catch (const CIMException& ce) { if (ce.getCode() == CIM_ERR_INVALID_CLASS || ce.getCode() == CIM_ERR_NOT_FOUND) { // The scoping class was not found in the schema. // Just swallow this error because according to the // spec we should be putting NULL in the result column, // which means skipping the property on the instance. PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"scope class not in schema"); } else { PEG_METHOD_EXIT(); throw; } } } PEG_METHOD_EXIT(); return filterable;}void CQLSelectStatementRep::filterInstance(CIMInstance& inst, Boolean& allPropsRequired, const CIMName& allPropsClass, Array<CIMName>& requiredProps, Boolean& preserveProps, Boolean allowMissing){ PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::filterInstance"); PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"instance = " + inst.getClassName().getString()); PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"allPropsClass = " + allPropsClass.getString()); // Implementation note: // Scoping operator before a wildcard is not allowed: // Example: // SELECT fromclass.embobj1.scope1::* FROM fromclass // // However, the following are allowed: // SELECT fromclass.embobj1.* FROM fromclass // (this means that all the properties on the class of instance embobj1 // are required) // // SELECT fromclass.* FROM fromclass // (this means that all the properties on class fromclass are required // to be on the instance being projected, not including any // properties on a subclass of fromclass) // If all properties are required (ie. wildcarded), then add // all the properties of allPropsClass to the required list. // The allPropsClass is either the FROM class or the class of an embedded instance. if (allPropsRequired) { PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"all props required"); CIMClass cls = _ctx->getClass(allPropsClass); Array<CIMName> clsProps; for (Uint32 i = 0; i < cls.getPropertyCount(); i++) { if (!containsProperty(cls.getProperty(i).getName(), requiredProps)) { requiredProps.append(cls.getProperty(i).getName()); } } } // Find out what properties are on the instance. Array<CIMName> supportedProps; for (Uint32 i = 0; i < inst.getPropertyCount(); i++) { supportedProps.append(inst.getProperty(i).getName()); } // Check that all required properties are on the instance. if (!allowMissing) { for (Uint32 i = 0; i < requiredProps.size(); i++) { if (!containsProperty(requiredProps[i], supportedProps)) { PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"missing:" + requiredProps[i].getString()); PEG_METHOD_EXIT(); MessageLoaderParms parms ("CQL.CQLSelectStatementRep.PROJ_MISSING_PROP", "The property $0 is missing on the instance of class $1.", requiredProps[i].getString(), inst.getClassName().getString()); throw QueryRuntimePropertyException(parms); } } } // If requested, remove the properties on the instance that are not required. if (!preserveProps) { for (Uint32 i = 0; i < supportedProps.size(); i++) { if (!containsProperty(supportedProps[i], requiredProps)) { Uint32 index = inst.findProperty(supportedProps[i]); PEGASUS_ASSERT(index != PEG_NOT_FOUND); PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"removing:" + supportedProps[i].getString()); inst.removeProperty(index); } } } PEG_METHOD_EXIT();}//// Validates that all the chained identifiers in the statement meet// the rules in the CQL spec vs.the class definitions in the repository//void CQLSelectStatementRep::validate(){ PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::validate"); if(_ctx == NULL) { PEG_TRACE_STRING (TRC_CQL, Tracer::LEVEL4,"null QC"); PEG_METHOD_EXIT(); MessageLoaderParms parms("CQL.CQLSelectStatementRep.QUERY_CONTEXT_IS_NULL", "Trying to process a query with a NULL Query Context."); throw QueryValidationException(parms); } if (!_contextApplied) applyContext(); for (Uint32 i = 0; i < _selectIdentifiers.size(); i++) { validateProperty(_selectIdentifiers[i]); } Array<QueryChainedIdentifier> _whereIdentifiers = _ctx->getWhereList(); for (Uint32 i = 0; i < _whereIdentifiers.size(); i++) { validateProperty(_whereIdentifiers[i]); } PEG_METHOD_EXIT();}//// Validates that the chained identifier meets all the rules in the CQL// spec vs.the class definitions in the repository//void CQLSelectStatementRep::validateProperty(QueryChainedIdentifier& chainId){ PEG_METHOD_ENTER (TRC_CQL, "CQLSelectStatementRep::validateProperty"); // Note: applyContext has been called beforehand Array<QueryIdentifier> ids = chainId.getSubIdentifiers(); Uint32 startingPos = 0; CIMName curContext; for (Uint32 pos = startingPos; pos < ids.size(); pos++) { // Determine the current class context if (ids[pos].isScoped()) { // The chain element is scoped. Use the scoping // class as the current context. Note: this depends // on applyContext resolving the class aliases before we get here. curContext = CIMName(ids[pos].getScope()); } else { // The chain element is not scoped. Assume that we are // before a position that is required to be scoped. // (applyContext validates that the chained identifier // has scoped identifiers in the required positions). // The current context is the name at the first position, // which must be a classname (ie. right side of ISA where // the only element in the chain is a classname, or
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -