Added support for insert row functionality. Also added SQLStatement object.

git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@503 0109f412-320b-0410-ab79-c3e0c5ffbbe6
This commit is contained in:
dsandersoremutah
2006-06-02 22:19:25 +00:00
parent 1f10166289
commit 699a677516
5 changed files with 710 additions and 111 deletions

View File

@@ -311,6 +311,23 @@ public:
return( NULL);
}
FINLINE F_COLUMN * findColumn(
F_TABLE * pTable,
const char * pszColumnName)
{
NAME_INFO * pNameInfo;
if (pTable->pColumnNames)
{
if ((pNameInfo = pTable->pColumnNames->findName( pszColumnName,
NULL)) != NULL)
{
return( getColumn( pTable, pNameInfo->uiItemNum));
}
}
return( NULL);
}
FINLINE F_INDEX * findIndex(
const char * pszIndexName)
{

View File

@@ -74,6 +74,47 @@ typedef struct SFLM_CREATE_OPTS
} SFLM_CREATE_OPTS;
/// Errors that can occur when parsing an SQL statement.
typedef enum
{
SQL_NO_ERROR = 0,
SQL_ERR_EXPECTING_WHITESPACE, ///< 1 = Whitespace required.
SQL_ERR_EXPECTING_INTO, ///< 2 = Expecting "INTO" keyword.
SQL_ERR_ILLEGAL_TABLE_NAME_CHAR, ///< 3 = Illegal character in table name.
SQL_ERR_TABLE_NAME_TOO_LONG, ///< 4 = Table name is too long.
SQL_ERR_UNDEFINED_TABLE, ///< 5 = Table name that was specified is not defined.
SQL_ERR_TABLE_ALREADY_DEFINED, ///< 6 = Table name is already defined in the database.
SQL_ERR_EXPECTING_COMMA, ///< 7 = Expecting comma.
SQL_ERR_UNDEFINED_COLUMN, ///< 8 = Column name not defined for table.
SQL_ERR_EXPECTING_LPAREN, ///< 9 = Expecting left parenthesis.
SQL_ERR_EXPECTING_RPAREN, ///< 10 = Expecting right parenthesis.
SQL_ERR_EXPECTING_QUOTE_CHAR, ///< 11 = Expecting a quote character - strings must be quoted.
SQL_ERR_MISSING_QUOTE, ///< 12 = Terminating quote missing on a string.
SQL_ERR_INVALID_ESCAPED_CHARACTER, ///< 13 = Can only escape quote characters or backslashes in strings.
SQL_ERR_CANNOT_UPDATE_SYSTEM_TABLE, ///< 14 = Inserting, modifying, or deleting rows in a system table is not allowed.
SQL_ERR_NUMBER_VALUE_EMPTY, ///< 15 = Number value is empty.
SQL_ERR_NON_HEX_CHARACTER, ///< 16 = Invalid hex character in binary value.
SQL_ERR_NON_NUMERIC_CHARACTER, ///< 17 = Non-numeric character in number value.
SQL_ERR_ILLEGAL_HEX_DIGIT, ///< 18 = Illegal hex digit in number value.
SQL_ERR_NUMBER_OVERFLOW, ///< 19 = Number exceeds limits for 64 bit numbers.
SQL_ERR_BINARY_VALUE_EMPTY, ///< 20 = Binary value is empty.
// IMPORTANT NOTE: If new codes are added, please update gv_SQLParseErrors in fshell.cpp
SQL_NUM_ERRORS
} SQLParseError;
/// Statistics gathered while parsing and executing an SQL statement.
typedef struct
{
FLMUINT uiLines; ///< Total lines read.
FLMUINT uiChars; ///< Total characters read.
FLMUINT uiErrLineNum; ///< Line number where error occurred.
FLMUINT uiErrLineOffset; ///< Offset in line where error occurred.| NOTE: This is a zero-based offset.
SQLParseError eErrorType; ///< Parsing error that occurred.
FLMUINT uiErrLineFilePos; ///< Absolute offset in the file (or buffer) where the line containing the error occurred.
FLMUINT uiErrLineBytes; ///< Number of bytes in the line that contains the error.
} SQL_STATS;
/// Database header.
typedef struct SFLM_DB_HDR
{
@@ -1152,7 +1193,8 @@ typedef struct
#define NE_SFLM_RESET_NEEDED 0xE058 ///< 0xE058 = Used during check operations to indicate we need to reset the view.\ NOTE: This is an internal error code.
#define NE_SFLM_ILLEGAL_LANGUAGE 0xE059 ///< 0xE059 = Invalid language specified in an index definition.
#define NE_SFLM_ROW_DELETED 0xE05A ///< 0xE05A = Row being accessed has been deleted.
#define NE_SFLM_ROW_NOT_FOUND 0xE05B ///< 0xE05B - Row being retrieved does not exist.
#define NE_SFLM_ROW_NOT_FOUND 0xE05B ///< 0xE05B = Row being retrieved does not exist.
#define NE_SFLM_INVALID_SQL 0xE05C ///< 0xE05C = SQL statement is invalid.
// Dictionary definition errors.
@@ -1293,6 +1335,19 @@ flminterface IF_BackupStatus : public F_Object
FLMUINT64 ui64BytesDone) = 0;
};
/// Structure for sending data in for table columns.
typedef struct F_COLUMN_VALUE
{
FLMUINT uiColumnNum; ///< Column data is for.
eDataType eColumnDataType; ///< Column's data type.
FLMBYTE* pucColumnValue; ///< Column's value.\ For string data it is a SEN followed by a UTF8 string.\ The SEN
///< gives the number of characters (as opposed to bytes) in the string.\ For number
///< data there are two pieces.\ The first byte is a 1 or 0, indicating if the
///< number is negative (1=negative, 0=positive).\ Following that byte is a
///< SEN that contains the absolute value of the number.\ Binary data may be anything.
FLMUINT uiValueLen; ///< Length of column's value.
} F_COLUMN_VALUE;
/****************************************************************************
Desc:
****************************************************************************/
@@ -1374,6 +1429,12 @@ flminterface IF_RestoreStatus : public F_Object
FLMUINT64 ui64TransId,
FLMUINT uiTableNum,
FLMUINT64 ui64NextRowId) = 0;
virtual RCODE reportInsertRow(
eRestoreAction * peAction,
FLMUINT uiTableNum,
F_COLUMN_VALUE * pColumnValues,
FLMUINT uiNumColumnValues) = 0;
};
/****************************************************************************

View File

@@ -485,6 +485,7 @@ FINLINE RCODE FlmStorage2UTF8(
#include "filesys.h"
#include "flog.h"
#include "f_nici.h"
#include "sqlstatement.h"
/****************************************************************************
Desc:
@@ -1905,6 +1906,11 @@ public:
FLMUINT uiTableNum,
FLMUINT64 ui64TransId);
RCODE insertRow(
FLMUINT uiTableNum,
F_COLUMN_VALUE * pColumnValues,
FLMUINT uiNumColumnValues);
private:
// This routine assumes that the database mutex is locked
@@ -2422,6 +2428,7 @@ friend class F_GlobalCacheMgr;
friend class F_QueryResultSet;
friend class F_BTreeInfo;
friend class SQLQuery;
friend class SQLStatement;
};
typedef struct BTREE_INFO

View File

@@ -46,55 +46,6 @@ FINLINE FLMBOOL F_Rfl::useDataOnlyBlocks(
}
}
/********************************************************************
Desc:
*********************************************************************/
class F_RflOStream : public IF_OStream
{
public:
F_RflOStream(
F_Rfl * pRfl,
F_Db * pDb)
{
m_pRfl = pRfl;
m_pRfl->AddRef();
m_pDb = pDb;
}
virtual ~F_RflOStream()
{
if( m_pRfl)
{
m_pRfl->Release();
}
}
RCODE write(
const void * pvBuffer,
FLMUINT uiBytesToWrite,
FLMUINT * puiBytesWritten = NULL);
RCODE write(
IF_PosIStream * pIStream);
FINLINE RCODE close( void)
{
if( m_pRfl)
{
m_pRfl->Release();
m_pRfl = NULL;
}
return( NE_SFLM_OK);
}
private:
F_Rfl * m_pRfl;
F_Db * m_pDb;
};
/********************************************************************
Desc:
*********************************************************************/
@@ -135,6 +86,7 @@ F_Rfl::F_Rfl()
m_pIxCompareObject = NULL;
m_pCompareObject = NULL;
m_uiDisableCount = 0;
m_tmpPool.poolInit( 2048);
}
/********************************************************************
@@ -186,6 +138,7 @@ F_Rfl::~F_Rfl()
{
m_pIxCompareObject->Release();
}
m_tmpPool.poolFree();
}
/********************************************************************
@@ -3943,54 +3896,222 @@ Exit:
/********************************************************************
Desc:
*********************************************************************/
RCODE F_RflOStream::write(
const void * pvBuffer,
FLMUINT uiBytesToWrite,
FLMUINT * puiBytesWritten)
RCODE F_Rfl::logColumnValues(
F_Db * pDb,
FLMUINT uiTableNum,
F_COLUMN_VALUE * pColumnValues,
FLMUINT uiNumColumnValues)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiPacketLen = RFL_PACKET_OVERHEAD;
FLMUINT uiBytesLeftToWrite;
FLMUINT uiBytesToWrite;
FLMBYTE * pucValue;
FLMBYTE * pucOut;
FLMBYTE * pucIV;
FLMBYTE * pucStart;
F_TABLE * pTable = pDb->m_pDict->getTable( uiTableNum);
F_COLUMN * pColumn;
F_ENCDEF * pTableEncDef = (pTable->lfInfo.uiEncDefNum)
? pDb->m_pDict->getEncDef( pTable->lfInfo.uiEncDefNum)
: (F_ENCDEF *)NULL;
F_ENCDEF * pEncDef;
FLMUINT uiIVLen;
FLMUINT uiEncLen;
FLMUINT uiSenLen1;
FLMUINT uiSenLen2;
FLMUINT uiSpaceNeeded;
FLMUINT uiEncOutputLen;
FLMUINT uiBytesAvail;
FLMBYTE * pucBuffer = (FLMBYTE *)pvBuffer;
flmAssert( m_pRfl->isLoggingEnabled());
flmAssert( isLoggingEnabled());
if( !m_pRfl->haveBuffSpace( RFL_PACKET_OVERHEAD))
if( !haveBuffSpace( RFL_PACKET_OVERHEAD))
{
if( RC_BAD( rc = m_pRfl->flush( m_pDb, m_pRfl->m_pCurrentBuf)))
if( RC_BAD( rc = flush( pDb, m_pCurrentBuf)))
{
goto Exit;
}
}
while( uiBytesToWrite)
// Go through each column's data
while (uiNumColumnValues)
{
if( RC_BAD( rc = m_pRfl->makeRoom( m_pDb, uiBytesToWrite,
&uiPacketLen, RFL_DATA_PACKET, &uiBytesAvail, NULL)))
{
goto Exit;
}
f_memcpy( m_pRfl->getPacketPtr() + uiPacketLen, pucBuffer, uiBytesAvail);
pucBuffer += uiBytesAvail;
uiBytesToWrite -= uiBytesAvail;
uiPacketLen += uiBytesAvail;
if( RC_BAD( rc = m_pRfl->finishPacket( m_pDb, RFL_DATA_PACKET,
uiPacketLen - RFL_PACKET_OVERHEAD, FALSE)))
pColumn = pDb->m_pDict->getColumn( pTable, pColumnValues->uiColumnNum);
if( RC_BAD( rc = makeRoom( pDb, FLM_MAX_SEN_LEN * 2 + 1,
&uiPacketLen, RFL_COLUMN_DATA_PACKET, NULL, NULL)))
{
goto Exit;
}
uiPacketLen = RFL_PACKET_OVERHEAD;
}
pucOut = pucStart = getPacketPtr() + uiPacketLen;
if( puiBytesWritten)
{
*puiBytesWritten = (FLMUINT)(pucBuffer - ((FLMBYTE *)pvBuffer));
// Output the column number.
f_encodeSEN( pColumnValues->uiColumnNum, &pucOut);
// Output the data type.
*pucOut++ = (FLMBYTE)pColumnValues->eColumnDataType;
// Output the value length
f_encodeSEN( pColumnValues->uiValueLen, &pucOut);
uiPacketLen += (FLMUINT)(pucOut - pucStart);
uiBytesLeftToWrite = pColumnValues->uiValueLen;
pucValue = pColumnValues->pucColumnValue;
while (uiBytesLeftToWrite)
{
// If the column or table are encrypted, we need to make enough room
// to encrypt the data.
pEncDef = (pColumn->uiEncDefNum)
? pDb->m_pDict->getEncDef( pColumn->uiEncDefNum)
: pTableEncDef;
if (!pEncDef)
{
if (RC_BAD( rc = makeRoom( pDb, uiBytesLeftToWrite,
&uiPacketLen, RFL_COLUMN_DATA_PACKET, &uiBytesToWrite, NULL)))
{
goto Exit;
}
f_memcpy( getPacketPtr() + uiPacketLen, pucValue, uiBytesToWrite);
pucValue += uiBytesToWrite;
uiBytesLeftToWrite -= uiBytesToWrite;
uiPacketLen += uiBytesToWrite;
}
else
{
uiIVLen = pEncDef->pCcs->getIVLen();
flmAssert( uiIVLen == 8 || uiIVLen == 16);
uiBytesToWrite = uiBytesLeftToWrite;
uiEncLen = getEncLen( uiBytesToWrite);
uiSenLen1 = f_getSENByteCount( uiEncLen);
uiSenLen2 = f_getSENByteCount( uiBytesToWrite);
uiSpaceNeeded = uiSenLen1 + uiSenLen2 + uiIVLen + uiEncLen;
if (RC_BAD( rc = makeRoom( pDb, uiSpaceNeeded,
&uiPacketLen, RFL_COLUMN_DATA_PACKET, &uiBytesAvail, NULL)))
{
goto Exit;
}
// If we can't hold the entire encrypted chunk, we must
// recalculate down.
if (uiBytesAvail < uiSpaceNeeded)
{
// If we cannot hold the encrypted length (as a SEN), the
// IV, and a minimal encrypted chunk, we need to flush
// out the current packet.
if (uiBytesAvail < uiSenLen1 + uiSenLen2 + uiIVLen + ENCRYPT_MIN_CHUNK_SIZE)
{
goto Finish_Packet;
}
// Round down to fit whatever data will end right on an
// encryption boundary.
uiBytesToWrite = uiBytesAvail - uiSenLen1 - uiSenLen2 - uiIVLen;
uiBytesToWrite -= extraEncBytes( uiBytesToWrite);
uiEncLen = getEncLen( uiBytesToWrite);
flmAssert( uiEncLen == uiBytesToWrite);
uiSenLen1 = f_getSENByteCount( uiEncLen);
uiSenLen2 = f_getSENByteCount( uiBytesToWrite);
uiSpaceNeeded = uiSenLen1 + uiSenLen2 + uiIVLen + uiEncLen;
if (RC_BAD( rc = makeRoom( pDb, uiSpaceNeeded,
&uiPacketLen, RFL_COLUMN_DATA_PACKET, &uiBytesAvail, NULL)))
{
goto Exit;
}
// We should be guaranteed enough room to write everything we
// asked for at this point.
flmAssert( uiBytesAvail >= uiSpaceNeeded);
}
// First output the encrypted length, then the IV, and finally
// the data. Then encrypt the data in place.
pucOut = getPacketPtr() + uiPacketLen;
// Output the encrypted length
f_encodeSEN( uiEncLen, &pucOut);
// Output the actual data length
f_encodeSEN( uiBytesToWrite, &pucOut);
// Output the IV
pucIV = pucOut;
if( RC_BAD( rc = pEncDef->pCcs->generateIV( uiIVLen, pucIV)))
{
goto Exit;
}
pucOut += uiIVLen;
// Output the unencrypted data and encrypt it in place.
f_memcpy( pucOut, pucValue, uiBytesToWrite);
if (RC_BAD( rc = pDb->encryptData( pEncDef->uiEncDefNum, pucIV,
pucOut, uiEncLen, uiBytesToWrite, &uiEncOutputLen)))
{
goto Exit;
}
flmAssert( uiEncOutputLen == uiEncLen);
pucValue += uiBytesToWrite;
uiBytesLeftToWrite -= uiBytesToWrite;
uiPacketLen += (uiSenLen1 + uiSenLen2 + uiIVLen + uiEncLen);
}
Finish_Packet:
if( RC_BAD( rc = finishPacket( pDb, RFL_COLUMN_DATA_PACKET,
uiPacketLen - RFL_PACKET_OVERHEAD, FALSE)))
{
goto Exit;
}
uiPacketLen = RFL_PACKET_OVERHEAD;
}
pColumnValues++;
uiNumColumnValues--;
}
// Add a column number of zero to terminate the columns.
if (RC_BAD( rc = makeRoom( pDb, 1, &uiPacketLen,
RFL_COLUMN_DATA_PACKET, NULL, NULL)))
{
goto Exit;
}
pucOut = getPacketPtr() + uiPacketLen;
*pucOut++ = 0;
uiPacketLen++;
// Finish the packet.
if (RC_BAD( rc = finishPacket( pDb, RFL_COLUMN_DATA_PACKET,
uiPacketLen - RFL_PACKET_OVERHEAD, FALSE)))
{
goto Exit;
}
Exit:
return( rc);
@@ -3999,52 +4120,407 @@ Exit:
/********************************************************************
Desc:
*********************************************************************/
RCODE F_RflOStream::write(
IF_PosIStream * pIStream)
RCODE F_Rfl::logInsertRow(
F_Db * pDb,
FLMUINT uiTableNum,
F_COLUMN_VALUE * pColumnValues,
FLMUINT uiNumColumnValues)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiPacketLen = RFL_PACKET_OVERHEAD;
FLMUINT uiBytesToWrite = (FLMUINT)pIStream->remainingSize();
FLMUINT uiBytesAvail;
RCODE rc = NE_SFLM_OK;
FLMUINT uiPacketBodyLen;
FLMBYTE * pucPacketBody;
FLMBYTE * pucPacketStart;
flmAssert( pDb->m_uiFlags & FDB_HAS_FILE_LOCK);
// Do nothing if logging is disabled.
flmAssert( m_pRfl->isLoggingEnabled());
if( !m_pRfl->haveBuffSpace( RFL_PACKET_OVERHEAD))
if( !isLoggingEnabled())
{
if( RC_BAD( rc = m_pRfl->flush( m_pDb, m_pRfl->m_pCurrentBuf)))
goto Exit;
}
// Better be in the middle of a transaction.
flmAssert( m_ui64CurrTransID);
// Increment the operation count
m_uiOperCount++;
// Make sure we have space in the RFL buffer for a complete packet. NOTE:
// this is calculating the maximum packet body length that would be needed.
if( !haveBuffSpace( FLM_MAX_SEN_LEN * 2 + RFL_PACKET_OVERHEAD))
{
if( RC_BAD( rc = flush( pDb, m_pCurrentBuf)))
{
goto Exit;
}
}
// Get a pointer to where we will be laying down the packet body.
pucPacketBody = pucPacketStart = getPacketBodyPtr();
// Output the table number
f_encodeSEN( uiTableNum, &pucPacketBody);
// Output the number of column values
f_encodeSEN( uiNumColumnValues, &pucPacketBody);
// Finish the packet - calculate the actual packet body length.
uiPacketBodyLen = (FLMUINT)(pucPacketBody - pucPacketStart);
flmAssert( uiPacketBodyLen <= FLM_MAX_SEN_LEN * 2);
if (RC_BAD( rc = finishPacket( pDb, RFL_INSERT_ROW_PACKET,
uiPacketBodyLen, FALSE)))
{
goto Exit;
}
// Now output the column data
if (RC_BAD( rc = logColumnValues( pDb, uiTableNum,
pColumnValues, uiNumColumnValues)))
{
goto Exit;
}
Exit:
return( rc);
}
/********************************************************************
Desc:
*********************************************************************/
RCODE F_Rfl::recovInsertRow(
F_Db * pDb,
const FLMBYTE * pucPacketBody,
FLMUINT uiPacketBodyLen,
eRestoreAction * peAction)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiTableNum;
FLMUINT uiNumColumnValues;
FLMUINT uiPacketType;
F_COLUMN_VALUE * pColValues;
F_COLUMN_VALUE * pColumnValue;
const FLMBYTE * pucEnd = pucPacketBody + uiPacketBodyLen;
FLMUINT uiIVLen;
FLMBOOL bHitEnd;
FLMUINT uiColumnNum;
F_TABLE * pTable;
F_COLUMN * pColumn;
F_ENCDEF * pTableEncDef;
F_ENCDEF * pEncDef;
FLMBYTE * pucValue;
FLMUINT uiBytesLeftToRead;
FLMUINT uiBytesToRead;
FLMUINT uiEncLen;
FLMBYTE ucIV [16];
// Get the table number from the packet
if (RC_BAD( rc = f_decodeSEN( &pucPacketBody, pucEnd, &uiTableNum)))
{
goto Exit;
}
if ((pTable = pDb->m_pDict->getTable( uiTableNum)) == NULL ||
pTable->bSystemTable)
{
rc = RC_SET( NE_SFLM_BAD_RFL_PACKET);
goto Exit;
}
pTableEncDef = (pTable->lfInfo.uiEncDefNum)
? pDb->m_pDict->getEncDef( pTable->lfInfo.uiEncDefNum)
: (F_ENCDEF *)NULL;
// Get the number of column values from the packet.
if (RC_BAD( rc = f_decodeSEN( &pucPacketBody, pucEnd, &uiNumColumnValues)))
{
goto Exit;
}
// Get the column values.
if (uiNumColumnValues)
{
// Allocate space for the values.
m_tmpPool.poolReset( NULL);
if (RC_BAD( rc = m_tmpPool.poolAlloc(
sizeof( F_COLUMN_VALUE) * uiNumColumnValues,
(void **)&pColValues)))
{
goto Exit;
}
// Go into a loop processing packets until we have retrieved all of
// the columns. At that point, we had better be at the end
// of the column data.
pColumnValue = pColValues;
pucPacketBody = pucEnd = NULL;
for (;;)
{
// If we have used everything in our current packet, get another.
if (pucPacketBody == pucEnd)
{
if( RC_BAD( rc = getPacket(
pDb, FALSE, &uiPacketType, &pucPacketBody, &uiPacketBodyLen,
&bHitEnd)))
{
goto Exit;
}
// Should not hit the end of the RFL here!
if (bHitEnd)
{
rc = RC_SET( NE_SFLM_RFL_INCOMPLETE);
goto Exit;
}
if (uiPacketType != RFL_COLUMN_DATA_PACKET)
{
rc = RC_SET( NE_SFLM_BAD_RFL_PACKET);
goto Exit;
}
pucEnd = pucPacketBody + uiPacketBodyLen;
}
// Get the column number.
if (RC_BAD( rc = f_decodeSEN( &pucPacketBody, pucEnd, &uiColumnNum)))
{
goto Exit;
}
// A zero column number means we are at the end
if (!uiColumnNum)
{
// Shouldn't have hit zero if we still have column values to
// process.
if (uiNumColumnValues)
{
rc = RC_SET( NE_SFLM_BAD_RFL_PACKET);
goto Exit;
}
break;
}
if ((pColumn = pDb->m_pDict->getColumn( pTable, uiColumnNum)) == NULL)
{
rc = RC_SET( NE_SFLM_BAD_RFL_PACKET);
goto Exit;
}
pColumnValue->uiColumnNum = uiColumnNum;
// Get the data type
if (pucPacketBody >= pucEnd)
{
rc = RC_SET( NE_SFLM_BAD_RFL_PACKET);
goto Exit;
}
pColumnValue->eColumnDataType = (eDataType)(*pucPacketBody);
switch (pColumnValue->eColumnDataType)
{
case SFLM_STRING_TYPE:
case SFLM_NUMBER_TYPE:
case SFLM_BINARY_TYPE:
break;
default:
rc = RC_SET( NE_SFLM_BAD_RFL_PACKET);
goto Exit;
}
pucPacketBody++;
// Get the value length.
if (RC_BAD( rc = f_decodeSEN( &pucPacketBody, pucEnd,
&uiBytesLeftToRead)))
{
goto Exit;
}
// Get the value, if there is one.
if ((pColumnValue->uiValueLen = uiBytesLeftToRead) != 0)
{
pEncDef = (pColumn->uiEncDefNum)
? pDb->m_pDict->getEncDef( pColumn->uiEncDefNum)
: pTableEncDef;
// If data is encrypted, allocate enough so that we can
// decrypt in place - rounding up to nearest encryption boundary
// should ensure that.
if (!pEncDef)
{
if (RC_BAD( rc = m_tmpPool.poolAlloc( uiBytesLeftToRead,
(void **)&pucValue)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = m_tmpPool.poolAlloc( getEncLen( uiBytesLeftToRead),
(void **)&pucValue)))
{
goto Exit;
}
}
pColumnValue->pucColumnValue = pucValue;
// Now get the value.
while (uiBytesLeftToRead)
{
// If we have used up our current packet, get another.
if (pucPacketBody == pucEnd)
{
if( RC_BAD( rc = getPacket(
pDb, FALSE, &uiPacketType, &pucPacketBody, &uiPacketBodyLen,
&bHitEnd)))
{
goto Exit;
}
// Should not hit the end of the RFL here!
if (bHitEnd)
{
rc = RC_SET( NE_SFLM_RFL_INCOMPLETE);
goto Exit;
}
if (uiPacketType != RFL_COLUMN_DATA_PACKET)
{
rc = RC_SET( NE_SFLM_BAD_RFL_PACKET);
goto Exit;
}
pucEnd = pucPacketBody + uiPacketBodyLen;
}
// Getting data is simple if it is not encrypted.
if (!pEncDef)
{
uiBytesToRead = (FLMUINT)(pucEnd - pucPacketBody);
if (uiBytesToRead > uiBytesLeftToRead)
{
uiBytesToRead = uiBytesLeftToRead;
}
f_memcpy( pucValue, pucPacketBody, uiBytesToRead);
pucPacketBody += uiBytesToRead;
pucValue += uiBytesToRead;
uiBytesLeftToRead -= uiBytesToRead;
}
else
{
// Encrypted data should have the encrypted length, the
// length of data encrypted, an IV, and the encrypted
// data - all in the same packet.
if (RC_BAD( rc = f_decodeSEN( &pucPacketBody, pucEnd,
&uiEncLen)))
{
goto Exit;
}
if (RC_BAD( rc = f_decodeSEN( &pucPacketBody, pucEnd,
&uiBytesToRead)))
{
goto Exit;
}
if (uiBytesToRead > uiEncLen || uiBytesToRead > uiBytesLeftToRead)
{
rc = RC_SET( NE_SFLM_BAD_RFL_PACKET);
goto Exit;
}
uiIVLen = pEncDef->pCcs->getIVLen();
flmAssert( uiIVLen == 8 || uiIVLen == 16);
// Make sure packet has the IV and the encrypted data.
if (pucPacketBody + uiIVLen + uiEncLen > pucEnd)
{
rc = RC_SET( NE_SFLM_BAD_RFL_PACKET);
goto Exit;
}
// Get the IV from the packet.
f_memcpy( ucIV, pucPacketBody, uiIVLen);
pucPacketBody += uiIVLen;
// Get the encrypted data into our buffer.
f_memcpy( pucValue, pucPacketBody, uiEncLen);
// Decrypt the data in place.
if (RC_BAD( rc = pDb->decryptData( pEncDef->uiEncDefNum, ucIV,
pucValue, uiEncLen, pucValue, uiEncLen)))
{
goto Exit;
}
// Increment our value buffer only past the decrypted data.
// Increment the packet body pointer past the encrypted data.
pucValue += uiBytesToRead;
uiBytesLeftToRead -= uiBytesToRead;
pucPacketBody += uiEncLen;
}
}
}
uiNumColumnValues--;
pColumnValue++;
}
}
if (m_pRestoreStatus)
{
if( RC_BAD( rc = m_pRestoreStatus->reportInsertRow(
peAction, uiTableNum, pColValues, uiNumColumnValues)))
{
goto Exit;
}
if( *peAction == SFLM_RESTORE_ACTION_STOP)
{
m_ui64CurrTransID = 0;
goto Exit;
}
}
while( uiBytesToWrite)
if( RC_BAD( rc = pDb->insertRow( uiTableNum, pColValues, uiNumColumnValues)))
{
if( RC_BAD( rc = m_pRfl->makeRoom( m_pDb, uiBytesToWrite,
&uiPacketLen, RFL_DATA_PACKET, &uiBytesAvail, NULL)))
{
goto Exit;
}
if( RC_BAD( rc = pIStream->read( m_pRfl->getPacketPtr()+ uiPacketLen,
uiBytesAvail)))
{
goto Exit;
}
uiBytesToWrite -= uiBytesAvail;
uiPacketLen += uiBytesAvail;
if( RC_BAD( rc = m_pRfl->finishPacket( m_pDb, RFL_DATA_PACKET,
uiPacketLen - RFL_PACKET_OVERHEAD, FALSE)))
{
goto Exit;
}
uiPacketLen = RFL_PACKET_OVERHEAD;
goto Exit;
}
Exit:
m_tmpPool.poolReset( NULL);
m_ui64CurrTransID = 0;
return( rc);
}
@@ -5369,6 +5845,23 @@ Finish_Transaction:
goto Finish_Transaction;
}
case RFL_INSERT_ROW_PACKET:
{
if( RC_BAD( rc = recovInsertRow( pDb,
pucPacketBody, uiPacketBodyLen, &eAction)))
{
goto Exit;
}
if( eAction == SFLM_RESTORE_ACTION_STOP)
{
bLastTransEndedAtFileEOF = FALSE;
goto Finish_Recovery;
}
break;
}
default:
{
// Should not be getting other packet types at this

View File

@@ -44,6 +44,8 @@ class IXKeyCompare;
#define RFL_DATA_PACKET 11
#define RFL_ROLL_OVER_DB_KEY_PACKET 12
#define RFL_ENC_DEF_KEY_PACKET 13
#define RFL_INSERT_ROW_PACKET 14
#define RFL_COLUMN_DATA_PACKET 15
#define RFL_PACKET_TYPE_MASK 0x7F
@@ -199,6 +201,24 @@ public:
RCODE logRollOverDbKey(
F_Db * pDb);
RCODE logColumnValues(
F_Db * pDb,
FLMUINT uiTableNum,
F_COLUMN_VALUE * pColumnValues,
FLMUINT uiNumColumnValues);
RCODE logInsertRow(
F_Db * pDb,
FLMUINT uiTableNum,
F_COLUMN_VALUE * pColumnValues,
FLMUINT uiNumColumnValues);
RCODE recovInsertRow(
F_Db * pDb,
const FLMBYTE * pucPacketBody,
FLMUINT uiPacketBodyLen,
eRestoreAction * peAction);
RCODE recover(
F_Db * pDb,
IF_RestoreClient * pRestore,
@@ -631,6 +651,7 @@ private:
IXKeyCompare * m_pIxCompareObject;
IF_ResultSetCompare * m_pCompareObject;
FLMUINT m_uiDisableCount; // Is logging currently disabled
F_Pool m_tmpPool;
friend class F_RflOStream;
};