我遇到了针对SQLite3数据库的DBIx :: Class问题。
如果您不想完整阅读以下内容,请参阅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
,则一切正常。
我的兴奋是:
SQLite字段具有“亲和力”,这意味着字段被识别为整数,但它们没有本机大小。因此,SQLite根据字段的内容“猜测”大小。由于last_error
字段中的值小于2147483647,但大于16777215,我猜测SQLite将字段视为SIGNED INTEGER(即带符号的32位数字)。
因此,我的猜测是,当bind_param
发生时,会进行某种检查,这会导致DBI将last_error
标识为SIGNED INTEGER。结果,4294967295的值溢出,或者被压缩到零或类似的东西,并且比较工作不正确。
因此,我的问题:
答案 0 :(得分:1)
如何在查询中使用文字sql:
my $cond = " < $range->{end} ";
my @entries = $self->{row}->search_related_rs('eventlog_entries')
->search_related('entry', {
first_error => {'>', $range->{start}},
last_error => \$cond,
}
)->all();
如果perl将$range->[end}
字符串化为正数,则应该有效。