sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // SQL parser sl@0: // sl@0: // sl@0: sl@0: #include "UQ_STD.H" sl@0: sl@0: // class TSqlParser sl@0: sl@0: const TInt KSqlError = -1; sl@0: sl@0: TSqlParser::TSqlParser(const TDesC& aSql) sl@0: : iSql(aSql) sl@0: { sl@0: NextToken(); // parse the first token sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::NextToken() sl@0: { sl@0: return iSql.NextToken(iToken); sl@0: } sl@0: sl@0: CSqlSearchCondition* TSqlParser::SqlError() sl@0: { sl@0: if (!Error()) sl@0: iToken.SetError(KErrArgument); sl@0: return 0; sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::SqlErrorL() sl@0: // sl@0: // Report a SQL syntax error sl@0: // sl@0: { sl@0: return TSqlTokenType(__LEAVE_IF_ERROR(KErrArgument)); sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::Parse(TSqlKeyword aKeyword) sl@0: // sl@0: // look for requested keyword, skip to the next token if found sl@0: // return the next token if found, else ESqlNoToken (==0) sl@0: // sl@0: { sl@0: return TSqlLexer::IsKeyword(aKeyword,iToken) ? NextToken() : ESqlNoToken; sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::ParseL(TSqlTokenType aToken) sl@0: // sl@0: // parse the desired token sl@0: // sl@0: { sl@0: return iToken!=aToken ? SqlErrorL() : NextToken(); sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::ParseL(TSqlKeyword aKeyword) sl@0: // sl@0: // parse the desired keyword sl@0: // sl@0: { sl@0: TSqlTokenType t=Parse(aKeyword); sl@0: return t==ESqlNoToken ? SqlErrorL() : t; sl@0: } sl@0: sl@0: TSqlKeyword TSqlParser::Keyword() sl@0: // sl@0: // parse a keyword sl@0: // sl@0: { sl@0: TSqlKeyword k=TSqlLexer::Keyword(iToken); sl@0: if (k!=ESqlNotKeyword) sl@0: NextToken(); sl@0: return k; sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::RightBracketL() sl@0: // sl@0: // parse a right bracket, and fail if not found sl@0: // sl@0: { sl@0: return ParseL(ESqlRightBracket); sl@0: } sl@0: sl@0: void TSqlParser::EndL() sl@0: // sl@0: // Check that the SQL has been fully parsed sl@0: // sl@0: { sl@0: if (iToken!=ESqlEos) sl@0: SqlErrorL(); sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::IdentifierL(TPtrC& aIdentifier) sl@0: // sl@0: // parse an identifer, fail if not found sl@0: // sl@0: { sl@0: if (iToken!=ESqlIdentifier) sl@0: return SqlErrorL(); sl@0: const TText* p=iToken.Literal().Ptr(); sl@0: TInt len=iToken.Literal().End()-p; sl@0: aIdentifier.Set(p,len); sl@0: return NextToken(); sl@0: } sl@0: sl@0: TPtrC TSqlParser::IdentifierL() sl@0: // sl@0: // parse an identifer, fail if not found sl@0: // sl@0: { sl@0: if (iToken!=ESqlIdentifier) sl@0: SqlErrorL(); sl@0: return iToken.Literal().DesC(); sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::ColumnNameL(RSqlColumnList& aList) sl@0: // sl@0: // Parse a column-identifier sl@0: // sl@0: { sl@0: __LEAVE_IF_ERROR(aList.Append(IdentifierL())); sl@0: return NextToken(); sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::ColumnListL(RSqlColumnList& aList) sl@0: // sl@0: // Parse a column-identifier-comma-list sl@0: // sl@0: { sl@0: for (;;) sl@0: { sl@0: TSqlTokenType t=ColumnNameL(aList); sl@0: if (t!=ESqlComma) sl@0: return t; sl@0: NextToken(); sl@0: } sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::AddColumnSpecL(TDbCol& aDef) sl@0: // sl@0: // Parse an add-column-spec sl@0: // sl@0: { sl@0: aDef.iAttributes=0; sl@0: aDef.iName=IdentifierL(); sl@0: NextToken(); sl@0: // sl@0: TDbColType type; sl@0: switch (Keyword()) sl@0: { sl@0: case ESqlKeyword_bit: sl@0: type=EDbColBit; sl@0: break; sl@0: case ESqlKeyword_tinyint: sl@0: type=EDbColInt8; sl@0: break; sl@0: case ESqlKeyword_smallint: sl@0: type=EDbColInt16; sl@0: break; sl@0: case ESqlKeyword_integer: sl@0: type=EDbColInt32; sl@0: break; sl@0: case ESqlKeyword_counter: sl@0: aDef.iAttributes=aDef.EAutoIncrement; sl@0: type=EDbColUint32; sl@0: break; sl@0: case ESqlKeyword_bigint: sl@0: type=EDbColInt64; sl@0: break; sl@0: case ESqlKeyword_real: sl@0: type=EDbColReal32; sl@0: break; sl@0: case ESqlKeyword_double: sl@0: //Return value is intentionaly not checked. Parse() checks for sl@0: //an optional SQL keyword and calls internal checks. sl@0: //coverity[check_return] sl@0: //coverity[unchecked_value] sl@0: Parse(ESqlKeyword_precision); sl@0: // fall through sl@0: case ESqlKeyword_float: sl@0: type=EDbColReal64; sl@0: break; sl@0: case ESqlKeyword_date: sl@0: case ESqlKeyword_time: sl@0: case ESqlKeyword_timestamp: sl@0: type=EDbColDateTime; sl@0: break; sl@0: case ESqlKeyword_char: sl@0: case ESqlKeyword_varchar: sl@0: type=EDbColText; sl@0: break; sl@0: case ESqlKeyword_binary: sl@0: case ESqlKeyword_varbinary: sl@0: type=EDbColBinary; sl@0: break; sl@0: case ESqlKeyword_unsigned: // unsigned tinyint, smallint or integer sl@0: switch (Keyword()) sl@0: { sl@0: case ESqlKeyword_tinyint: sl@0: type=EDbColUint8; sl@0: break; sl@0: case ESqlKeyword_smallint: sl@0: type=EDbColUint16; sl@0: break; sl@0: case ESqlKeyword_integer: sl@0: type=EDbColUint32; sl@0: break; sl@0: default: sl@0: return SqlErrorL(); sl@0: }; sl@0: break; sl@0: case ESqlKeyword_long: // varchar or varbinary sl@0: switch (Keyword()) sl@0: { sl@0: case ESqlKeyword_varchar: sl@0: type=EDbColLongText; sl@0: break; sl@0: case ESqlKeyword_varbinary: sl@0: type=EDbColLongBinary; sl@0: break; sl@0: default: sl@0: return SqlErrorL(); sl@0: }; sl@0: break; sl@0: default: sl@0: return SqlErrorL(); sl@0: } sl@0: aDef.iType=type; sl@0: // sl@0: // get any optional length sl@0: aDef.iMaxLength=KDbUndefinedLength; sl@0: TSqlTokenType t=iToken.Type(); sl@0: switch (type) sl@0: { sl@0: case EDbColText: sl@0: case EDbColBinary: sl@0: if (t==ESqlLeftBracket) sl@0: { sl@0: if (NextToken()==ESqlLiteralInt) sl@0: { sl@0: iToken.Literal().ToInt32L(); sl@0: aDef.iMaxLength=iToken.Literal().Int32(); sl@0: NextToken(); sl@0: t=RightBracketL(); sl@0: } sl@0: else sl@0: return SqlErrorL(); sl@0: } sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: return t; sl@0: } sl@0: sl@0: CSqlSearchCondition* TSqlParser::SearchCondition(TInt aNot) sl@0: // sl@0: // Parse a search-condition sl@0: // sl@0: { sl@0: CSqlSearchCondition* left=BooleanTerm(aNot); sl@0: if (left==0 || Parse(ESqlKeyword_or)==ESqlNoToken) sl@0: return left; sl@0: return CSqlMultiNode::New(aNot ? CSqlMultiNode::EAnd : CSqlMultiNode::EOr,left,SearchCondition(aNot)); sl@0: } sl@0: sl@0: CSqlSearchCondition* TSqlParser::BooleanTerm(TInt aNot) sl@0: // sl@0: // Parse a boolean-term sl@0: // sl@0: { sl@0: CSqlSearchCondition* left=BooleanFactor(aNot); sl@0: if (left==0 || Parse(ESqlKeyword_and)==ESqlNoToken) sl@0: return left; sl@0: return CSqlMultiNode::New(aNot ? CSqlMultiNode::EOr : CSqlMultiNode::EAnd,left,BooleanTerm(aNot)); sl@0: } sl@0: sl@0: CSqlSearchCondition* TSqlParser::BooleanFactor(TInt aNot) sl@0: // sl@0: // Parse a boolean-factor sl@0: // sl@0: { sl@0: while (Parse(ESqlKeyword_not)) sl@0: aNot=~aNot; sl@0: return BooleanPrimary(aNot); sl@0: } sl@0: sl@0: CSqlSearchCondition* TSqlParser::BooleanPrimary(TInt aNot) sl@0: // sl@0: // Parse a boolean-factor sl@0: // sl@0: { sl@0: // brackets only allowed in this element, so this ordering is valid sl@0: if (iToken!=ESqlLeftBracket) sl@0: return Predicate(aNot); sl@0: // bracketed search condition sl@0: NextToken(); sl@0: CSqlSearchCondition* node=SearchCondition(aNot); sl@0: if (!node) sl@0: return node; sl@0: if (iToken==ESqlRightBracket) sl@0: { sl@0: NextToken(); sl@0: return node; sl@0: } sl@0: delete node; sl@0: return SqlError(); sl@0: } sl@0: sl@0: CSqlSearchCondition* TSqlParser::Predicate(TInt aNot) sl@0: // sl@0: // Parse predicate sl@0: // On null return, error will already be set sl@0: // sl@0: { sl@0: if (iToken!=ESqlIdentifier) // column name sl@0: return SqlError(); sl@0: TPtrC column(iToken.Literal().DesC()); sl@0: TSqlTokenType t=NextToken(); sl@0: if (t==ESqlIdentifier) sl@0: { // like-predicate or null-predicate sl@0: switch (Keyword()) sl@0: { sl@0: case ESqlKeyword_is: // IS [NOT] NULL sl@0: if (Parse(ESqlKeyword_not)) sl@0: aNot=~aNot; sl@0: if (Parse(ESqlKeyword_null)==ESqlNoToken) sl@0: return SqlError(); sl@0: return new CSqlNullPredicate(aNot ? CSqlNullPredicate::EIsNotNull : CSqlNullPredicate::EIsNull,column); sl@0: case ESqlKeyword_not: // NOT LIKE sl@0: if (Parse(ESqlKeyword_like)==ESqlNoToken) sl@0: return SqlError(); sl@0: aNot=~aNot; sl@0: // drop through to Like sl@0: case ESqlKeyword_like: // LIKE sl@0: { sl@0: if (iToken!=ESqlLiteralText) sl@0: return SqlError(); sl@0: sl@0: //Following code is for the implementation of limited-ESCAPE-clause sl@0: const TText *next = iSql.Next(); //remember thecurrent position in the SQL statement sl@0: RSqlLiteral pattern = iToken.Literal(); //this is the LIKE pattern, remember it, because the next keyword might be ESCAPE sl@0: sl@0: NextToken(); // Searching for ESCAPE keyword sl@0: sl@0: if (Keyword() == ESqlKeyword_escape) sl@0: { sl@0: if (pattern.DesC().Length() <= 0 || pattern.DesC().Length() > (KMaxSegmentLength + 2 )) sl@0: return SqlError(); sl@0: TPtrC escapeChar(iToken.Literal().DesC()); sl@0: if (escapeChar.Length() <= 0) sl@0: return SqlError(); sl@0: TChar escchar = escapeChar[0]; sl@0: TText newPattern[KMaxSegmentLength + 2]; // '*' can come as first and last char sl@0: TInt count = PatternFilter(pattern.DesC(),escchar, newPattern);//remove the escape characters from the pattern and store it in "newPattern" variable sl@0: if (count <=0 ) sl@0: return SqlError(); sl@0: iToken.Literal().SetText(newPattern,(newPattern + count)); sl@0: // copy the text to RSqlLiteral as "newPattern" is stack based variable and will go out of scope sl@0: if (iToken.Literal().CopyText() != KErrNone) sl@0: { sl@0: return SqlError(); sl@0: } sl@0: CSqlSearchCondition* node = new CSqlLikePredicate(aNot ? CSqlLikePredicate::ENotLike : CSqlLikePredicate::ELike,column,iToken.Literal()); sl@0: //cleanup iToken.Literal(), because if there is another LIKE predicate, the allocated by CopyText() buffer will sl@0: //be shared between two RSqlLiteral instances and RSqlLiteral::Close() call will crash. sl@0: //RSqlLiteral::RSqlLiteral() will set the "iBuffer" data member to NULL. sl@0: iToken.Literal() = RSqlLiteral(); sl@0: if (node) sl@0: { sl@0: NextToken(); sl@0: node->iIsEscape = ETrue; sl@0: } sl@0: return node; sl@0: } sl@0: else sl@0: { sl@0: //Set to the previous node sl@0: iSql.Set(next); sl@0: CSqlSearchCondition* node = new CSqlLikePredicate(aNot ? CSqlLikePredicate::ENotLike : CSqlLikePredicate::ELike,column,pattern); sl@0: if(node) sl@0: NextToken(); sl@0: return node; sl@0: sl@0: } sl@0: } sl@0: default: sl@0: return SqlError(); sl@0: } sl@0: } sl@0: // Comparison predicate... sl@0: CSqlSearchCondition::TType op; sl@0: switch (t) sl@0: { sl@0: case ESqlGreaterEqual: sl@0: aNot=~aNot; sl@0: // drop through to less sl@0: case ESqlLess: sl@0: op=aNot ? CSqlSearchCondition::EGreaterEqual : CSqlSearchCondition::ELess; sl@0: break; sl@0: case ESqlGreater: sl@0: aNot=~aNot; sl@0: // drop through to less equal sl@0: case ESqlLessEqual: sl@0: op=aNot ? CSqlSearchCondition::EGreater: CSqlSearchCondition::ELessEqual; sl@0: break; sl@0: case ESqlNotEqual: sl@0: aNot=~aNot; sl@0: // drop through to equal sl@0: case ESqlEqual: sl@0: op=aNot ? CSqlSearchCondition::ENotEqual : CSqlSearchCondition::EEqual; sl@0: break; sl@0: default: sl@0: return SqlError(); sl@0: } sl@0: t=NextToken(); sl@0: if (t!=ESqlLiteralInt && t!=ESqlLiteralReal && t!=ESqlLiteralTime && t!=ESqlLiteralText) sl@0: return SqlError(); sl@0: CSqlSearchCondition* node=new CSqlCompPredicate(op,column,iToken.Literal()); sl@0: if (node) sl@0: NextToken(); sl@0: return node; sl@0: } sl@0: sl@0: CSqlSearchCondition* TSqlParser::SearchConditionL() sl@0: // sl@0: // Parse a search-condition sl@0: // sl@0: { sl@0: CSqlSearchCondition* sc=SearchCondition(0); sl@0: if (!sc) sl@0: { sl@0: __LEAVE_IF_ERROR(Error()); // syntax error sl@0: User::LeaveNoMemory(); // otherwise a OOM error sl@0: } sl@0: return sc; sl@0: } sl@0: sl@0: void TSqlParser::SortSpecificationL(CDbKey& aKey) sl@0: // sl@0: // Parse a sort-specification sl@0: // sl@0: { sl@0: for (;;) sl@0: { sl@0: TDbKeyCol col(IdentifierL()); sl@0: NextToken(); sl@0: if (Parse(ESqlKeyword_desc)) sl@0: col.iOrder=col.EDesc; sl@0: else sl@0: { sl@0: //Return value is intentionaly not checked. Parse() checks for sl@0: //an optional SQL keyword and calls internal checks. sl@0: //coverity[check_return] sl@0: //coverity[unchecked_value] sl@0: Parse(ESqlKeyword_asc); sl@0: col.iOrder=col.EAsc; sl@0: } sl@0: aKey.AddL(col); sl@0: if (iToken!=ESqlComma) sl@0: break; sl@0: NextToken(); sl@0: } sl@0: } sl@0: sl@0: CSqlQuery* TSqlParser::QueryLC() sl@0: // sl@0: // Generate a CSqlQuery sl@0: // sl@0: { sl@0: CSqlQuery* query=new(ELeave) CSqlQuery; sl@0: CleanupStack::PushL(query); sl@0: if (ParseL(ESqlKeyword_select)==ESqlAsterisk) sl@0: NextToken(); sl@0: else sl@0: ColumnListL(query->iColumns); sl@0: ParseL(ESqlKeyword_from); sl@0: IdentifierL(query->iTable); sl@0: if (Parse(ESqlKeyword_where)) sl@0: query->iSearchCondition=SearchConditionL(); sl@0: if (Parse(ESqlKeyword_order)) sl@0: { sl@0: ParseL(ESqlKeyword_by); sl@0: SortSpecificationL(query->SortSpecificationL()); sl@0: } sl@0: EndL(); sl@0: return query; sl@0: } sl@0: sl@0: CSqlSearchCondition* TSqlParser::SearchConditionLC() sl@0: // sl@0: // Parse a standalone search-condition sl@0: // sl@0: { sl@0: CSqlSearchCondition* sc=SearchConditionL(); sl@0: CleanupStack::PushL(sc); sl@0: EndL(); sl@0: return sc; sl@0: } sl@0: sl@0: CSqlDDLStatement* TSqlParser::CreateTableLC() sl@0: // sl@0: // Parse a CREATE TABLE statement sl@0: // sl@0: { sl@0: CSqlCreateTableStatement* statement=new(ELeave) CSqlCreateTableStatement; sl@0: CleanupStack::PushL(statement); sl@0: IdentifierL(statement->iName); sl@0: ParseL(ESqlLeftBracket); sl@0: TDbCol def; sl@0: for (;;) sl@0: { sl@0: AddColumnSpecL(def); sl@0: if (Parse(ESqlKeyword_not)) sl@0: { sl@0: ParseL(ESqlKeyword_null); sl@0: def.iAttributes|=TDbCol::ENotNull; sl@0: } sl@0: statement->iColumns.AddL(def); sl@0: if (iToken!=ESqlComma) sl@0: break; sl@0: NextToken(); sl@0: } sl@0: RightBracketL(); sl@0: return statement; sl@0: } sl@0: sl@0: CSqlDDLStatement* TSqlParser::DropTableLC() sl@0: // sl@0: // Parse a DROP TABLE statement sl@0: // sl@0: { sl@0: CSqlDropTableStatement* statement=new(ELeave) CSqlDropTableStatement; sl@0: CleanupStack::PushL(statement); sl@0: IdentifierL(statement->iName); sl@0: return statement; sl@0: } sl@0: sl@0: CSqlDDLStatement* TSqlParser::AlterTableLC() sl@0: // sl@0: // Parse a CREATE TABLE statement sl@0: // sl@0: { sl@0: CSqlAlterTableStatement* statement=new(ELeave) CSqlAlterTableStatement; sl@0: CleanupStack::PushL(statement); sl@0: IdentifierL(statement->iName); sl@0: TSqlTokenType t=Parse(ESqlKeyword_add); sl@0: if (t!=ESqlNoToken) sl@0: { sl@0: TDbCol def; sl@0: if (t==ESqlLeftBracket) sl@0: { sl@0: NextToken(); sl@0: for (;;) sl@0: { sl@0: t=AddColumnSpecL(def); sl@0: statement->iAdd.AddL(def); sl@0: if (t!=ESqlComma) sl@0: break; sl@0: NextToken(); sl@0: } sl@0: RightBracketL(); sl@0: } sl@0: else sl@0: { sl@0: AddColumnSpecL(def); sl@0: statement->iAdd.AddL(def); sl@0: } sl@0: } sl@0: t=Parse(ESqlKeyword_drop); sl@0: if (t!=ESqlNoToken) sl@0: { sl@0: if (t!=ESqlLeftBracket) sl@0: ColumnNameL(statement->iDrop); sl@0: else sl@0: { sl@0: NextToken(); sl@0: ColumnListL(statement->iDrop); sl@0: RightBracketL(); sl@0: } sl@0: } sl@0: return statement; sl@0: } sl@0: sl@0: CSqlDDLStatement* TSqlParser::CreateIndexLC(TBool aUnique) sl@0: // sl@0: // Parse a CREATE INDEX statement sl@0: // sl@0: { sl@0: CSqlCreateIndexStatement* statement=new(ELeave) CSqlCreateIndexStatement; sl@0: CleanupStack::PushL(statement); sl@0: if (aUnique) sl@0: statement->iKey.MakeUnique(); sl@0: IdentifierL(statement->iName); sl@0: ParseL(ESqlKeyword_on); sl@0: IdentifierL(statement->iTable); sl@0: ParseL(ESqlLeftBracket); sl@0: SortSpecificationL(statement->iKey); sl@0: RightBracketL(); sl@0: return statement; sl@0: } sl@0: sl@0: CSqlDDLStatement* TSqlParser::DropIndexLC() sl@0: // sl@0: // Parse a DROP INDEX statement sl@0: // sl@0: { sl@0: CSqlDropIndexStatement* statement=new(ELeave) CSqlDropIndexStatement; sl@0: CleanupStack::PushL(statement); sl@0: IdentifierL(statement->iName); sl@0: ParseL(ESqlKeyword_from); sl@0: IdentifierL(statement->iTable); sl@0: return statement; sl@0: } sl@0: sl@0: CSqlDDLStatement* TSqlParser::DDLStatementLC() sl@0: { sl@0: CSqlDDLStatement* statement; sl@0: if (Parse(ESqlKeyword_create)) sl@0: { sl@0: if (Parse(ESqlKeyword_table)) sl@0: statement=CreateTableLC(); sl@0: else sl@0: { sl@0: TSqlTokenType unique=Parse(ESqlKeyword_unique); sl@0: ParseL(ESqlKeyword_index); sl@0: statement=CreateIndexLC(unique); sl@0: } sl@0: } sl@0: else if (Parse(ESqlKeyword_drop)) sl@0: { sl@0: if (Parse(ESqlKeyword_table)) sl@0: statement=DropTableLC(); sl@0: else sl@0: { sl@0: ParseL(ESqlKeyword_index); sl@0: statement=DropIndexLC(); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: ParseL(ESqlKeyword_alter); sl@0: ParseL(ESqlKeyword_table); sl@0: statement=AlterTableLC(); sl@0: } sl@0: EndL(); sl@0: return statement; sl@0: } sl@0: sl@0: TSqlTokenType TSqlParser::ColumnValueL(CSqlValues& aValues) sl@0: // sl@0: // parse a column-value and add to aValues sl@0: // sl@0: { sl@0: switch (iToken.Type()) sl@0: { sl@0: case ESqlLiteralInt: sl@0: case ESqlLiteralReal: sl@0: case ESqlLiteralTime: sl@0: case ESqlLiteralText: sl@0: aValues.AddL(iToken.Literal()); sl@0: return NextToken(); sl@0: case ESqlIdentifier: // NULL sl@0: { sl@0: TSqlTokenType t=ParseL(ESqlKeyword_null); sl@0: aValues.AddL(RSqlLiteral()); // default c'ted RSqlLiteral is null sl@0: return t; sl@0: } sl@0: default: // SQL error sl@0: return SqlErrorL(); sl@0: } sl@0: } sl@0: sl@0: CSqlDMLStatement* TSqlParser::InsertStatementLC() sl@0: // sl@0: // parse an insert-statement sl@0: // sl@0: { sl@0: ParseL(ESqlKeyword_into); sl@0: CSqlInsertStatement* statement=CSqlInsertStatement::NewLC(); sl@0: if (IdentifierL(statement->iQuery.iTable)==ESqlLeftBracket) sl@0: { sl@0: NextToken(); sl@0: ColumnListL(statement->iQuery.iColumns); sl@0: RightBracketL(); sl@0: } sl@0: ParseL(ESqlKeyword_values); sl@0: ParseL(ESqlLeftBracket); sl@0: CSqlValues& values=statement->ValuesL(); sl@0: while (ColumnValueL(values)==ESqlComma) sl@0: NextToken(); sl@0: RightBracketL(); sl@0: return statement; sl@0: } sl@0: sl@0: CSqlDMLStatement* TSqlParser::UpdateStatementLC() sl@0: // sl@0: // parse an update-statement sl@0: // sl@0: { sl@0: CSqlModifyStatement* statement=CSqlModifyStatement::NewLC(); sl@0: IdentifierL(statement->iQuery.iTable); sl@0: ParseL(ESqlKeyword_set); sl@0: CSqlValues& values=statement->ValuesL(); sl@0: for (;;) sl@0: { sl@0: ColumnNameL(statement->iQuery.iColumns); sl@0: ParseL(ESqlEqual); sl@0: if (ColumnValueL(values)!=ESqlComma) sl@0: break; sl@0: NextToken(); sl@0: } sl@0: if (Parse(ESqlKeyword_where)) sl@0: statement->iQuery.iSearchCondition=SearchConditionL(); sl@0: return statement; sl@0: } sl@0: sl@0: CSqlDMLStatement* TSqlParser::DeleteStatementLC() sl@0: // sl@0: // parse a delete-statement sl@0: // sl@0: { sl@0: ParseL(ESqlKeyword_from); sl@0: CSqlModifyStatement* statement=CSqlModifyStatement::NewLC(); sl@0: IdentifierL(statement->iQuery.iTable); sl@0: if (Parse(ESqlKeyword_where)) sl@0: statement->iQuery.iSearchCondition=SearchConditionL(); sl@0: return statement; sl@0: } sl@0: sl@0: CSqlDMLStatement* TSqlParser::DMLStatementLC() sl@0: { sl@0: CSqlDMLStatement* statement; sl@0: if (Parse(ESqlKeyword_insert)) sl@0: statement=InsertStatementLC(); sl@0: else if (Parse(ESqlKeyword_update)) sl@0: statement=UpdateStatementLC(); sl@0: else sl@0: { sl@0: ParseL(ESqlKeyword_delete); sl@0: statement=DeleteStatementLC(); sl@0: } sl@0: EndL(); sl@0: return statement; sl@0: } sl@0: sl@0: Sql::TStatementType TSqlParser::Type() sl@0: { sl@0: TSqlKeyword k=TSqlLexer::Keyword(iToken); sl@0: if (k==ESqlKeyword_create || k==ESqlKeyword_alter || k==ESqlKeyword_drop) sl@0: return Sql::EDDL; sl@0: if (k==ESqlKeyword_insert || k==ESqlKeyword_update || k==ESqlKeyword_delete) sl@0: return Sql::EDML; sl@0: return Sql::ENone; sl@0: } sl@0: sl@0: TInt TSqlParser::PatternFilter(const TDesC& aPattern,const TChar aEscape,TText *aNewPatternBuffer ) sl@0: { sl@0: TInt length = aPattern.Length(); sl@0: TInt count =0; sl@0: sl@0: // Ensure that the pattern begins and ends with an '*' sl@0: if ((length < 2) || (aPattern[0] != KMatchAny || aPattern[length-1] != KMatchAny)) sl@0: { sl@0: return KSqlError; sl@0: } sl@0: sl@0: for (TInt i = 1 ; i< length -1 ;++i) sl@0: { sl@0: if (aPattern[i]== (TUint)aEscape) sl@0: { sl@0: if ((aPattern[i + 1] == KMatchAny) || (aPattern[i + 1] == KMatchOne) || (aPattern[i + 1] == (TUint)aEscape)) sl@0: { sl@0: i++; sl@0: aNewPatternBuffer[count++] = aPattern[i]; sl@0: } sl@0: else sl@0: { sl@0: return KSqlError; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if ((aPattern[i] == KMatchAny || aPattern[i] == KMatchOne) ) sl@0: { sl@0: return KSqlError; sl@0: } sl@0: else sl@0: { sl@0: aNewPatternBuffer[count++] = aPattern[i]; sl@0: } sl@0: } sl@0: } sl@0: sl@0: return count; sl@0: }