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