Baby Moose Update

Its get more done day here in the Moose-Pen

Now that I have got 'create/insert' to work in yesterday's post I think I will move on down the line and get the next one easy one to work 'update'.

This first thing though is to get rig of this waring;


Commit ineffective while AutoCommit is on-1 at D:\GitHub\database-accessor-driver-dbi\lib/Database/Accessor/Driver/DBI.pm line 64
ok 1 - Create function

nothing major really the waring is perfectly harmless but I could see some people getting annoyed at that and the fix is simple, if the DBI 'AutoCommit' flag is set don't try and commit. So here is that change;

$dbh->commit()
-- unless($self->da_no_effect);
++ if ($dbh->{AutoCommit} == 0 and !$self->da_no_effect);

might as well get the easy stuff early, now onto update sub.

It is much the same as the 'insert' and it really only took me one quick iteration to correct a few syntax typos and I had it working, so here you go;


sub _update {
my $self = shift;
my ($container) = @_;
my @fields = ();
my $update_clause = join(" ",Database::Accessor::Driver::DBI::SQL::UPDATE, $self->view()->name());
$self->da_warn("_update","Update clause='$update_clause'")
if $self->da_warning()>=5;
foreach my $key ( keys( %{$container} ) ) {
my $field = $self->get_element_by_name(sub {$_->name eq $key});
push(@fields,join(" ",$field->name,'=',Database::Accessor::Driver::DBI::SQL::PARAM));
my $param = Database::Accessor::Param->new({value=> $container->{$key}});
$self->add_param($param);
}
my $set_clause = join(" ",Database::Accessor::Driver::DBI::SQL::SET,
join(",",@fields)
);
$self->da_warn("_update"," Set clause='$set_clause'")
if $self->da_warning()>=5;
return join(" ",$update_clause,$set_clause);
}

Again I am going with the most simple use case as there are a few things I have left out for now such as the DBI returning_in function. I again iterate over the container as that should be a trusted value coming from Accessor.pm and in this iteration I did not take into account that I could be using a complex expression rather that a simple param. For example I will have to account for something like this

set cost = price*quantity

or maybe a parametrized expression like this

set cost = ? * ?

and don't even get me started on date/time functions.

I next added in this test to the 10_crud_basic.t test case;


$container->{username} ='Uchanged';
$container->{address} ='Achanged';
eval{
$user->update($utils->connect(),$container);
};
if ($@) {
fail("Update function error=$@");
}
else {
pass("Update function");
}
ok($user->result()->effected == 2,"Two rows effected");

and when I first ran it I got this result as I expected I would;

Failed test 'Update function error=Attempt to UPDATE without condition at

This error is a result of my update command not having a 'Condition/Where' clause. Now I am again leaving that out for now as just want to get the very very simple use case working. Now to get around this I just added this;

return $class->$orig({
view=>{name=>'user'},
elements=>[{name=> 'username'},
{name=> 'address'}],
++ update_requires_condition=>0,
++ delete_requires_condition=>0
});
};

to the Test::DB::User class that I am calling as my DA.

After that I now get;


ok 1 - Create function
ok 2 - One row effected
ok 3 - Update function
ok 4 - Two rows effected

as my canned DB comes with 1 row present I have to test for two updates rather that one . So things are coming together.

IMG_0008a.jpg

Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations