我面臨DBIx :: Class針對SQLite3數據庫的問題。整數比較使用DBD :: SQLite
如果你不想讀滿了之後,這裏的TL; DR版本:
有沒有辦法迫使DBD :: SQLite的治療整型字段爲未簽名,當它來比較?
表定義是在這裏:
sqlite> PRAGMA table_info(entry);
0|entry_key|INTEGER|1||1
1|node|varchar(256)|1||0
2|object_type|varchar(128)|1||0
3|object_id|int|1||0
4|copy_id|tinyint|0||0
5|seq_number|int|1||0
6|root_seq_number|int|1||0
7|first_error|int|1||0
8|last_error|int|1||0
9|error_count|int|1||0
10|error_id|int|1||0
11|error_code|int|0||0
12|status|varchar(64)|1||0
13|type|varchar(64)|1||0
14|sense|char(256)|0||0
感興趣的領域是first_error
和last_error
。這些字段包含紀元時間值。 因此,它們是32位數字,但它們小於2147483647
在我的代碼,我有以下:
my @entries = $self->{row}->search_related_rs('eventlog_entries')
->search_related('entry', {
first_error => {'>', $range->{start}},
last_error => {'<', $range->{end}},
}
)->all();
start
被設置爲0; end
設置爲2**32 - 1
當DBI_TRACE=1
運行,我得到:
<- prepare_cached('SELECT entry.entry_key, entry.node, entry.object_type,
entry.object_id, entry.copy_id, entry.seq_number,
entry.root_seq_number, entry.first_error, entry.last_error,
entry.error_count, entry.error_id, entry.error_code, entry.status,
entry.type, entry.sense FROM eventlog_entry me JOIN entry entry ON
entry.entry_key = me.entry_key WHERE (((first_error > ? AND
last_error < ?) AND me.eventlog_key = ?))',
HASH(0x2472b54), ...)= (DBI::st=HASH(0x2442efc)) [1 items]
at DBI.pm line 2245
<- bind_param(1, 0, ...)= (1) [1 items] at DBI.pm line 1574
<- bind_param(2, '4294967295', ...)= (1) [1 items] at DBI.pm line 1574
<- bind_param(3, 1, ...)= (1) [1 items] at DBI.pm line 1574
<- execute= ('0E0') [1 items] at DBI.pm line 1586
<- fetchall_arrayref= ([ ]) [1 items] row-1 at Cursor.pm line 133
在這種情況下,@entries
是一個空數組。
另一方面,如果我設置end
設置爲2**31 - 1
,一切正常。
我hyopthesis是這樣的:
SQLite的領域有一個「親」,這意味着該領域被認爲是整數,但他們沒有本土的大小。因此,SQLite根據字段的內容「猜測」大小。由於last_error
字段中的值小於2147483647,但大於16777215,所以我猜測SQLite將該字段視爲SIGNED INTEGER(即帶符號的32位數字)。
因此,我的猜測是,當bind_param
發生時,會進行某種檢查,導致DBI將last_error
識別爲SIGNED INTEGER。結果,4294967295的值溢出,或被擠壓到零,或類似的東西,並且比較工作不正確。
因此,我的問題(S):
- 這是假設正確的(根據一些資料,我已經忽略了)?或
- 有沒有辦法確認這個假設?
- 這是一個錯誤,或者是有一個合理的解決辦法,記住,我使用DBIx ::類軸承,所以我有點抽象從數據庫了。
你是對的類型'親和力'。請參閱sqlite數據類型文檔(http://www.sqlite.org/datatype3.html)中的第2.0節「類型相關性」。sqlite總是將整數視爲無符號,所以我認爲問題出現在'DBD :: SQLite' – ErikR
實際上,仔細觀察後,我看到:「INTEGER。該值是一個有符號整數,根據值的大小存儲在1,2,3,4,6或8個字節中。」...因此INTEGER被簽名。 ..所以問題實際上是推斷的大小。 – Dancrumb
對不起 - 我的意思是說「sql始終將整數視爲_signed_」而不是「unsigned」:-) – ErikR