updated _resolve_column_source to _resolve_column_info as per ribasushi's suggestion
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / ODBC / Microsoft_SQL_Server.pm
1 package DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server;
2 use strict;
3 use warnings;
4
5 use base qw/DBIx::Class::Storage::DBI::MSSQL/;
6
7 sub insert_bulk {
8   my ($self, $source, $cols, $data) = @_;
9   next::method(@_);
10 }
11
12 sub _prep_for_execute {
13   my $self = shift;
14   my ($op, $extra_bind, $ident, $args) = @_;
15
16   my ($sql, $bind) = $self->next::method (@_);
17   $sql .= ';SELECT SCOPE_IDENTITY()' if $op eq 'insert';
18
19   my %identity_insert_tables;
20   my $col_info = $self->_resolve_column_info($ident, [map $_->[0], @{$bind}]);
21
22   foreach my $bound (@{$bind}) {
23     my $col = $bound->[0];
24     if ($col_info->{$col}->{is_auto_increment}) {
25       my $table = $col_info->{$col}->{-result_source}->from;
26       $identity_insert_tables{$table} = 1;
27     }
28   }
29
30   my $identity_insert_on = join '', map { "SET IDENTITY_INSERT $_ ON; " } keys %identity_insert_tables;
31   my $identity_insert_off = join '', map { "SET IDENTITY_INSERT $_ OFF; " } keys %identity_insert_tables;
32   $sql = "$identity_insert_on $sql $identity_insert_off";
33
34   return ($sql, $bind);
35 }
36
37 sub _execute {
38     my $self = shift;
39     my ($op) = @_;
40
41     my ($rv, $sth, @bind) = $self->dbh_do($self->can('_dbh_execute'), @_);
42     if ($op eq 'insert') {
43       $self->{_scope_identity} = $sth->fetchrow_array;
44       $sth->finish;
45     }
46
47     return wantarray ? ($rv, $sth, @bind) : $rv;
48 }
49
50 sub last_insert_id { shift->{_scope_identity} }
51
52 1;
53
54 __END__
55
56 =head1 NAME
57
58 DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server - Support specific
59 to Microsoft SQL Server over ODBC
60
61 =head1 DESCRIPTION
62
63 This class implements support specific to Microsoft SQL Server over ODBC,
64 including auto-increment primary keys and SQL::Abstract::Limit dialect.  It
65 is loaded automatically by by DBIx::Class::Storage::DBI::ODBC when it
66 detects a MSSQL back-end.
67
68 =head1 IMPLEMENTATION NOTES
69
70 Microsoft SQL Server supports three methods of retrieving the IDENTITY
71 value for inserted row: IDENT_CURRENT, @@IDENTITY, and SCOPE_IDENTITY().
72 SCOPE_IDENTITY is used here because it is the safest.  However, it must
73 be called is the same execute statement, not just the same connection.
74
75 So, this implementation appends a SELECT SCOPE_IDENTITY() statement
76 onto each INSERT to accommodate that requirement.
77
78 =head1 AUTHORS
79
80 Marc Mims C<< <marc@questright.com> >>
81
82 =head1 LICENSE
83
84 You may distribute this code under the same terms as Perl itself.
85
86 =cut
87 # vim: sw=2 sts=2