#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
#define LEAK_NUMERIC 1 //Use this to determine NUMERIC or BINARY leak
void HandleError(SQLHANDLE hHandle, SQLSMALLINT hType, RETCODE RetCode)
{
SQLSMALLINT iRec = 0;
SQLINTEGER iError;
TCHAR szMessage[1000];
TCHAR szState[SQL_SQLSTATE_SIZE];
if (RetCode == SQL_INVALID_HANDLE)
{
fprintf(stderr,"Invalid handle!\n");
return;
}
while (SQLGetDiagRec(hType,
hHandle,
++iRec,
(SQLCHAR *)szState,
&iError,
(SQLCHAR *)szMessage,
(SQLSMALLINT)(sizeof(szMessage) / sizeof(TCHAR)),
(SQLSMALLINT *)NULL) == SQL_SUCCESS)
{
fprintf(stderr,TEXT("[%5.5s] %s (%d)\n"),szState,szMessage,iError);
}
}
char* szConnStringIn = "Driver={Microsoft Access Driver (*.mdb)};DBQ=E:\\JetLeak\\TestDatabase.mdb";
char* szDropTable = "DROP TABLE LeakTable";
//char* szInsertStatement = "INSERT INTO LeakTable VALUES (?)";
char* szSelectStatement = "SELECT * FROM LeakTable WHERE val1 = ?";
const int nParamCount = 1;
#if LEAK_NUMERIC
char* szCreateTable = "CREATE TABLE LeakTable (val1 long)";
#else
char* szCreateTable = "CREATE TABLE LeakTable (val1 varchar(10))";
#endif
void main(int argc, char* argv[])
{
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
SQLRETURN nstatus;
char szConnStringOut[1024];
SQLSMALLINT cbConnOut;
SQLINTEGER status[nParamCount];
#if LEAK_NUMERIC
SQLCHAR szParam[nParamCount][10] = {"12345"};
#else
BYTE szParam[nParamCount][10] = {0x31,0x33,0x34,0x39};
#endif
//Not checking the return codes in some cases for clarity.
nstatus = SQLAllocHandle(SQL_HANDLE_ENV,NULL,&henv);
nstatus = SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER) SQL_OV_ODBC3,0);
nstatus = SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
nstatus = SQLDriverConnect(hdbc,
NULL,
(SQLCHAR*) szConnStringIn,
SQL_NTS,
(SQLCHAR*) szConnStringOut,
sizeof (szConnStringOut),
&cbConnOut,
SQL_DRIVER_COMPLETE);
if (nstatus != SQL_SUCCESS && nstatus != SQL_SUCCESS_WITH_INFO)
{
HandleError(hdbc,SQL_HANDLE_DBC,nstatus);
return;
}
nstatus = SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hstmt);
nstatus = SQLExecDirect(hstmt, (SQLCHAR*) szDropTable, SQL_NTS);
nstatus = SQLExecDirect(hstmt, (SQLCHAR*) szCreateTable, SQL_NTS);
if (!SQL_SUCCEEDED(nstatus))
{
HandleError(hstmt,SQL_HANDLE_STMT,nstatus);
}
int i;
//only one parameter in this case
for (i=0; i < nParamCount; i++)
{
status[i] = SQL_NTS;
#if LEAK_NUMERIC
nstatus = SQLBindParameter(hstmt,
i+1,
SQL_PARAM_INPUT,
SQL_C_CHAR,
SQL_NUMERIC,
10,
0,
szParam[i],
10,
&status[i]);
#else
nstatus = SQLBindParameter(hstmt,
i+1,
SQL_PARAM_INPUT,
SQL_C_BINARY,
SQL_WCHAR,
10,
0,
szParam[i],
10,
&status[i]);
#endif
}
nstatus = SQLPrepare(hstmt,(SQLCHAR*) szSelectStatement, SQL_NTS);
if (nstatus != SQL_SUCCESS)
{
HandleError(hstmt,SQL_HANDLE_STMT,nstatus);
}
for (i=0; i < 100000; i++)
{
if (i % 100 == 0)
{
printf("Selected %d times\n", i);
//printf("Inserted %d records\n", i);
Sleep(100);
}
nstatus = SQLExecute(hstmt);
if (nstatus != SQL_SUCCESS)
{
HandleError(hstmt,SQL_HANDLE_STMT,nstatus);
}
SQLFreeStmt(hstmt, SQL_CLOSE);
}
nstatus = SQLExecDirect(hstmt, (SQLCHAR*) "DELETE FROM LeakTable", SQL_NTS);
if (nstatus != SQL_SUCCESS)
{
HandleError(hstmt,SQL_HANDLE_STMT,nstatus);
}
SQLFreeStmt(hstmt, SQL_CLOSE);
SQLDisconnect(hdbc);
}