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