PostgreSQL数据库可打印字符转换为八位位组与在Linux平台上BYTEA列

问题描述:

这里的情景:PostgreSQL数据库可打印字符转换为八位位组与在Linux平台上BYTEA列

CREATE TABLE amaaa 
(
    laaaid integer NOT NULL DEFAULT 0, 
    blobdata bytea 
) 
INSERT INTO amaaa(laaaid)VALUES (1); 
SQLRETURN connect() 
{ 
    SQLRETURN ret; /* ODBC API return status */ 

    /* Allocate an environment handle */ 
    ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &myestenv); 

    /* We want ODBC 3 support */ 
    if (!ret) ret = SQLSetEnvAttr(myestenv, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0); 

    /* Allocate a connection handle */ 
    if (!ret) ret = SQLAllocHandle(SQL_HANDLE_DBC, myestenv, &dbc); 

    SQLSetConnectOption(dbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON); 
    const char* connectStr = "ByteaAsLongVarBinary=1;LFConversion=0;DSN=AMPG961;UID=postgres;PWD={postgres}"; 
    if (!ret) ret = SQLDriverConnect(dbc, NULL, (SQLCHAR*)connectStr, strlen(connectStr), NULL, 0, NULL, SQL_DRIVER_NOPROMPT); 

    /* Allocate a statement handle */ 
    if (!ret) ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); 

    if (ret) getErr(ret); 

    return ret; 
} 

void disconnect() 
{ 
    /* Disconnect and free all the handles */ 
    SQLRETURN ret = SQLFreeHandle(SQL_HANDLE_STMT, stmt); 
    ret = SQLDisconnect(dbc); 
    ret = SQLFreeHandle(SQL_HANDLE_DBC, dbc); 
    ret = SQLFreeHandle(SQL_HANDLE_ENV, myestenv); 
} 

const USHORT LEN = 3; 
SQLRETURN update() 
{ 
    SQLRETURN ret = connect(); 
    if (ret) return ret; 

    const unsigned char vLob[LEN] = "v="; 
    long lBlobLen = LEN - 1; 
    int lMainRecordId = 1; 

    SQLLEN cbValue = lBlobLen; 

    ret = SQLPrepare(stmt, (SQLCHAR*)"UPDATE \"amaaa\" set blobdata = ? where laaaid = ?;", SQL_NTS); 

    if (!ret) ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, 
     SQL_BINARY, SQL_LONGVARBINARY, 0, 
    0, (void*)vLob, lBlobLen, &cbValue); 

    SQLLEN cbLen = 4; 

    ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, 
         SQL_C_LONG, SQL_INTEGER, 0, 
         0, (void*)&lMainRecordId, sizeof(long), &cbLen); 

    if (!ret) ret = SQLExecute(stmt); 
    if ((ret != SQL_SUCCESS) && (ret != SQL_NEED_DATA) && (ret != SQL_SUCCESS_WITH_INFO)) { 
    printf("SQLExecDirect Failed\n\n"); 
    getErr(ret); 
    disconnect(); 
    } 
    return ret; 
} 

当我从数据库中查询blobdata列,该值始终是“V \ 075”,其实我的价值我输入的是'v ='; 但在Windows平台上相同的代码没有问题。 有什么想法吗?

在此先感谢。

+0

这个问题还不清楚。任何东西都不会插入到表格中,所以它一定是空的。这个查询应该有一个'odbc'标签,abd'c'而不是'C++'。 –

+0

感谢您的建议,我更新了它。 – Ramin

它看起来像一切都很好!

你存储在数据库中的字节是用于v=的ASCII值,它是118和61,或十六进制0x76和0x3D之间,或八进制0166和075.

正是这两个字节获得存储在bytea柱!

这个明显的问题是你用来查询数据库的工具。
它似乎将与ASCII字符相对应的所有字节显示为相应的字符,而将所有其他字节显示为三位八进制数字(前面带有反斜杠)。
这就是为什么你的价值显示为v\075

问题可以在CentOS 7.2上复制,它使用的是CentOS RPM中最新的psqlODBC 9.03。

该问题已通过将psqlODBC版本从9.03升级到9.05而得到修复。

psqlODBC 9.05是我自己在CentOS上编译的。

希望对他人有帮助。