os/persistentdata/persistentstorage/dbms/pcdbms/usql/UQ_PARSE.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 	}