Inflated DateTime column not updated on $row->update({ ts_column => undef })

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Inflated DateTime column not updated on $row->update({ ts_column => undef })

Lasse Makholm
It seems DBIx::Class::InflateColumn::DateTime does not update the inflated column value on: $row->update({ ts_column => undef })

Given:

CREATE TABLE `foo` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `ts` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

Doing:

package My::Schema;

use DateTime;
use base qw(DBIx::Class::Schema::Loader);

__PACKAGE__->loader_options(
components => [qw(InflateColumn::DateTime)],
naming => "current",
);

package main;

my $schema = My::Schema->connect("dbi:mysql:test");
$schema->storage->debug(1);

print "create";
my $foo = $schema->resultset('Foo')->create({ ts => DateTime->now });
print "ts = ", defined($foo->ts) ? $foo->ts : 'null';

print "update({ ts => undef })";
$foo->update({ ts => undef });
print "ts = ", defined($foo->ts) ? $foo->ts : 'null';

print "discard_changes";
$foo->discard_changes;
print "ts = ", defined($foo->ts) ? $foo->ts : 'null';

Yields:

create
BEGIN WORK
INSERT INTO `foo` ( `ts`) VALUES ( ? ): '2015-05-22 19:44:54'
COMMIT
ts = 2015-05-22T19:44:54

update({ ts => undef })
UPDATE `foo` SET `ts` = ? WHERE ( `id` = ? ): NULL, '16'
ts = 2015-05-22T19:44:54

discard_changes
SELECT `me`.`id`, `me`.`ts` FROM `foo` `me` WHERE ( `me`.`id` = ? ): '16'
ts = null

I would have expected the inflated column value to be updated on update({ ... }).

Passing a DateTime object instead of undef does update the inflated column value appropriately.
And doing:

$row->ts_column(undef);
$row->update();

...(obviously) works as expected too.

Is this a known bug or by design? Or am I simply missing something?

Thanx
/L

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inflated DateTime column not updated on $row->update({ ts_column => undef })

Dmitry Latin
Looks like bug. Even if you try to use non ref data inside update,
column data didn't updated (actually updated, but not inflated data)

$foo->update({ ts => '2010-02-05' });

But this will do the trick:
delete $foo->{_inflated_column}{ts};


So, possibly this string should be placed into
DBIx::Class::Row::set_inflated_columns.

Here is patch (I use v0.082820):

$ cat Row.pm.patch

--- Row.pm_     2015-05-23 00:17:57.574979705 +0300
+++ Row.pm      2015-05-23 00:20:46.498736716 +0300
@@ -1113,6 +1113,9 @@
         $self->set_inflated_column($key, delete $upd->{$key});
       }
     }
+    else {
+        delete $self->{_inflated_column}{$key};
+    }
   }
   $self->set_columns($upd);
 }


On 22 May 2015 at 22:57, Lasse Makholm <[hidden email]> wrote:

> It seems DBIx::Class::InflateColumn::DateTime does not update the inflated
> column value on: $row->update({ ts_column => undef })
>
> Given:
>
> CREATE TABLE `foo` (
>   `id` bigint(20) NOT NULL AUTO_INCREMENT,
>   `ts` timestamp NULL DEFAULT NULL,
>   PRIMARY KEY (`id`)
> ) ENGINE=InnoDB;
>
> Doing:
>
> package My::Schema;
>
> use DateTime;
> use base qw(DBIx::Class::Schema::Loader);
>
> __PACKAGE__->loader_options(
> components => [qw(InflateColumn::DateTime)],
> naming => "current",
> );
>
> package main;
>
> my $schema = My::Schema->connect("dbi:mysql:test");
> $schema->storage->debug(1);
>
> print "create";
> my $foo = $schema->resultset('Foo')->create({ ts => DateTime->now });
> print "ts = ", defined($foo->ts) ? $foo->ts : 'null';
>
> print "update({ ts => undef })";
> $foo->update({ ts => undef });
> print "ts = ", defined($foo->ts) ? $foo->ts : 'null';
>
> print "discard_changes";
> $foo->discard_changes;
> print "ts = ", defined($foo->ts) ? $foo->ts : 'null';
>
> Yields:
>
> create
> BEGIN WORK
> INSERT INTO `foo` ( `ts`) VALUES ( ? ): '2015-05-22 19:44:54'
> COMMIT
> ts = 2015-05-22T19:44:54
>
> update({ ts => undef })
> UPDATE `foo` SET `ts` = ? WHERE ( `id` = ? ): NULL, '16'
> ts = 2015-05-22T19:44:54
>
> discard_changes
> SELECT `me`.`id`, `me`.`ts` FROM `foo` `me` WHERE ( `me`.`id` = ? ): '16'
> ts = null
>
> I would have expected the inflated column value to be updated on update({
> ... }).
>
> Passing a DateTime object instead of undef does update the inflated column
> value appropriately.
> And doing:
>
> $row->ts_column(undef);
> $row->update();
>
> ...(obviously) works as expected too.
>
> Is this a known bug or by design? Or am I simply missing something?
>
> Thanx
> /L
>
> _______________________________________________
> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
> IRC: irc.perl.org#dbix-class
> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
> Searchable Archive:
> http://www.grokbase.com/group/dbix-class@...



--
//wbr, Dmitry L.

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Inflated DateTime column not updated on $row->update({ ts_column => undef })

Lasse Makholm
In reply to this post by Lasse Makholm


On Sat, May 23, 2015 at 9:35 AM, Peter Rabbitson <[hidden email]> wrote:
On 05/22/2015 09:57 PM, Lasse Makholm wrote:
It seems DBIx::Class::InflateColumn::DateTime does not update the
inflated column value on: $row->update({ ts_column => undef })

That is a bug, not sure how it went overlooked for so long :( It is present as far back as 0.08112 (2009), likely earlier.

Yeah, it seems remarkable that I'm the first to stumble across this. On the other hand, I only found it because I was trying to get 100% condition coverage on something and was updating a row through all permutations of a couple of conditions.

I guess, generally, updating a timestamp column to null after it has had a value, is just not a very common thing to do.
 
Because of the nontrivial possibility of negative impact of changing something so fundamental, I have to think this through before going forward.

Yeah, I don't really see a pretty way around this without risking a lot of random breakage. 

In the meantime an easy workaround for you is to add the following to a base result class (this is a hack, a real fix will materialize later):

  sub store_column {
    delete $_[0]->{_inflated_column}{$_[1]};
    shift->next::method(@_);
  }

Sorry for not being able to offer anything better at the moment :(

No worries. As far as workarounds/hacks go, this one is pretty decent. I've seen and done a lot worse... :-) 

Thanks for confirming this.

/L


_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Loading...