#include #include #include #include #include // generated DSN. problem does not occur if the 'no_ssps' option is removed. #define DSN "Driver=MySQL ODBC 8.0 Unicode Driver;Server=localhost;Port=3306;Database=test;BIG_PACKETS=1;FORWARD_CURSOR=1;FOUND_ROWS=1;no_ssps=1;LOG_QUERY=1;" #pragma comment(lib, "odbc32.lib") void printerr(SQLUSMALLINT type, SQLHANDLE handle, int rc) { SQLINTEGER sqlcode; SQLSMALLINT len; char sqlstate[6] = "", message[512] = ""; if (SQLGetDiagRec (type, handle, 1, (SQLCHAR*)sqlstate, &sqlcode, (SQLCHAR*)message, _countof(message), &len) == SQL_SUCCESS) { printf("[%s - %d] %s\n", sqlstate, sqlcode, message); } else { printf("Unexpected error %d\n", rc); } } typedef struct { long length; unsigned char * data; } T_LOB; int main (int argc, char ** argv) { long rc, exitCode = -1; SQLSMALLINT dsnlen = 0, len; SQLHANDLE env = 0, con = 0, stmt = 0; char dsn[1024] = ""; rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); rc = SQLSetEnvAttr (env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); rc = SQLAllocHandle (SQL_HANDLE_DBC, env, &con); rc = SQLDriverConnect (con, NULL, (SQLTCHAR*)DSN, SQL_NTS, dsn, 1024, &len, SQL_DRIVER_NOPROMPT); if (rc != SQL_SUCCESS) { printerr(SQL_HANDLE_DBC, con, rc); printf("connexion failed...\n"); SQLFreeHandle (SQL_HANDLE_DBC, con); SQLFreeHandle (SQL_HANDLE_ENV, env); return -1; } rc = SQLAllocHandle (SQL_HANDLE_STMT, con, &stmt); rc = SQLExecDirect (stmt, "create table if not exists test_images (c1 int, c2 int, c3 longblob)", SQL_NTS); rc = SQLExecDirect (stmt, "delete from test_images", SQL_NTS); SQLFreeHandle (SQL_HANDLE_STMT, stmt); // main test - insert a 4MB image rc = SQLAllocHandle (SQL_HANDLE_STMT, con, &stmt); T_LOB c3; int i, c1 = 1, c2 = 4096; c3.length = c2; c3.data = malloc(c3.length); if (c3.data == NULL) { printerr(SQL_HANDLE_STMT, stmt, rc); printf("malloc failed...\n"); SQLDisconnect (con); SQLFreeHandle (SQL_HANDLE_DBC, con); SQLFreeHandle (SQL_HANDLE_ENV, env); return -1; } for (c1 = 1; c1 <= 10; c1++) { c3.length = (c1 % 2)? 944 : 3312; // corruption seems dependent of image size... thoses are the actual image sizes in the real world program, it fails on our system. SQLLEN indic1 = sizeof(long), indic2 = sizeof(long), indic3 = SQL_LEN_DATA_AT_EXEC(c3.length); for (i = 0; i < c3.length; i++) { c3.data[i] = i % 256; } rc = SQLBindParameter (stmt, (short) 1, (short) SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, sizeof(long), 0, &c1, sizeof(long), (SQLLEN*) &indic1); rc = SQLBindParameter (stmt, (short) 2, (short) SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, sizeof(long), 0, &c2, sizeof(long), (SQLLEN*) &indic2); rc = SQLBindParameter (stmt, (short) 3, (short) SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, sizeof(T_LOB), 0, &c3, sizeof(T_LOB), (SQLLEN*) &indic3); rc = SQLExecDirect (stmt, "insert into test_images(c1, c2, c3) values (?, ?, ?)", SQL_NTS); if (rc != SQL_NEED_DATA) { printerr(SQL_HANDLE_STMT, stmt, rc); printf("insertion failed...\n"); SQLDisconnect (con); SQLFreeHandle (SQL_HANDLE_DBC, con); SQLFreeHandle (SQL_HANDLE_ENV, env); return -1; } T_LOB * pt; rc = SQLParamData (stmt, (SQLPOINTER) &pt); if (rc != SQL_NEED_DATA) { printerr(SQL_HANDLE_STMT, stmt, rc); printf("SQLParamData failed...\n"); SQLDisconnect (con); SQLFreeHandle (SQL_HANDLE_DBC, con); SQLFreeHandle (SQL_HANDLE_ENV, env); return -1; } rc = SQLPutData (stmt, pt->data, pt->length); if (rc != SQL_SUCCESS) { printerr(SQL_HANDLE_STMT, stmt, rc); printf("SQLPutData failed...\n"); SQLDisconnect (con); SQLFreeHandle (SQL_HANDLE_DBC, con); SQLFreeHandle (SQL_HANDLE_ENV, env); return -1; } rc = SQLParamData (stmt, (SQLPOINTER) &pt); if (rc != SQL_SUCCESS) { printerr(SQL_HANDLE_STMT, stmt, rc); printf("insertion failed...\n"); SQLDisconnect (con); SQLFreeHandle (SQL_HANDLE_DBC, con); SQLFreeHandle (SQL_HANDLE_ENV, env); return -1; } printf("image %d inserted successfully\n", c1); } printf("test succeeded\n"); SQLFreeHandle (SQL_HANDLE_STMT, stmt); SQLDisconnect (con); SQLFreeHandle (SQL_HANDLE_DBC, con); SQLFreeHandle (SQL_HANDLE_ENV, env); return 0; }