void OdbcConnection::Close()
{
	// Disconnect from server.
	SQLDisconnect(m_connHandle);

	// Reset handles
	ResetHandles();
}
bool OdbcConnection::Connect()
{
	if (m_szDSN.length() == 0)
		return false;

	tstring szConn = _T("DSN=") + m_szDSN + _T(";");
	// Reconnect if we need to.
	if (isConnected())
		Disconnect();

	// Allocate enviroment handle
	if (!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_envHandle)))
	{
		ReportSQLError(SQL_HANDLE_ENV, m_envHandle, _T("SQLAllocHandle"), _T("Unable to allocate environment handle."));
		goto error_handler;
	}

	// Request ODBC3 support
	if (!SQL_SUCCEEDED(SQLSetEnvAttr(m_envHandle, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0)))
	{
		ReportSQLError(SQL_HANDLE_ENV, m_envHandle, _T("SQLSetEnvAttr"), _T("Unable to set environment attribute (SQL_ATTR_ODBC_VERSION)."));
		goto error_handler;
	}

	// Allocate the connection handle
	if (!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_DBC, m_envHandle, &m_connHandle)))
	{
		ReportSQLError(SQL_HANDLE_ENV, m_envHandle, _T("SQLAllocHandle"), _T("Unable to allocate connection handle."));
		goto error_handler;
	}

	if (m_szUser.length())
	{
		szConn += _T("UID=") + m_szUser + _T(";");
		if (m_szPass.length())
			szConn += _T("PWD=") + m_szPass + _T(";");
	}

	// Enable multiple active result sets
	if (m_bMarsEnabled)
		szConn += _T("MARS_Connection=yes;");

	if (!SQL_SUCCEEDED(SQLDriverConnect(m_connHandle, NULL, (SQLTCHAR *)szConn.c_str(), SQL_NTS, NULL, NULL, NULL, NULL)))
	{
		ReportSQLError(SQL_HANDLE_DBC, m_connHandle, _T("SQLDriverConnect"), _T("Unable to establish connection."));
		goto error_handler;
	}

	for (auto itr = m_commandSet.begin(); itr != m_commandSet.end(); itr++)
		(*itr)->SetConnectionHandle(m_connHandle);

	return true;

error_handler:
	ResetHandles();
	return false;
}
bool OdbcConnection::Connect()
{
	if (m_szDSN.empty())
		return false;

	FastGuard lock(m_lock);

	tstring szConn = _T("DSN=") + m_szDSN + _T(";");
	// Reconnect if we need to.
	if (isConnected())
		Disconnect();

	// Allocate enviroment handle
	if (!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_envHandle)))
	{
		ReportSQLError(SQL_HANDLE_ENV, m_envHandle, _T("SQLAllocHandle"), _T("Unable to allocate environment handle."));
		goto error_handler;
	}

	// Request ODBC3 support
	if (!SQL_SUCCEEDED(SQLSetEnvAttr(m_envHandle, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0)))
	{
		ReportSQLError(SQL_HANDLE_ENV, m_envHandle, _T("SQLSetEnvAttr"), _T("Unable to set environment attribute (SQL_ATTR_ODBC_VERSION)."));
		goto error_handler;
	}

	// Allocate the connection handle
	if (!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_DBC, m_envHandle, &m_connHandle)))
	{
		ReportSQLError(SQL_HANDLE_ENV, m_envHandle, _T("SQLAllocHandle"), _T("Unable to allocate connection handle."));
		goto error_handler;
	}

	if (m_szUser.length())
	{
		szConn += _T("UID=") + m_szUser + _T(";");
		if (m_szPass.length())
			szConn += _T("PWD=") + m_szPass + _T(";");
	}

	// Enable multiple active result sets
	if (m_bMarsEnabled)
	{
		if (!SQL_SUCCEEDED(SQLSetConnectAttr(m_connHandle, SQL_COPT_SS_MARS_ENABLED, SQL_MARS_ENABLED_YES, SQL_IS_UINTEGER)))
		{
			printf("** WARNING **\n\n");
			printf("Attempted to used MARS (Multiple Active Result Sets), but this\n");
			printf("feature is not supported by your ODBC driver or SQL Server version.\n\n");
			printf("To benefit from MARS, you need to be using at least SQL Server 2005, and at\n");
			printf("least the 'SQL Native Client' ODBC driver (as opposed to the vastly outdated\n'SQL Server' driver).\n\n");
			printf("Continuing to connect without MARS.\n\n");
			m_bMarsEnabled = false;
		}

		// NOTE: We can enable MARS via specifying the following, but we are unable to detect if it's supported this way.
		// szConn += _T("MARS_Connection=yes;");
	}

	if (!SQL_SUCCEEDED(SQLDriverConnect(m_connHandle, SQL_NULL_HANDLE, (SQLTCHAR *)szConn.c_str(), SQL_NTS, 0, 0, 0, 0)))
	{
		ReportSQLError(SQL_HANDLE_DBC, m_connHandle, _T("SQLDriverConnect"), _T("Unable to establish connection."));
		goto error_handler;
	}

	for (auto itr = m_commandSet.begin(); itr != m_commandSet.end(); itr++)
		(*itr)->SetConnectionHandle(m_connHandle);

	return true;

error_handler:
	ResetHandles();
	return false;
}