| ODBClass.cpp #include<windows.h> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<string.h> #include"SQL.H" #include"sqlext.h" #include"odbclass.h" #ifndefNULL #defineNULL0 #endif //Staticvariablesneedtobedefinedlikethisexactlyonce, //whichiswhytheyaredefinedintheCPPfileratherthan //intheHfilewheretheirclassisdefined. intCODBCDatabase::referenceCount=0; HENVCODBCDatabase::henv=0; CRITICAL_SECTIONCODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char*_dataSourceName,char*_uid, char*_password) { RETCODErc=SQL_SUCCESS; numTables=0; EnterCriticalSection(&CriticalSection); //Allocateenvironment(onlyforfirstinstance). if(referenceCount==0) { SDWORDvalEnv=SQL_OV_ODBC3; RETCODErc2; //Allocateanenvironmenthandle. rc=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE, &henv); //Settheversioninformation.(Withouttheversion //information,youwillgetsequenceerrors.) rc2=SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER); if(rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if(rc==SQL_SUCCESSrc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); //Allocateaconnectionhandle. rc=SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc); if(rc!=SQL_SUCCESS&&rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV,henv); connected=FALSE; } else { strcpy(dataSourceName,_dataSourceName); //DefaultvaluesfortheseareNULL.SomeODBC //drivers(notablyOpenM)failonNULLuserorpassword. if(_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if(_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } //Connecttothedatasource.Thedatasourcemustbeset //upusingtheODBCAdministrator(orthe //32-BitAdministrator)program. rc=SQLConnect(hdbc,(unsignedchar*)dataSourceName, SQL_NTS,(unsignedchar*)uid,SQL_NTS, (unsignedchar*)password,SQL_NTS); lastRetCode=rc; if(rc!=SQL_SUCCESS&&rc!=SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { //ThesethreefunctionsarepairedwithSQLConnect, //SQLAllocConnect,andSQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; //Isthelastinstancebeingdestroyed? if(referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODECODBCDatabase::ExecuteSQL(char*command) { HSTMThstmt; RETCODEret; lastRetCode=SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hstmt); if(lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC,hdbc); } else { if((lastRetCode=SQLExecDirect(hstmt, (unsignedchar*)command,SQL_NTS))!=SQL_SUCCESS&& lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT,hstmt); } ret=SQLFreeHandle(SQL_HANDLE_STMT,hstmt); if(ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT,hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURNCODBCDatabase::GetSQLError(SQLSMALLINTHandleType, SQLHANDLEhandle) { SQLRETURNrc; charszSqlState[256]; charszErrorMsg[256]; SQLSMALLINTbufLen=255; SQLSMALLINTtextLen; SDWORDpfNativeError=255; shortrecNum=1; do{ rc=SQLGetDiagRec(HandleType, handle, recNum++,//Getrecord1,try2,andsoon. (unsignedchar*)szSqlState, &pfNativeError, (unsignedchar*)szErrorMsg, bufLen, &textLen); if(rc==SQL_SUCCESS) { printf("\nSqlState=%sszErrorMsg=%src=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%drc=%d", SQL_INVALID_HANDLE,rc); } }while(rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase*db) { intloop; InitializeCriticalSection(&CriticalSection); if(db==0db->isConnected()==0) { return; } _database=db; //Allocateastatementhandle;thestatementhandleisused //forothertransactions. lastRetCode=SQLAllocStmt(_database->hdbc,&hstmt); if(lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC,_database->hdbc); } for(loop=0;loop<MAX_COLUMNS;loop++) { colInfo[loop]=0; } tableClause[0]=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } '; orderByClause[0]=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } '; whereClause[0]=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } '; m_topN=0; } CODBCCursor::~CODBCCursor() { intloop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for(loop=1;loop<MAX_COLUMNS&&colInfo[loop]!=0;loop++) { deletecolInfo[loop]->name; deletecolInfo[loop]->data; deletecolInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODECODBCCursor::bindColumn(UWORD&col,char*columnName, SDWORDlen,SWORDtype) { SDWORDretLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName,len); colInfo[col]->type=type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt,col,type,colInfo[col]->data, len,&retLen)); } UWORDCODBCCursor::assignColumn(char*columnName,SDWORDlen) { UWORDloop=1; while(colInfo[loop]!=0) { loop++; } colInfo[loop]=newstructCOLUMN_INFO; numCols=loop; if(colInfo[loop]!=0) { //Allocatethespaceforthenameandthedataelement. colInfo[loop]->name=newchar[(strlen(columnName))+1]; colInfo[loop]->data=newchar[len+1]; colInfo[loop]->len=len; if(colInfo[loop]->name==0colInfo[loop]->data==0) { deletecolInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name,columnName); } return(loop); } intCODBCCursor::doSelect() { charselect[1280]; UWORDloop; UWORDcol=1; UWORDrc; memset(select,' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } ',1024); if(tableClause[0]!=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } ') { //ConstructaSELECTstatement. if(getNumCol()) { if(m_topN>0) { sprintf(select,"SELECTTOP%d",m_topN); } else { strcpy(select,"SELECT"); } for(loop=1;colInfo[loop]!=0;loop++) { if(loop>1) { strcat(select,","); } else { strcat(select,""); } strcat(select,colInfo[loop]->name); } strcat(select,"FROM"); strcat(select,tableClause); if(whereClause[0]!=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } ') { strcat(select,""); strcat(select,whereClause); } if(orderByClause[0]!=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } ') { strcat(select,"ORDERBY"); strcat(select,orderByClause); } if((lastRetCode=SQLExecDirect(hstmt, (unsignedchar*)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT,hstmt); } return(lastRetCode); } } return(SQL_ERROR); } intCODBCCursor::doDelete() { chardel[1280]; memset(del,' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } ',1024); if(tableClause[0]!=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } ') { //ConstructaDELETEstatement. if(getNumCol()) { strcpy(del,"DELETE*"); strcat(del,"FROM"); strcat(del,tableClause); if(whereClause[0]!=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } ') { strcat(del,""); strcat(del,whereClause); } if((lastRetCode=SQLExecDirect(hstmt, (unsignedchar*)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT,hstmt); } return(lastRetCode); } } return(SQL_ERROR); } intCODBCCursor::doUpdate() { charupdate[1280]; memset(update,' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } ',1024); if(tableClause[0]!=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } 'setClause[0]!=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } ') { //ConstructanUPDATEstatement. if(getNumCol()) { strcpy(update,"UPDATE"); strcat(update,tableClause); strcat(update,"SET"); strcat(update,setClause); if(whereClause[0]!=' #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include "SQL.H" #include "sqlext.h" #include "odbclass.h" #ifndef NULL #define NULL 0 #endif // Static variables need to be defined like this exactly once, // which is why they are defined in the CPP file rather than // in the H file where their class is defined. int CODBCDatabase::referenceCount=0; HENV CODBCDatabase::henv=0; CRITICAL_SECTION CODBCDatabase::CriticalSection; CODBCDatabase::CODBCDatabase(char *_dataSourceName,char *_uid, char *_password) { RETCODE rc = SQL_SUCCESS; numTables = 0; EnterCriticalSection(&CriticalSection); // Allocate environment (only for first instance). if (referenceCount==0) { SDWORD valEnv=SQL_OV_ODBC3; RETCODE rc2; // Allocate an environment handle. rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the version information. (Without the version // information, you will get sequence errors.) rc2 = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (rc2!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_ENV,henv); } } if (rc==SQL_SUCCESS rc==SQL_SUCCESS_WITH_INFO) { referenceCount++; } LeaveCriticalSection(&CriticalSection); // Allocate a connection handle. rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_ENV, henv); connected=FALSE; } else { strcpy(dataSourceName, _dataSourceName); // Default values for these are NULL. Some ODBC // drivers (notably OpenM) fail on NULL user or password. if (_uid!=NULL) { strcpy(uid,_uid); } else { strcpy(uid,""); } if (_password!=NULL) { strcpy(password,_password); } else { strcpy(password,""); } // Connect to the data source. The data source must be set // up using the ODBC Administrator (or the // 32-Bit Administrator) program. rc = SQLConnect(hdbc, (unsigned char *)dataSourceName, SQL_NTS, (unsigned char *)uid, SQL_NTS, (unsigned char *)password, SQL_NTS); lastRetCode = rc; if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { connected=FALSE; this->GetSQLError(SQL_HANDLE_DBC,hdbc); } else { connected=TRUE; } } } CODBCDatabase::~CODBCDatabase() { // These three functions are paired with SQLConnect, // SQLAllocConnect, and SQLAllocEnv. SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC,hdbc); EnterCriticalSection(&CriticalSection); referenceCount--; // Is the last instance being destroyed? if (referenceCount==0) { SQLFreeHandle(SQL_HANDLE_ENV,henv); } LeaveCriticalSection(&CriticalSection); } RETCODE CODBCDatabase::ExecuteSQL(char *command) { HSTMT hstmt; RETCODE ret; lastRetCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, hdbc); } else { if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)command, SQL_NTS))!=SQL_SUCCESS && lastRetCode!=SQL_SUCCESS_WITH_INFO) { GetSQLError(SQL_HANDLE_STMT, hstmt); } ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if (ret!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } return(SQL_ERROR); } SQLRETURN CODBCDatabase::GetSQLError(SQLSMALLINT HandleType, SQLHANDLE handle) { SQLRETURN rc; char szSqlState[256]; char szErrorMsg[256]; SQLSMALLINT bufLen = 255; SQLSMALLINT textLen; SDWORD pfNativeError = 255; short recNum = 1; do{ rc = SQLGetDiagRec(HandleType, handle, recNum++, // Get record 1, try 2, and so on. (unsigned char *)szSqlState, &pfNativeError, (unsigned char *)szErrorMsg, bufLen, &textLen); if (rc==SQL_SUCCESS) { printf("\nSqlState=%s szErrorMsg=%s rc=%d", szSqlState,szErrorMsg,rc); printf("\nSQL_INVALID_HANDLE=%d rc=%d ", SQL_INVALID_HANDLE, rc); } } while (rc==SQL_SUCCESS); return(rc); } CODBCCursor::CODBCCursor(CODBCDatabase *db) { int loop; InitializeCriticalSection(&CriticalSection); if (db==0 db->isConnected()==0) { return; } _database=db; // Allocate a statement handle; the statement handle is used // for other transactions. lastRetCode=SQLAllocStmt(_database->hdbc, &hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_DBC, _database->hdbc); } for (loop=0 ; loop<MAX_COLUMNS ; loop++) { colInfo[loop] = 0; } tableClause[0] = '\0'; orderByClause[0] = '\0'; whereClause[0] = '\0'; m_topN=0; } CODBCCursor::~CODBCCursor() { int loop; SQLFreeHandle(SQL_HANDLE_STMT,hstmt); for (loop=1 ; loop<MAX_COLUMNS && colInfo[loop]!=0 ; loop++) { delete colInfo[loop]->name; delete colInfo[loop]->data; delete colInfo[loop]; } DeleteCriticalSection(&CriticalSection); } RETCODE CODBCCursor::bindColumn(UWORD& col, char *columnName, SDWORD len, SWORD type) { SDWORD retLen; EnterCriticalSection(&CriticalSection); col=assignColumn(columnName, len); colInfo[col]->type = type; LeaveCriticalSection(&CriticalSection); return(SQLBindCol(hstmt, col, type, colInfo[col]->data, len, &retLen)); } UWORD CODBCCursor::assignColumn(char *columnName, SDWORD len) { UWORD loop = 1; while (colInfo[loop]!=0) { loop++; } colInfo[loop] = new struct COLUMN_INFO; numCols = loop; if (colInfo[loop]!=0) { // Allocate the space for the name and the data element. colInfo[loop]->name = new char[(strlen(columnName))+1]; colInfo[loop]->data = new char[len+1]; colInfo[loop]->len = len; if (colInfo[loop]->name==0 colInfo[loop]->data==0) { delete colInfo[loop]; colInfo[loop]=0; } strcpy(colInfo[loop]->name, columnName); } return(loop); } int CODBCCursor::doSelect() { char select[1280]; UWORD loop; UWORD col = 1; UWORD rc; memset(select, '\0', 1024); if (tableClause[0]!='\0') { // Construct a SELECT statement. if (getNumCol()) { if (m_topN>0) { sprintf(select, "SELECT TOP %d ", m_topN); } else { strcpy(select, "SELECT "); } for (loop=1 ; colInfo[loop]!=0 ; loop++) { if (loop>1) { strcat(select, ", "); } else { strcat(select, " "); } strcat(select,colInfo[loop]->name); } strcat(select, " FROM "); strcat(select, tableClause); if (whereClause[0]!='\0') { strcat(select, " "); strcat(select, whereClause); } if (orderByClause[0]!='\0') { strcat(select, " ORDER BY "); strcat(select, orderByClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)select,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doDelete() { char del[1280]; memset(del, '\0', 1024); if (tableClause[0]!='\0') { // Construct a DELETE statement. if (getNumCol()) { strcpy(del, "DELETE * "); strcat(del, " FROM "); strcat(del, tableClause); if (whereClause[0]!='\0') { strcat(del, " "); strcat(del, whereClause); } if ((lastRetCode = SQLExecDirect(hstmt, (unsigned char *)del,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } int CODBCCursor::doUpdate() { char update[1280]; memset(update, '\0', 1024); if (tableClause[0]!='\0' setClause[0]!='\0') { // Construct an UPDATE statement. if (getNumCol()) { strcpy(update, "UPDATE "); strcat(update, tableClause); strcat(update, " SET "); strcat(update, setClause); if (whereClause[0]!='\0') { strcat(update, " "); strcat(update, whereClause); } if ((lastRetCode=SQLExecDirect(hstmt, (unsigned char *)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODE CODBCCursor::fetch() { int col; // This function retrieves the data. The function returns a // single row at a time and moves the cursor one row forward. for (col=1 ; colInfo[col]!=0 ; col++) { memset (colInfo[col]->data, 0, colInfo[col]->len); } lastRetCode = SQLFetch(hstmt); if (lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT, hstmt); } return(lastRetCode); } ') { strcat(update,""); strcat(update,whereClause); } if((lastRetCode=SQLExecDirect(hstmt, (unsignedchar*)update,SQL_NTS))!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT,hstmt); } return(lastRetCode); } } return(SQL_ERROR); } RETCODECODBCCursor::fetch() { intcol; //Thisfunctionretrievesthedata.Thefunctionreturnsa //singlerowatatimeandmovesthecursoronerowforward. for(col=1;colInfo[col]!=0;col++) { memset(colInfo[col]->data,0,colInfo[col]->len); } lastRetCode=SQLFetch(hstmt); if(lastRetCode!=SQL_SUCCESS) { GetSQLError(SQL_HANDLE_STMT,hstmt); } return(lastRetCode); } |