[Bast-commits] r7106 - in DBIx-Class/0.08/branches/mssql_storage_minor_refactor: lib/DBIx/Class/Storage/DBI lib/DBIx/Class/Storage/DBI/ODBC lib/DBIx/Class/Storage/DBI/Sybase t/inflate

caelum at dev.catalyst.perl.org caelum at dev.catalyst.perl.org
Fri Jul 24 05:28:11 GMT 2009


Author: caelum
Date: 2009-07-24 05:28:11 +0000 (Fri, 24 Jul 2009)
New Revision: 7106

Added:
   DBIx-Class/0.08/branches/mssql_storage_minor_refactor/t/inflate/datetime_mssql.t
Modified:
   DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/MSSQL.pm
   DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm
   DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/Sybase/Microsoft_SQL_Server.pm
Log:
moved code to ::DBI::MSSQL and added DT inflation test

Modified: DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/MSSQL.pm
===================================================================
--- DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/MSSQL.pm	2009-07-24 05:26:13 UTC (rev 7105)
+++ DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/MSSQL.pm	2009-07-24 05:28:11 UTC (rev 7106)
@@ -0,0 +1,142 @@
+package DBIx::Class::Storage::DBI::MSSQL;
+
+use strict;
+use warnings;
+
+use base qw/DBIx::Class::Storage::DBI::AmbiguousGlob DBIx::Class::Storage::DBI/;
+use mro 'c3';
+
+use List::Util();
+
+__PACKAGE__->sql_maker_class('DBIx::Class::SQLAHacks::MSSQL');
+
+sub insert_bulk {
+  my $self = shift;
+  my ($source, $cols, $data) = @_;
+
+  my $identity_insert = 0;
+
+  COLUMNS:
+  foreach my $col (@{$cols}) {
+    if ($source->column_info($col)->{is_auto_increment}) {
+      $identity_insert = 1;
+      last COLUMNS;
+    }
+  }
+
+  if ($identity_insert) {
+    my $table = $source->from;
+    $self->dbh->do("SET IDENTITY_INSERT $table ON");
+  }
+
+  $self->next::method(@_);
+
+  if ($identity_insert) {
+    my $table = $source->from;
+    $self->dbh->do("SET IDENTITY_INSERT $table OFF");
+  }
+}
+
+sub _prep_for_execute {
+  my $self = shift;
+  my ($op, $extra_bind, $ident, $args) = @_;
+
+# cast MONEY values properly
+  if ($op eq 'insert' || $op eq 'update') {
+    my $fields = $args->[0];
+    my $col_info = $self->_resolve_column_info($ident, [keys %$fields]);
+
+    for my $col (keys %$fields) {
+      if ($col_info->{$col}{data_type} =~ /^money\z/i) {
+        my $val = $fields->{$col};
+        $fields->{$col} = \['CAST(? AS MONEY)', [ $col => $val ]];
+      }
+    }
+  }
+
+  my ($sql, $bind) = $self->next::method (@_);
+
+  if ($op eq 'insert') {
+    $sql .= ';SELECT SCOPE_IDENTITY()';
+
+    my $col_info = $self->_resolve_column_info($ident, [map $_->[0], @{$bind}]);
+    if (List::Util::first { $_->{is_auto_increment} } (values %$col_info) ) {
+
+      my $table = $ident->from;
+      my $identity_insert_on = "SET IDENTITY_INSERT $table ON";
+      my $identity_insert_off = "SET IDENTITY_INSERT $table OFF";
+      $sql = "$identity_insert_on; $sql; $identity_insert_off";
+    }
+  }
+
+  return ($sql, $bind);
+}
+
+sub _execute {
+  my $self = shift;
+  my ($op) = @_;
+
+  my ($rv, $sth, @bind) = $self->dbh_do($self->can('_dbh_execute'), @_);
+  if ($op eq 'insert') {
+    $self->{_scope_identity} = $sth->fetchrow_array;
+    $sth->finish;
+  }
+
+  return wantarray ? ($rv, $sth, @bind) : $rv;
+}
+
+
+sub last_insert_id { shift->{_scope_identity} }
+
+sub build_datetime_parser {
+  my $self = shift;
+  my $type = "DateTime::Format::Strptime";
+  eval "use ${type}";
+  $self->throw_exception("Couldn't load ${type}: $@") if $@;
+  return $type->new( pattern => '%Y-%m-%d %H:%M:%S' );  # %F %T
+}
+
+sub sqlt_type { 'SQLServer' }
+
+sub _sql_maker_opts {
+  my ( $self, $opts ) = @_;
+
+  if ( $opts ) {
+    $self->{_sql_maker_opts} = { %$opts };
+  }
+
+  return { limit_dialect => 'Top', %{$self->{_sql_maker_opts}||{}} };
+}
+
+1;
+
+=head1 NAME
+
+DBIx::Class::Storage::DBI::MSSQL - Base Class for Microsoft SQL Server support
+in DBIx::Class
+
+=head1 SYNOPSIS
+
+This is the base class for Microsoft SQL Server support, used by
+L<DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server> and
+L<DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server>.
+
+=head1 IMPLEMENTATION NOTES
+
+Microsoft SQL Server supports three methods of retrieving the IDENTITY
+value for inserted row: IDENT_CURRENT, @@IDENTITY, and SCOPE_IDENTITY().
+SCOPE_IDENTITY is used here because it is the safest.  However, it must
+be called is the same execute statement, not just the same connection.
+
+So, this implementation appends a SELECT SCOPE_IDENTITY() statement
+onto each INSERT to accommodate that requirement.
+
+=head1 AUTHOR
+
+See L<DBIx::Class/CONTRIBUTORS>.
+
+=head1 LICENSE
+
+You may distribute this code under the same terms as Perl itself.
+
+=cut

