1 package DBIx::Class::Storage::DBI::MSSQL;
6 use base qw/DBIx::Class::Storage::DBI::AmbiguousGlob DBIx::Class::Storage::DBI/;
11 __PACKAGE__->sql_maker_class('DBIx::Class::SQLAHacks::MSSQL');
15 my ($source, $cols, $data) = @_;
17 my $identity_insert = 0;
20 foreach my $col (@{$cols}) {
21 if ($source->column_info($col)->{is_auto_increment}) {
27 if ($identity_insert) {
28 my $table = $source->from;
29 $self->dbh->do("SET IDENTITY_INSERT $table ON");
32 $self->next::method(@_);
34 if ($identity_insert) {
35 my $table = $source->from;
36 $self->dbh->do("SET IDENTITY_INSERT $table OFF");
40 sub _prep_for_execute {
42 my ($op, $extra_bind, $ident, $args) = @_;
44 # cast MONEY values properly
45 if ($op eq 'insert' || $op eq 'update') {
46 my $fields = $args->[0];
47 my $col_info = $self->_resolve_column_info($ident, [keys %$fields]);
49 for my $col (keys %$fields) {
50 if ($col_info->{$col}{data_type} =~ /^money\z/i) {
51 my $val = $fields->{$col};
52 $fields->{$col} = \['CAST(? AS MONEY)', [ $col => $val ]];
57 my ($sql, $bind) = $self->next::method (@_);
59 if ($op eq 'insert') {
60 $sql .= ';SELECT SCOPE_IDENTITY()';
62 my $col_info = $self->_resolve_column_info($ident, [map $_->[0], @{$bind}]);
63 if (List::Util::first { $_->{is_auto_increment} } (values %$col_info) ) {
65 my $table = $ident->from;
66 my $identity_insert_on = "SET IDENTITY_INSERT $table ON";
67 my $identity_insert_off = "SET IDENTITY_INSERT $table OFF";
68 $sql = "$identity_insert_on; $sql; $identity_insert_off";
79 my ($rv, $sth, @bind) = $self->dbh_do($self->can('_dbh_execute'), @_);
80 if ($op eq 'insert') {
81 $self->{_scope_identity} = $sth->fetchrow_array;
85 return wantarray ? ($rv, $sth, @bind) : $rv;
89 sub last_insert_id { shift->{_scope_identity} }
91 sub build_datetime_parser {
93 my $type = "DateTime::Format::Strptime";
95 $self->throw_exception("Couldn't load ${type}: $@") if $@;
96 return $type->new( pattern => '%Y-%m-%d %H:%M:%S' ); # %F %T
99 sub sqlt_type { 'SQLServer' }
101 sub _sql_maker_opts {
102 my ( $self, $opts ) = @_;
105 $self->{_sql_maker_opts} = { %$opts };
108 return { limit_dialect => 'Top', %{$self->{_sql_maker_opts}||{}} };
115 DBIx::Class::Storage::DBI::MSSQL - Base Class for Microsoft SQL Server support
120 This is the base class for Microsoft SQL Server support, used by
121 L<DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server> and
122 L<DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server>.
124 =head1 IMPLEMENTATION NOTES
126 Microsoft SQL Server supports three methods of retrieving the IDENTITY
127 value for inserted row: IDENT_CURRENT, @@IDENTITY, and SCOPE_IDENTITY().
128 SCOPE_IDENTITY is used here because it is the safest. However, it must
129 be called is the same execute statement, not just the same connection.
131 So, this implementation appends a SELECT SCOPE_IDENTITY() statement
132 onto each INSERT to accommodate that requirement.
136 See L<DBIx::Class/CONTRIBUTORS>.
140 You may distribute this code under the same terms as Perl itself.