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

/*
*	Broker Volume database class that uses stored procedures for individual frames.
*/

#include "stdafx.h"

using namespace TPCE;

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

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

	//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 input/output parameters for each stored procedure

	// Frame1 input
	
	// Bind broker names.
	for (i = 1; i <= sizeof(Frame1Input.broker_list)/sizeof(Frame1Input.broker_list[0]); ++i)
	{
		if (SQLBindParameter(m_hstmtFrame1, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, cB_NAME_len, 0, &Frame1Input.broker_list[i-1], cB_NAME_len+1, NULL)!=SQL_SUCCESS)
			ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame1);
	}
	// Bind the rest of input parameters.
	if (  SQLBindParameter(m_hstmtFrame1, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, cSC_NAME_len, 0, &Frame1Input.sector_name, cSC_NAME_len, NULL)!=SQL_SUCCESS
		 )
		ThrowError(CODBCERR::eBindParam, SQL_HANDLE_STMT, m_hstmtFrame1);
	
	//Frame1 output	
	SQLSetStmtAttr(m_hstmtFrame1, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);
	SQLSetStmtAttr(m_hstmtFrame1, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)(sizeof(Frame1Output.broker_name)/sizeof(Frame1Output.broker_name[0])), SQL_IS_INTEGER);
	//SQLSetStmtAttr(m_hstmtFrame1, SQL_ATTR_ROW_STATUS_PTR, StatusArray, 0);
	SQLSetStmtAttr(m_hstmtFrame1, SQL_ATTR_ROWS_FETCHED_PTR, &Frame1Output.list_len, SQL_IS_POINTER);
	
	i = 0;
	if (   SQLBindCol(m_hstmtFrame1, ++i, SQL_C_CHAR, &Frame1Output.broker_name[0], sizeof(Frame1Output.broker_name[0]), NULL) != SQL_SUCCESS
		|| SQLBindCol(m_hstmtFrame1, ++i, SQL_C_DOUBLE, &Frame1Output.volume[0], 0, NULL) != SQL_SUCCESS
		)
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame1);
	
	//Set statement descriptor for the parameters and the second (dummy) 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);
	i = 0;
	if (   SQLBindCol(m_hstmtFrame1, ++i, SQL_C_SLONG, &m_lDummySet2, 0, NULL) != SQL_SUCCESS		
		)
		ThrowError(CODBCERR::eBindCol, SQL_HANDLE_STMT, m_hstmtFrame1);
	
	//Set statement descriptor for the parameters and the first rowset as it is the only one that is used
	if ( SQLSetStmtAttrW( m_hstmtFrame1, SQL_ATTR_APP_ROW_DESC, m_descFrame1Col1, SQL_IS_POINTER ) != SQL_SUCCESS )
		ThrowError(CODBCERR::eSetStmtAttr, SQL_HANDLE_STMT, m_hstmtFrame1);
};

void CBrokerVolumeDB::DoBrokerVolumeFrame1(const TBrokerVolumeFrame1Input *pFrame1Input, PBrokerVolumeFrame1Output pFrame1Output)
{
	int rc;

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

	// Initialize to 1 to prevent executing with sp_cursoropen
	//
	SQLSetStmtAttr(m_hstmtFrame1, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)1, SQL_IS_INTEGER);

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

	//initialize list_len to 0 as there can be no rows returned and then
	//the list_len will not be initialized by SQLFetch()
	Frame1Output.list_len = 0;

	SQLSetStmtAttr(m_hstmtFrame1, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)(sizeof(Frame1Output.broker_name)/sizeof(Frame1Output.broker_name[0])), SQL_IS_INTEGER);

	if ( SQLFetch(m_hstmtFrame1) == SQL_ERROR)
		ThrowError(CODBCERR::eFetch, SQL_HANDLE_STMT, m_hstmtFrame1, "DoBrokerVolumeFrame1");
	
	// copy output parameters back
	//
	if (Frame1Output.list_len > 0)	// copy only if there is something to copy
	{
		*pFrame1Output = Frame1Output;	//invoke default assignment operator
	}

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

    // 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 CBrokerVolumeDB::Cleanup(void* pException)
{
	SQLCloseCursor(m_hstmtFrame1);
}