Modified: DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm
===================================================================
--- DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm	2009-07-24 05:26:13 UTC (rev 7105)
+++ DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm	2009-07-24 05:28:11 UTC (rev 7106)
@@ -5,85 +5,6 @@
 use base qw/DBIx::Class::Storage::DBI::MSSQL/;
 use mro 'c3';
 
-use List::Util();
-
-sub insert_bulk {
-  my $self = shift;
-  my ($source, $cols, $data) = @_;
-
-  my $identity_insert = 0;
-
-  COLUMNS:
-  foreach my $col (@{$cols}) {
-    if ($source->column_info($col)->{is_auto_increment}) {
-      $identity_insert = 1;
-      last COLUMNS;
-    }
-  }
-
-  if ($identity_insert) {
-    my $table = $source->from;
-    $self->dbh->do("SET IDENTITY_INSERT $table ON");
-  }
-
-  $self->next::method(@_);
-
-  if ($identity_insert) {
-    my $table = $source->from;
-    $self->dbh->do("SET IDENTITY_INSERT $table OFF");
-  }
-}
-
-sub _prep_for_execute {
-  my $self = shift;
-  my ($op, $extra_bind, $ident, $args) = @_;
-
-# cast MONEY values properly
-  if ($op eq 'insert' || $op eq 'update') {
-    my $fields = $args->[0];
-    my $col_info = $self->_resolve_column_info($ident, [keys %$fields]);
-
-    for my $col (keys %$fields) {
-      if ($col_info->{$col}{data_type} =~ /^money\z/i) {
-        my $val = $fields->{$col};
-        $fields->{$col} = \['CAST(? AS MONEY)', [ $col => $val ]];
-      }
-    }
-  }
-
-  my ($sql, $bind) = $self->next::method (@_);
-
-  if ($op eq 'insert') {
-    $sql .= ';SELECT SCOPE_IDENTITY()';
-
-    my $col_info = $self->_resolve_column_info($ident, [map $_->[0], @{$bind}]);
-    if (List::Util::first { $_->{is_auto_increment} } (values %$col_info) ) {
-
-      my $table = $ident->from;
-      my $identity_insert_on = "SET IDENTITY_INSERT $table ON";
-      my $identity_insert_off = "SET IDENTITY_INSERT $table OFF";
-      $sql = "$identity_insert_on; $sql; $identity_insert_off";
-    }
-  }
-
-  return ($sql, $bind);
-}
-
-sub _execute {
-    my $self = shift;
-    my ($op) = @_;
-
-    my ($rv, $sth, @bind) = $self->dbh_do($self->can('_dbh_execute'), @_);
-    if ($op eq 'insert') {
-      $self->{_scope_identity} = $sth->fetchrow_array;
-      $sth->finish;
-    }
-
-    return wantarray ? ($rv, $sth, @bind) : $rv;
-}
-
-sub last_insert_id { shift->{_scope_identity} }
-
 1;
 
 __END__
@@ -95,25 +16,17 @@
 
 =head1 DESCRIPTION
 
-This class implements support specific to Microsoft SQL Server over ODBC,
-including auto-increment primary keys and SQL::Abstract::Limit dialect.  It
-is loaded automatically by by DBIx::Class::Storage::DBI::ODBC when it
-detects a MSSQL back-end.
+This class implements support specific to Microsoft SQL Server over ODBC.  It is
+loaded automatically by by DBIx::Class::Storage::DBI::ODBC when it detects a
+MSSQL back-end.
 
-=head1 IMPLEMENTATION NOTES
+Most of the functionality is provided from the superclass
+L<DBIx::Class::Storage::DBI::MSSQL>.
 
-Microsoft SQL Server supports three methods of retrieving the IDENTITY
-value for inserted row: IDENT_CURRENT, @@IDENTITY, and SCOPE_IDENTITY().
-SCOPE_IDENTITY is used here because it is the safest.  However, it must
-be called is the same execute statement, not just the same connection.
+=head1 AUTHOR
 
