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 humberto 1.1.2.1 PEGASUS_NAMESPACE_BEGIN
39
|
40 humberto 1.1.2.3 CQLChainedIdentifierRep::CQLChainedIdentifierRep(){
41 }
42
|
43 humberto 1.1.2.1 CQLChainedIdentifierRep::CQLChainedIdentifierRep(String inString)
44 {
45 parse(inString);
46 }
47
|
48 humberto 1.1.2.12 CQLChainedIdentifierRep::CQLChainedIdentifierRep(const CQLIdentifier &id)
|
49 humberto 1.1.2.1 {
50 _subIdentifiers.append(id);
51 }
52
|
53 humberto 1.1.2.3 CQLChainedIdentifierRep::CQLChainedIdentifierRep(const CQLChainedIdentifierRep* rep){
54 _subIdentifiers = rep->_subIdentifiers;
55 }
56
57 CQLChainedIdentifierRep::~CQLChainedIdentifierRep(){
58
|
59 humberto 1.1.2.1 }
60
61 const Array<CQLIdentifier>& CQLChainedIdentifierRep::getSubIdentifiers()const
62 {
63 return _subIdentifiers;
64 }
65
|
66 humberto 1.1.2.12 CQLIdentifier CQLChainedIdentifierRep::getLastIdentifier()const{
|
67 humberto 1.1.2.1 if(_subIdentifiers.size() > 0)
68 return _subIdentifiers[_subIdentifiers.size()-1];
69 return CQLIdentifier();
70 }
71
72 String CQLChainedIdentifierRep::toString()const{
73 String s;
74 for(Uint32 i = 0; i < _subIdentifiers.size(); i++){
75 s.append(_subIdentifiers[i].toString());
76 if(i < _subIdentifiers.size() - 1)
77 s.append(".");
78 }
79 return s;
80 }
81
|
82 humberto 1.1.2.12 void CQLChainedIdentifierRep::append(const CQLIdentifier & id){
|
83 humberto 1.1.2.1 _subIdentifiers.append(id);
84 }
85
|
86 humberto 1.1.2.12 Boolean CQLChainedIdentifierRep::isSubChain(const CQLChainedIdentifier & chain)const{
|
87 humberto 1.1.2.1 Array<CQLIdentifier> ids = chain.getSubIdentifiers();
88 for(Uint32 i = 0; i < ids.size(); i++){
89 if(ids[i] != _subIdentifiers[i].getName())
90 return false;
91 }
92 return true;
93 }
94
|
95 david 1.1.2.15 CQLIdentifier CQLChainedIdentifierRep::operator[](Uint32 index)const
96 {
97 return CQLIdentifier(_subIdentifiers[index]);
|
98 humberto 1.1.2.1 }
99
|
100 humberto 1.1.2.3 CQLChainedIdentifierRep& CQLChainedIdentifierRep::operator=(const CQLChainedIdentifierRep& rhs){
101 if(&rhs != this){
102 _subIdentifiers = rhs._subIdentifiers;
103 }
104 return *this;
105 }
106
|
107 humberto 1.1.2.12 Uint32 CQLChainedIdentifierRep::size()const{
|
108 humberto 1.1.2.1 return _subIdentifiers.size();
109 }
110
|
111 humberto 1.1.2.12 Boolean CQLChainedIdentifierRep::prepend(const CQLIdentifier & id){
|
112 humberto 1.1.2.1 /*
113 Compare id against the first element in _subIdentifiers,
114 if not an exact match, then prepend. This is used to fully
115 qualify the chained identifier.
116 */
117 if(id != _subIdentifiers[0]){
118 _subIdentifiers.prepend(id);
119 return true;
120 }
121 return false;
122 }
123
|
124 chuck 1.1.2.4 void CQLChainedIdentifierRep::applyContext(QueryContext& inContext)
125 {
|
126 chuck 1.1.2.9 if (_subIdentifiers.size() == 0)
127 return;
128
|
129 chuck 1.1.2.11 // Chained identifiers that are standalone symbolic constants
130 // should have had the context applied already. If this method
131 // is called and this is still a standalone symbolic constant,
132 // then that is an error.
133 if (_subIdentifiers.size() == 1 &&
134 _subIdentifiers[0].getName().getString().size() == 0 &&
135 _subIdentifiers[0].isSymbolicConstant())
136 {
137 throw Exception("TEMP MSG: CQLChainedIdentifierRep::applyContext - standalone symb const");
138 }
139
|
140 chuck 1.1.2.5 CQLIdentifier firstId = _subIdentifiers[0];
141
|
142 chuck 1.1.2.13 // Process if the first identifier has some contents.
143 if ((firstId.getName().getString().size() != 0) || firstId.isWildcard())
|
144 chuck 1.1.2.5 {
145 Array<CQLIdentifier> fromList = inContext.getFromList();
146
147 if (firstId.isWildcard())
148 {
|
149 chuck 1.1.2.13 // Single element chain that is wildcarded.
150 // Prepend the FROM class.
|
151 chuck 1.1.2.5 _subIdentifiers.prepend(fromList[0]);
152 }
153 else
154 {
|
155 chuck 1.1.2.13 // Not a single element wildcard.
|
156 chuck 1.1.2.10 if (firstId.isScoped())
|
157 chuck 1.1.2.5 {
|
158 chuck 1.1.2.13 // The first identifier is a scoped property or a
159 // scoped symbolic constant.
160 // Prepend the FROM class.
161 // Example: SELECT * FROM F WHERE someprop = X::p#'OK'
|
162 chuck 1.1.2.5 _subIdentifiers.prepend(fromList[0]);
163 }
164 else
|
165 chuck 1.1.2.10 {
|
166 chuck 1.1.2.13 // The first identifier is not a scoped property or a scoped
167 // symbolic constant.
168
169 // Determine if the first identifier's name is in the FROM list.
|
170 chuck 1.1.2.10 String classContext = firstId.getName().getString();
171 CQLIdentifier matchedId = inContext.findClass(classContext);
|
172 chuck 1.1.2.14 if (matchedId.getName().getString().size() == 0)
|
173 chuck 1.1.2.5 {
|
174 chuck 1.1.2.10 // Could not find the firstId in the FROM list.
|
175 chuck 1.1.2.13 // Assume the firstId is a property on the FROM class,
176 // and prepend the FROM class, except in the case described below.
177 //
178 // NOTE:
179 // We need special handling for symbolic constants, because there are cases
180 // where the first id is a class that is not the FROM class.
181 // Refer to section 5.4.3 of the CQL spec.
182 //
183 // Examples:
184 // SELECT * FROM F WHERE F.someprop = ClassNotInFromList.prop#'OK'
185 // We don't want to prepend the FROM class to ClassNotInFromList
186 // in this case.
187 //
188 // SELECT * FROM F WHERE F.someprop = embeddedObject.X::p#'OK'
189 // Even though embeddedObject may an property on F, and not
190 // a classname, we still don't need to prepend F because the
191 // scoping class X will be used to get the value of 'OK' on property
192 // p.
193 //
194 // SELECT * FROM F WHERE F.someprop = propOnClassF#'OK'
195 // We want to prepend in this case. The identifier propOnClassF
196 chuck 1.1.2.13 // is assumed to be a property on the FROM class, not a classname
197 // itself.
198 //
199 // Note that standalone symbolic constants, like #'OK'
200 // are errors in this code.
201 // See above for details.
202 //
|
203 chuck 1.1.2.10 if (_subIdentifiers.size() == 1 ||
204 !_subIdentifiers[_subIdentifiers.size()-1].isSymbolicConstant())
205 {
206 _subIdentifiers.prepend(fromList[0]);
207 }
208 }
209 else
210 {
211 // The firstId was found in the FROM list, but it could have been
212 // an alias
213 if (!matchedId.getName().equal(firstId.getName()))
214 {
215 // It was an alias.
216 // Replace the alias with the FROM class
217 _subIdentifiers[0] = matchedId;
218 }
219 else
220 {
221 // It was not an alias. Do nothing.
222 ;
223 }
|
224 chuck 1.1.2.5 }
225 }
226 }
227 }
|
228 chuck 1.1.2.10
|
229 chuck 1.1.2.13 // Go through and replace any aliases on scoping classes
|
230 chuck 1.1.2.10 for (Uint32 i = 0; i < _subIdentifiers.size(); i++)
231 {
232 if (_subIdentifiers[i].isScoped())
233 {
234 CQLIdentifier match = inContext.findClass(_subIdentifiers[i].getScope());
|
235 chuck 1.1.2.13 if (match.getName().getString().size() != 0)
|
236 chuck 1.1.2.10 {
|
237 chuck 1.1.2.13 // The scoping class was either the FROM class, or an alias of the
238 // FROM class. Replace the scoping class with the FROM class.
|
239 chuck 1.1.2.10 _subIdentifiers[i].applyScope(match.getName().getString());
240 }
241 }
242 }
|
243 humberto 1.1.2.1 }
244
245 void CQLChainedIdentifierRep::parse(String & string){
246 /*
247 - parse string on "."
248 - start from the end of string
249 - if more than one substring found,
250 -- store first found string then
251 -- prepend remaining substrings
252 */
253 Char16 delim('.');
254 Uint32 index;
255 String range;
256
257 /* remove any array ranges so we dont parse a false . */
258 if((index = string.find("[")) != PEG_NOT_FOUND){
259 range = string.subString(index);
260 string.remove(index);
261 }
262
263 index = string.reverseFind(delim);
264 humberto 1.1.2.1 if(index == PEG_NOT_FOUND){
265 /* append the range we may have removed */
266 string.append(range);
267 _subIdentifiers.append(CQLIdentifier(string));
268 }else{
269 /* append the range we may have removed */
270 String tmp = string.subString(index+1);
271 tmp.append(range);
272 PEGASUS_STD(cout) << "tmp = " << tmp << PEGASUS_STD(endl);
273 _subIdentifiers.append(CQLIdentifier(tmp));
274
275 while(index != PEG_NOT_FOUND){
276 tmp = string.subString(0,index);
277 index = tmp.reverseFind(delim);
278 if(index == PEG_NOT_FOUND){
279 _subIdentifiers.prepend(CQLIdentifier(tmp));
280 }
281 else{
282 _subIdentifiers.prepend(CQLIdentifier(tmp.subString(index+1)));
283 }
284 }
285 humberto 1.1.2.1 }
286 }
287
288 PEGASUS_NAMESPACE_END
|