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

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

#include "stdafx.h"

using namespace TPCE;

CTradeLookupDB::CTradeLookupDB(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_STMT, m_hdbc, &m_hstmtFrame4) != 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
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame4Col1) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame4Col2) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame4Col3) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eAllocHandle, SQL_HANDLE_STMT, m_hdbc);	

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

CTradeLookupDB::~CTradeLookupDB()
{
	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_DESC, m_descFrame4Col1);
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame4Col2);
	SQLFreeHandle(SQL_HANDLE_DESC, m_descFrame4Col3);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame1);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame2);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame3);
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame4);
}

void CTradeLookupDB::InitFrame1()
{
	int i, 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
		 )
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame1);

	// bind an array of trade id parameters
	//
	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		
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1);
}

void CTradeLookupDB::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_hstmtFrame2);

	// 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_SLONG, SQL_BIGINT, 0, 0, &Frame2Input.max_trades, 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_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
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame2);
}

void CTradeLookupDB::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_CHAR, SQL_VARCHAR, cSYMBOL_len, 0, &Frame3Input.symbol, cSYMBOL_len+1, 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_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		
		)
		ThrowError(CODBCERR::eBindCol, 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		
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame3);
}

void CTradeLookupDB::InitFrame4()
{
	int i;

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

	//Frame4 input
	i = 0;
	if (   SQLBindParameter(m_hstmtFrame4, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame4Input.acct_id, 0, NULL)!=SQL_SUCCESS
		|| SQLBindParameter(m_hstmtFrame4, ++i, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 23, 3, &Frame4Input.trade_dts, 0, NULL)!=SQL_SUCCESS
		 )
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame4);

	//Frame4 output	
	i = 0;
	if (
		   SQLBindCol(m_hstmtFrame4, ++i, SQL_C_IDENT, &Frame4Output.trade_id, 0, NULL) != SQL_SUCCESS		
		|| SQLBindCol(m_hstmtFrame4, ++i, SQL_C_SLONG, &Frame4Output.num_trades_found, 0, NULL) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame4);	
	
	//Set statement descriptor for the second rowset
	if ( SQLSetStmtAttrW( m_hstmtFrame4, SQL_ATTR_APP_ROW_DESC, m_descFrame4Col2, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame4);	

	SQLSetStmtAttr(m_hstmtFrame4, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER)sizeof(Frame4Output.trade_info[0]), 0);	//set row-wise binding
	SQLSetStmtAttr(m_hstmtFrame4, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)(sizeof(Frame4Output.trade_info)/sizeof(Frame4Output.trade_info[0])), SQL_IS_INTEGER);
	SQLSetStmtAttr(m_hstmtFrame4, SQL_ATTR_ROWS_FETCHED_PTR, &Frame4Output.num_found, SQL_IS_POINTER);

	i = 0;
	if (   SQLBindCol(m_hstmtFrame4, ++i, SQL_C_IDENT, &Frame4Output.trade_info[0].holding_history_trade_id, 0, &Frame4Output.trade_info[0].holding_history_trade_id_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame4, ++i, SQL_C_IDENT, &Frame4Output.trade_info[0].holding_history_id, 0, &Frame4Output.trade_info[0].holding_history_id_ind) != SQL_SUCCESS		
		|| SQLBindCol(m_hstmtFrame4, ++i, SQL_C_SLONG, &Frame4Output.trade_info[0].quantity_before, 0, &Frame4Output.trade_info[0].quantity_before_ind) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame4, ++i, SQL_C_SLONG, &Frame4Output.trade_info[0].quantity_after, 0, &Frame4Output.trade_info[0].quantity_after_ind) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame4);

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

	i = 0;
	if (
		   SQLBindCol(m_hstmtFrame4, ++i, SQL_C_SLONG, &Frame4Output.num_found, 0, NULL) != SQL_SUCCESS		
		)
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame4);
}

