ODBC fixes: superfluous connection in rebless; undef PK on first insert in MSSQL
[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/;
6
7 sub _prep_for_execute {
8     my $self = shift;
9     my ($op, $extra_bind, $ident, $args) = @_;
10
11     my ($sql, $bind) = $self->SUPER::_prep_for_execute(@_);
12     $sql .= ';SELECT SCOPE_IDENTITY()' if $op eq 'insert';
13
14     return ($sql, $bind);
15 }
16
17 sub _execute {
18     my $self = shift;
19     my ($op) = @_;
20
21     my ($rv, $sth, @bind) = $self->dbh_do($self->can('_dbh_execute'), @_);
22     $self->{_scope_identity} = $sth->fetchrow_array if $op eq 'insert';
23
24     return wantarray ? ($rv, $sth, @bind) : $rv;
25 }
26
27 sub last_insert_id { shift->{_scope_identity} }
28
29 sub sqlt_type { 'SQLServer' }
30
31 sub _sql_maker_opts {
32     my ( $self, $opts ) = @_;
33
34     if ( $opts ) {
35         $self->{_sql_maker_opts} = { %$opts };
36     }
37
38     return { limit_dialect => 'Top', %{$self->{_sql_maker_opts}||{}} };
39 }
40
41 sub build_datetime_parser {
42   my $self = shift;
43   my $type = "DateTime::Format::Strptime";
44   eval "use ${type}";
45   $self->throw_exception("Couldn't load ${type}: $@") if $@;
46   return $type->new( pattern => '%F %T' );
47 }
48
49 1;
50
51 __END__
52
53 =head1 NAME
54
55 DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server - Support specific
56 to Microsoft SQL Server over ODBC
57
58 =head1 DESCRIPTION
59
60 This class implements support specific to Microsoft SQL Server over ODBC,
61 including auto-increment primary keys and SQL::Abstract::Limit dialect.  It
62 is loaded automatically by by DBIx::Class::Storage::DBI::ODBC when it
63 detects a MSSQL back-end.
64
65 =head1 IMPLEMENTATION NOTES
66
67 Microsoft SQL Server supports three methods of retrieving the IDENTITY
68 value for inserted row: IDENT_CURRENT, @@IDENTITY, and SCOPE_IDENTITY().
69 SCOPE_IDENTITY is used here because it is the safest.  However, it must
70 be called is the same execute statement, not just the same connection.
71
72 So, this implementation appends a SELECT SCOPE_IDENTITY() statement
73 onto each INSERT to accommodate that requirement.
74
75 =head1 METHODS
76
77 =head2 last_insert_id
78
79 =head2 sqlt_type
80
81 =head2 build_datetime_parser
82
83 The resulting parser handles the MSSQL C<DATETIME> type, but is almost
84 certainly not sufficient for the other MSSQL 2008 date/time types.
85
86 =head1 AUTHORS
87
88 Marc Mims C<< <marc@questright.com> >>
89
90 =head1 LICENSE
91
92 You may distribute this code under the same terms as Perl itself.
93
94 =cut