Дамп ядра при вставке BLOB в informix через ODBC - PullRequest
2 голосов
/ 21 апреля 2011

Подключение к версии 11.50 версии IDS с включенным ведением журнала транзакций:

onstat -version
Program Name:   onstat
Build Version:  11.50.UC5XE
Build Number:   N104
Build Host:     ku
Build OS:       Linux kernel-2.6.9-34.ELsmp glibc-2.3.4-2.19 compat-glibc-2.3.2-95.30
Build Date:     Thu Jul 15 12:44:25 CDT 2010
GLS Version:    glslib-4.50.UC6

Использование UnixODBC 2.2.11 поверх версии 3.50UC8 ​​драйверов Connect в той же системе, что и экземпляр IDS (RHEL 4.8 32-bit) или удаленная система, работающая под управлением CentOS 4.8 32-bit.Я получаю segfault всякий раз, когда пытаюсь вставить BLOB в базу данных.

Вот пример кода, демонстрирующий проблему:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sqlext.h>

#define CONNECTION_STRING "<valid connection string>"

#define CREATE_TABLE "CREATE TABLE blob_test(id SERIAL, test BLOB)"
#define INSERT_BLOB "INSERT INTO blob_test(test) VALUES(?)"

#define BLOB_SIZE 4096

int main(int argc, const char ** args) {
    printf("Informix ODBC BLOB test.\n");

    int exitCode = 0;

    SQLHENV henv;
    SQLHDBC hdbc;
    SQLHSTMT hstmt;
    SQLLEN ind;
    SQLRETURN ret;

    char data[BLOB_SIZE];
    char * paramData = NULL;

    // Allocate environment handle
    if(!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv))) {
        printf("Failed to allocate environment handle.\n");
        goto exit;
    }

    if(!SQL_SUCCEEDED(SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0))) {
        printf("Failed to initialize environment handle.\n");
        goto cleanup_env;
    }

    // Connect
    if(!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc))) {
        printf("Failed to allocate connection handle.\n");
        goto cleanup_env;
    }

    if(!SQL_SUCCEEDED(SQLDriverConnectA(hdbc, NULL, 
            (SQLCHAR *)CONNECTION_STRING, SQL_NTS, 
            NULL, 0, NULL, SQL_DRIVER_COMPLETE))) {
        printf("Failed to connect.\n");
        goto cleanup_dbc;
    }
    printf("Connected.\n");

    // Allocate statement
    if(!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt))) {
        printf("Failed to allocate statement handle.\n");
        goto disconnect;
    }

    //Create table
    if(!SQL_SUCCEEDED(SQLExecDirectA(hstmt, 
            (SQLCHAR *)CREATE_TABLE, strlen(CREATE_TABLE)))) {
        printf("Failed to create table.\n");
        //continue anyway
    } else {
        printf("Created test table.\n");
    }

    //Prepare data
    memset(data, 0, BLOB_SIZE);

    //Prepare statement
    if(!SQL_SUCCEEDED(SQLPrepareA(hstmt, 
            (SQLCHAR *)INSERT_BLOB, strlen(INSERT_BLOB)))) {
        printf("Failed to prepare statement.\n");
        goto cleanup_stmt;
    }

    //Bind data
    ind = SQL_LEN_DATA_AT_EXEC(BLOB_SIZE);
    if(!SQL_SUCCEEDED(SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY,
            SQL_LONGVARBINARY, BLOB_SIZE, 0, &data, 0, &ind))) {
        printf("Failed to bind blob.\n");
        goto cleanup_stmt;
    }

    //Execute
    printf("Inserting BLOB.\n");
    ret = SQLExecute(hstmt);
    if(SQL_NEED_DATA == ret) {
        //send additional data
        ret = SQLParamData(hstmt, 
            reinterpret_cast<SQLPOINTER *>(&paramData));

        if(paramData != data) {
            printf("Warning, data pointers(%p,%p) do not match!\n", data, paramData);
        }

        while(SQL_NEED_DATA == ret) {
            ret = SQLPutData(hstmt, data, BLOB_SIZE);

            if(!SQL_SUCCEEDED(ret)) {
                printf("Error setting parameter data.\n");
                goto cleanup_stmt;
            }

            //Read the next parameter requiring data, if any
            /**
             * ===== CRASH HAPPENS ON THIS LINE =====
             */
            ret = SQLParamData(hstmt, 
                reinterpret_cast<SQLPOINTER *>(&paramData));            
        }
    }

    if(!SQL_SUCCEEDED(ret)) {
        printf("Failed to execute.\n");
        goto cleanup_stmt;
    }
    printf("Inserted blob data.\n");

