/*
*	©Copyright 2002,2003, Microsoft Corporation
*	Microsoft Confidential.
*	Written by Sergey Vasilevskiy, 2002-2003.
*/

/*
*	Trade Result database class that uses stored procedures for individual frames.
*/

#include "stdafx.h"

using namespace TPCE;

CTradeResultDB::CTradeResultDB(CDBConnection *pDBConn)
: CTxnHarnessDBBase(pDBConn)
{
	int i;	

	//Allocate one handle per stored procedure (frame)
	if (SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmtFrame1) != SQL_SUCCESS)
		ThrowError(CODBCERR::eAllocHandle, SQL_HANDLE_STMT, m_hdbc);
	if (SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmtFrame2) != SQL_SUCCESS)
		ThrowError(CODBCERR::eAllocHandle, SQL_HANDLE_STMT, m_hdbc);
	if (SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmtFrame3) != SQL_SUCCESS)
		ThrowError(CODBCERR::eAllocHandle, SQL_HANDLE_STMT, m_hdbc);
	if (SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmtFrame4) != SQL_SUCCESS)
		ThrowError(CODBCERR::eAllocHandle, SQL_HANDLE_STMT, m_hdbc);
	if (SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmtFrame5) != SQL_SUCCESS)
		ThrowError(CODBCERR::eAllocHandle, SQL_HANDLE_STMT, m_hdbc);
	if (SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmtFrame6) != SQL_SUCCESS)
		ThrowError(CODBCERR::eAllocHandle, SQL_HANDLE_STMT, m_hdbc);

	//Bind input/output parameters for each stored procedure

	//Frame1 input
	i = 0;
	if (   //SQLBindParameter(m_hstmtFrame1, ++i, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame1Output.status, 0, NULL)!=SQL_SUCCESS //sp return code
		   SQLBindParameter(m_hstmtFrame1, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame1Input.trade_id, 0, NULL)!=SQL_SUCCESS )
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame1);
	//Frame1 output
	i = 0;
	if (   SQLBindCol(m_hstmtFrame1, ++i, SQL_C_IDENT, &Frame1Output.acct_id, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_DOUBLE, &Frame1Output.charge, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.hs_qty, 0, &m_HS_QTY_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, Frame1Output.symbol, cSYMBOL_len+1, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.trade_is_cash, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.trade_qty, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, Frame1Output.type_id, cTT_ID_len+1, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.type_is_market, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.type_is_sell, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, Frame1Output.type_name, cTT_NAME_len+1, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.is_lifo, 0, NULL) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame1);

	//Frame 2 input
	//
	i = 0;	
	if (   SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame2Input.trade_id, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame2Input.acct_id, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, cSYMBOL_len+1, 0, Frame2Input.symbol, cSYMBOL_len+1, NULL) != SQL_SUCCESS		
		|| SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_TINYINT, 0, 0, &Frame2Input.is_lifo, 0, NULL)!=SQL_SUCCESS		
		|| SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &Frame2Input.trade_price, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame2Input.trade_qty, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_TINYINT, 0, 0, &Frame2Input.type_is_sell, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame2Input.hs_qty, 0, NULL)!=SQL_SUCCESS
		)
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame2);

	//Frame 2 output	
	i = 0;
	if (   SQLBindCol(m_hstmtFrame2, ++i, SQL_C_DOUBLE, &Frame2Output.buy_value, 0, NULL)!=SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_DOUBLE, &Frame2Output.sell_value, 0, NULL)!=SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_TYPE_TIMESTAMP, &Frame2Output.trade_dts, 0, NULL)!=SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_IDENT, &Frame2Output.broker_id, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_IDENT, &Frame2Output.cust_id, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_SLONG, &Frame2Output.tax_status, 0, NULL) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame2);

	//Frame 3 input
	i = 0;
	if (   //SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame3Output.status, 0, NULL)!=SQL_SUCCESS //sp return code
		   SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame3Input.trade_id, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame3Input.cust_id, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &Frame3Input.buy_value, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &Frame3Input.sell_value, 0, NULL)!=SQL_SUCCESS
		)
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame3);
	//Frame 3 output
	i = 0;
	if ( SQLBindCol(m_hstmtFrame3, ++i, SQL_C_DOUBLE, &Frame3Output.tax_amount, 0, NULL)!=SQL_SUCCESS )
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame3);
	
	//Frame 4 input
	i = 0;
	if (   //SQLBindParameter(m_hstmtFrame4, ++i, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame4Output.status, 0, NULL)!=SQL_SUCCESS //sp return code
		   SQLBindParameter(m_hstmtFrame4, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame4Input.cust_id, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame4, ++i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, cSYMBOL_len+1, 0, Frame4Input.symbol, cSYMBOL_len+1, NULL) != SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame4, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame4Input.trade_qty, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame4, ++i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, cTT_ID_len+1, 0, &Frame4Input.type_id, cTT_ID_len+1, NULL)!=SQL_SUCCESS		
		)
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame4);
	//Frame 4 output
	i = 0;
	if (   SQLBindCol(m_hstmtFrame4, ++i, SQL_C_DOUBLE, &Frame4Output.comm_rate, 0, NULL)!=SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame4, ++i, SQL_C_CHAR, &Frame4Output.s_name, cS_NAME_len+1, NULL)!=SQL_SUCCESS
		)
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame4);
	
	//Frame5 input
	i = 0;
	if (   //SQLBindParameter(m_hstmtFrame5, ++i, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame5Output.status, 0, NULL)!=SQL_SUCCESS //sp return code
		   SQLBindParameter(m_hstmtFrame5, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame5Input.broker_id, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame5, ++i, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &Frame5Input.comm_amount, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame5, ++i, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 23, 3, &Frame5Input.trade_dts, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame5, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame5Input.trade_id, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame5, ++i, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &Frame5Input.trade_price, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame5, ++i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, cST_ID_len+1, 0, &Frame5Input.st_completed_id, cST_ID_len+1, NULL)!=SQL_SUCCESS
		)
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame5);
	
	//Frame6 input
	i = 0;
	if (   //SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame6Output.status, 0, NULL)!=SQL_SUCCESS //sp return code
		   SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame6Input.acct_id, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 23, 3, &Frame6Input.due_date, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, cS_NAME_len, 0, &Frame6Input.s_name, cS_NAME_len+1, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &Frame6Input.se_amount, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 23, 3, &Frame6Input.trade_dts, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame6Input.trade_id, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_TINYINT, 0, 0, &Frame6Input.trade_is_cash, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame6Input.trade_qty, 0, NULL)!=SQL_SUCCESS
		//|| SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_TINYINT, 0, 0, &Frame6Input.type_is_margin, 0, NULL)!=SQL_SUCCESS
		//|| SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_TINYINT, 0, 0, &Frame6Input.type_is_sell, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame6, ++i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, cTT_NAME_len, 0, &Frame6Input.type_name, cTT_NAME_len+1, NULL)!=SQL_SUCCESS
		)
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame6);
	
	//Frame 6 output
	i = 0;
	if (   SQLBindCol(m_hstmtFrame6, ++i, SQL_C_DOUBLE, &Frame6Output.acct_bal, 0, NULL)!=SQL_SUCCESS		
		)
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame6);
};

