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