-So, this implementation appends a SELECT SCOPE_IDENTITY() statement
-onto each INSERT to accommodate that requirement.
+See L<DBIx::Class/CONTRIBUTORS>.
 
-=head1 AUTHORS
-
-Marc Mims C<< <marc at questright.com> >>
-
 =head1 LICENSE
 
 You may distribute this code under the same terms as Perl itself.

Modified: DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/Sybase/Microsoft_SQL_Server.pm
===================================================================
--- DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/Sybase/Microsoft_SQL_Server.pm	2009-07-24 05:26:13 UTC (rev 7105)
+++ DBIx-Class/0.08/branches/mssql_storage_minor_refactor/lib/DBIx/Class/Storage/DBI/Sybase/Microsoft_SQL_Server.pm	2009-07-24 05:28:11 UTC (rev 7106)
@@ -5,7 +5,7 @@
 
 use base qw/
   DBIx::Class::Storage::DBI::Sybase::Base
-  DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server
+  DBIx::Class::Storage::DBI::MSSQL
 /;
 use mro 'c3';
 
@@ -13,8 +13,8 @@
 
 =head1 NAME
 
-DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server - Storage::DBI subclass for MSSQL via
-DBD::Sybase
+DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server - Support for Microsoft
+SQL Server via DBD::Sybase
 
 =head1 SYNOPSIS
 
@@ -29,12 +29,10 @@
 More importantly this means that caching of prepared statements is explicitly
 disabled, as the interpolation renders it useless.
 
-=head1 AUTHORS
+=head1 AUTHOR
 
-Brandon L Black <blblack at gmail.com>
+See L<DBIx::Class/CONTRIBUTORS>.
 
-Justin Hunter <justin.d.hunter at gmail.com>
-
 =head1 LICENSE
 
 You may distribute this code under the same terms as Perl itself.

Added: DBIx-Class/0.08/branches/mssql_storage_minor_refactor/t/inflate/datetime_mssql.t
===================================================================
--- DBIx-Class/0.08/branches/mssql_storage_minor_refactor/t/inflate/datetime_mssql.t	                        (rev 0)
+++ DBIx-Class/0.08/branches/mssql_storage_minor_refactor/t/inflate/datetime_mssql.t	2009-07-24 05:28:11 UTC (rev 7106)
@@ -0,0 +1,80 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use Test::Exception;
+use lib qw(t/lib);
+use DBICTest;
+
+my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_MSSQL_ODBC_${_}" } qw/DSN USER PASS/};
+
+if (not ($dsn && $user)) {
+  plan skip_all =>
+    'Set $ENV{DBICTEST_MSSQL_ODBC_DSN}, _USER and _PASS to run this test' .
+    "\nWarning: This test drops and creates a table called 'track'";
+} else {
+  eval "use DateTime; use DateTime::Format::Strptime;";
+  if ($@) {
+    plan skip_all => 'needs DateTime and DateTime::Format::Strptime for testing';
+  }
+  else {
+    plan tests => 4 * 2; # (tests * dt_types)
+  }
+}
+
+my $schema = DBICTest::Schema->clone;
+
+$schema->connection($dsn, $user, $pass);
+$schema->storage->ensure_connected;
+
+my @dt_types = (
+  ['DATETIME', {
+    year => 2004,
+    month => 8,
+    day => 21,
+    hour => 14,
+    minute => 36,
+    second => 48,
+    nanosecond => 500000000,
+  }],
+  ['SMALLDATETIME', { # minute precision
+    year => 2004,
+    month => 8,
+    day => 21,
+    hour => 14,
+    minute => 36,
+  }],
+);
+
+for my $dt_type (@dt_types) {
+  my ($type, $sample_dt) = @$dt_type;
+
+  eval { $schema->storage->dbh->do("DROP TABLE track") };
+  $schema->storage->dbh->do(<<"SQL");
+CREATE TABLE track (
+ trackid INT IDENTITY PRIMARY KEY,
+ cd INT,
+ position INT,
+ last_updated_on $type,
+)
+SQL
+  ok(my $dt = DateTime->new($sample_dt));
+
+  my $row;
+  ok( $row = $schema->resultset('Track')->create({
+        last_updated_on => $dt,
+        cd => 1,
+      }));
+  ok( $row = $schema->resultset('Track')
+    ->search({ trackid => $row->trackid }, { select => ['last_updated_on'] })
+    ->first
+  );
+  is( $row->updated_date, $dt, 'DateTime roundtrip' );
+}
+
+# clean up our mess
+END {
+  if (my $dbh = eval { $schema->storage->_dbh }) {
+    $dbh->do('DROP TABLE track');
+  }
+}




More information about the Bast-commits mailing list