DBIx :: Class update带有函数的Inflate列

时间:2014-08-28 14:34:05

标签: perl postgresql dbix-class

我尝试在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不期望那里的功能。这个问题是否有任何干净的解决方法?

1 个答案:

答案 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 });
}