void CTradeLookupDB::DoTradeLookupFrame1(const TTradeLookupFrame1Input *pFrame1Input, PTradeLookupFrame1Output 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, "DoTradeLookupFrame1");

	rc = SQLExecDirect(m_hstmtFrame1, (SQLCHAR*)"{call TradeLookupFrame1(?, "
																		"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
																		"?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}", SQL_NTS);
	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
		ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeLookupFrame1");
	
	m_BindOffsetFrame1Col1 = 0;
	m_BindOffsetFrame1Col2 = 0;	

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

	while (iColumnCount > 1 && 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, "DoTradeLookupFrame1");

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

		//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, "DoTradeLookupFrame1");

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

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

		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=1)
		//
		if (SQLNumResultCols(m_hstmtFrame1, &iColumnCount) == SQL_ERROR)
			ThrowError(CODBCERR::eNumResultCols, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeLookupFrame1");
	}

	//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, "DoTradeLookupFrame1");

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

	//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, "DoTradeLookupFrame1");

};

void CTradeLookupDB::DoTradeLookupFrame2(const TTradeLookupFrame2Input *pFrame2Input, PTradeLookupFrame2Output pFrame2Output)
{
	int			rc;
	SQLSMALLINT	iColumnCount;	// number of columns in the result set

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

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

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

	m_BindOffsetFrame2Col1 = 0;
	m_BindOffsetFrame2Col2 = 0;	

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

	while (iColumnCount > 1 && 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, "DoTradeLookupFrame2");

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

		//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, "DoTradeLookupFrame2");

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

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

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

		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=1)
		//
		if (SQLNumResultCols(m_hstmtFrame2, &iColumnCount) == SQL_ERROR)
			ThrowError(CODBCERR::eNumResultCols, SQL_HANDLE_STMT, m_hstmtFrame2, "DoTradeLookupFrame2");
	}

	//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, "DoTradeLookupFrame2");

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

	//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, "DoTradeLookupFrame2");
};

void CTradeLookupDB::DoTradeLookupFrame3(const TTradeLookupFrame3Input *pFrame3Input, PTradeLookupFrame3Output pFrame3Output)
{
	int			rc;	
	SQLSMALLINT	iColumnCount;	// number of columns in the result set

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

	rc = SQLExecDirect(m_hstmtFrame3, (SQLCHAR*)"{call TradeLookupFrame3(?, ?, ?, ?, ?)}", SQL_NTS);
	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
		ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeLookupFrame3");	
	
	m_BindOffsetFrame3Col1 = 0;
	m_BindOffsetFrame3Col2 = 0;	

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

	while (iColumnCount > 1 && 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, "DoTradeLookupFrame3");

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

		//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, "DoTradeLookupFrame3");

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

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

		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=1)
		//
		if (SQLNumResultCols(m_hstmtFrame3, &iColumnCount) == SQL_ERROR)
			ThrowError(CODBCERR::eNumResultCols, SQL_HANDLE_STMT, m_hstmtFrame3, "DoTradeLookupFrame3");
	}

	//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, "DoTradeLookupFrame3");

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

	//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, "DoTradeLookupFrame3");
	
};

void CTradeLookupDB::DoTradeLookupFrame4(const TTradeLookupFrame4Input *pFrame4Input, PTradeLookupFrame4Output pFrame4Output)
{
	int rc;

	//copy input parameters into bound locations
	Frame4Input = *pFrame4Input;	

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

	rc = SQLExecDirect(m_hstmtFrame4, (SQLCHAR*)"{call TradeLookupFrame4(?, ?)}", SQL_NTS);
	if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
		ThrowError(CODBCERR::eExecDirect, SQL_HANDLE_STMT, m_hstmtFrame4, "DoTradeLookupFrame4");
	
	if ( SQLFetch(m_hstmtFrame4) == SQL_ERROR)
		ThrowError(CODBCERR::eFetch, SQL_HANDLE_STMT, m_hstmtFrame4, "DoTradeLookupFrame4");

	// Move on to the second result set
	//
	if ( (rc = SQLMoreResults(m_hstmtFrame4)) == SQL_ERROR)
		ThrowError(CODBCERR::eMoreResults, SQL_HANDLE_STMT, m_hstmtFrame4, "DoTradeLookupFrame4");

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

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

	//copy output parameters back
	*pFrame4Output = Frame4Output;	//invoke default assignment operator	

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

void CTradeLookupDB::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);
	}
	SQLCloseCursor(m_hstmtFrame4);
	if (SQLMoreResults(m_hstmtFrame4) != SQL_ERROR)
	{
		SQLCloseCursor(m_hstmtFrame4);
	}
}