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

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

#include "stdafx.h"

using namespace TPCE;

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

	//Allocate one handle per stored procedure (frame)
	if (   SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmtFrame1) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame1Col1) != SQL_SUCCESS
		|| SQLAllocHandle(SQL_HANDLE_DESC, m_hdbc, &m_descFrame1Col2) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eAllocHandle, SQL_HANDLE_STMT, m_hdbc);	

	//Bind input/output parameters for each stored procedure

	//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);

	//Frame1 input
	i = 0;
	if (   SQLBindParameter(m_hstmtFrame1, ++i, SQL_PARAM_INPUT, SQL_C_IDENT, SQL_IDENT, 0, 0, &Frame1Input.acct_id, 0, NULL)!=SQL_SUCCESS
		 )
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame1);

	//Frame1 output	

	i = 0;
	if (   SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.broker_name[0], sizeof(Frame1Output.broker_name), &Frame1Ind.broker_name) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.cust_f_name[0], sizeof(Frame1Output.cust_f_name), &Frame1Ind.cust_f_name) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.cust_l_name[0], sizeof(Frame1Output.cust_l_name), &Frame1Ind.cust_l_name) != 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);

	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.charge)/sizeof(Frame1Output.charge[0])), SQL_IS_INTEGER);
	SQLSetStmtAttr(m_hstmtFrame1, SQL_ATTR_ROWS_FETCHED_PTR, &m_len, SQL_IS_POINTER);
	
	i = 0;
	if (   SQLBindCol(m_hstmtFrame1, ++i, SQL_C_DOUBLE, &Frame1Output.charge[0], 0, &Frame1Ind.charge[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.exec_name[0][0], sizeof(Frame1Output.exec_name[0]), &Frame1Ind.exec_name[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.ex_name[0][0], sizeof(Frame1Output.ex_name[0]), &Frame1Ind.ex_name[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.s_name[0][0], sizeof(Frame1Output.s_name[0]), &Frame1Ind.s_name[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.status_name[0][0], sizeof(Frame1Output.status_name[0]), &Frame1Ind.status_name[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.symbol[0][0], sizeof(Frame1Output.symbol[0]), &Frame1Ind.symbol[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_TIMESTAMP, &Frame1Output.trade_dts[0], 0, &Frame1Ind.trade_dts[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_IDENT, &Frame1Output.trade_id[0], 0, &Frame1Ind.trade_id[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &Frame1Output.trade_qty[0], 0, &Frame1Ind.trade_qty[0]) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.type_name[0][0], sizeof(Frame1Output.type_name[0]), &Frame1Ind.type_name[0]) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame1);
};

CTradeStatusDB::~CTradeStatusDB()
{
	SQLFreeHandle(SQL_HANDLE_STMT, m_hstmtFrame1);
}

void CTradeStatusDB::DoTradeStatusFrame1(const TTradeStatusFrame1Input *pFrame1Input, PTradeStatusFrame1Output pFrame1Output)
{
	int rc;

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

	// copy input parameters into bound locations
	Frame1Input.acct_id = pFrame1Input->acct_id;

	//	Configure block cursor to avoid sp_cursoropen
	//
	if ( SQLSetStmtAttrW(m_hstmtFrame1, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)1, 0) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeStatusFrame1");

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

	//	Configure block cursor back to receive all the rows
	//
	if ( SQLSetStmtAttrW(m_hstmtFrame1, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)max_trade_status_len, 0) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeStatusFrame1");

	// fetch first result set
	if ( SQLFetch(m_hstmtFrame1) == SQL_ERROR)
		ThrowError(CODBCERR::eFetch, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeStatusFrame1");

	// move on to the second result set
	if ( SQLMoreResults(m_hstmtFrame1) == SQL_ERROR)
		ThrowError(CODBCERR::eMoreResults, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeStatusFrame1");

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

	m_len = 0;	// in case there are no rows and SQLFetch doesn't initialize m_len

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

	// copy output parameters back
	*pFrame1Output = Frame1Output;	//invoke default assignment operator
	pFrame1Output->num_found = m_len;

	if ( (rc = SQLCloseCursor(m_hstmtFrame1)) == SQL_ERROR)
		ThrowError(CODBCERR::eCloseCursor, SQL_HANDLE_STMT, m_hstmtFrame1, "DoTradeStatusFrame1");
};

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