cleanup_stmt:   
    printf("Freeing hstmt.\n");
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
disconnect:
    printf("Disconnecting.\n");
    SQLDisconnect(hdbc);
cleanup_dbc:
    printf("Freeing hdbc.\n");
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
cleanup_env:
    printf("Freeing henv.\n");
    SQLFreeHandle(SQL_HANDLE_ENV, henv);
exit:
    return exitCode;
}

Makefile:

blob_test : main.cpp
    g++ -o blob_test -l odbc main.cpp

Итрассировка стека:

#0  0x00a07363 in memmove () from /lib/tls/libc.so.6
#1  0x001fccbe in _iwrite () from /opt/informix/lib/cli/iclit09b.so
#2  0x001fb431 in _iputpbuf () from /opt/informix/lib/cli/iclit09b.so
#3  0x00184c42 in _Odbcputpbuf () from /opt/informix/lib/cli/iclit09b.so
#4  0x00182cc8 in _OdbcPutChstrNoCsc () from /opt/informix/lib/cli/iclit09b.so
#5  0x00164b4f in _OdbcPutAsfLvarcharVal () from /opt/informix/lib/cli/iclit09b.so
#6  0x001acef8 in _OdbcExtBinary2IntSendrecv () from /opt/informix/lib/cli/iclit09b.so
#7  0x0016ca48 in _OdbcPutBindings () from /opt/informix/lib/cli/iclit09b.so
#8  0x0016c836 in _OdbcAssignInputParams () from /opt/informix/lib/cli/iclit09b.so
#9  0x0016d373 in _OdbcExecute () from /opt/informix/lib/cli/iclit09b.so
#10 0x0014c125 in _OdbcExecuteRow () from /opt/informix/lib/cli/iclit09b.so
#11 0x0014c3a4 in SQLParamData () from /opt/informix/lib/cli/iclit09b.so
#12 0x00b17f09 in SQLParamData () from /usr/lib/libodbc.so.1
#13 0x08048a16 in main ()

И наконец, трассировка от драйвера odbc:

[ODBC][26114][SQLPrepare.c][189]
                Entry:
                        Statement = 0x9e56060
                        SQL = [INSERT INTO blob_test(test) VALUES(?)][length = 37]
[ODBC][26114][SQLPrepare.c][364]
                Exit:[SQL_SUCCESS]
[ODBC][26114][SQLBindParameter.c][193]
                Entry:
                        Statement = 0x9e56060
                        Param Number = 1
                        Param Type = 1
                        C Type = -2 SQL_C_BINARY
                        SQL Type = -4 SQL_LONGVARBINARY
                        Col Def = 4096
                        Scale = 0
                        Rgb Value = 0xbfe9a990
                        Value Max = 0
                        StrLen Or Ind = 0xbfe9b99c
[ODBC][26114][SQLBindParameter.c][339]
                Exit:[SQL_SUCCESS]
[ODBC][26114][SQLExecute.c][183]
                Entry:
                        Statement = 0x9e56060
[ODBC][26114][SQLExecute.c][344]
                Exit:[SQL_NEED_DATA]
[ODBC][26114][SQLParamData.c][156]
                Entry:
                        Statement = 0x9e56060
                        Value = 0xbfe9a98c
[ODBC][26114][SQLParamData.c][327]
                Exit:[SQL_NEED_DATA]
                        Value = 0xbfe9a990
[ODBC][26114][SQLPutData.c][144]
                Entry:
                        Statement = 0x9e56060
                        Data = 0xbfe9a990
                        StrLen = 4096
[ODBC][26114][SQLPutData.c][289]
                Exit:[SQL_SUCCESS]
[ODBC][26114][SQLParamData.c][156]
                Entry:
                        Statement = 0x9e56060
                        Value = 0xbfe9a98c

Я что-то упустил или у меня где-то есть посторонний вызов?

Ответы [ 2 ]

1 голос
/ 23 апреля 2011

ОБРАЩАЙТЕСЬ К: «Руководство по программированию драйвера IBM Informix ODBC» http://publib.boulder.ibm.com/infocenter/idshelp/v10/index.jsp?topic=/com.ibm.odbc.doc/odbc20.htm

0 голосов
/ 21 апреля 2011

В ESQL / C тип данных для переменной хоста, хранящей BLOB или TEXT, равен loc_t, тип структуры, определенный в заголовке, "locator.h".Я не эксперт ODBC, но я ожидаю, что вам нужна такая же структура с ODBC.

...