#ifdef _WIN32 #include #endif #include #include #include #ifndef OK # define OK 0 #endif #ifndef FAIL # define FAIL 1 #endif static void print_diag(SQLRETURN rc, SQLSMALLINT htype, SQLHANDLE handle, const char *text, const char *file, int line) { if (rc != SQL_SUCCESS) { SQLCHAR sqlstate[6], message[SQL_MAX_MESSAGE_LENGTH]; SQLINTEGER native_error; SQLSMALLINT length; SQLRETURN drc; /** @todo map rc to SQL_SUCCESS_WITH_INFO, etc */ printf("# %s = %d\n", text, rc); /** @todo Handle multiple diagnostic records. */ drc = SQLGetDiagRec(htype, handle, 1, sqlstate, &native_error, message, SQL_MAX_MESSAGE_LENGTH - 1, &length); if (SQL_SUCCEEDED(drc)) printf("# [%6s] %*s in %s on line %d\n", sqlstate, length, message, file, line); else printf("# Did not get expected diagnostics from SQLGetDiagRec() = %d" " in file %s on line %d\n", drc, file, line); } } #define ok_env(environ, call) \ do { \ SQLRETURN rc= (call); \ print_diag(rc, SQL_HANDLE_ENV, (environ), #call, __FILE__, __LINE__); \ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) \ return FAIL; \ } while (0) #define ok_stmt(statement, call) \ do { \ SQLRETURN rc= (call); \ print_diag(rc, SQL_HANDLE_STMT, (statement), #call, __FILE__, __LINE__); \ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) \ return FAIL; \ } while (0) #define ok_sql(statement, query) \ do { \ SQLRETURN rc= SQLExecDirect((statement), (SQLCHAR *)(query), SQL_NTS); \ print_diag(rc, SQL_HANDLE_STMT, (statement), \ "SQLExecDirect(" #statement ", \"" query "\", SQL_NTS)",\ __FILE__, __LINE__); \ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) \ return FAIL; \ } while (0) #define ok_con(con, call) \ do { \ SQLRETURN rc= (call); \ print_diag(rc, SQL_HANDLE_DBC, (con), #call, __FILE__, __LINE__); \ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) \ return FAIL; \ } while (0) int main() { #undef ROWNUM #define ROWNUM 2 int res = OK; SQLHENV henv; SQLHDBC hdbc; SQLHSTMT hstmt; SQLULEN nrows = 0; SQLINTEGER id = 2; SQLUINTEGER c1_arr[ROWNUM]; SQLCHAR c2_arr[ROWNUM][128]; SQLCHAR c3_arr[ROWNUM][16384]; SQLCHAR c4_arr[ROWNUM][128]; ok_env(henv, SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv)); ok_env(henv, SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0)); ok_env(henv, SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc)); /* TODO: Replace `test` with a relevant and valid DSN name that exists in your system */ ok_con(hdbc, SQLDriverConnect(hdbc, NULL, "DSN=test", SQL_NTS, NULL, 0, NULL, 0)); ok_con(hdbc, SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt)); ok_sql(hstmt, "DROP DATABASE IF EXISTS test_rows"); ok_sql(hstmt, "CREATE DATABASE test_rows"); ok_sql(hstmt, "CREATE TABLE `test_rows`.`bug30697308` (" \ "`c1` int(11) NOT NULL," \ "`c2` varchar(64) DEFAULT NULL," \ "`c3` mediumblob," \ "`c4` mediumblob" \ ") ENGINE = InnoDB DEFAULT CHARSET = utf8"); ok_sql(hstmt, "INSERT INTO `test_rows`.`bug30697308` VALUES (" \ "1, 'Everything', repeat('A', 5824), 'ZZ')"); ok_sql(hstmt, "INSERT INTO `test_rows`.`bug30697308` VALUES (" \ "2, 'Something', repeat('B', 5824), 'YY')"); ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); ok_stmt(hstmt, SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_STATIC, 0)); ok_stmt(hstmt, SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)ROWNUM, 0)); ok_stmt(hstmt, SQLSetStmtAttr(hstmt, SQL_ATTR_ROWS_FETCHED_PTR, &nrows, 0)); ok_stmt(hstmt, SQLPrepare(hstmt, "SELECT c1, c2, c3, c4 FROM `test_rows`.`bug30697308` WHERE c1 = ?", SQL_NTS)); ok_stmt(hstmt, SQLBindCol(hstmt, 1, SQL_C_ULONG, c1_arr, sizeof(SQLUINTEGER), NULL)); ok_stmt(hstmt, SQLBindCol(hstmt, 2, SQL_C_CHAR, c2_arr, 128, NULL)); ok_stmt(hstmt, SQLBindCol(hstmt, 3, SQL_C_BINARY, c3_arr, 16384, NULL)); ok_stmt(hstmt, SQLBindCol(hstmt, 4, SQL_C_BINARY, c4_arr, 128, NULL)); ok_stmt(hstmt, SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &id, 0, NULL)); ok_stmt(hstmt, SQLExecute(hstmt)); ok_stmt(hstmt, SQLFetch(hstmt)); printf("c1 = %d, c2 = %s\n", c1_arr[0], c2_arr[0]); if (c1_arr[0] != 2) { printf("Wrong integer data result!\n"); res = FAIL; goto do_exit; } if (strncmp(c2_arr[0], "Something", 9) != 0 || c3_arr[0][5823] != 'B' || c4_arr[0][1] != 'Y' ) { printf("Wrong string data result!\n"); res = FAIL; goto do_exit; } printf("\nSUCCESS!!!\n"); do_exit: SQLFreeStmt(hstmt, SQL_CLOSE); SQLDisconnect(hdbc); return res; }