//Destructor
CTradeResultDB::~CTradeResultDB()
{
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame1);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame2);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame3);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame4);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame5);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame6);
}

void CTradeResultDB::DoTradeResultFrame1(const TTradeResultFrame1Input *pFrame1Input, PTradeResultFrame1Output pFrame1Output)
{
	int rc;

	Frame1Input = *pFrame1Input;	//input parameter
	
	rc = SQLExecDirect(m_hstmtFrame1, (SQLCHAR*)"{call TradeResultFrame1(?)}", SQL_NTS);
	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
		ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeResultFrame1");

	if ( (rc = SQLFetch(m_hstmtFrame1)) == SQL_ERROR)
		ThrowError(CODBCERR::eFetch, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeResultFrame1");

	if (m_HS_QTY_ind == SQL_NULL_DATA)	// test for NULL value returned
	{
		Frame1Output.hs_qty = 0;
	}

	// Status code change introduced in EGen 1.6.0.
	//
	if (rc != SQL_NO_DATA)	// check whether SQLFetch returned any rows
	{
		//copy output parameters back
		*pFrame1Output = Frame1Output;	//invoke default assignment operator
		pFrame1Output->num_found = 1;
	}
	else
	{
		pFrame1Output->num_found = 0;
	}

	// Need two SQLFreeStmt calls for some reason to clean the statement
	// handle properly after the server sent "Transaction count incorrect after batch" message
	// with the result set.
	//
	rc = SQLFreeStmt(m_hstmtFrame1, SQL_CLOSE);
	rc = SQLFreeStmt(m_hstmtFrame1, SQL_CLOSE);
};

void CTradeResultDB::DoTradeResultFrame2(const TTradeResultFrame2Input *pFrame2Input, PTradeResultFrame2Output pFrame2Output)
{
	int rc;

	//copy inputs into bound locations
	Frame2Input = *pFrame2Input;

	rc = SQLExecDirect(m_hstmtFrame2, 
		(SQLCHAR*)"{call TradeResultFrame2(?, ?, ?, ?, ?, ?, ?, ?)}", SQL_NTS);
	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
		ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeResultFrame2");

	if ( SQLFetch(m_hstmtFrame2) == SQL_ERROR)
		ThrowError(CODBCERR::eFetch, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeResultFrame2");

	//copy output parameters back
	*pFrame2Output = Frame2Output;	

	// Need two SQLFreeStmt calls for some reason to clean the statement
	// handle properly after the server sent "Transaction count incorrect after batch" message
	// with the result set.
	//
	rc = SQLFreeStmt(m_hstmtFrame2, SQL_CLOSE);
	rc = SQLFreeStmt(m_hstmtFrame2, SQL_CLOSE);
};

void CTradeResultDB::DoTradeResultFrame3(const TTradeResultFrame3Input *pFrame3Input, PTradeResultFrame3Output pFrame3Output)
{
	int rc;

	//copy inputs into bound locations
	Frame3Input = *pFrame3Input;	

	rc = SQLExecDirect(m_hstmtFrame3,
		(SQLCHAR*)"{call TradeResultFrame3(?, ?, ?, ?)}", SQL_NTS);
	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
		ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeResultFrame3");

	if ( SQLFetch(m_hstmtFrame3) == SQL_ERROR)
		ThrowError(CODBCERR::eFetch, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeResultFrame3");

	//copy output parameters back
	*pFrame3Output = Frame3Output;

	// Need two SQLFreeStmt calls for some reason to clean the statement
	// handle properly after the server sent "Transaction count incorrect after batch" message
	// with the result set.
	//
	rc = SQLFreeStmt(m_hstmtFrame3, SQL_CLOSE);
	rc = SQLFreeStmt(m_hstmtFrame3, SQL_CLOSE);
};

void CTradeResultDB::DoTradeResultFrame4(const TTradeResultFrame4Input *pFrame4Input, PTradeResultFrame4Output pFrame4Output)
{
	int rc;

	//copy inputs into bound locations
	Frame4Input = *pFrame4Input;	

	rc = SQLExecDirect(m_hstmtFrame4,
		(SQLCHAR*)"{call TradeResultFrame4(?, ?, ?, ?)}", SQL_NTS);
	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
		ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame4, "DoTradeResultFrame4");

	if ( SQLFetch(m_hstmtFrame4) == SQL_ERROR)
		ThrowError(CODBCERR::eFetch, SQL_HANDLE_STMT, m_hstmtFrame4, "DoTradeResultFrame4");

	//copy output parameters back
	*pFrame4Output = Frame4Output;	

	// Need two SQLFreeStmt calls for some reason to clean the statement
	// handle properly after the server sent "Transaction count incorrect after batch" message
	// with the result set.
	//
	rc = SQLFreeStmt(m_hstmtFrame4, SQL_CLOSE);
	rc = SQLFreeStmt(m_hstmtFrame4, SQL_CLOSE);
};

void CTradeResultDB::DoTradeResultFrame5(const TTradeResultFrame5Input *pFrame5Input)
{
	int rc;
	long lNativeError;

	//copy inputs into bound locations
	Frame5Input = *pFrame5Input;	

	rc = SQLExecDirect(m_hstmtFrame5,
		(SQLCHAR*)"{call TradeResultFrame5(?, ?, ?, ?, ?, ?)}", SQL_NTS);
	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
	{
		rc = SQLGetDiagRec( SQL_HANDLE_STMT, m_hstmtFrame5, 1, NULL, &lNativeError,
					  NULL, 0, NULL);

		if (lNativeError != 2627)	//not a dublicate primary key
			ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame5, "DoTradeResultFrame5");
		else
		{
			char szMsg[64];
			_snprintf(szMsg, sizeof(szMsg), "Error 2627 (dublicate key) in TradeResultFrame5 for trade_id=%I64d\n",
				Frame5Input.trade_id);
			cout<<szMsg;
		}
	}

	// Need two SQLFreeStmt calls for some reason to clean the statement
	// handle properly after the server sent "Transaction count incorrect after batch" message
	// with the result set.
	//
	rc = SQLFreeStmt(m_hstmtFrame4, SQL_CLOSE);
	rc = SQLFreeStmt(m_hstmtFrame4, SQL_CLOSE);
};

void CTradeResultDB::DoTradeResultFrame6(const TTradeResultFrame6Input *pFrame6Input, PTradeResultFrame6Output pFrame6Output)
{
	int rc;

	//copy inputs into bound locations
	Frame6Input = *pFrame6Input;	

	rc = SQLExecDirect(m_hstmtFrame6,
		(SQLCHAR*)"{call TradeResultFrame6(?, ?, ?, ?, ?, ?, ?, ?, ?)}", SQL_NTS);
	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
		ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame6, "DoTradeResultFrame6");

	if ( SQLFetch(m_hstmtFrame6) == SQL_ERROR)
		ThrowError(CODBCERR::eFetch, SQL_HANDLE_STMT, m_hstmtFrame6, "DoTradeResultFrame6");

	//copy output parameters back	
	*pFrame6Output = Frame6Output;

	// Need two SQLFreeStmt calls for some reason to clean the statement
	// handle properly after the server sent "Transaction count incorrect after batch" message
	// with the result set.
	//
	rc = SQLFreeStmt(m_hstmtFrame6, SQL_CLOSE);
	rc = SQLFreeStmt(m_hstmtFrame6, SQL_CLOSE);
};

void CTradeResultDB::Cleanup(void* pException)
{
	SQLFreeStmt(m_hstmtFrame1, SQL_CLOSE);
	SQLFreeStmt(m_hstmtFrame1, SQL_CLOSE);
	SQLCloseCursor(m_hstmtFrame1);
	SQLCloseCursor(m_hstmtFrame2);
	SQLCloseCursor(m_hstmtFrame3);
	SQLCloseCursor(m_hstmtFrame4);
	SQLCloseCursor(m_hstmtFrame5);
	SQLCloseCursor(m_hstmtFrame6);
}
