File Coverage

blib/lib/Alzabo/Runtime/InsertHandle.pm
Criterion Covered Total %
statement 15 64 23.4
branch 0 20 0.0
condition 0 3 0.0
subroutine 5 7 71.4
pod 1 2 50.0
total 21 96 21.8


line stmt bran cond sub pod time code
1             package Alzabo::Runtime::InsertHandle;
2              
3 11     11   60 use strict;
  11         21  
  11         608  
4              
5 11     11   72 use Alzabo::Exceptions ( abbr => [ qw( exception params_exception ) ] );
  11         20  
  11         95  
6 11     11   61 use Alzabo::Runtime;
  11         29  
  11         254  
7              
8 11     11   56 use Params::Validate qw( :all );
  11         20  
  11         3284  
9             Params::Validate::validation_options( on_fail => sub { params_exception join '', @_ } );
10              
11 11         10714 use constant NEW_SPEC => { table => { isa => 'Alzabo::Runtime::Table' },
12             sql => { isa => 'Alzabo::SQLMaker' },
13             columns => { type => ARRAYREF },
14             values => { type => HASHREF, default => {} },
15 11     11   71 };
  11         22  
16              
17             sub new
18             {
19 0     0 0   my $class = shift;
20              
21 0           my %p = validate( @_, NEW_SPEC );
22              
23 0           my $self = bless \%p, $class;
24              
25 0           $self->{handle} =
26             $self->{table}->schema->driver->statement_no_execute( sql => $p{sql}->sql );
27              
28 0           return $self;
29             }
30              
31             sub insert
32             {
33 0     0 1   my $self = shift;
34              
35 0           my %p = @_;
36 0           %p = validate( @_,
37 0           { ( map { $_ => { optional => 1 } } keys %p ),
38             values => { type => HASHREF, default => {} },
39             },
40             );
41              
42 0           my $vals = { %{ $self->{values} },
  0            
43 0           %{ $p{values} },
44             };
45              
46 0           my $schema = $self->{table}->schema;
47 0           my $driver = $schema->driver;
48              
49 0           my %ph = $self->{sql}->placeholders;
50 0           my @val_order;
51 0           while ( my ( $name, $i ) = each %ph )
52             {
53 0           $val_order[$i] = $name;
54             }
55              
56 0           foreach my $name ( keys %$vals )
57             {
58 0 0         params_exception
59             "Cannot provide a value for a column that was not specified ".
60             "when the insert handle was created ($name)."
61             unless exists $ph{$name};
62             }
63              
64 0           my @pk = $self->{table}->primary_key;
65 0           foreach my $pk (@pk)
66             {
67 0 0         unless ( exists $vals->{ $pk->name } )
68             {
69 0 0         if ( $pk->sequenced )
70             {
71 0           $vals->{ $pk->name } = $driver->next_sequence_number($pk);
72             }
73             else
74             {
75 0           params_exception
76             ( "No value provided for primary key (" .
77             $pk->name . ") and no sequence is available." );
78             }
79             }
80             }
81              
82 0           foreach my $c ( @{ $self->{columns} } )
  0            
83             {
84 0 0 0       delete $vals->{ $c->name }
85             if ! defined $vals->{ $c->name } && defined $c->default;
86             }
87              
88 0           my @fk = $self->{table}->all_foreign_keys;
89              
90 0           my %id;
91              
92 0 0         $schema->begin_work if @fk;
93             eval
94 0           {
95 0           foreach my $fk (@fk)
96             {
97 0           $fk->register_insert( map { $_->name => $vals->{ $_->name } } $fk->columns_from );
  0            
98             }
99              
100 0           $self->{sql}->debug(\*STDERR) if Alzabo::Debug::SQL;
101 0           print STDERR Devel::StackTrace->new if Alzabo::Debug::TRACE;
102              
103 0 0         $self->{handle}->execute_no_result
104 0           ( map { exists $vals->{$_} ? $vals->{$_} : undef } @val_order );
105              
106 0           foreach my $pk (@pk)
107             {
108 0 0         $id{ $pk->name } = ( defined $vals->{ $pk->name } ?
109             $vals->{ $pk->name } :
110             $driver->get_last_id($self) );
111             }
112              
113             # must come after call to ->get_last_id for MySQL because the
114             # id will no longer be available after the transaction ends.
115 0 0         $schema->commit if @fk;
116             };
117 0 0         if (my $e = $@)
118             {
119 0           eval { $schema->rollback };
  0            
120              
121 0           rethrow_exception $e;
122             }
123              
124 0 0         return unless defined wantarray;
125              
126 0           return $self->{table}->row_by_pk( pk => \%id,
127             no_cache => $self->{no_cache},
128             %p,
129             );
130             }
131              
132             1;
133              
134             __END__