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