[Python] 塞 NULL 字元進 PostgreSQL 資料庫時,出現 A string literal cannot contain NUL (0x00) characters 的錯誤訊息

[Python] 塞 NULL 字元進 PostgreSQL 資料庫時,出現 A string literal cannot contain NUL (0x00) characters 的錯誤訊息

今天專案的 python 程式,

在把一串資料塞進 PostgreSQL 時,突然出現了 exception:

ValueError: A string literal cannot contain NUL (0x00) characters.

 

檢查了一下,要塞進去的資料是一個 byte 的 NULL 字元,

以 python 來說是 “\x00″,

但以前同樣的程式沒有問題,為什麼現在出錯了呢?

 

首先懷疑是 PostgreSQL 不吃 NULL 字元…

但試著塞一個 \x00 字串進去,是成功的:

testdb=> insert into tbl_info values('xxx', decode('00', 'hex'));
INSERT 0 1

 

用 SELECT 也看的到這個 \x00 NULL 字元:

testdb=> select * from tbl_info;
    name    |      value     |         updatetime
------------+----------------+----------------------------
 xxx        | \x00           | 2018-06-12 04:08:46.910405

 

到底是怎麼一回事呢?

如果 PostgreSQL 可以吃 NULL 字元,這個 exception 又是哪裡來的?

 

在網路上找了一下,似乎在不同的專案間都有這個 exception 的身影…

後來注意到 psycopg2,這是我們用來存取資料庫用的 Python 第三方模組,

這個 exception 的訊息在 psycopg/utils.c 可以看到:

char *
psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len,
                       char *to, Py_ssize_t *tolen)
{
    // ...

    } else if (strchr(from, '\0') != from + len) {
        PyErr_Format(PyExc_ValueError, "A string literal cannot contain NUL (0x00) characters.");

    // ...
}

 

從這段程式可以很清楚看到,只要字串裡有 \x00 NULL 字元,

psycopg2 就會彈一個 ValueError 的 exception,

內容就是 A string literal cannot contain NUL (0x00) characters.

 

這段程式在新版 psycopg2 2.7 版有出現,

但在我們之前使用的舊版 2.4.5 版本上沒有出現。

這就解釋了為什麼現在才冒出這個問題,

因為專案的舊版本搭配 psycopg2 2.4.5 版,所以沒事。

專案的新版本搭配了 psycopg2 2.7 版,所以出事了…

 

目前的解法,就是採取類似 C/C++ 對字串的處理方式,

把 \x00 NULL 字元連同後面的字串都截掉,

這樣字串的中間就不會有 \x00 NULL 字元,

也就不會觸發新版 psycopg2 的 exception 囉~

 

(本頁面已被瀏覽過 2,993 次)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料