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

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

#include "stdafx.h"

using namespace TPCE;

CTradeUpdateDB::CTradeUpdateDB(CDBConnection *pDBConn)
: CTxnHarnessDBBase(pDBConn)
{
	//Allocate one handle per stored procedure (frame)
	if (   SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmtFrame1) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmtFrame2) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmtFrame3) != SQL_SUCCESS		
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame1Col1) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame1Col2) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame1Col3) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame2Col1) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame2Col2) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame2Col3) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame3Col1) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame3Col2) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame3Col3) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eAllocHandle, SQL_HANDLE_STMT, m_hdbc);	

	//Bind input/output parameters for each stored procedure
	InitFrame1();
	InitFrame2();
	InitFrame3();	
};

CTradeUpdateDB::~CTradeUpdateDB()
{
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame1Col1);
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame1Col2);
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame1Col3);
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame2Col1);
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame2Col2);
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame2Col3);
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame3Col1);
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame3Col2);
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame3Col3);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame1);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame2);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame3);	
}

void CTradeUpdateDB::InitFrame1()
{
	int i;
	int j;

	//Set statement descriptor for the parameters and the first rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame1, SQL_ATTR_APP_ROW_DESC, m_descFrame1Col1, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1);

	// Bind offset pointer for the first column set
	if ( SQLSetStmtAttrW( m_hstmtFrame1, SQL_ATTR_ROW_BIND_OFFSET_PTR, &m_BindOffsetFrame1Col1, SQL_IS_POINTER ) != SQL_SUCCESS )	
		ThrowError(CODBCERR::eSetStmtAttr);

	//Frame1 input
	i = 0;
	if (   SQLBindParameter(m_hstmtFrame1, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame1Input.max_trades, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame1, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame1Input.max_updates, 0, NULL)!=SQL_SUCCESS		
		 )
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame1);

	for (j = 0; j < sizeof(Frame1Input.trade_id)/sizeof(Frame1Input.trade_id[0]); ++j)
	{
		if (   SQLBindParameter(m_hstmtFrame1, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame1Input.trade_id[j], 0, NULL)!=SQL_SUCCESS
		   )
		 ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame1);
	}

	//Frame1 output	
	i = 0;
	if (   SQLBindCol(m_hstmtFrame1, ++i, SQL_C_DOUBLE, &Frame1Output.trade_info[0].bid_price, 0, &Frame1Output.trade_info[0].bid_price_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_DOUBLE, &Frame1Output.trade_info[0].cash_transaction_amount, 0, &Frame1Output.trade_info[0].cash_transaction_amount_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_TIMESTAMP, &Frame1Output.trade_info[0].cash_transaction_dts, 0, &Frame1Output.trade_info[0].cash_transaction_dts_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.trade_info[0].cash_transaction_name, sizeof(Frame1Output.trade_info[0].cash_transaction_name), &Frame1Output.trade_info[0].cash_transaction_name_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.trade_info[0].exec_name, sizeof(Frame1Output.trade_info[0].exec_name), &Frame1Output.trade_info[0].exec_name_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.trade_info[0].is_cash, 0, &Frame1Output.trade_info[0].is_cash_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.trade_info[0].is_market, 0, &Frame1Output.trade_info[0].is_market_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_DOUBLE, &Frame1Output.trade_info[0].settlement_amount, 0, &Frame1Output.trade_info[0].settlement_amount_ind) != SQL_SUCCESS		
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_TIMESTAMP, &Frame1Output.trade_info[0].settlement_cash_due_date, 0, &Frame1Output.trade_info[0].settlement_cash_due_date_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.trade_info[0].settlement_cash_type, sizeof(Frame1Output.trade_info[0].settlement_cash_type), &Frame1Output.trade_info[0].settlement_cash_type_ind) != SQL_SUCCESS				
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_DOUBLE, &Frame1Output.trade_info[0].trade_price, 0, &Frame1Output.trade_info[0].trade_price_ind) != SQL_SUCCESS		
		)
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame1);


	//Set statement descriptor for the second rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame1, SQL_ATTR_APP_ROW_DESC, m_descFrame1Col2, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1);

	// Bind offset pointer for the second column set
	if ( SQLSetStmtAttrW( m_hstmtFrame1, SQL_ATTR_ROW_BIND_OFFSET_PTR, &m_BindOffsetFrame1Col2, SQL_IS_POINTER ) != SQL_SUCCESS )	
		ThrowError(CODBCERR::eSetStmtAttr);

	SQLSetStmtAttr(m_hstmtFrame1, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);	//set column-wise binding although it is the default
	SQLSetStmtAttr(m_hstmtFrame1, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)(sizeof(Frame1Output.trade_info[0].trade_history_dts)/sizeof(Frame1Output.trade_info[0].trade_history_dts[0])), SQL_IS_INTEGER);
	//SQLSetStmtAttr(m_hstmtFrame1, SQL_ATTR_ROWS_FETCHED_PTR, &Frame1Output.num_found, SQL_IS_POINTER);

	i = 0;
	if (
		   SQLBindCol(m_hstmtFrame1, ++i, SQL_C_TIMESTAMP, &Frame1Output.trade_info[0].trade_history_dts[0], 0, &Frame1Output.trade_info[0].trade_history_dts_ind[0]) != SQL_SUCCESS		
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.trade_info[0].trade_history_status_id[0], 
														sizeof(Frame1Output.trade_info[0].trade_history_status_id[0]), 
														&Frame1Output.trade_info[0].trade_history_status_id_ind[0]) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1);



	//Set statement descriptor for the third rowset
	//
	if ( SQLSetStmtAttrW( m_hstmtFrame1, SQL_ATTR_APP_ROW_DESC, m_descFrame1Col3, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1);

	i = 0;
	if (
		   SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.num_found, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.num_updated, 0, NULL) != SQL_SUCCESS		
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1);
}

