persistentstorage/sql/SRC/Server/SqlSrvBlob.cpp
changeset 0 08ec8eefde2f
child 23 26645d81f48d
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2008-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 //
       
    15 
       
    16 #include "sqlite3.h"
       
    17 #include "SqlPanic.h"
       
    18 #include "SqlSrvBlob.h"
       
    19 #include "SqliteSymbian.h"
       
    20 #include "SqlSrvUtil.h"
       
    21 #include "SqlSrvStrings.h"
       
    22 #include "SqlDb.h"
       
    23 
       
    24 /**
       
    25 Creates a new HBlobBuf instance.
       
    26 
       
    27 @param aDb 			 The database handle
       
    28 @param aDbName 		 The database name, zero-terminated. If the blob belongs to one of the attached databases, 
       
    29 					 then the attached database name should be used as the value of aDbName, otherwise the
       
    30 					 value should be "main"
       
    31 @param aTableName    The name of the table to which the blob belongs, zero-terminated.
       
    32 @param aColumnName   The name of the blob column, zero-terminated.
       
    33 @param aRowId        The ROWID of the row to which the blob belongs
       
    34 @param aMode		 Specifies the blob access mode, either HBlobBuf::EReadOnly or HBlobBuf::EReadWrite
       
    35 
       
    36 @leave KErrNoMemory, An out of memory condition has occurred;
       
    37                      Note that the function may also leave with some other system wide errors or 
       
    38                      database specific errors categorised as ESqlDbError.
       
    39 
       
    40 @return A pointer to the created HBlobBuf instance
       
    41                      
       
    42 @panic SqlDb 4 In _DEBUG mode. NULL aDb parameter.
       
    43 @panic SqlDb 4 In _DEBUG mode. Negative or zero aRowId.
       
    44 @panic SqlDb 4 In _DEBUG mode. aMode parameter is not HBlobBuf::EReadOnly or HBlobBuf::EReadWrite.
       
    45 */
       
    46 HBlobBuf* HBlobBuf::NewL(sqlite3* aDb, const TDesC8& aDbName, const TDesC8& aTableName, const TDesC8& aColumnName, TInt64 aRowId, TMode aMode)
       
    47 	{
       
    48 	__SQLASSERT(aDb != NULL, ESqlPanicBadArgument);
       
    49 	__SQLASSERT(aRowId > 0, ESqlPanicBadArgument);
       
    50 	__SQLASSERT(aMode == HBlobBuf::EReadOnly || aMode == HBlobBuf::EReadWrite, ESqlPanicBadArgument);
       
    51 	
       
    52 	HBlobBuf* self = new (ELeave) HBlobBuf;
       
    53 	CleanupStack::PushL(self);
       
    54 	self->ConstructL(aDb, aDbName, aTableName, aColumnName, aRowId, aMode);
       
    55 	CleanupStack::Pop(self);
       
    56 	return self;
       
    57 	}
       
    58 
       
    59 /**
       
    60 Initializes HBlobBuf data members with their default values.
       
    61 */
       
    62 HBlobBuf::HBlobBuf() :
       
    63 	iBlobHandle(NULL),
       
    64 	iWrPos(KMinTInt),
       
    65 	iRdPos(KMinTInt)
       
    66 	{
       
    67 	}
       
    68 
       
    69 /**
       
    70 Initializes a new HBlobBuf instance.
       
    71 
       
    72 @param aDb 			 The database handle
       
    73 @param aDbName 		 The database name, zero-terminated. If the blob belongs to one of the attached databases, 
       
    74 					 then the attached database name should be used as a value of aDbName, otherwise the
       
    75 					 value should be "main"
       
    76 @param aTableName    The name of the table to which the blob belongs, zero-terminated.
       
    77 @param aColumnName   The name of the blob column, zero-terminated.
       
    78 @param aRowId        The ROWID of the row to which the blob belongs
       
    79 @param aMode		 Specifies the blob access mode, either HBlobBuf::EReadOnly or HBlobBuf::EReadWrite
       
    80 
       
    81 @leave KErrNoMemory, 	An out of memory condition has occurred;
       
    82                      	Note that the function may also leave with some other system wide errors or 
       
    83                     	database specific errors categorised as ESqlDbError.
       
    84                      
       
    85 @panic SqlDb 4 In _DEBUG mode. NULL aDb parameter.
       
    86 @panic SqlDb 4 In _DEBUG mode. Negative or zero aRowId.
       
    87 @panic SqlDb 4 In _DEBUG mode. aMode parameter is not HBlobBuf::EReadOnly or HBlobBuf::EReadWrite.
       
    88 @panic SqlDb 7 In _DEBUG mode. NULL blob handle.
       
    89 */
       
    90 void HBlobBuf::ConstructL(sqlite3* aDb, const TDesC8& aDbName, const TDesC8& aTableName, const TDesC8& aColumnName, TInt64 aRowId, TMode aMode)
       
    91 	{
       
    92 	__SQLASSERT(aDb != NULL, ESqlPanicBadArgument);
       
    93 	__SQLASSERT(aRowId > 0, ESqlPanicBadArgument);
       
    94 	__SQLASSERT(aMode == HBlobBuf::EReadOnly || aMode == HBlobBuf::EReadWrite, ESqlPanicBadArgument);
       
    95 	
       
    96 	(void)sqlite3SymbianLastOsError();//clear last OS error
       
    97 			
       
    98 	TInt err = sqlite3_blob_open(aDb, (const char*)aDbName.Ptr(), (const char*)aTableName.Ptr(), (const char*)aColumnName.Ptr(), 
       
    99 								 aRowId, aMode & HBlobBuf::EReadWrite, &iBlobHandle);
       
   100 	__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
       
   101 	__SQLASSERT(iBlobHandle != NULL, ESqlPanicInternalError);
       
   102 	iBlobSize = sqlite3_blob_bytes(iBlobHandle);
       
   103 	iWrPos = iRdPos = 0;
       
   104 	}
       
   105 
       
   106 /**
       
   107 Closes the blob handle as part of the HBlobBuf object being destroyed.
       
   108 */
       
   109 void HBlobBuf::DoRelease()
       
   110 	{
       
   111 	TRAP_IGNORE(DoSynchL());
       
   112 	}
       
   113 	
       
   114 /**
       
   115 Closes the blob handle.
       
   116 Any buffered data is delivered to the stream.
       
   117 */	
       
   118 void HBlobBuf::DoSynchL()
       
   119 	{
       
   120 	if(iBlobHandle)
       
   121 		{
       
   122 		TInt err = sqlite3_blob_close(iBlobHandle);
       
   123 		iBlobHandle = NULL; // the close is unconditional, even if an error occurs
       
   124 		__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
       
   125 		}	
       
   126 	}
       
   127 
       
   128 /**
       
   129 Reads a data block from the blob with the specified length.
       
   130 
       
   131 @param aPtr Pointer to the location where the blob data will be copied
       
   132 @param aMaxLength The length of the data block to be read
       
   133 
       
   134 @leave KErrNoMemory,  An out of memory condition has occurred;
       
   135        KErrEof, 	  An attempt has been made to read beyond the end of the blob;
       
   136        KErrBadHandle, NULL blob handle;
       
   137                       Note that the function may also leave with some other system 
       
   138                       wide errors or database specific errors categorised as ESqlDbError.
       
   139 
       
   140 @return The number of bytes read.
       
   141 
       
   142 @panic SqlDb 4 In _DEBUG mode. NULL aPtr parameter.
       
   143 @panic SqlDb 4 In _DEBUG mode. Negative aMaxLength parameter.
       
   144 @panic SqlDb 2 In _DEBUG mode. NULL iBlobHandle.
       
   145 */
       
   146 TInt HBlobBuf::DoReadL(TAny* aPtr, TInt aMaxLength)
       
   147 	{
       
   148 	__SQLASSERT(aPtr != NULL, ESqlPanicBadArgument);
       
   149 	__SQLASSERT(aMaxLength >= 0, ESqlPanicBadArgument);
       
   150 	__SQLASSERT(iBlobHandle != NULL, ESqlPanicInvalidObj);
       
   151 	
       
   152 	if(aMaxLength <= 0)
       
   153 		{
       
   154 		return 0;	
       
   155 		}
       
   156 	
       
   157 	(void)sqlite3SymbianLastOsError();//clear last OS error
       
   158 	
       
   159 	if(iRdPos >= iBlobSize)
       
   160 		{
       
   161 		__SQLLEAVE(KErrEof);	
       
   162 		}
       
   163 	if((aMaxLength + iRdPos) > iBlobSize)
       
   164 		{
       
   165 		aMaxLength = iBlobSize - iRdPos;
       
   166 		}
       
   167 	TInt err = sqlite3_blob_read(BlobHandleL(), aPtr, aMaxLength, iRdPos);
       
   168 	__SQLLEAVE_IF_ERROR(::Sql2OsErrCode(err, sqlite3SymbianLastOsError()));
       
   169 	iRdPos += aMaxLength;
       
   170 	return aMaxLength;
       
   171 	}
       
   172 
       
   173 /**
       
   174 Writes a data block with the specified length to the blob.
       
   175 
       
   176 @param aPtr Pointer to the location with the blob data to be written
       
   177 @param aLength The length of the data block to be written
       
   178 
       
   179 @leave KErrNoMemory,  An out of memory condition has occurred;
       
   180        KErrEof,       An attempt has been made to write beyond the end of the blob;
       
   181        KErrBadHandle, NULL blob handle;
       
   182                       Note that the function may also leave with some other system 
       
   183                       wide errors or database specific errors categorised as ESqlDbError.
       
   184 
       
   185 @panic SqlDb 4 In _DEBUG mode. NULL aPtr parameter.
       
   186 @panic SqlDb 4 In _DEBUG mode. Negative aLength parameter.
       
   187 @panic SqlDb 2 In _DEBUG mode. NULL iBlobHandle.
       
   188 */
       
   189 void HBlobBuf::DoWriteL(const TAny* aPtr, TInt aLength)
       
   190 	{
       
   191 	__SQLASSERT(aPtr != NULL, ESqlPanicBadArgument);
       
   192 	__SQLASSERT(aLength >= 0, ESqlPanicBadArgument);
       
   193 	__SQLASSERT(iBlobHandle != NULL, ESqlPanicInvalidObj);
       
   194 	
       
   195 	if(aLength <= 0)
       
   196 		{
       
   197 		return;
       
   198 		}
       
   199 		
       
   200 	if((iWrPos + aLength) > iBlobSize)
       
   201 		{
       
   202 		__SQLLEAVE(KErrEof);
       
   203 		}
       
   204 
       
   205 	(void)sqlite3SymbianLastOsError();//clear last OS error
       
   206 	TInt err = sqlite3_blob_write(BlobHandleL(), aPtr, aLength, iWrPos);
       
   207 	err = ::Sql2OsErrCode(err, sqlite3SymbianLastOsError());
       
   208 	
       
   209 	__SQLLEAVE_IF_ERROR(err);
       
   210 	iWrPos += aLength;
       
   211 	}
       
   212 
       
   213 /**
       
   214 Positions the mark(s) indicated by aMark at aOffset from aLocation.
       
   215 
       
   216 @leave KErrEof,       An attempt has been made to seek beyond the end of the blob;
       
   217 	   KErrBadHandle, NULL blob handle;
       
   218                       Note that the function may also leave with some other system wide errors or 
       
   219                       database specific errors categorised as ESqlDbError.
       
   220 
       
   221 @return The new stream position (read or write)
       
   222 
       
   223 @panic SqlDb 2 In _DEBUG mode. NULL iBlobHandle.
       
   224 @panic SqlDb 4 In _DEBUG mode. Negative aOffset parameter.
       
   225 @panic SqlDb 8 In _DEBUG mode. Invalid aMark parameter.
       
   226 @panic SqlDb 9 In _DEBUG mode. Invalid aLocation parameter.
       
   227 */
       
   228 TStreamPos HBlobBuf::DoSeekL(MStreamBuf::TMark aMark, TStreamLocation aLocation, TInt aOffset)
       
   229 	{
       
   230 	__SQLASSERT_ALWAYS(!(aMark & ~(ERead | EWrite)), ESqlPanicStreamMarkInvalid);
       
   231 	__SQLASSERT(aOffset >= 0, ESqlPanicBadArgument);
       
   232 	__SQLASSERT(iBlobHandle != NULL, ESqlPanicInvalidObj);
       
   233 	
       
   234 	TInt newPos = 0;
       
   235 	switch(aLocation)
       
   236 		{
       
   237 	case EStreamBeginning:
       
   238 		newPos = aOffset;
       
   239 		break;
       
   240 	case EStreamMark:
       
   241 		newPos = (aMark & MStreamBuf::EWrite ? iWrPos : iRdPos) + aOffset;
       
   242 		break;
       
   243 	case EStreamEnd:
       
   244 		newPos = iBlobSize + aOffset;
       
   245 		break;
       
   246 	default:
       
   247 		__SQLASSERT(0, ESqlPanicStreamLocationInvalid);
       
   248 		newPos = -1;
       
   249 		break;
       
   250 		}
       
   251 	if(newPos < 0 || newPos > iBlobSize)
       
   252 		{
       
   253 		__SQLLEAVE(KErrEof);
       
   254 		}
       
   255 	if(aMark & MStreamBuf::EWrite)
       
   256 		{
       
   257 		iWrPos = newPos;
       
   258 		}
       
   259 	else if(aMark & MStreamBuf::ERead)
       
   260 		{
       
   261 		iRdPos = newPos;	
       
   262 		}
       
   263 	return TStreamPos(newPos);
       
   264 	}
       
   265 
       
   266 /**
       
   267 Returns the blob handle, if it is not NULL.
       
   268 
       
   269 @leave KErrBadHandle, The blob handle is NULL.
       
   270 
       
   271 @return The blob handle
       
   272 */
       
   273 sqlite3_blob* HBlobBuf::BlobHandleL()
       
   274 	{
       
   275 	if(!iBlobHandle)
       
   276 		{
       
   277 		__SQLLEAVE(KErrBadHandle);
       
   278 		}
       
   279 	return iBlobHandle;
       
   280 	}