/* CC -I${ODBC_HOME}/include -L${ODBC_HOME}/lib -lodbc \ -g -o myOdbcBug myOdbcBug.cc */ #include #include #include #include #include void CheckRC(SQLRETURN rc, char* msg, char* filename, int lineno); #define CHECKRC(FUNCSHN,MSG) CheckRC(FUNCSHN, MSG, __FILE__, __LINE__) SQLHENV hEnv = SQL_NULL_HENV; SQLHDBC hDbc = SQL_NULL_HDBC; SQLHSTMT hStmt = SQL_NULL_HSTMT; SQLCHAR* connString; SQLCHAR connOut[255]; /* buffer for connection output */ SQLSMALLINT szConnOut; /* num bytes returned in connOut */ short numResultCol; //---- main() ------------------- int main(int argc, char** argv) { if (argc < 2 || strlen(argv[1]) == 0) { fprintf(stderr,"ERROR: ODBC connect string not specified!\n"); return 1; } connString = (SQLCHAR *)argv[1]; //---- SETUP ------------------------------------------- if (SQLAllocEnv(&hEnv) != SQL_SUCCESS) { fprintf(stderr, "Unable to allocate SQLHENV\n"); return(1); } CHECKRC( SQLAllocConnect(hEnv, &hDbc), "SQLAllocConnect()" ); CHECKRC( SQLDriverConnect(hDbc, NULL, connString, SQL_NTS, connOut, 255, &szConnOut, SQL_DRIVER_NOPROMPT), "SQLDriverConnect()" ); //---- STATEMENTS -------------------------------------- CHECKRC( SQLAllocStmt(hDbc, &hStmt), "SQLAllocStmt()" ); SQLCHAR* sqlStmt = (SQLCHAR*) "INSERT INTO ThreeCol VALUES (?, ?, ?)"; CHECKRC( SQLPrepare(hStmt, sqlStmt, SQL_NTS), "SQLPrepare()" ); CHECKRC( SQLNumResultCols(hStmt,&numResultCol), "SQLNumResultCols()"); /**** * At this point, even though we have not actually bound any params nor * have we even run SQLExecute(), you will see a "blank" row in the * database! *****/ //---- TEAR DOWN ------------------------------------------- CHECKRC( SQLFreeStmt(hStmt, SQL_DROP), "SQLFreeStmt()" ); CHECKRC( SQLDisconnect(hDbc), "SQLDisconnect()" ); CHECKRC( SQLFreeConnect(hDbc), "SQLFreeConnect()" ); CHECKRC( SQLFreeEnv(hEnv), "SQLFreeEnv()" ); return 0; } //---- Helper function ------------- void CheckRC(SQLRETURN rc, char* msg, char* filename, int lineno) { #define MSG_LNG 512 SQLCHAR szSqlState[MSG_LNG]; SQLINTEGER pfNativeError; SQLCHAR szErrorMsg[MSG_LNG]; SQLSMALLINT pcbErrorMsg; SQLRETURN ret = SQL_SUCCESS; bool error = false; if (rc != SQL_SUCCESS && rc != SQL_NO_DATA_FOUND) { if (rc != SQL_SUCCESS_WITH_INFO) { // An error, not a warning fprintf(stderr, "\nERROR (%s:%d): %s\n", filename, lineno, msg); error = true; } // Find the reason for the err/warning while (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) { ret = SQLError(hEnv, hDbc, hStmt, szSqlState, &pfNativeError, szErrorMsg, MSG_LNG, &pcbErrorMsg); switch (ret) { case SQL_SUCCESS: // This means SQLError() returned normally if (rc == SQL_SUCCESS_WITH_INFO) { fprintf(stderr, "\nINFO: (%s:%d): %s\n", filename, lineno, msg); } fprintf(stderr, "*** %s\n*** ODBC Code: %s, " "Driver Code: %ld\n\n", szErrorMsg, szSqlState, pfNativeError); break; case SQL_NO_DATA_FOUND: // from SQLError() break; default: fprintf(stderr, "*** SQLError() failed with code=%d\n\n", ret); break; } } } if (error) exit(1); }