2011-04-21 68 views
2

Informix中插入连接到版本11.50版本IDS的事务记录开启:核心转储通过ODBC

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版本的驱动程序连接的,在任一与IDS实例(RHEL 4.8 32位)相同的系统或运行CentOS 4.8 32位的远程系统。每当我尝试将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 

我是否错过了某些东西,或者我是否有外部电话?

+0

不,这有助于解决问题,甚至不一定证明什么,但我跑你确切的代码对另一个ODBC驱动程序,它完美地工作。 – 2011-04-21 19:47:37

+0

谢谢,我也成功地运行这个对MySQL,所以我倾向于这是一个informix驱动程序问题。我可能需要采取不同的方法和/或将此提交给IBM,希望得到修复或解决方法。 – 2011-04-21 20:10:47

回答

0

在ESQL/C中,存储BYTE或TEXT blob的主机变量的数据类型为loc_t,这是一种标头中定义的结构类型,"locator.h"。我不是一位ODBC专家,但我期望您也需要与ODBC相同的结构。

+0

不幸的是,我的要求是使用纯粹的ODBC,而locator.h,loc_t和SQL_C_BLOB_LOCATOR类型似乎是特定于informix的。 (至少它们不适用于我的测试应用程序,它只能访问ODBC标题) – 2011-04-21 17:11:39

+0

在这种情况下,您很可能隐藏起来。我没有阅读过Informix ODBC手册,所以可能还有其他的东西。但是驱动程序必须将你的供应转换为服务器所期望的(这意味着定位器结构),但我不知道驱动程序如何/在哪里执行此操作。 – 2011-04-21 17:44:32