version 1.1.2.18, 2004/11/04 18:04:05
|
version 1.2, 2004/11/21 12:13:07
|
|
|
#include "CQLChainedIdentifier.h" | #include "CQLChainedIdentifier.h" |
#include "CQLChainedIdentifierRep.h" | #include "CQLChainedIdentifierRep.h" |
#include <Pegasus/CQL/CQLFactory.h> | #include <Pegasus/CQL/CQLFactory.h> |
#include <Pegasus/CQL/QueryContext.h> |
#include <Pegasus/Query/QueryCommon/QueryContext.h> |
#include "QueryException.h" |
#include <Pegasus/Query/QueryCommon/QueryIdentifier.h> |
|
#include <Pegasus/Query/QueryCommon/QueryException.h> |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
CQLChainedIdentifierRep::CQLChainedIdentifierRep(){ |
CQLChainedIdentifierRep::CQLChainedIdentifierRep(): |
|
QueryChainedIdentifierRep() |
|
{ |
} | } |
| |
CQLChainedIdentifierRep::CQLChainedIdentifierRep(String inString) |
CQLChainedIdentifierRep::CQLChainedIdentifierRep(String inString): |
|
QueryChainedIdentifierRep() |
{ | { |
parse(inString); | parse(inString); |
} | } |
| |
CQLChainedIdentifierRep::CQLChainedIdentifierRep(const CQLIdentifier &id) |
CQLChainedIdentifierRep::CQLChainedIdentifierRep(const CQLIdentifier &id): |
|
QueryChainedIdentifierRep() |
{ | { |
_subIdentifiers.append(id); | _subIdentifiers.append(id); |
} | } |
| |
CQLChainedIdentifierRep::CQLChainedIdentifierRep(const CQLChainedIdentifierRep* rep){ |
CQLChainedIdentifierRep::CQLChainedIdentifierRep(const CQLChainedIdentifierRep* rep): |
|
QueryChainedIdentifierRep() |
|
{ |
_subIdentifiers = rep->_subIdentifiers; | _subIdentifiers = rep->_subIdentifiers; |
} | } |
| |
|
|
| |
} | } |
| |
const Array<CQLIdentifier>& CQLChainedIdentifierRep::getSubIdentifiers()const |
Array<CQLIdentifier> CQLChainedIdentifierRep::getSubIdentifiers()const |
{ | { |
return _subIdentifiers; |
Array<CQLIdentifier> result; |
} |
|
| |
CQLIdentifier CQLChainedIdentifierRep::getLastIdentifier()const{ |
for (Uint32 i = 0; i < _subIdentifiers.size(); i++) |
if(_subIdentifiers.size() > 0) |
{ |
return _subIdentifiers[_subIdentifiers.size()-1]; |
result.append(CQLIdentifier(_subIdentifiers[i])); |
return CQLIdentifier(); |
|
} |
|
|
|
String CQLChainedIdentifierRep::toString()const{ |
|
String s; |
|
for(Uint32 i = 0; i < _subIdentifiers.size(); i++){ |
|
s.append(_subIdentifiers[i].toString()); |
|
if(i < _subIdentifiers.size() - 1) |
|
s.append("."); |
|
} |
|
return s; |
|
} | } |
| |
void CQLChainedIdentifierRep::append(const CQLIdentifier & id){ |
return result; |
_subIdentifiers.append(id); |
|
} | } |
| |
Boolean CQLChainedIdentifierRep::isSubChain(const CQLChainedIdentifier & chain)const{ |
CQLIdentifier CQLChainedIdentifierRep::getLastIdentifier()const{ |
Array<CQLIdentifier> ids = chain.getSubIdentifiers(); |
if(_subIdentifiers.size() > 0) |
for(Uint32 i = 0; i < ids.size(); i++){ |
return CQLIdentifier(_subIdentifiers[_subIdentifiers.size()-1]); |
if(ids[i] != _subIdentifiers[i].getName()) |
return CQLIdentifier(); |
return false; |
|
} |
|
return true; |
|
} | } |
| |
CQLIdentifier CQLChainedIdentifierRep::operator[](Uint32 index)const | CQLIdentifier CQLChainedIdentifierRep::operator[](Uint32 index)const |
|
|
return *this; | return *this; |
} | } |
| |
Uint32 CQLChainedIdentifierRep::size()const{ |
|
return _subIdentifiers.size(); |
|
} |
|
|
|
Boolean CQLChainedIdentifierRep::prepend(const CQLIdentifier & id){ |
|
/* |
|
Compare id against the first element in _subIdentifiers, |
|
if not an exact match, then prepend. This is used to fully |
|
qualify the chained identifier. |
|
*/ |
|
if(id != _subIdentifiers[0]){ |
|
_subIdentifiers.prepend(id); |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
void CQLChainedIdentifierRep::applyContext(QueryContext& inContext) |
|
{ |
|
if (_subIdentifiers.size() == 0) |
|
return; |
|
|
|
// Chained identifiers that are standalone symbolic constants |
|
// should have had the context applied already. If this method |
|
// is called and this is still a standalone symbolic constant, |
|
// then that is an error. |
|
if (_subIdentifiers.size() == 1 && |
|
_subIdentifiers[0].getName().getString().size() == 0 && |
|
_subIdentifiers[0].isSymbolicConstant()) |
|
{ |
|
throw CQLValidationException( |
|
MessageLoaderParms(String("CQL.CQLChainedIdentifier.STAND_ALONE_SYMBOLIC_CONSTANT"), |
|
String("The stand alone chained identifier should have had the context applied already.")) |
|
); |
|
} |
|
|
|
CQLIdentifier firstId = _subIdentifiers[0]; |
|
|
|
// Process if the first identifier has some contents. |
|
if ((firstId.getName().getString().size() != 0) || firstId.isWildcard()) |
|
{ |
|
Array<CQLIdentifier> fromList = inContext.getFromList(); |
|
|
|
if (firstId.isWildcard()) |
|
{ |
|
// First chain element is wildcarded. |
|
// Prepend the FROM class. |
|
_subIdentifiers.prepend(fromList[0]); |
|
} |
|
else |
|
{ |
|
// Not a wildcard. |
|
if (firstId.isScoped()) |
|
{ |
|
// The first identifier is a scoped property or a |
|
// scoped symbolic constant. |
|
// Prepend the FROM class. |
|
// Example: SELECT * FROM F WHERE someprop = X::p#'OK' |
|
_subIdentifiers.prepend(fromList[0]); |
|
} |
|
else |
|
{ |
|
// The first identifier is not a scoped property or a scoped |
|
// symbolic constant. |
|
|
|
// Determine if the first identifier's name is in the FROM list. |
|
String classContext = firstId.getName().getString(); |
|
CQLIdentifier matchedId = inContext.findClass(classContext); |
|
if (matchedId.getName().getString().size() == 0) |
|
{ |
|
// Could not find the firstId in the FROM list. |
|
// Assume the firstId is a property on the FROM class. |
|
// Prepend the FROM class, except in the cases described below. |
|
// |
|
// NOTE: |
|
// We need special handling for symbolic constants, because there are cases |
|
// where the first id is a class that is not the FROM class. |
|
// Refer to section 5.4.3 of the CQL spec. |
|
// |
|
// Examples: |
|
// SELECT * FROM F WHERE F.someprop = prop#'OK' |
|
// Prepend the FROM class because symbolic constants can only |
|
// apply to properties, and properties in the first position |
|
// are assumed to be on the FROM class. |
|
// |
|
// SELECT * FROM F WHERE F.someprop = ClassNotInFromList.prop#'OK' |
|
// We don't want to prepend the FROM class to ClassNotInFromList |
|
// in this case. But we need to get the FROM class from the schema |
|
// to make sure ClassNotInFromList is not a property on the FROM class. |
|
// |
|
// SELECT * FROM F WHERE F.someprop = embeddedObjectOnF.X::p#'OK' |
|
// In this case embeddedObjectOnF is an embedded object property |
|
// on the FROM class. We want to prepend the FROM class. But |
|
// we need to get FROM class from the schema first to make sure. |
|
// |
|
// SELECT * FROM F WHERE F.someprop = embeddedObjectOnF.X::p |
|
// In this case embeddedObjectOnF is an embedded object property |
|
// on the FROM class. We want to prepend the FROM class. Since |
|
// the last id is not a symbolic constant we can prepend without |
|
// getting the FROM class from the schema. |
|
// |
|
// Note that standalone symbolic constants, like #'OK' |
|
// are errors when this code is run. |
|
// See above for details. |
|
// |
|
|
|
if (firstId.isSymbolicConstant() || |
|
!getLastIdentifier().isSymbolicConstant()) |
|
{ |
|
// Must be a property on the FROM class. |
|
_subIdentifiers.prepend(fromList[0]); |
|
} |
|
else |
|
{ |
|
// Get the FROM class. |
|
try |
|
{ |
|
CIMClass fromClass = inContext.getClass(fromList[0].getName()); |
|
if (fromClass.findProperty(firstId.getName()) != PEG_NOT_FOUND) |
|
{ |
|
// A property on the FROM class. |
|
_subIdentifiers.prepend(fromList[0]); |
|
} |
|
} |
|
catch (CIMException& ce) |
|
{ |
|
if (ce.getCode() == CIM_ERR_INVALID_CLASS || |
|
ce.getCode() == CIM_ERR_NOT_FOUND) |
|
{ |
|
// ATTN may just want to throw the CIMException rather than |
|
// CQL exception |
|
throw Exception("TEMP MSG - CQLChainId::applyContext - FROM class does not exist"); |
|
throw CQLValidationException( |
|
MessageLoaderParms(String("CQL.CQLChainedIdentifier.FROM_CLASS_DOES_NOT_EXIST"), |
|
String("The FROM class does not exist while applying context.")) |
|
); |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
// The firstId was found in the FROM list, but it could have been |
|
// an alias |
|
if (!matchedId.getName().equal(firstId.getName())) |
|
{ |
|
// It was an alias. |
|
// Replace the alias with the FROM class |
|
_subIdentifiers[0] = matchedId; |
|
} |
|
else |
|
{ |
|
// It was not an alias. Do nothing. |
|
; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
// Go through and replace any aliases on scoping classes |
|
for (Uint32 i = 0; i < _subIdentifiers.size(); i++) |
|
{ |
|
if (_subIdentifiers[i].isScoped()) |
|
{ |
|
CQLIdentifier match = inContext.findClass(_subIdentifiers[i].getScope()); |
|
if (match.getName().getString().size() != 0) |
|
{ |
|
// The scoping class was either the FROM class, or an alias of the |
|
// FROM class. Replace the scoping class with the FROM class. |
|
_subIdentifiers[i].applyScope(match.getName().getString()); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CQLChainedIdentifierRep::parse(String & string){ | void CQLChainedIdentifierRep::parse(String & string){ |
/* | /* |
- parse string on "." | - parse string on "." |