diff -r 000000000000 -r 08ec8eefde2f persistentstorage/sql/SRC/Client/SqlStatementImpl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/sql/SRC/Client/SqlStatementImpl.h Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,178 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#ifndef __SQLSTATEMENTIMPL_H__ +#define __SQLSTATEMENTIMPL_H__ + +#include "SqlBufIterator.h" //TSqlBufFlat, TSqlBufRIterator, TSqlBufWIterator +#include "SqlDatabaseImpl.h"//CSqlDatabaseImpl +#include "SqlStmtSession.h" //RSqlStatementSession + +//Forward declarations +class MStreamBuf; +class CSqlStatementImpl; + +#ifdef _DEBUG +#define LONGCOL_INVARIANT() Invariant() +#else +#define LONGCOL_INVARIANT() +#endif + +/** +RSqlLongColumnColl class represents a collection of long text/binary column values. +Once a column value is added to the collection, it is guaranteed that the memory address of the +column value will never change. +The class was designed to solve one specific problem - to exclude the possibility that SQL clients +may get a dangling pointer to a block of memory which already has been deleted. +Without RSqlLongColumnColl class, it may happen for example, when client prepares a SELECT sql +statement, where the record consists of two long binary/text column values. +The client calls RSqlStatement::Next() to move to a record. Since the column values are long, they will +not be transferred on the client side by the Next() call, so the client side row buffer (CSqlStatementImpl::iColumnValueBuf) +will mark them as "not present". +Then the client calls RSqlStatement::ColumnBinary(0, TPtrC8&) to get a pointer to the first column value. +The row buffer is reallocated, and the column value is retrieved from the server and copied into the buffer, the client's pointer +is set to point to the place in the row buffer, where the column value is. +While keeping the pointer to the first column value, the client calls again RSqlStatement::ColumnBinary(1, TPtrC8&) to retrieve +the second column value. In which case, the row buffer may get reallocated again, so the first pointer will point to a +block of memory, which has been deleted. +With the implementation and use of RSqlLongColumnColl class, the long column values will be kept in a different place, +RSqlLongColumnColl's collection, where it is guaranteed that the memory address of the column value is constant. + +@internalComponent +*/ +NONSHARABLE_CLASS(RSqlLongColumnColl) + { +public: + struct TColumnReader + { + virtual TInt Read(TInt aColumnIndex, TDes8& aBuf) = 0; + }; + +public: + inline RSqlLongColumnColl(); + inline void Close(); + inline void Reset(); + TInt Append(TColumnReader& aReader, TInt aColumnIndex, TInt aColumnSize); + inline TPtrC Text(TInt aColumnIndex) const; + inline TPtrC8 Binary(TInt aColumnIndex) const; + inline TBool IsPresent(TInt aColumnIndex) const; + +private: + inline TInt FindValue(TInt aColumnIndex) const; +#ifdef _DEBUG + void Invariant() const; +#endif + +private: + struct TData + { + static TBool Compare(const TInt* aIndex, const TData& aData); + inline TData(TInt aIndex, HBufC8* aData); + TInt iIndex; + HBufC8* iData; + }; + enum {KLongColumnCollGranularity = 8}; + RArray iValues; + + }; + +template TInt SqlCreateStatement(CSqlStatementImpl*& aImpl, CSqlDatabaseImpl& aDatabase, const DES& aSqlStmt); + +/** +CSqlStatementImpl implements RSqlStatement functionality. +CSqlStatementImpl can prepare and execute parametrized SQL statements and SQL statements without parameters. +CSqlStatementImpl cannot prepare and execute SQL strings containing more than one SQL statement. +@internalComponent +*/ +NONSHARABLE_CLASS(CSqlStatementImpl) : public CBase + { + template friend TInt SqlCreateStatement(CSqlStatementImpl*& aImpl, CSqlDatabaseImpl& aDatabase, const DES& aSqlStmt); + +public: + static inline TInt New(CSqlStatementImpl*& aImpl, CSqlDatabaseImpl& aDatabase, const TDesC16& aSqlStmt); + static inline TInt New(CSqlStatementImpl*& aImpl, CSqlDatabaseImpl& aDatabase, const TDesC8& aSqlStmt); + virtual ~CSqlStatementImpl(); + + inline TBool AtRow() const; + + TInt Reset(); + TInt Exec(); + void Exec(TRequestStatus& aStatus); + TInt Next(); + + TInt BindNull(TInt aParamIndex); + TInt BindInt(TInt aParamIndex, TInt aParamValue); + TInt BindInt64(TInt aParamIndex, TInt64 aParamValue); + TInt BindReal(TInt aParamIndex, TReal aParamValue); + TInt BindText(TInt aParamIndex, const TDesC& aParamText); + TInt BindBinary(TInt aParamIndex, const TDesC8& aParamData); + TInt BindZeroBlob(TInt aParamIndex, TInt aBlobSize); + + inline TInt ColumnCount() const; + TSqlColumnType ColumnType(TInt aColumnIndex); + TInt DeclaredColumnType(TInt aColumnIndex, TSqlColumnType& aColumnType); + TInt ColumnSize(TInt aColumnIndex); + TInt ColumnInt(TInt aColumnIndex); + TInt64 ColumnInt64(TInt aColumnIndex); + TReal ColumnReal(TInt aColumnIndex); + TInt ColumnText(TInt aColumnIndex, TPtrC& aPtr); + TInt ColumnText(TInt aColumnIndex, TDes& aDest); + TInt ColumnBinary(TInt aColumnIndex, TPtrC8& aPtr); + TInt ColumnBinary(TInt aColumnIndex, TDes8& aDest); + + TInt ColumnName(TInt aColumnIndex, TPtrC& aNameDest); + TInt ParameterName(TInt aParamIndex, TPtrC& aNameDest); + + inline TInt ParamIndex(const TDesC& aParamName); + inline TInt ColumnIndex(const TDesC& aColumnName); + + inline MStreamBuf* ColumnSourceL(TInt aColumnIndex); + inline MStreamBuf* ParamSinkL(TSqlSrvFunction aFunction, TInt aParamIndex); + + HBufC* GetDeclColumnTypesL(); + +private: + inline CSqlStatementImpl(); + template TInt Construct(CSqlDatabaseImpl& aDatabase, const DES& aSqlStmt); + TInt Name2Index(const TDesC& aName, RSqlBufFlat& aNameBufFlat, TInt aCount, TSqlSrvFunction aFunction, TBool& aPresent); + TInt Index2Name(TInt aIndex, RSqlBufFlat& aNameBufFlat, TInt aCount, TSqlSrvFunction aFunction, TBool& aPresent, TPtrC& aColName); + TInt CheckNameBufPresent(TBool& aPresent, RSqlBufFlat& aNameBufFlat, TInt aCount, TSqlSrvFunction aFunction); + +private: + RSqlStatementSession iSqlStmtSession; + TBool iBound; + enum TState {EUnknown, EAtRow}; + TState iState; + + TInt iColumnCnt; + TBool iColumnNameBufPresent; + RSqlBufFlat iColumnNameBuf; + RSqlBufFlat iColumnValueBuf; + TSqlBufRIterator iColumnValBufIt; + + TInt iParamCnt; + TBool iParamNameBufPresent; + RSqlBufFlat iParamNameBuf; + RSqlBufFlat iParamValueBuf; + TSqlBufWIterator iParamValBufIt; + + RSqlLongColumnColl iLongColumnColl; + + RArray iDeclaredColumnTypes; //Array of declared column types for current statement. + }; + +#include "SqlStatementImpl.inl" + +#endif //__SQLSTATEMENTIMPL_H__