|
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // SQL parser |
|
15 // |
|
16 // |
|
17 |
|
18 #include "UQ_STD.H" |
|
19 #include "D32Assert.h" |
|
20 |
|
21 // class TSqlParser |
|
22 |
|
23 const TInt KSqlError = -1; |
|
24 |
|
25 TSqlParser::TSqlParser(const TDesC& aSql) |
|
26 : iSql(aSql) |
|
27 { |
|
28 NextToken(); // parse the first token |
|
29 } |
|
30 |
|
31 TSqlTokenType TSqlParser::NextToken() |
|
32 { |
|
33 return iSql.NextToken(iToken); |
|
34 } |
|
35 |
|
36 CSqlSearchCondition* TSqlParser::SqlError() |
|
37 { |
|
38 if (!Error()) |
|
39 iToken.SetError(KErrArgument); |
|
40 return 0; |
|
41 } |
|
42 |
|
43 TSqlTokenType TSqlParser::SqlErrorL() |
|
44 // |
|
45 // Report a SQL syntax error |
|
46 // |
|
47 { |
|
48 return TSqlTokenType(__LEAVE_IF_ERROR(KErrArgument)); |
|
49 } |
|
50 |
|
51 TSqlTokenType TSqlParser::Parse(TSqlKeyword aKeyword) |
|
52 // |
|
53 // look for requested keyword, skip to the next token if found |
|
54 // return the next token if found, else ESqlNoToken (==0) |
|
55 // |
|
56 { |
|
57 return TSqlLexer::IsKeyword(aKeyword,iToken) ? NextToken() : ESqlNoToken; |
|
58 } |
|
59 |
|
60 TSqlTokenType TSqlParser::ParseL(TSqlTokenType aToken) |
|
61 // |
|
62 // parse the desired token |
|
63 // |
|
64 { |
|
65 return iToken!=aToken ? SqlErrorL() : NextToken(); |
|
66 } |
|
67 |
|
68 TSqlTokenType TSqlParser::ParseL(TSqlKeyword aKeyword) |
|
69 // |
|
70 // parse the desired keyword |
|
71 // |
|
72 { |
|
73 TSqlTokenType t=Parse(aKeyword); |
|
74 return t==ESqlNoToken ? SqlErrorL() : t; |
|
75 } |
|
76 |
|
77 TSqlKeyword TSqlParser::Keyword() |
|
78 // |
|
79 // parse a keyword |
|
80 // |
|
81 { |
|
82 TSqlKeyword k=TSqlLexer::Keyword(iToken); |
|
83 if (k!=ESqlNotKeyword) |
|
84 NextToken(); |
|
85 return k; |
|
86 } |
|
87 |
|
88 TSqlTokenType TSqlParser::RightBracketL() |
|
89 // |
|
90 // parse a right bracket, and fail if not found |
|
91 // |
|
92 { |
|
93 return ParseL(ESqlRightBracket); |
|
94 } |
|
95 |
|
96 void TSqlParser::EndL() |
|
97 // |
|
98 // Check that the SQL has been fully parsed |
|
99 // |
|
100 { |
|
101 if (iToken!=ESqlEos) |
|
102 SqlErrorL(); |
|
103 } |
|
104 |
|
105 TSqlTokenType TSqlParser::IdentifierL(TPtrC& aIdentifier) |
|
106 // |
|
107 // parse an identifer, fail if not found |
|
108 // |
|
109 { |
|
110 if (iToken!=ESqlIdentifier) |
|
111 return SqlErrorL(); |
|
112 const TText* p=iToken.Literal().Ptr(); |
|
113 TInt len=iToken.Literal().End()-p; |
|
114 aIdentifier.Set(p,len); |
|
115 return NextToken(); |
|
116 } |
|
117 |
|
118 TPtrC TSqlParser::IdentifierL() |
|
119 // |
|
120 // parse an identifer, fail if not found |
|
121 // |
|
122 { |
|
123 if (iToken!=ESqlIdentifier) |
|
124 SqlErrorL(); |
|
125 return iToken.Literal().DesC(); |
|
126 } |
|
127 |
|
128 TSqlTokenType TSqlParser::ColumnNameL(RSqlColumnList& aList) |
|
129 // |
|
130 // Parse a column-identifier |
|
131 // |
|
132 { |
|
133 __LEAVE_IF_ERROR(aList.Append(IdentifierL())); |
|
134 return NextToken(); |
|
135 } |
|
136 |
|
137 TSqlTokenType TSqlParser::ColumnListL(RSqlColumnList& aList) |
|
138 // |
|
139 // Parse a column-identifier-comma-list |
|
140 // |
|
141 { |
|
142 for (;;) |
|
143 { |
|
144 TSqlTokenType t=ColumnNameL(aList); |
|
145 if (t!=ESqlComma) |
|
146 return t; |
|
147 NextToken(); |
|
148 } |
|
149 } |
|
150 |
|
151 TSqlTokenType TSqlParser::AddColumnSpecL(TDbCol& aDef) |
|
152 // |
|
153 // Parse an add-column-spec |
|
154 // |
|
155 { |
|
156 aDef.iAttributes=0; |
|
157 aDef.iName=IdentifierL(); |
|
158 NextToken(); |
|
159 // |
|
160 TDbColType type; |
|
161 switch (Keyword()) |
|
162 { |
|
163 case ESqlKeyword_bit: |
|
164 type=EDbColBit; |
|
165 break; |
|
166 case ESqlKeyword_tinyint: |
|
167 type=EDbColInt8; |
|
168 break; |
|
169 case ESqlKeyword_smallint: |
|
170 type=EDbColInt16; |
|
171 break; |
|
172 case ESqlKeyword_integer: |
|
173 type=EDbColInt32; |
|
174 break; |
|
175 case ESqlKeyword_counter: |
|
176 aDef.iAttributes=aDef.EAutoIncrement; |
|
177 type=EDbColUint32; |
|
178 break; |
|
179 case ESqlKeyword_bigint: |
|
180 type=EDbColInt64; |
|
181 break; |
|
182 case ESqlKeyword_real: |
|
183 type=EDbColReal32; |
|
184 break; |
|
185 case ESqlKeyword_double: |
|
186 Parse(ESqlKeyword_precision); |
|
187 // fall through |
|
188 case ESqlKeyword_float: |
|
189 type=EDbColReal64; |
|
190 break; |
|
191 case ESqlKeyword_date: |
|
192 case ESqlKeyword_time: |
|
193 case ESqlKeyword_timestamp: |
|
194 type=EDbColDateTime; |
|
195 break; |
|
196 case ESqlKeyword_char: |
|
197 case ESqlKeyword_varchar: |
|
198 type=EDbColText; |
|
199 break; |
|
200 case ESqlKeyword_char8: |
|
201 case ESqlKeyword_varchar8: |
|
202 type=EDbColText8; |
|
203 break; |
|
204 case ESqlKeyword_binary: |
|
205 case ESqlKeyword_varbinary: |
|
206 type=EDbColBinary; |
|
207 break; |
|
208 case ESqlKeyword_unsigned: // unsigned tinyint, smallint or integer |
|
209 switch (Keyword()) |
|
210 { |
|
211 case ESqlKeyword_tinyint: |
|
212 type=EDbColUint8; |
|
213 break; |
|
214 case ESqlKeyword_smallint: |
|
215 type=EDbColUint16; |
|
216 break; |
|
217 case ESqlKeyword_integer: |
|
218 type=EDbColUint32; |
|
219 break; |
|
220 default: |
|
221 return SqlErrorL(); |
|
222 }; |
|
223 break; |
|
224 case ESqlKeyword_long: // varchar or varbinary |
|
225 switch (Keyword()) |
|
226 { |
|
227 case ESqlKeyword_varchar8: |
|
228 type=EDbColLongText8; |
|
229 break; |
|
230 case ESqlKeyword_varchar: |
|
231 type=EDbColLongText; |
|
232 break; |
|
233 case ESqlKeyword_varbinary: |
|
234 type=EDbColLongBinary; |
|
235 break; |
|
236 default: |
|
237 return SqlErrorL(); |
|
238 }; |
|
239 break; |
|
240 default: |
|
241 return SqlErrorL(); |
|
242 } |
|
243 aDef.iType=type; |
|
244 // |
|
245 // get any optional length |
|
246 aDef.iMaxLength=KDbUndefinedLength; |
|
247 TSqlTokenType t=iToken.Type(); |
|
248 switch (type) |
|
249 { |
|
250 case EDbColText: |
|
251 case EDbColBinary: |
|
252 if (t==ESqlLeftBracket) |
|
253 { |
|
254 if (NextToken()==ESqlLiteralInt) |
|
255 { |
|
256 iToken.Literal().ToInt32L(); |
|
257 aDef.iMaxLength=iToken.Literal().Int32(); |
|
258 NextToken(); |
|
259 t=RightBracketL(); |
|
260 } |
|
261 else |
|
262 return SqlErrorL(); |
|
263 } |
|
264 break; |
|
265 default: |
|
266 break; |
|
267 } |
|
268 return t; |
|
269 } |
|
270 |
|
271 CSqlSearchCondition* TSqlParser::SearchCondition(TInt aNot) |
|
272 // |
|
273 // Parse a search-condition |
|
274 // |
|
275 { |
|
276 CSqlSearchCondition* left=BooleanTerm(aNot); |
|
277 if (left==0 || Parse(ESqlKeyword_or)==ESqlNoToken) |
|
278 return left; |
|
279 return CSqlMultiNode::New(aNot ? CSqlMultiNode::EAnd : CSqlMultiNode::EOr,left,SearchCondition(aNot)); |
|
280 } |
|
281 |
|
282 CSqlSearchCondition* TSqlParser::BooleanTerm(TInt aNot) |
|
283 // |
|
284 // Parse a boolean-term |
|
285 // |
|
286 { |
|
287 CSqlSearchCondition* left=BooleanFactor(aNot); |
|
288 if (left==0 || Parse(ESqlKeyword_and)==ESqlNoToken) |
|
289 return left; |
|
290 return CSqlMultiNode::New(aNot ? CSqlMultiNode::EOr : CSqlMultiNode::EAnd,left,BooleanTerm(aNot)); |
|
291 } |
|
292 |
|
293 CSqlSearchCondition* TSqlParser::BooleanFactor(TInt aNot) |
|
294 // |
|
295 // Parse a boolean-factor |
|
296 // |
|
297 { |
|
298 while (Parse(ESqlKeyword_not)) |
|
299 aNot=~aNot; |
|
300 return BooleanPrimary(aNot); |
|
301 } |
|
302 |
|
303 CSqlSearchCondition* TSqlParser::BooleanPrimary(TInt aNot) |
|
304 // |
|
305 // Parse a boolean-factor |
|
306 // |
|
307 { |
|
308 // brackets only allowed in this element, so this ordering is valid |
|
309 if (iToken!=ESqlLeftBracket) |
|
310 return Predicate(aNot); |
|
311 // bracketed search condition |
|
312 NextToken(); |
|
313 CSqlSearchCondition* node=SearchCondition(aNot); |
|
314 if (!node) |
|
315 return node; |
|
316 if (iToken==ESqlRightBracket) |
|
317 { |
|
318 NextToken(); |
|
319 return node; |
|
320 } |
|
321 delete node; |
|
322 return SqlError(); |
|
323 } |
|
324 |
|
325 CSqlSearchCondition* TSqlParser::Predicate(TInt aNot) |
|
326 // |
|
327 // Parse predicate |
|
328 // On null return, error will already be set |
|
329 // |
|
330 { |
|
331 if (iToken!=ESqlIdentifier) // column name |
|
332 return SqlError(); |
|
333 TPtrC column(iToken.Literal().DesC()); |
|
334 TSqlTokenType t=NextToken(); |
|
335 if (t==ESqlIdentifier) |
|
336 { // like-predicate or null-predicate |
|
337 switch (Keyword()) |
|
338 { |
|
339 case ESqlKeyword_is: // IS [NOT] NULL |
|
340 if (Parse(ESqlKeyword_not)) |
|
341 aNot=~aNot; |
|
342 if (Parse(ESqlKeyword_null)==ESqlNoToken) |
|
343 return SqlError(); |
|
344 return new CSqlNullPredicate(aNot ? CSqlNullPredicate::EIsNotNull : CSqlNullPredicate::EIsNull,column); |
|
345 case ESqlKeyword_not: // NOT LIKE |
|
346 if (Parse(ESqlKeyword_like)==ESqlNoToken) |
|
347 return SqlError(); |
|
348 aNot=~aNot; |
|
349 // drop through to Like |
|
350 case ESqlKeyword_like: // LIKE |
|
351 { |
|
352 if (iToken!=ESqlLiteralText) |
|
353 return SqlError(); |
|
354 |
|
355 //Following code is for the implementation of limited-ESCAPE-clause |
|
356 const TText *next = iSql.Next(); |
|
357 TPtrC pattern(iToken.Literal().DesC()); |
|
358 RSqlLiteral tmp = iToken.Literal(); |
|
359 |
|
360 NextToken(); // Searching for ESCAPE Key word |
|
361 |
|
362 if (Keyword() == ESqlKeyword_escape) |
|
363 { |
|
364 TInt length = pattern.Length(); |
|
365 if (length <= 0 || length > (KMaxSegmentLength + 2 )) |
|
366 return SqlError(); |
|
367 TPtrC escapeChar(iToken.Literal().DesC()); |
|
368 if (escapeChar.Length() <= 0) |
|
369 return SqlError(); |
|
370 TChar escchar = escapeChar[0]; |
|
371 TText newPattern[KMaxSegmentLength + 2]; // '*' can come as first and last char |
|
372 TInt count = PatternFilter(pattern,escchar, newPattern); |
|
373 if (count <=0 ) |
|
374 return SqlError(); |
|
375 iToken.Literal().SetText(newPattern,(newPattern + count)); |
|
376 // copy the text to RSqlLiteral as newpattern could go out of scope |
|
377 if (iToken.Literal().CopyText() != KErrNone) |
|
378 { |
|
379 return SqlError(); |
|
380 } |
|
381 CSqlSearchCondition* node = new CSqlLikePredicate(aNot ? CSqlLikePredicate::ENotLike : CSqlLikePredicate::ELike,column,iToken.Literal()); |
|
382 if (node) |
|
383 { |
|
384 NextToken(); |
|
385 node->iIsEscape = ETrue; |
|
386 } |
|
387 return node; |
|
388 } |
|
389 else |
|
390 { |
|
391 //Setto the previous node |
|
392 iSql.Set(next); |
|
393 CSqlSearchCondition* node = new CSqlLikePredicate(aNot ? CSqlLikePredicate::ENotLike : CSqlLikePredicate::ELike,column,tmp); |
|
394 if(node) |
|
395 NextToken(); |
|
396 return node; |
|
397 |
|
398 } |
|
399 } |
|
400 default: |
|
401 return SqlError(); |
|
402 } |
|
403 } |
|
404 // Comparison predicate... |
|
405 CSqlSearchCondition::TType op; |
|
406 switch (t) |
|
407 { |
|
408 case ESqlGreaterEqual: |
|
409 aNot=~aNot; |
|
410 // drop through to less |
|
411 case ESqlLess: |
|
412 op=aNot ? CSqlSearchCondition::EGreaterEqual : CSqlSearchCondition::ELess; |
|
413 break; |
|
414 case ESqlGreater: |
|
415 aNot=~aNot; |
|
416 // drop through to less equal |
|
417 case ESqlLessEqual: |
|
418 op=aNot ? CSqlSearchCondition::EGreater: CSqlSearchCondition::ELessEqual; |
|
419 break; |
|
420 case ESqlNotEqual: |
|
421 aNot=~aNot; |
|
422 // drop through to equal |
|
423 case ESqlEqual: |
|
424 op=aNot ? CSqlSearchCondition::ENotEqual : CSqlSearchCondition::EEqual; |
|
425 break; |
|
426 default: |
|
427 return SqlError(); |
|
428 } |
|
429 t=NextToken(); |
|
430 if (t!=ESqlLiteralInt && t!=ESqlLiteralReal && |
|
431 t!=ESqlLiteralTime && t!=ESqlLiteralText && |
|
432 t!=ESqlLiteralBlob ) |
|
433 return SqlError(); |
|
434 CSqlSearchCondition* node=new CSqlCompPredicate(op,column,iToken.Literal()); |
|
435 if (node) |
|
436 NextToken(); |
|
437 return node; |
|
438 } |
|
439 |
|
440 CSqlSearchCondition* TSqlParser::SearchConditionL() |
|
441 // |
|
442 // Parse a search-condition |
|
443 // |
|
444 { |
|
445 CSqlSearchCondition* sc=SearchCondition(0); |
|
446 if (!sc) |
|
447 { |
|
448 __LEAVE_IF_ERROR(Error()); // syntax error |
|
449 User::LeaveNoMemory(); // otherwise a OOM error |
|
450 } |
|
451 return sc; |
|
452 } |
|
453 |
|
454 void TSqlParser::SortSpecificationL(CDbKey& aKey) |
|
455 // |
|
456 // Parse a sort-specification |
|
457 // |
|
458 { |
|
459 for (;;) |
|
460 { |
|
461 TDbKeyCol col(IdentifierL()); |
|
462 NextToken(); |
|
463 if (Parse(ESqlKeyword_desc)) |
|
464 col.iOrder=col.EDesc; |
|
465 else |
|
466 { |
|
467 Parse(ESqlKeyword_asc); |
|
468 col.iOrder=col.EAsc; |
|
469 } |
|
470 aKey.AddL(col); |
|
471 if (iToken!=ESqlComma) |
|
472 break; |
|
473 NextToken(); |
|
474 } |
|
475 } |
|
476 |
|
477 CSqlQuery* TSqlParser::QueryLC() |
|
478 // |
|
479 // Generate a CSqlQuery |
|
480 // |
|
481 { |
|
482 CSqlQuery* query=new(ELeave) CSqlQuery; |
|
483 CleanupStack::PushL(query); |
|
484 if (ParseL(ESqlKeyword_select)==ESqlAsterisk) |
|
485 NextToken(); |
|
486 else |
|
487 ColumnListL(query->iColumns); |
|
488 ParseL(ESqlKeyword_from); |
|
489 IdentifierL(query->iTable); |
|
490 if (Parse(ESqlKeyword_where)) |
|
491 query->iSearchCondition=SearchConditionL(); |
|
492 if (Parse(ESqlKeyword_order)) |
|
493 { |
|
494 ParseL(ESqlKeyword_by); |
|
495 SortSpecificationL(query->SortSpecificationL()); |
|
496 } |
|
497 EndL(); |
|
498 return query; |
|
499 } |
|
500 |
|
501 CSqlSearchCondition* TSqlParser::SearchConditionLC() |
|
502 // |
|
503 // Parse a standalone search-condition |
|
504 // |
|
505 { |
|
506 CSqlSearchCondition* sc=SearchConditionL(); |
|
507 CleanupStack::PushL(sc); |
|
508 EndL(); |
|
509 return sc; |
|
510 } |
|
511 |
|
512 CSqlDDLStatement* TSqlParser::CreateTableLC() |
|
513 // |
|
514 // Parse a CREATE TABLE statement |
|
515 // |
|
516 { |
|
517 CSqlCreateTableStatement* statement=new(ELeave) CSqlCreateTableStatement; |
|
518 CleanupStack::PushL(statement); |
|
519 IdentifierL(statement->iName); |
|
520 ParseL(ESqlLeftBracket); |
|
521 TDbCol def; |
|
522 for (;;) |
|
523 { |
|
524 AddColumnSpecL(def); |
|
525 if (Parse(ESqlKeyword_not)) |
|
526 { |
|
527 ParseL(ESqlKeyword_null); |
|
528 def.iAttributes|=TDbCol::ENotNull; |
|
529 } |
|
530 if (Parse(ESqlKeyword_autoincrement)) |
|
531 { |
|
532 def.iAttributes|=TDbCol::EAutoIncrement; |
|
533 } |
|
534 statement->iColumns.AddL(def); |
|
535 if (iToken!=ESqlComma) |
|
536 break; |
|
537 NextToken(); |
|
538 } |
|
539 RightBracketL(); |
|
540 return statement; |
|
541 } |
|
542 |
|
543 CSqlDDLStatement* TSqlParser::DropTableLC() |
|
544 // |
|
545 // Parse a DROP TABLE statement |
|
546 // |
|
547 { |
|
548 CSqlDropTableStatement* statement=new(ELeave) CSqlDropTableStatement; |
|
549 CleanupStack::PushL(statement); |
|
550 IdentifierL(statement->iName); |
|
551 return statement; |
|
552 } |
|
553 |
|
554 CSqlDDLStatement* TSqlParser::AlterTableLC() |
|
555 // |
|
556 // Parse a CREATE TABLE statement |
|
557 // |
|
558 { |
|
559 CSqlAlterTableStatement* statement=new(ELeave) CSqlAlterTableStatement; |
|
560 CleanupStack::PushL(statement); |
|
561 IdentifierL(statement->iName); |
|
562 TSqlTokenType t=Parse(ESqlKeyword_add); |
|
563 if (t!=ESqlNoToken) |
|
564 { |
|
565 TDbCol def; |
|
566 if (t==ESqlLeftBracket) |
|
567 { |
|
568 NextToken(); |
|
569 for (;;) |
|
570 { |
|
571 t=AddColumnSpecL(def); |
|
572 statement->iAdd.AddL(def); |
|
573 if (t!=ESqlComma) |
|
574 break; |
|
575 NextToken(); |
|
576 } |
|
577 RightBracketL(); |
|
578 } |
|
579 else |
|
580 { |
|
581 AddColumnSpecL(def); |
|
582 statement->iAdd.AddL(def); |
|
583 } |
|
584 } |
|
585 t=Parse(ESqlKeyword_drop); |
|
586 if (t!=ESqlNoToken) |
|
587 { |
|
588 if (t!=ESqlLeftBracket) |
|
589 ColumnNameL(statement->iDrop); |
|
590 else |
|
591 { |
|
592 NextToken(); |
|
593 ColumnListL(statement->iDrop); |
|
594 RightBracketL(); |
|
595 } |
|
596 } |
|
597 return statement; |
|
598 } |
|
599 |
|
600 CSqlDDLStatement* TSqlParser::CreateIndexLC(TBool aUnique) |
|
601 // |
|
602 // Parse a CREATE INDEX statement |
|
603 // |
|
604 { |
|
605 CSqlCreateIndexStatement* statement=new(ELeave) CSqlCreateIndexStatement; |
|
606 CleanupStack::PushL(statement); |
|
607 if (aUnique) |
|
608 statement->iKey.MakeUnique(); |
|
609 IdentifierL(statement->iName); |
|
610 ParseL(ESqlKeyword_on); |
|
611 IdentifierL(statement->iTable); |
|
612 ParseL(ESqlLeftBracket); |
|
613 SortSpecificationL(statement->iKey); |
|
614 RightBracketL(); |
|
615 statement->iKey.SetComparison(EDbCompareNormal); |
|
616 TSqlTokenType collate=Parse(ESqlKeyword_collate); |
|
617 if ( collate != ESqlNoToken ) |
|
618 { |
|
619 TSqlTokenType normal=Parse(ESqlKeyword_normal); |
|
620 if ( normal == ESqlNoToken ) |
|
621 { |
|
622 TSqlTokenType collated=Parse(ESqlKeyword_collated); |
|
623 if ( collated == ESqlNoToken ) |
|
624 { |
|
625 TSqlTokenType folded=Parse(ESqlKeyword_folded); |
|
626 if ( folded != ESqlNoToken) |
|
627 { |
|
628 statement->iKey.SetComparison(EDbCompareFolded); |
|
629 } |
|
630 } |
|
631 else |
|
632 { |
|
633 statement->iKey.SetComparison(EDbCompareCollated); |
|
634 } |
|
635 } |
|
636 } |
|
637 return statement; |
|
638 } |
|
639 |
|
640 CSqlDDLStatement* TSqlParser::DropIndexLC() |
|
641 // |
|
642 // Parse a DROP INDEX statement |
|
643 // |
|
644 { |
|
645 CSqlDropIndexStatement* statement=new(ELeave) CSqlDropIndexStatement; |
|
646 CleanupStack::PushL(statement); |
|
647 IdentifierL(statement->iName); |
|
648 ParseL(ESqlKeyword_from); |
|
649 IdentifierL(statement->iTable); |
|
650 return statement; |
|
651 } |
|
652 |
|
653 CSqlDDLStatement* TSqlParser::DDLStatementLC() |
|
654 { |
|
655 CSqlDDLStatement* statement; |
|
656 if (Parse(ESqlKeyword_create)) |
|
657 { |
|
658 if (Parse(ESqlKeyword_table)) |
|
659 statement=CreateTableLC(); |
|
660 else |
|
661 { |
|
662 TSqlTokenType unique=Parse(ESqlKeyword_unique); |
|
663 ParseL(ESqlKeyword_index); |
|
664 statement=CreateIndexLC(unique); |
|
665 } |
|
666 } |
|
667 else if (Parse(ESqlKeyword_drop)) |
|
668 { |
|
669 if (Parse(ESqlKeyword_table)) |
|
670 statement=DropTableLC(); |
|
671 else |
|
672 { |
|
673 ParseL(ESqlKeyword_index); |
|
674 statement=DropIndexLC(); |
|
675 } |
|
676 } |
|
677 else |
|
678 { |
|
679 ParseL(ESqlKeyword_alter); |
|
680 ParseL(ESqlKeyword_table); |
|
681 statement=AlterTableLC(); |
|
682 } |
|
683 EndL(); |
|
684 return statement; |
|
685 } |
|
686 |
|
687 TSqlTokenType TSqlParser::ColumnValueL(CSqlValues& aValues) |
|
688 // |
|
689 // parse a column-value and add to aValues |
|
690 // |
|
691 { |
|
692 switch (iToken.Type()) |
|
693 { |
|
694 case ESqlLiteralInt: |
|
695 case ESqlLiteralReal: |
|
696 case ESqlLiteralTime: |
|
697 case ESqlLiteralText: |
|
698 case ESqlLiteralBlob: |
|
699 aValues.AddL(iToken.Literal()); |
|
700 return NextToken(); |
|
701 case ESqlIdentifier: // NULL |
|
702 { |
|
703 TSqlTokenType t=ParseL(ESqlKeyword_null); |
|
704 aValues.AddL(RSqlLiteral()); // default c'ted RSqlLiteral is null |
|
705 return t; |
|
706 } |
|
707 default: // SQL error |
|
708 return SqlErrorL(); |
|
709 } |
|
710 } |
|
711 |
|
712 CSqlDMLStatement* TSqlParser::InsertStatementLC() |
|
713 // |
|
714 // parse an insert-statement |
|
715 // |
|
716 { |
|
717 ParseL(ESqlKeyword_into); |
|
718 CSqlInsertStatement* statement=CSqlInsertStatement::NewLC(); |
|
719 if (IdentifierL(statement->iQuery.iTable)==ESqlLeftBracket) |
|
720 { |
|
721 NextToken(); |
|
722 ColumnListL(statement->iQuery.iColumns); |
|
723 RightBracketL(); |
|
724 } |
|
725 ParseL(ESqlKeyword_values); |
|
726 ParseL(ESqlLeftBracket); |
|
727 CSqlValues& values=statement->ValuesL(); |
|
728 while (ColumnValueL(values)==ESqlComma) |
|
729 NextToken(); |
|
730 RightBracketL(); |
|
731 return statement; |
|
732 } |
|
733 |
|
734 CSqlDMLStatement* TSqlParser::UpdateStatementLC() |
|
735 // |
|
736 // parse an update-statement |
|
737 // |
|
738 { |
|
739 CSqlModifyStatement* statement=CSqlModifyStatement::NewLC(); |
|
740 IdentifierL(statement->iQuery.iTable); |
|
741 ParseL(ESqlKeyword_set); |
|
742 CSqlValues& values=statement->ValuesL(); |
|
743 for (;;) |
|
744 { |
|
745 ColumnNameL(statement->iQuery.iColumns); |
|
746 ParseL(ESqlEqual); |
|
747 if (ColumnValueL(values)!=ESqlComma) |
|
748 break; |
|
749 NextToken(); |
|
750 } |
|
751 if (Parse(ESqlKeyword_where)) |
|
752 statement->iQuery.iSearchCondition=SearchConditionL(); |
|
753 return statement; |
|
754 } |
|
755 |
|
756 CSqlDMLStatement* TSqlParser::DeleteStatementLC() |
|
757 // |
|
758 // parse a delete-statement |
|
759 // |
|
760 { |
|
761 ParseL(ESqlKeyword_from); |
|
762 CSqlModifyStatement* statement=CSqlModifyStatement::NewLC(); |
|
763 IdentifierL(statement->iQuery.iTable); |
|
764 if (Parse(ESqlKeyword_where)) |
|
765 statement->iQuery.iSearchCondition=SearchConditionL(); |
|
766 return statement; |
|
767 } |
|
768 |
|
769 CSqlDMLStatement* TSqlParser::DMLStatementLC() |
|
770 { |
|
771 CSqlDMLStatement* statement; |
|
772 if (Parse(ESqlKeyword_insert)) |
|
773 statement=InsertStatementLC(); |
|
774 else if (Parse(ESqlKeyword_update)) |
|
775 statement=UpdateStatementLC(); |
|
776 else |
|
777 { |
|
778 ParseL(ESqlKeyword_delete); |
|
779 statement=DeleteStatementLC(); |
|
780 } |
|
781 EndL(); |
|
782 return statement; |
|
783 } |
|
784 |
|
785 Sql::TStatementType TSqlParser::Type() |
|
786 { |
|
787 TSqlKeyword k=TSqlLexer::Keyword(iToken); |
|
788 if (k==ESqlKeyword_create || k==ESqlKeyword_alter || k==ESqlKeyword_drop) |
|
789 return Sql::EDDL; |
|
790 if (k==ESqlKeyword_insert || k==ESqlKeyword_update || k==ESqlKeyword_delete) |
|
791 return Sql::EDML; |
|
792 return Sql::ENone; |
|
793 } |
|
794 |
|
795 TInt TSqlParser::PatternFilter(const TDesC& aPattern,const TChar aEscape,TText *aNewPatternBuffer ) |
|
796 { |
|
797 TInt length = aPattern.Length(); |
|
798 TInt count =0; |
|
799 |
|
800 // Ensure that the pattern begins and ends with an '*' |
|
801 if ((length < 2) || (aPattern[0] != KMatchAny || aPattern[length-1] != KMatchAny)) |
|
802 { |
|
803 return KSqlError; |
|
804 } |
|
805 |
|
806 for (TInt i = 1 ; i< length -1 ;++i) |
|
807 { |
|
808 if (aPattern[i]== (TUint)aEscape) |
|
809 { |
|
810 if ((aPattern[i + 1] == KMatchAny) || (aPattern[i + 1] == KMatchOne) || (aPattern[i + 1] == (TUint)aEscape)) |
|
811 { |
|
812 i++; |
|
813 aNewPatternBuffer[count++] = aPattern[i]; |
|
814 } |
|
815 else |
|
816 { |
|
817 return KSqlError; |
|
818 } |
|
819 } |
|
820 else |
|
821 { |
|
822 if ((aPattern[i] == KMatchAny || aPattern[i] == KMatchOne) ) |
|
823 { |
|
824 return KSqlError; |
|
825 } |
|
826 else |
|
827 { |
|
828 aNewPatternBuffer[count++] = aPattern[i]; |
|
829 } |
|
830 } |
|
831 } |
|
832 |
|
833 return count; |
|
834 } |