我尝试在DBIx::Class
中针对update_or_new
函数模拟此SQL。
UPDATE user SET lastseen = GREATEST( lastseen, ?::timestamp ) WHERE userid = ?
它在inflate列上显示错误,表示无法在is_infinity
上调用undef
。
$schema->resultset('user')->update_or_new( {
userid => 'peter',
lastseen => \[ 'GREATEST( lastseen, ?::timestamp )', DateTime->from_epoch(epoch => 1234) ]
} );
我想这是因为InflateColumn::DataTime
不期望那里的功能。这个问题是否有任何干净的解决方法?
答案 0 :(得分:0)
这是DBIx :: Class中的错误(在此处解决:https://github.com/dbsrgits/dbix-class/pull/44)并且修复已合并。在下一个版本中应该没问题。 也就是说,如果您使用的是DBIx :: Class< = 0.08270 ......
您正在使用update_or_new,但该函数仅在行已存在时才有意义:
如果该行尚不存在,则GREATEST( lastseen, ?::timestamp )
lastseen未定义。
我仔细阅读了源代码+文档,无法找到回避InflateColumn
代码并仍然具有绑定值的方法。您可以使用标量引用(\'NOW()')传递文字SQL,但不能传递数组引用。
您最好的选择是使用the ResultSet's update method instead,,它不会'处理/收缩传入的任何值。这与DBIx :: Class :: Row中相应的“更新”不同。
my $dtf = $schema->storage->datetime_parser; #https://metacpan.org/pod/DBIx::Class::Storage::DBI#datetime_parser
my $user_rs = $schema->resultset('User')->search({ userid => 'peter' });
my $dt = DateTime->from_epoch(epoch => 1234);
#select count(*) where userid = 'peter';
if( $user_rs->count ) {
$user_rs->update(
lastseen => \[ 'GREATEST( lastseen, ? )', $dtf->format_datetime($dt) ]
);
} else {
$user_rs->create({ lastseen => $dt });
}