persistentstorage/sql/SRC/Server/SqlSrvBlob.cpp
changeset 0 08ec8eefde2f
child 23 26645d81f48d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sql/SRC/Server/SqlSrvBlob.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,280 @@
+// Copyright (c) 2008-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:
+//
+
+#include "sqlite3.h"
+#include "SqlPanic.h"
+#include "SqlSrvBlob.h"
+#include "SqliteSymbian.h"
+#include "SqlSrvUtil.h"
+#include "SqlSrvStrings.h"
+#include "SqlDb.h"
+
+/**
+Creates a new HBlobBuf instance.
+
+@param aDb 			 The database handle
+@param aDbName 		 The database name, zero-terminated. If the blob belongs to one of the attached databases, 
+					 then the attached database name should be used as the value of aDbName, otherwise the
+					 value should be "main"
+@param aTableName    The name of the table to which the blob belongs, zero-terminated.
+@param aColumnName   The name of the blob column, zero-terminated.
+@param aRowId        The ROWID of the row to which the blob belongs
+@param aMode		 Specifies the blob access mode, either HBlobBuf::EReadOnly or HBlobBuf::EReadWrite
+
+@leave KErrNoMemory, An out of memory condition has occurred;
+                     Note that the function may also leave with some other system wide errors or 
+                     database specific errors categorised as ESqlDbError.
+
+@return A pointer to the created HBlobBuf instance
+                     
+@panic SqlDb 4 In _DEBUG mode. NULL aDb parameter.
+@panic SqlDb 4 In _DEBUG mode. Negative or zero aRowId.
+@panic SqlDb 4 In _DEBUG mode. aMode parameter is not HBlobBuf::EReadOnly or HBlobBuf::EReadWrite.
+*/
+HBlobBuf* HBlobBuf::NewL(sqlite3* aDb, const TDesC8& aDbName, const TDesC8& aTableName, const TDesC8& aColumnName, TInt64 aRowId, TMode aMode)
+	{
+	__SQLASSERT(aDb != NULL, ESqlPanicBadArgument);
+	__SQLASSERT(aRowId > 0, ESqlPanicBadArgument);
+	__SQLASSERT(aMode == HBlobBuf::EReadOnly || aMode == HBlobBuf::EReadWrite, ESqlPanicBadArgument);
+	
+	HBlobBuf* self = new (ELeave) HBlobBuf;
+	CleanupStack::PushL(self);
+	self->ConstructL(aDb, aDbName, aTableName, aColumnName, aRowId, aMode);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+Initializes HBlobBuf data members with their default values.
+*/
+HBlobBuf::HBlobBuf() :
+	iBlobHandle(NULL),
+	iWrPos(KMinTInt),
+	iRdPos(KMinTInt)
+	{
+	}
+
+/**
+Initializes a new HBlobBuf instance.
+
+@param aDb 			 The database handle
+@param aDbName 		 The database name, zero-terminated. If the blob belongs to one of the attached databases, 
+					 then the attached database name should be used as a value of aDbName, otherwise the
+					 value should be "main"
+@param aTableName    The name of the table to which the blob belongs, zero-terminated.
+@param aColumnName   The name of the blob column, zero-terminated.
+@param aRowId        The ROWID of the row to which the blob belongs
+@param aMode		 Specifies the blob access mode, either HBlobBuf::EReadOnly or HBlobBuf::EReadWrite
+
+@leave KErrNoMemory, 	An out of memory condition has occurred;
+                     	Note that the function may also leave with some other system wide errors or 
+                    	database specific errors categorised as ESqlDbError.
+                     
+@panic SqlDb 4 In _DEBUG mode. NULL aDb parameter.
+@panic SqlDb 4 In _DEBUG mode. Negative or zero aRowId.
+@panic SqlDb 4 In _DEBUG mode. aMode parameter is not HBlobBuf::EReadOnly or HBlobBuf::EReadWrite.
+@panic SqlDb 7 In _DEBUG mode. NULL blob handle.
+*/
+void HBlobBuf::ConstructL(sqlite3* aDb, const TDesC8& aDbName, const TDesC8& aTableName, const TDesC8& aColumnName, TInt64 aRowId, TMode aMode)
+	{
+	__SQLASSERT(aDb != NULL, ESqlPanicBadArgument);
+	__SQLASSERT(aRowId > 0, ESqlPanicBadArgument);
+	__SQLASSERT(aMode == HBlobBuf::EReadOnly || aMode == HBlobBuf::EReadWrite, ESqlPanicBadArgument);
+	
+	(void)sqlite3SymbianLastOsError();//clear last OS error
+			
+	TInt err = sqlite3_blob_open(aDb, (const char*)aDbName.Ptr(), (const char*)aTableName.Ptr(), (const char*)aColumnName.Ptr(), 
+								 aRowId, aMode & HBlobBuf::EReadWrite, &iBlobHandle);
+	__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
+	__SQLASSERT(iBlobHandle != NULL, ESqlPanicInternalError);
+	iBlobSize = sqlite3_blob_bytes(iBlobHandle);
+	iWrPos = iRdPos = 0;
+	}
+
+/**
+Closes the blob handle as part of the HBlobBuf object being destroyed.
+*/
+void HBlobBuf::DoRelease()
+	{
+	TRAP_IGNORE(DoSynchL());
+	}
+	
+/**
+Closes the blob handle.
+Any buffered data is delivered to the stream.
+*/	
+void HBlobBuf::DoSynchL()
+	{
+	if(iBlobHandle)
+		{
+		TInt err = sqlite3_blob_close(iBlobHandle);
+		iBlobHandle = NULL; // the close is unconditional, even if an error occurs
+		__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
+		}	
+	}
+
+/**
+Reads a data block from the blob with the specified length.
+
+@param aPtr Pointer to the location where the blob data will be copied
+@param aMaxLength The length of the data block to be read
+
+@leave KErrNoMemory,  An out of memory condition has occurred;
+       KErrEof, 	  An attempt has been made to read beyond the end of the blob;
+       KErrBadHandle, NULL blob handle;
+                      Note that the function may also leave with some other system 
+                      wide errors or database specific errors categorised as ESqlDbError.
+
+@return The number of bytes read.
+
+@panic SqlDb 4 In _DEBUG mode. NULL aPtr parameter.
+@panic SqlDb 4 In _DEBUG mode. Negative aMaxLength parameter.
+@panic SqlDb 2 In _DEBUG mode. NULL iBlobHandle.
+*/
+TInt HBlobBuf::DoReadL(TAny* aPtr, TInt aMaxLength)
+	{
+	__SQLASSERT(aPtr != NULL, ESqlPanicBadArgument);
+	__SQLASSERT(aMaxLength >= 0, ESqlPanicBadArgument);
+	__SQLASSERT(iBlobHandle != NULL, ESqlPanicInvalidObj);
+	
+	if(aMaxLength <= 0)
+		{
+		return 0;	
+		}
+	
+	(void)sqlite3SymbianLastOsError();//clear last OS error
+	
+	if(iRdPos >= iBlobSize)
+		{
+		__SQLLEAVE(KErrEof);	
+		}
+	if((aMaxLength + iRdPos) > iBlobSize)
+		{
+		aMaxLength = iBlobSize - iRdPos;
+		}
+	TInt err = sqlite3_blob_read(BlobHandleL(), aPtr, aMaxLength, iRdPos);
+	__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
+	iRdPos += aMaxLength;
+	return aMaxLength;
+	}
+
+/**
+Writes a data block with the specified length to the blob.
+
+@param aPtr Pointer to the location with the blob data to be written
+@param aLength The length of the data block to be written
+
+@leave KErrNoMemory,  An out of memory condition has occurred;
+       KErrEof,       An attempt has been made to write beyond the end of the blob;
+       KErrBadHandle, NULL blob handle;
+                      Note that the function may also leave with some other system 
+                      wide errors or database specific errors categorised as ESqlDbError.
+
+@panic SqlDb 4 In _DEBUG mode. NULL aPtr parameter.
+@panic SqlDb 4 In _DEBUG mode. Negative aLength parameter.
+@panic SqlDb 2 In _DEBUG mode. NULL iBlobHandle.
+*/
+void HBlobBuf::DoWriteL(const TAny* aPtr, TInt aLength)
+	{
+	__SQLASSERT(aPtr != NULL, ESqlPanicBadArgument);
+	__SQLASSERT(aLength >= 0, ESqlPanicBadArgument);
+	__SQLASSERT(iBlobHandle != NULL, ESqlPanicInvalidObj);
+	
+	if(aLength <= 0)
+		{
+		return;
+		}
+		
+	if((iWrPos + aLength) > iBlobSize)
+		{
+		__SQLLEAVE(KErrEof);
+		}
+
+	(void)sqlite3SymbianLastOsError();//clear last OS error
+	TInt err = sqlite3_blob_write(BlobHandleL(), aPtr, aLength, iWrPos);
+	err = ::Sql2OsErrCode(err, sqlite3SymbianLastOsError());
+	
+	__SQLLEAVE_IF_ERROR(err);
+	iWrPos += aLength;
+	}
+
+/**
+Positions the mark(s) indicated by aMark at aOffset from aLocation.
+
+@leave KErrEof,       An attempt has been made to seek beyond the end of the blob;
+	   KErrBadHandle, NULL blob handle;
+                      Note that the function may also leave with some other system wide errors or 
+                      database specific errors categorised as ESqlDbError.
+
+@return The new stream position (read or write)
+
+@panic SqlDb 2 In _DEBUG mode. NULL iBlobHandle.
+@panic SqlDb 4 In _DEBUG mode. Negative aOffset parameter.
+@panic SqlDb 8 In _DEBUG mode. Invalid aMark parameter.
+@panic SqlDb 9 In _DEBUG mode. Invalid aLocation parameter.
+*/
+TStreamPos HBlobBuf::DoSeekL(MStreamBuf::TMark aMark, TStreamLocation aLocation, TInt aOffset)
+	{
+	__SQLASSERT_ALWAYS(!(aMark & ~(ERead | EWrite)), ESqlPanicStreamMarkInvalid);
+	__SQLASSERT(aOffset >= 0, ESqlPanicBadArgument);
+	__SQLASSERT(iBlobHandle != NULL, ESqlPanicInvalidObj);
+	
+	TInt newPos = 0;
+	switch(aLocation)
+		{
+	case EStreamBeginning:
+		newPos = aOffset;
+		break;
+	case EStreamMark:
+		newPos = (aMark & MStreamBuf::EWrite ? iWrPos : iRdPos) + aOffset;
+		break;
+	case EStreamEnd:
+		newPos = iBlobSize + aOffset;
+		break;
+	default:
+		__SQLASSERT(0, ESqlPanicStreamLocationInvalid);
+		newPos = -1;
+		break;
+		}
+	if(newPos < 0 || newPos > iBlobSize)
+		{
+		__SQLLEAVE(KErrEof);
+		}
+	if(aMark & MStreamBuf::EWrite)
+		{
+		iWrPos = newPos;
+		}
+	else if(aMark & MStreamBuf::ERead)
+		{
+		iRdPos = newPos;	
+		}
+	return TStreamPos(newPos);
+	}
+
+/**
+Returns the blob handle, if it is not NULL.
+
+@leave KErrBadHandle, The blob handle is NULL.
+
+@return The blob handle
+*/
+sqlite3_blob* HBlobBuf::BlobHandleL()
+	{
+	if(!iBlobHandle)
+		{
+		__SQLLEAVE(KErrBadHandle);
+		}
+	return iBlobHandle;
+	}