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