/* BUG 3028 ========================================== PURPOSE: To demonstrate problem at C-API level. DESCRIPTION: I have created this to demonstrate problem stated in BUG 3028. You must change connect params for this to work in your environment. ENVIRONMENT: - MyODBC 3.51 (from BK) - MySQL client 4.0.17 - MySQL server 4.0.17 - unixODBC 2.2.8 - Linux SuSE 9.0 AUTHOR: Peter Harvey peterh@mysql.com CREATED: Sun Mar 7 20:40:14 PST 2004 */ #include #include #include #include #include /* #define TEST_AS_STRUCT */ /* max message len for ODBC error messages */ #define MAX_MSG 1024 /* max buf len for regular data types */ #define MAX_CHAR 255 /* max connect string len */ #define MAX_CON 500 /* this space saving macro can be used to evaluate ret value */ #define MYSQLSUCCESS(rc) ((rc==SQL_SUCCESS)||(rc==SQL_SUCCESS_WITH_INFO)) SQLRETURN do_SQLError( SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt) { SQLRETURN rc; SQLCHAR state[MAX_MSG]; SQLINTEGER error_num; SQLCHAR error_str[MAX_MSG]; SQLSMALLINT error_len = 0; rc = SQLError(env, dbc, stmt, state, &error_num, error_str, MAX_MSG, &error_len); if (error_len) printf("state = %s error_num = %d error_str = %s\n", state, error_num, error_str); switch (rc) { case SQL_SUCCESS: break; case SQL_ERROR: printf("SQLError = %d = SQL_ERROR\n", rc); break; default: printf("SQLError = %d = unknown return value\n", rc); } return rc; } SQLRETURN do_SQLAllocEnv(SQLHENV *env) { SQLRETURN rc; rc = SQLAllocEnv(env); switch (rc) { case SQL_SUCCESS_WITH_INFO: printf("SQLAllocEnv = %d = SQL_SUCCESS_WITH_INFO\n", rc); do_SQLError(env, NULL, NULL); case SQL_SUCCESS: break; case SQL_ERROR: printf("SQLAllocEnv = %d = SQL_ERROR\n", rc); do_SQLError(env, NULL, NULL); break; default: printf("SQLAllocEnv = %d = unknown return value\n", rc); } return rc; } SQLRETURN do_SQLFreeEnv(SQLHENV env) { SQLRETURN rc; rc = SQLFreeEnv(env); switch (rc) { case SQL_SUCCESS_WITH_INFO: printf("SQLFreeEnv = %d = SQL_SUCCESS_WITH_INFO\n", rc); do_SQLError(env, NULL, NULL); case SQL_SUCCESS: break; case SQL_ERROR: printf("SQLFreeEnv = %d = SQL_ERROR\n", rc); do_SQLError(env, NULL, NULL); break; default: printf("SQLFreeEnv = %d = unknown return value\n", rc); } return rc; } SQLRETURN do_SQLAllocConnect(SQLHENV env, SQLHDBC *dbc) { SQLRETURN rc; rc = SQLAllocConnect(env, dbc); switch (rc) { case SQL_SUCCESS_WITH_INFO: printf("SQLAllocConnect = %d = SQL_SUCCESS_WITH_INFO\n", rc); do_SQLError(env, dbc, NULL); case SQL_SUCCESS: break; case SQL_ERROR: printf("SQLAllocConnect = %d = SQL_ERROR\n", rc); do_SQLError(env, dbc, NULL); break; default: printf("SQLAllocConnect = %d = unknown return value\n", rc); } return rc; } SQLRETURN do_SQLFreeConnect(SQLHDBC dbc) { SQLRETURN rc; rc = SQLFreeConnect(dbc); switch (rc) { case SQL_SUCCESS_WITH_INFO: printf("SQLFreeConnect = %d = SQL_SUCCESS_WITH_INFO\n", rc); do_SQLError(NULL, dbc, NULL); case SQL_SUCCESS: break; case SQL_ERROR: printf("SQLFreeConnect = %d = SQL_ERROR\n", rc); do_SQLError(NULL, dbc, NULL); break; default: printf("SQLFreeConnect = %d = unknown return value\n", rc); } return rc; } SQLRETURN do_SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt) { SQLRETURN rc; rc = SQLAllocStmt(dbc, stmt); switch (rc) { case SQL_SUCCESS_WITH_INFO: printf("SQLAllocStmt = %d = SQL_SUCCESS_WITH_INFO\n", rc); do_SQLError(NULL, dbc, NULL); case SQL_SUCCESS: break; case SQL_ERROR: printf("SQLAllocStmt = %d = SQL_ERROR\n", rc); do_SQLError(NULL, dbc, NULL); break; default: printf("SQLAllocStmt = %d = unknown return value\n", rc); } return rc; } SQLRETURN do_SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT option) { SQLRETURN rc; rc = SQLFreeStmt(stmt, option); switch (rc) { case SQL_SUCCESS_WITH_INFO: printf("SQLFreeStmt = %d = SQL_SUCCESS_WITH_INFO\n", rc); do_SQLError(NULL, NULL, stmt); case SQL_SUCCESS: break; case SQL_INVALID_HANDLE: printf("SQLFreeStmt = %d = SQL_INVALID_HANDLE\n", rc); break; case SQL_ERROR: printf("SQLFreeStmt = %d = SQL_ERROR\n", rc); do_SQLError(NULL, NULL, stmt); break; default: printf("SQLFreeStmt = %d = unknown return value\n", rc); } return rc; } SQLRETURN do_SQLDriverConnect(SQLHDBC dbc) { SQLRETURN rc; SQLCHAR connect_string_in[MAX_CON]; SQLCHAR connect_string_out[MAX_CON]; SQLSMALLINT connect_string_out_len; SQLUSMALLINT prompt = SQL_DRIVER_NOPROMPT; sprintf( connect_string_in, "DRIVER=myodbc3;SERVER=192.168.0.16;DATABASE=test;UID=pharvey;PWD=pharvey" ); rc = SQLDriverConnect( dbc, NULL, connect_string_in, strlen(connect_string_in), connect_string_out, MAX_CON, &connect_string_out_len, prompt); switch (rc) { case SQL_SUCCESS_WITH_INFO: printf("SQLDriverConnect = %d = SQL_SUCCESS_WITH_INFO\n", rc); do_SQLError(NULL, dbc, NULL); case SQL_SUCCESS: break; case SQL_NO_DATA: printf("SQLDriverConnect = %d = SQL_NO_DATA\n", rc); break; case SQL_ERROR: printf("SQLDriverConnect = %d = SQL_ERROR\n", rc); do_SQLError(NULL, dbc, NULL); break; case SQL_INVALID_HANDLE: printf("SQLDriverConnect = %d = SQL_INVALID_HANDLE\n", rc); break; default: printf("SQLDriverConnect = %d = unknown return value\n", rc); } return rc; } SQLRETURN do_SQLDisconnect(SQLHDBC dbc) { SQLRETURN rc; rc = SQLDisconnect(dbc); switch (rc) { case SQL_SUCCESS_WITH_INFO: printf("SQLDisconnect = %d = SQL_SUCCESS_WITH_INFO\n", rc); do_SQLError(NULL, dbc, NULL); case SQL_SUCCESS: break; case SQL_INVALID_HANDLE: printf("SQLDisconnect = %d = SQL_INVALID_HANDLE\n", rc); break; case SQL_ERROR: printf("SQLDisconnect = %d = SQL_ERROR\n", rc); do_SQLError(NULL, dbc, NULL); break; default: printf("SQLDisconnect = %d = unknown return value\n", rc); } return rc; } SQLRETURN do_SQLExecDirect(SQLHSTMT stmt, SQLCHAR *sql, SQLINTEGER len) { SQLRETURN rc; rc = SQLExecDirect(stmt, sql, len); switch (rc) { case SQL_SUCCESS_WITH_INFO: printf("SQLExecDirect = %d = SQL_SUCCESS_WITH_INFO\n", rc); do_SQLError(NULL, NULL, stmt); case SQL_SUCCESS: break; case SQL_NEED_DATA: printf("SQLExecDirect = %d = SQL_NEED_DATA\n", rc); break; case SQL_NO_DATA: printf("SQLExecDirect = %d = SQL_NO_DATA\n", rc); break; case SQL_STILL_EXECUTING: /* handle this better in future */ printf("SQLExecDirect = %d = SQL_STILL_EXECUTING\n", rc); break; case SQL_INVALID_HANDLE: printf("SQLExecDirect = %d = SQL_INVALID_HANDLE\n", rc); break; case SQL_ERROR: printf("SQLExecDirect = %d = SQL_ERROR\n", rc); do_SQLError(NULL, NULL, stmt); break; default: printf("SQLExecDirect = %d = unknown return value\n", rc); } return rc; } SQLRETURN do_SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT param_num, SQLSMALLINT io_type, SQLSMALLINT val_type, SQLSMALLINT param_type, SQLUINTEGER col_size, SQLSMALLINT dec_digits, SQLPOINTER param_val_ptr, SQLINTEGER buffer_len, SQLINTEGER *str_len_or_ind_ptr) { SQLRETURN rc; rc = SQLBindParameter(stmt, param_num, io_type, val_type, param_type, col_size, dec_digits, param_val_ptr, buffer_len, str_len_or_ind_ptr); switch (rc) { case SQL_SUCCESS_WITH_INFO: printf("SQLBindParameter = %d = SQL_SUCCESS_WITH_INFO\n", rc); do_SQLError(NULL, NULL, stmt); case SQL_SUCCESS: break; case SQL_INVALID_HANDLE: printf("SQLBindParameter = %d = SQL_INVALID_HANDLE\n", rc); break; case SQL_ERROR: printf("SQLBindParameter = %d = SQL_ERROR\n", rc); do_SQLError(NULL, NULL, stmt); break; default: printf("SQLBindParameter = %d = unknown return value\n", rc); } return rc; } /* do_Init Create our connection. Create a test table. */ int do_Init(SQLHENV *env, SQLHDBC *dbc ) { SQLHSTMT stmt; SQLCHAR * sql = "CREATE TABLE venuemaster (" \ " id bigint(20) unsigned NOT NULL auto_increment," \ " lockKey int(11) default '0'," \ " whenCreated datetime default '0000-00-00 00:00:00'," \ " venueName varchar(254) default ''," \ " address1 varchar(200) default ''," \ " address2 varchar(200) default ''," \ " city varchar(100) default ''," \ " theState char(2) default ''," \ " zip varchar(10) default ''," \ " phone varchar(15) default ''," \ " fax varchar(15) default ''," \ " tollfree varchar(15) default ''," \ " contactLast varchar(100) default ''," \ " contactFirst varchar(50) default ''," \ " contactExtension varchar(15) default ''," \ " contactEmail varchar(200) default ''," \ " website varchar(200) default ''," \ " directions text," \ " defaultEventTax decimal(10,0) default '0'," \ " active tinyint(1) default '0'," \ " PRIMARY KEY (id)" \ ") TYPE=MyISAM;"; do_SQLAllocEnv(env); do_SQLAllocConnect(*env, dbc); do_SQLDriverConnect(*dbc); do_SQLAllocStmt(*dbc, &stmt); do_SQLExecDirect(stmt, sql, SQL_NTS); do_SQLFreeStmt(stmt, SQL_DROP); return 1; } int do_Fini(SQLHENV env, SQLHDBC dbc) { SQLHSTMT stmt; SQLCHAR * sql = "DROP TABLE venuemaster;"; do_SQLAllocStmt(dbc, &stmt); do_SQLExecDirect(stmt, sql, strlen(sql)); do_SQLFreeStmt(stmt, SQL_DROP); do_SQLDisconnect(dbc); do_SQLFreeConnect(dbc); do_SQLFreeEnv(env); return 1; } int do_Insert(SQLHDBC dbc) { SQLHSTMT stmt; SQLCHAR * sql = "INSERT venuemaster (defaultEventTax) VALUES (1.1);"; do_SQLAllocStmt(dbc, &stmt); do_SQLExecDirect(stmt, sql, SQL_NTS); do_SQLFreeStmt(stmt, SQL_DROP); return 1; } int do_Update_1(SQLHDBC dbc) { SQLHSTMT stmt; SQLCHAR * sql = "UPDATE venuemaster SET defaultEventTax = 2.2;"; do_SQLAllocStmt(dbc, &stmt); do_SQLExecDirect(stmt, sql, SQL_NTS); do_SQLFreeStmt(stmt, SQL_DROP); return 1; } int do_Update_2(SQLHDBC dbc) { SQLHSTMT stmt; SQLHDESC desc = NULL; SQLCHAR * sql = "UPDATE venuemaster SET defaultEventTax = ?;"; SQLRETURN rc; SQL_NUMERIC_STRUCT numeric_struct; SQLINTEGER ind; do_SQLAllocStmt(dbc, &stmt); ind = sizeof(numeric_struct); numeric_struct.sign = 1; /* 1 if positive, 2 if negative */ memset(numeric_struct.val, 0, 16); numeric_struct.val[0] = 0x39; numeric_struct.val[1] = 0x30; do_SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_NUMERIC, 10, 0, &numeric_struct, 0, &ind); SQLGetStmtAttr(stmt, SQL_ATTR_APP_PARAM_DESC, &desc, 0, NULL); SQLSetDescField(desc, 1, SQL_DESC_TYPE, (SQLPOINTER) SQL_C_NUMERIC, 0); SQLSetDescField(desc, 1, SQL_DESC_PRECISION, (SQLPOINTER) 10, 0); SQLSetDescField(desc, 1, SQL_DESC_SCALE, (SQLPOINTER) 0, 0); SQLSetDescField(desc, 1, SQL_DESC_DATA_PTR, (SQLPOINTER) &numeric_struct, 0); do_SQLExecDirect(stmt, sql, SQL_NTS); do_SQLFreeStmt(stmt, SQL_DROP); return 1; } /* main The entry point for this program - it all starts here. */ int main(int argc, char *argv[]) { SQLHENV env; SQLHDBC dbc; /* init */ printf("BEGIN: ...\n"); do_Init(&env, &dbc); do_Insert(dbc); do_Update_2(dbc); do_Fini(env, dbc); printf("END: .\n"); exit(0); }