1 chuck 1.1.2.7 //%2003////////////////////////////////////////////////////////////////////////
|
2 chuck 1.1.2.6 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Development
4 // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
|
5 chuck 1.1.2.8 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
|
6 chuck 1.1.2.6 // IBM Corp.; EMC Corporation, The Open Group.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
16 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
17 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
18 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
19 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 //==============================================================================
25 //
26 // Authors: David Rosckes (rosckes@us.ibm.com)
27 chuck 1.1.2.6 // Bert Rivero (hurivero@us.ibm.com)
28 // Chuck Carmack (carmack@us.ibm.com)
29 // Brian Lucier (lucier@us.ibm.com)
30 //
31 // Modified By:
32 //
33 //%/////////////////////////////////////////////////////////////////////////////
34
|
35 humberto 1.1.2.1 #include "CQLChainedIdentifier.h"
36 #include "CQLChainedIdentifierRep.h"
|
37 humberto 1.1.2.2 #include <Pegasus/CQL/CQLFactory.h>
|
38 chuck 1.1.2.17 #include <Pegasus/CQL/QueryContext.h>
|
39 humberto 1.1.2.18 #include "QueryException.h"
|
40 chuck 1.1.2.17
|
41 humberto 1.1.2.1 PEGASUS_NAMESPACE_BEGIN
42
|
43 humberto 1.1.2.3 CQLChainedIdentifierRep::CQLChainedIdentifierRep(){
44 }
45
|
46 humberto 1.1.2.1 CQLChainedIdentifierRep::CQLChainedIdentifierRep(String inString)
47 {
48 parse(inString);
49 }
50
|
51 humberto 1.1.2.12 CQLChainedIdentifierRep::CQLChainedIdentifierRep(const CQLIdentifier &id)
|
52 humberto 1.1.2.1 {
53 _subIdentifiers.append(id);
54 }
55
|
56 humberto 1.1.2.3 CQLChainedIdentifierRep::CQLChainedIdentifierRep(const CQLChainedIdentifierRep* rep){
57 _subIdentifiers = rep->_subIdentifiers;
58 }
59
60 CQLChainedIdentifierRep::~CQLChainedIdentifierRep(){
61
|
62 humberto 1.1.2.1 }
63
64 const Array<CQLIdentifier>& CQLChainedIdentifierRep::getSubIdentifiers()const
65 {
66 return _subIdentifiers;
67 }
68
|
69 humberto 1.1.2.12 CQLIdentifier CQLChainedIdentifierRep::getLastIdentifier()const{
|
70 humberto 1.1.2.1 if(_subIdentifiers.size() > 0)
71 return _subIdentifiers[_subIdentifiers.size()-1];
72 return CQLIdentifier();
73 }
74
75 String CQLChainedIdentifierRep::toString()const{
76 String s;
77 for(Uint32 i = 0; i < _subIdentifiers.size(); i++){
78 s.append(_subIdentifiers[i].toString());
79 if(i < _subIdentifiers.size() - 1)
80 s.append(".");
81 }
82 return s;
83 }
84
|
85 humberto 1.1.2.12 void CQLChainedIdentifierRep::append(const CQLIdentifier & id){
|
86 humberto 1.1.2.1 _subIdentifiers.append(id);
87 }
88
|
89 humberto 1.1.2.12 Boolean CQLChainedIdentifierRep::isSubChain(const CQLChainedIdentifier & chain)const{
|
90 humberto 1.1.2.1 Array<CQLIdentifier> ids = chain.getSubIdentifiers();
91 for(Uint32 i = 0; i < ids.size(); i++){
92 if(ids[i] != _subIdentifiers[i].getName())
93 return false;
94 }
95 return true;
96 }
97
|
98 david 1.1.2.15 CQLIdentifier CQLChainedIdentifierRep::operator[](Uint32 index)const
99 {
100 return CQLIdentifier(_subIdentifiers[index]);
|
101 humberto 1.1.2.1 }
102
|
103 humberto 1.1.2.3 CQLChainedIdentifierRep& CQLChainedIdentifierRep::operator=(const CQLChainedIdentifierRep& rhs){
104 if(&rhs != this){
105 _subIdentifiers = rhs._subIdentifiers;
106 }
107 return *this;
108 }
109
|
110 humberto 1.1.2.12 Uint32 CQLChainedIdentifierRep::size()const{
|
111 humberto 1.1.2.1 return _subIdentifiers.size();
112 }
113
|
114 humberto 1.1.2.12 Boolean CQLChainedIdentifierRep::prepend(const CQLIdentifier & id){
|
115 humberto 1.1.2.1 /*
116 Compare id against the first element in _subIdentifiers,
117 if not an exact match, then prepend. This is used to fully
118 qualify the chained identifier.
119 */
120 if(id != _subIdentifiers[0]){
121 _subIdentifiers.prepend(id);
122 return true;
123 }
124 return false;
125 }
126
|
127 chuck 1.1.2.4 void CQLChainedIdentifierRep::applyContext(QueryContext& inContext)
128 {
|
129 chuck 1.1.2.9 if (_subIdentifiers.size() == 0)
130 return;
131
|
132 chuck 1.1.2.11 // Chained identifiers that are standalone symbolic constants
133 // should have had the context applied already. If this method
134 // is called and this is still a standalone symbolic constant,
135 // then that is an error.
136 if (_subIdentifiers.size() == 1 &&
137 _subIdentifiers[0].getName().getString().size() == 0 &&
138 _subIdentifiers[0].isSymbolicConstant())
139 {
|
140 humberto 1.1.2.18 throw CQLValidationException(
141 MessageLoaderParms(String("CQL.CQLChainedIdentifier.STAND_ALONE_SYMBOLIC_CONSTANT"),
142 String("The stand alone chained identifier should have had the context applied already."))
143 );
|
144 chuck 1.1.2.11 }
145
|
146 chuck 1.1.2.5 CQLIdentifier firstId = _subIdentifiers[0];
147
|
148 chuck 1.1.2.13 // Process if the first identifier has some contents.
149 if ((firstId.getName().getString().size() != 0) || firstId.isWildcard())
|
150 chuck 1.1.2.5 {
151 Array<CQLIdentifier> fromList = inContext.getFromList();
152
153 if (firstId.isWildcard())
154 {
|
155 chuck 1.1.2.16 // First chain element is wildcarded.
|
156 chuck 1.1.2.13 // Prepend the FROM class.
|
157 chuck 1.1.2.5 _subIdentifiers.prepend(fromList[0]);
158 }
159 else
160 {
|
161 chuck 1.1.2.16 // Not a wildcard.
|
162 chuck 1.1.2.10 if (firstId.isScoped())
|
163 chuck 1.1.2.5 {
|
164 chuck 1.1.2.13 // The first identifier is a scoped property or a
165 // scoped symbolic constant.
166 // Prepend the FROM class.
167 // Example: SELECT * FROM F WHERE someprop = X::p#'OK'
|
168 chuck 1.1.2.5 _subIdentifiers.prepend(fromList[0]);
169 }
170 else
|
171 chuck 1.1.2.10 {
|
172 chuck 1.1.2.13 // The first identifier is not a scoped property or a scoped
173 // symbolic constant.
174
175 // Determine if the first identifier's name is in the FROM list.
|
176 chuck 1.1.2.10 String classContext = firstId.getName().getString();
177 CQLIdentifier matchedId = inContext.findClass(classContext);
|
178 chuck 1.1.2.14 if (matchedId.getName().getString().size() == 0)
|
179 chuck 1.1.2.5 {
|
180 chuck 1.1.2.10 // Could not find the firstId in the FROM list.
|
181 chuck 1.1.2.16 // Assume the firstId is a property on the FROM class.
182 // Prepend the FROM class, except in the cases described below.
|
183 chuck 1.1.2.13 //
184 // NOTE:
185 // We need special handling for symbolic constants, because there are cases
186 // where the first id is a class that is not the FROM class.
187 // Refer to section 5.4.3 of the CQL spec.
188 //
189 // Examples:
|
190 chuck 1.1.2.16 // SELECT * FROM F WHERE F.someprop = prop#'OK'
191 // Prepend the FROM class because symbolic constants can only
192 // apply to properties, and properties in the first position
193 // are assumed to be on the FROM class.
194 //
|
195 chuck 1.1.2.13 // SELECT * FROM F WHERE F.someprop = ClassNotInFromList.prop#'OK'
196 // We don't want to prepend the FROM class to ClassNotInFromList
|
197 chuck 1.1.2.16 // in this case. But we need to get the FROM class from the schema
198 // to make sure ClassNotInFromList is not a property on the FROM class.
|
199 chuck 1.1.2.13 //
|
200 chuck 1.1.2.16 // SELECT * FROM F WHERE F.someprop = embeddedObjectOnF.X::p#'OK'
201 // In this case embeddedObjectOnF is an embedded object property
202 // on the FROM class. We want to prepend the FROM class. But
203 // we need to get FROM class from the schema first to make sure.
204 //
205 // SELECT * FROM F WHERE F.someprop = embeddedObjectOnF.X::p
206 // In this case embeddedObjectOnF is an embedded object property
207 // on the FROM class. We want to prepend the FROM class. Since
208 // the last id is not a symbolic constant we can prepend without
209 // getting the FROM class from the schema.
|
210 chuck 1.1.2.13 //
211 // Note that standalone symbolic constants, like #'OK'
|
212 chuck 1.1.2.16 // are errors when this code is run.
|
213 chuck 1.1.2.13 // See above for details.
214 //
|
215 chuck 1.1.2.16
216 if (firstId.isSymbolicConstant() ||
217 !getLastIdentifier().isSymbolicConstant())
218 {
219 // Must be a property on the FROM class.
220 _subIdentifiers.prepend(fromList[0]);
221 }
222 else
223 {
224 // Get the FROM class.
225 try
226 {
227 CIMClass fromClass = inContext.getClass(fromList[0].getName());
228 if (fromClass.findProperty(firstId.getName()) != PEG_NOT_FOUND)
229 {
230 // A property on the FROM class.
231 _subIdentifiers.prepend(fromList[0]);
232 }
233 }
234 catch (CIMException& ce)
235 {
236 chuck 1.1.2.16 if (ce.getCode() == CIM_ERR_INVALID_CLASS ||
237 ce.getCode() == CIM_ERR_NOT_FOUND)
238 {
239 // ATTN may just want to throw the CIMException rather than
240 // CQL exception
241 throw Exception("TEMP MSG - CQLChainId::applyContext - FROM class does not exist");
|
242 humberto 1.1.2.18 throw CQLValidationException(
243 MessageLoaderParms(String("CQL.CQLChainedIdentifier.FROM_CLASS_DOES_NOT_EXIST"),
244 String("The FROM class does not exist while applying context."))
245 );
|
246 chuck 1.1.2.16 }
247 }
248 }
|
249 chuck 1.1.2.10 }
250 else
251 {
252 // The firstId was found in the FROM list, but it could have been
253 // an alias
254 if (!matchedId.getName().equal(firstId.getName()))
255 {
256 // It was an alias.
257 // Replace the alias with the FROM class
258 _subIdentifiers[0] = matchedId;
259 }
260 else
261 {
262 // It was not an alias. Do nothing.
263 ;
264 }
|
265 chuck 1.1.2.5 }
266 }
267 }
268 }
|
269 chuck 1.1.2.10
|
270 chuck 1.1.2.13 // Go through and replace any aliases on scoping classes
|
271 chuck 1.1.2.10 for (Uint32 i = 0; i < _subIdentifiers.size(); i++)
272 {
273 if (_subIdentifiers[i].isScoped())
274 {
275 CQLIdentifier match = inContext.findClass(_subIdentifiers[i].getScope());
|
276 chuck 1.1.2.13 if (match.getName().getString().size() != 0)
|
277 chuck 1.1.2.10 {
|
278 chuck 1.1.2.13 // The scoping class was either the FROM class, or an alias of the
279 // FROM class. Replace the scoping class with the FROM class.
|
280 chuck 1.1.2.10 _subIdentifiers[i].applyScope(match.getName().getString());
281 }
282 }
283 }
|
284 humberto 1.1.2.1 }
285
286 void CQLChainedIdentifierRep::parse(String & string){
287 /*
288 - parse string on "."
289 - start from the end of string
290 - if more than one substring found,
291 -- store first found string then
292 -- prepend remaining substrings
293 */
294 Char16 delim('.');
295 Uint32 index;
296 String range;
297
298 /* remove any array ranges so we dont parse a false . */
299 if((index = string.find("[")) != PEG_NOT_FOUND){
300 range = string.subString(index);
301 string.remove(index);
302 }
303
304 index = string.reverseFind(delim);
305 humberto 1.1.2.1 if(index == PEG_NOT_FOUND){
306 /* append the range we may have removed */
307 string.append(range);
308 _subIdentifiers.append(CQLIdentifier(string));
309 }else{
310 /* append the range we may have removed */
311 String tmp = string.subString(index+1);
312 tmp.append(range);
313 _subIdentifiers.append(CQLIdentifier(tmp));
314
315 while(index != PEG_NOT_FOUND){
316 tmp = string.subString(0,index);
317 index = tmp.reverseFind(delim);
318 if(index == PEG_NOT_FOUND){
319 _subIdentifiers.prepend(CQLIdentifier(tmp));
320 }
321 else{
322 _subIdentifiers.prepend(CQLIdentifier(tmp.subString(index+1)));
323 }
324 }
325 }
326 humberto 1.1.2.1 }
327
328 PEGASUS_NAMESPACE_END
|