void CTradeUpdateDB::InitFrame2()
{
	int i;

	//Set statement descriptor for the parameters and the first rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame2, SQL_ATTR_APP_ROW_DESC, m_descFrame2Col1, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1);

	// Bind offset pointer for the first column set
	if ( SQLSetStmtAttrW( m_hstmtFrame2, SQL_ATTR_ROW_BIND_OFFSET_PTR, &m_BindOffsetFrame2Col1, SQL_IS_POINTER ) != SQL_SUCCESS )	
		ThrowError(CODBCERR::eSetStmtAttr);

	//Frame2 input
	i = 0;
	if (   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_SLONG, SQL_INTEGER, 0, 0, &Frame2Input.max_trades, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame2Input.max_updates, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 23, 3, &Frame2Input.start_trade_dts, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame2, ++i, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 23, 3, &Frame2Input.end_trade_dts, 0, NULL)!=SQL_SUCCESS
		 )
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame2);

	//Frame2 output	
	i = 0;
	if (   SQLBindCol(m_hstmtFrame2, ++i, SQL_C_DOUBLE, &Frame2Output.trade_info[0].bid_price, 0, &Frame2Output.trade_info[0].bid_price_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_DOUBLE, &Frame2Output.trade_info[0].cash_transaction_amount, 0, &Frame2Output.trade_info[0].cash_transaction_amount_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_TIMESTAMP, &Frame2Output.trade_info[0].cash_transaction_dts, 0, &Frame2Output.trade_info[0].cash_transaction_dts_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_CHAR, &Frame2Output.trade_info[0].cash_transaction_name, sizeof(Frame2Output.trade_info[0].cash_transaction_name), &Frame2Output.trade_info[0].cash_transaction_name_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_CHAR, &Frame2Output.trade_info[0].exec_name, sizeof(Frame2Output.trade_info[0].exec_name), &Frame2Output.trade_info[0].exec_name_ind) != SQL_SUCCESS		
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_SLONG, &Frame2Output.trade_info[0].is_cash, 0, &Frame2Output.trade_info[0].is_cash_ind) != SQL_SUCCESS		

		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_DOUBLE, &Frame2Output.trade_info[0].settlement_amount, 0, &Frame2Output.trade_info[0].settlement_amount_ind) != SQL_SUCCESS		
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_TIMESTAMP, &Frame2Output.trade_info[0].settlement_cash_due_date, 0, &Frame2Output.trade_info[0].settlement_cash_due_date_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_CHAR, &Frame2Output.trade_info[0].settlement_cash_type, sizeof(Frame2Output.trade_info[0].settlement_cash_type), &Frame2Output.trade_info[0].settlement_cash_type_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_IDENT, &Frame2Output.trade_info[0].trade_id, 0, &Frame2Output.trade_info[0].trade_id_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_DOUBLE, &Frame2Output.trade_info[0].trade_price, 0, &Frame2Output.trade_info[0].trade_price_ind) != SQL_SUCCESS		
		)
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame2);	

	//Set statement descriptor for the second rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame2, SQL_ATTR_APP_ROW_DESC, m_descFrame2Col2, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame2);

	// Bind offset pointer for the second column set
	if ( SQLSetStmtAttrW( m_hstmtFrame2, SQL_ATTR_ROW_BIND_OFFSET_PTR, &m_BindOffsetFrame2Col2, SQL_IS_POINTER ) != SQL_SUCCESS )	
		ThrowError(CODBCERR::eSetStmtAttr);

	SQLSetStmtAttr(m_hstmtFrame2, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);	//set column-wise binding although it is the default
	SQLSetStmtAttr(m_hstmtFrame2, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)(sizeof(Frame2Output.trade_info[0].trade_history_dts)/sizeof(Frame2Output.trade_info[0].trade_history_dts[0])), SQL_IS_INTEGER);
	//SQLSetStmtAttr(m_hstmtFrame2, SQL_ATTR_ROWS_FETCHED_PTR, &Frame2Output.num_found, SQL_IS_POINTER);

	i = 0;
	if (
		   SQLBindCol(m_hstmtFrame2, ++i, SQL_C_TIMESTAMP, &Frame2Output.trade_info[0].trade_history_dts[0], 0, &Frame2Output.trade_info[0].trade_history_dts_ind[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_CHAR, &Frame2Output.trade_info[0].trade_history_status_id[0], 
														sizeof(Frame2Output.trade_info[0].trade_history_status_id[0]), 
														&Frame2Output.trade_info[0].trade_history_status_id_ind[0]) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame2);



	//Set statement descriptor for the third rowset
	//
	if ( SQLSetStmtAttrW( m_hstmtFrame2, SQL_ATTR_APP_ROW_DESC, m_descFrame2Col3, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame2);

	i = 0;
	if (
		   SQLBindCol(m_hstmtFrame2, ++i, SQL_C_SLONG, &Frame2Output.num_found, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame2, ++i, SQL_C_SLONG, &Frame2Output.num_updated, 0, NULL) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame2);
}

void CTradeUpdateDB::InitFrame3()
{
	int i;

	//Set statement descriptor for the parameters and the first rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame3, SQL_ATTR_APP_ROW_DESC, m_descFrame3Col1, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3);	

	// Bind offset pointer for the first column set
	if ( SQLSetStmtAttrW( m_hstmtFrame3, SQL_ATTR_ROW_BIND_OFFSET_PTR, &m_BindOffsetFrame3Col1, SQL_IS_POINTER ) != SQL_SUCCESS )	
		ThrowError(CODBCERR::eSetStmtAttr);

	//Frame3 input
	i = 0;
	if (   SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame3Input.max_trades, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &Frame3Input.max_updates, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(Frame3Input.symbol)-1, 0, &Frame3Input.symbol, sizeof(Frame3Input.symbol), NULL)!=SQL_SUCCESS		
		|| SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 23, 3, &Frame3Input.start_trade_dts, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 23, 3, &Frame3Input.end_trade_dts, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame3, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame3Input.max_acct_id, 0, NULL)!=SQL_SUCCESS
		 )
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame3);

	//Frame3 output	
	i = 0;
	if (
		   SQLBindCol(m_hstmtFrame3, ++i, SQL_C_IDENT, &Frame3Output.trade_info[0].acct_id, 0, &Frame3Output.trade_info[0].acct_id_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_DOUBLE, &Frame3Output.trade_info[0].cash_transaction_amount, 0, &Frame3Output.trade_info[0].cash_transaction_amount_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_TIMESTAMP, &Frame3Output.trade_info[0].cash_transaction_dts, 0, &Frame3Output.trade_info[0].cash_transaction_dts_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_CHAR, &Frame3Output.trade_info[0].cash_transaction_name, sizeof(Frame3Output.trade_info[0].cash_transaction_name), &Frame3Output.trade_info[0].cash_transaction_name_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_CHAR, &Frame3Output.trade_info[0].exec_name, sizeof(Frame3Output.trade_info[0].exec_name), &Frame3Output.trade_info[0].exec_name_ind) != SQL_SUCCESS		
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_SLONG, &Frame3Output.trade_info[0].is_cash, 0, &Frame3Output.trade_info[0].is_cash_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_DOUBLE, &Frame3Output.trade_info[0].price, 0, &Frame3Output.trade_info[0].price_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_SLONG, &Frame3Output.trade_info[0].quantity, 0, &Frame3Output.trade_info[0].quantity_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_CHAR, &Frame3Output.trade_info[0].s_name, sizeof(Frame3Output.trade_info[0].s_name), &Frame3Output.trade_info[0].s_name_ind) != SQL_SUCCESS

		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_DOUBLE, &Frame3Output.trade_info[0].settlement_amount, 0, &Frame3Output.trade_info[0].settlement_amount_ind) != SQL_SUCCESS		
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_TIMESTAMP, &Frame3Output.trade_info[0].settlement_cash_due_date, 0, &Frame3Output.trade_info[0].settlement_cash_due_date_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_CHAR, &Frame3Output.trade_info[0].settlement_cash_type, sizeof(Frame3Output.trade_info[0].settlement_cash_type), &Frame3Output.trade_info[0].settlement_cash_type_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_TIMESTAMP, &Frame3Output.trade_info[0].trade_dts, 0, &Frame3Output.trade_info[0].trade_dts_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_IDENT, &Frame3Output.trade_info[0].trade_id, 0, &Frame3Output.trade_info[0].trade_id_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_CHAR, &Frame3Output.trade_info[0].trade_type, sizeof(Frame3Output.trade_info[0].trade_type), &Frame3Output.trade_info[0].trade_type_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_CHAR, &Frame3Output.trade_info[0].type_name, sizeof(Frame3Output.trade_info[0].type_name), &Frame3Output.trade_info[0].type_name_ind) != SQL_SUCCESS

		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3);	
	
	//Set statement descriptor for the second rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame3, SQL_ATTR_APP_ROW_DESC, m_descFrame3Col2, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3);	

	// Bind offset pointer for the second column set
	if ( SQLSetStmtAttrW( m_hstmtFrame3, SQL_ATTR_ROW_BIND_OFFSET_PTR, &m_BindOffsetFrame3Col2, SQL_IS_POINTER ) != SQL_SUCCESS )	
		ThrowError(CODBCERR::eSetStmtAttr);

	SQLSetStmtAttr(m_hstmtFrame3, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);	//set column-wise binding although it is the default
	SQLSetStmtAttr(m_hstmtFrame3, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)(sizeof(Frame3Output.trade_info[0].trade_history_dts)/sizeof(Frame3Output.trade_info[0].trade_history_dts[0])), SQL_IS_INTEGER);
	//SQLSetStmtAttr(m_hstmtFrame3, SQL_ATTR_ROWS_FETCHED_PTR, &Frame3Output.num_found, SQL_IS_POINTER);

	i = 0;
	if (
		   SQLBindCol(m_hstmtFrame3, ++i, SQL_C_TIMESTAMP, &Frame3Output.trade_info[0].trade_history_dts[0], 0, &Frame3Output.trade_info[0].trade_history_dts_ind[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_CHAR, &Frame3Output.trade_info[0].trade_history_status_id[0], 
														sizeof(Frame3Output.trade_info[0].trade_history_status_id[0]), 
														&Frame3Output.trade_info[0].trade_history_status_id_ind[0]) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3);



	//Set statement descriptor for the third rowset
	//
	if ( SQLSetStmtAttrW( m_hstmtFrame3, SQL_ATTR_APP_ROW_DESC, m_descFrame3Col3, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3);

	i = 0;
	if (
		   SQLBindCol(m_hstmtFrame3, ++i, SQL_C_SLONG, &Frame3Output.num_found, 0, NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame3, ++i, SQL_C_SLONG, &Frame3Output.num_updated, 0, NULL) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3);	
}



void CTradeUpdateDB::DoTradeUpdateFrame1(const TTradeUpdateFrame1Input *pFrame1Input, PTradeUpdateFrame1Output pFrame1Output)
{
	int			rc;	
	SQLSMALLINT	iColumnCount;	// number of columns in the result set

	//copy input parameters into bound locations
	Frame1Input = *pFrame1Input;	

	//Set statement descriptor for the parameters and the first rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame1, SQL_ATTR_APP_ROW_DESC, m_descFrame1Col1, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeUpdateFrame1");

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

	m_BindOffsetFrame1Col1 = 0;
	m_BindOffsetFrame1Col2 = 0;	

	// Get the number of columns to make sure it is not the last result set (with num col=2)
	//
	if (SQLNumResultCols(m_hstmtFrame1, &iColumnCount) == SQL_ERROR)
		ThrowError(CODBCERR::eNumResultCols, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeUpdateFrame1");

	while (iColumnCount > 2 && rc != SQL_NO_DATA)
	{
		//Set statement descriptor for the first rowset
		if ( SQLSetStmtAttrW( m_hstmtFrame1, SQL_ATTR_APP_ROW_DESC, m_descFrame1Col1, SQL_IS_POINTER ) != SQL_SUCCESS )
			ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeUpdateFrame1");

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

		if ( (rc = SQLMoreResults(m_hstmtFrame1)) == SQL_ERROR)
			ThrowError(CODBCERR::eMoreResults, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeUpdateFrame1");

		//Set statement descriptor for the second rowset
		if ( SQLSetStmtAttrW( m_hstmtFrame1, SQL_ATTR_APP_ROW_DESC, m_descFrame1Col2, SQL_IS_POINTER ) != SQL_SUCCESS )
			ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeUpdateFrame1");

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

		m_BindOffsetFrame1Col1 += sizeof(Frame1Output.trade_info[0]);
		m_BindOffsetFrame1Col2 += sizeof(Frame1Output.trade_info[0]);

		// Get the number of columns to make sure it is not the last result set (with num col=2)
		//
		if (SQLNumResultCols(m_hstmtFrame1, &iColumnCount) == SQL_ERROR)
			ThrowError(CODBCERR::eNumResultCols, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeUpdateFrame1");
	}

	//Set statement descriptor for the third rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame1, SQL_ATTR_APP_ROW_DESC, m_descFrame1Col3, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeUpdateFrame1");

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

	//copy output parameters back
	*pFrame1Output = Frame1Output;	//invoke default assignment operator	

	if ( (rc = SQLCloseCursor(m_hstmtFrame1)) != SQL_SUCCESS)
		ThrowError(CODBCERR::eCloseCursor, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeUpdateFrame1");

};

void CTradeUpdateDB::DoTradeUpdateFrame2(const TTradeUpdateFrame2Input *pFrame2Input, PTradeUpdateFrame2Output pFrame2Output)
{
	int			rc;
	SQLSMALLINT	iColumnCount;	// number of columns in the result set

	//copy input parameters into bound locations
	Frame2Input = *pFrame2Input;

	//Set statement descriptor for the parameters and the first rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame2, SQL_ATTR_APP_ROW_DESC, m_descFrame2Col1, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");

	rc = SQLExecDirect(m_hstmtFrame2, (SQLCHAR*)"{call TradeUpdateFrame2(?, ?, ?, ?, ?)}", SQL_NTS);

	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
		ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");

	m_BindOffsetFrame2Col1 = 0;
	m_BindOffsetFrame2Col2 = 0;	

	// Get the number of columns to make sure it is not the last result set (with num col=2)
	//
	if (SQLNumResultCols(m_hstmtFrame2, &iColumnCount) == SQL_ERROR)
		ThrowError(CODBCERR::eNumResultCols, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");

	while (iColumnCount > 2 && rc != SQL_NO_DATA)
	{
		//Set statement descriptor for the first rowset
		if ( SQLSetStmtAttrW( m_hstmtFrame2, SQL_ATTR_APP_ROW_DESC, m_descFrame2Col1, SQL_IS_POINTER ) != SQL_SUCCESS )
			ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");

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

		if ( (rc = SQLMoreResults(m_hstmtFrame2)) == SQL_ERROR)
			ThrowError(CODBCERR::eMoreResults, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");

		//Set statement descriptor for the second rowset
		if ( SQLSetStmtAttrW( m_hstmtFrame2, SQL_ATTR_APP_ROW_DESC, m_descFrame2Col2, SQL_IS_POINTER ) != SQL_SUCCESS )
			ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");

		if ( (rc = SQLFetch(m_hstmtFrame2)) == SQL_ERROR)
			ThrowError(CODBCERR::eFetch, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");
		
		if ( (rc = SQLMoreResults(m_hstmtFrame2)) == SQL_ERROR)
			ThrowError(CODBCERR::eMoreResults, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");

		m_BindOffsetFrame2Col1 += sizeof(Frame2Output.trade_info[0]);
		m_BindOffsetFrame2Col2 += sizeof(Frame2Output.trade_info[0]);

		// Get the number of columns to make sure it is not the last result set (with num col=2)
		//
		if (SQLNumResultCols(m_hstmtFrame2, &iColumnCount) == SQL_ERROR)
			ThrowError(CODBCERR::eNumResultCols, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");
	}

	//Set statement descriptor for the third rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame2, SQL_ATTR_APP_ROW_DESC, m_descFrame2Col3, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");

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

	//copy output parameters back
	*pFrame2Output = Frame2Output;	//invoke default assignment operator
	
	if ( (rc = SQLCloseCursor(m_hstmtFrame2)) != SQL_SUCCESS)
		ThrowError(CODBCERR::eCloseCursor, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeUpdateFrame2");
};

void CTradeUpdateDB::DoTradeUpdateFrame3(const TTradeUpdateFrame3Input *pFrame3Input, PTradeUpdateFrame3Output pFrame3Output)
{
	int			rc;
	SQLSMALLINT	iColumnCount;	// number of columns in the result set

	//copy input parameters into bound locations
	Frame3Input = *pFrame3Input;	

	//Set statement descriptor for the parameters and the first rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame3, SQL_ATTR_APP_ROW_DESC, m_descFrame3Col1, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");

	rc = SQLExecDirect(m_hstmtFrame3, (SQLCHAR*)"{call TradeUpdateFrame3(?, ?, ?, ?, ?, ?)}", SQL_NTS);

	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
		ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");
	
	m_BindOffsetFrame3Col1 = 0;
	m_BindOffsetFrame3Col2 = 0;	

	// Get the number of columns to make sure it is not the last result set (with num col=2)
	//
	if (SQLNumResultCols(m_hstmtFrame3, &iColumnCount) == SQL_ERROR)
		ThrowError(CODBCERR::eNumResultCols, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");

	while (iColumnCount > 2 && rc != SQL_NO_DATA)
	{
		//Set statement descriptor for the first rowset
		if ( SQLSetStmtAttrW( m_hstmtFrame3, SQL_ATTR_APP_ROW_DESC, m_descFrame3Col1, SQL_IS_POINTER ) != SQL_SUCCESS )
			ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");

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

		if ( (rc = SQLMoreResults(m_hstmtFrame3)) == SQL_ERROR)
			ThrowError(CODBCERR::eMoreResults, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");

		//Set statement descriptor for the second rowset
		if ( SQLSetStmtAttrW( m_hstmtFrame3, SQL_ATTR_APP_ROW_DESC, m_descFrame3Col2, SQL_IS_POINTER ) != SQL_SUCCESS )
			ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");

		if ( (rc = SQLFetch(m_hstmtFrame3)) == SQL_ERROR)
			ThrowError(CODBCERR::eFetch, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");
		
		if ( (rc = SQLMoreResults(m_hstmtFrame3)) == SQL_ERROR)
			ThrowError(CODBCERR::eMoreResults, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");

		m_BindOffsetFrame3Col1 += sizeof(Frame3Output.trade_info[0]);
		m_BindOffsetFrame3Col2 += sizeof(Frame3Output.trade_info[0]);

		// Get the number of columns to make sure it is not the last result set (with num col=2)
		//
		if (SQLNumResultCols(m_hstmtFrame3, &iColumnCount) == SQL_ERROR)
			ThrowError(CODBCERR::eNumResultCols, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");
	}

	//Set statement descriptor for the third rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame3, SQL_ATTR_APP_ROW_DESC, m_descFrame3Col3, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");

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

	//copy output parameters back
	*pFrame3Output = Frame3Output;	//invoke default assignment operator	

	if ( (rc = SQLCloseCursor(m_hstmtFrame3)) != SQL_SUCCESS)
		ThrowError(CODBCERR::eCloseCursor, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeUpdateFrame3");	
};

void CTradeUpdateDB::Cleanup(void* pException)
{
	SQLCloseCursor(m_hstmtFrame1);
	if (SQLMoreResults(m_hstmtFrame1) != SQL_ERROR)
	{
		SQLCloseCursor(m_hstmtFrame1);
	}
	SQLCloseCursor(m_hstmtFrame2);
	if (SQLMoreResults(m_hstmtFrame2) != SQL_ERROR)
	{
		SQLCloseCursor(m_hstmtFrame2);
	}
	SQLCloseCursor(m_hstmtFrame3);	

	if (SQLMoreResults(m_hstmtFrame3) != SQL_ERROR)
	{
		SQLCloseCursor(m_hstmtFrame3);
	}
}