Merge 'mssql_money_type' into 'trunk'
Rafael Kitover [Thu, 23 Jul 2009 18:14:11 +0000 (18:14 +0000)]
r6092@hlagh (orig r7090):  caelum | 2009-07-23 08:24:39 -0400
new branch for fixing the MONEY type in MSSQL
r6093@hlagh (orig r7091):  caelum | 2009-07-23 08:34:01 -0400
add test
r6283@hlagh (orig r7093):  caelum | 2009-07-23 10:31:08 -0400
fix money columns
r6284@hlagh (orig r7094):  caelum | 2009-07-23 10:34:06 -0400
minor change
r6285@hlagh (orig r7095):  caelum | 2009-07-23 11:01:37 -0400
add test for updating money value to NULL
r6286@hlagh (orig r7096):  caelum | 2009-07-23 14:09:26 -0400
add money type tests to dbd::sybase+mssql tests

lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm
t/746mssql.t
t/74mssql.t
t/lib/DBICTest/Schema.pm
t/lib/DBICTest/Schema/Money.pm [new file with mode: 0644]

index 2fde285..48f281b 100644 (file)
@@ -38,6 +38,19 @@ 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') {
index f5c0071..fa8f137 100644 (file)
@@ -12,7 +12,7 @@ my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_MSSQL_ODBC_${_}" } qw/DSN USER PA
 plan skip_all => 'Set $ENV{DBICTEST_MSSQL_ODBC_DSN}, _USER and _PASS to run this test'
   unless ($dsn && $user);
 
-plan tests => 27;
+plan tests => 33;
 
 my $schema = DBICTest::Schema->connect($dsn, $user, $pass);
 
@@ -75,6 +75,42 @@ $it->next;
 is( $it->next->name, "Artist 2", "iterator->next ok" );
 is( $it->next, undef, "next past end of resultset ok" );
 
+# test MONEY type
+$schema->storage->dbh_do (sub {
+    my ($storage, $dbh) = @_;
+    eval { $dbh->do("DROP TABLE money_test") };
+    $dbh->do(<<'SQL');
+
+CREATE TABLE money_test (
+   id INT IDENTITY PRIMARY KEY,
+   amount MONEY NULL
+)
+
+SQL
+
+});
+
+my $rs = $schema->resultset('Money');
+
+my $row;
+lives_ok {
+  $row = $rs->create({ amount => 100 });
+} 'inserted a money value';
+
+is $rs->find($row->id)->amount, '100.00', 'money value round-trip';
+
+lives_ok {
+  $row->update({ amount => 200 });
+} 'updated a money value';
+
+is $rs->find($row->id)->amount, '200.00', 'updated money value round-trip';
+
+lives_ok {
+  $row->update({ amount => undef });
+} 'updated a money value to NULL';
+
+is $rs->find($row->id)->amount, undef,'updated money value to NULL round-trip';
+
 $schema->storage->dbh_do (sub {
     my ($storage, $dbh) = @_;
     eval { $dbh->do("DROP TABLE Owners") };
@@ -232,7 +268,11 @@ $schema->storage->_sql_maker->{name_sep} = '.';
 
 # clean up our mess
 END {
-    my $dbh = eval { $schema->storage->_dbh };
-    $dbh->do('DROP TABLE artist') if $dbh;
+    if (my $dbh = eval { $schema->storage->_dbh }) {
+      $dbh->do('DROP TABLE artist');
+      $dbh->do('DROP TABLE money_test');
+      $dbh->do('DROP TABLE Books');
+      $dbh->do('DROP TABLE Owners');
+    }
 }
 # vim:sw=2 sts=2
index c0cea0c..cbaffc0 100644 (file)
@@ -18,7 +18,7 @@ my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_MSSQL_${_}" } qw/DSN USER PASS/};
 plan skip_all => 'Set $ENV{DBICTEST_MSSQL_DSN}, _USER and _PASS to run this test'
   unless ($dsn);
 
-plan tests => 7;
+plan tests => 13;
 
 my $schema = DBICTest::Schema->clone;
 $schema->connection($dsn, $user, $pass);
@@ -74,10 +74,48 @@ $it->next;
 $it->next;
 is( $it->next, undef, "next past end of resultset ok" );
 
+# test MONEY column support
+$schema->storage->dbh_do (sub {
+    my ($storage, $dbh) = @_;
+    eval { $dbh->do("DROP TABLE money_test") };
+    $dbh->do(<<'SQL');
+
+CREATE TABLE money_test (
+   id INT IDENTITY PRIMARY KEY,
+   amount MONEY NULL
+)
+
+SQL
+
+});
+
+my $rs = $schema->resultset('Money');
+
+my $row;
+lives_ok {
+  $row = $rs->create({ amount => 100 });
+} 'inserted a money value';
+
+is $rs->find($row->id)->amount, 100, 'money value round-trip';
+
+lives_ok {
+  $row->update({ amount => 200 });
+} 'updated a money value';
+
+is $rs->find($row->id)->amount, 200, 'updated money value round-trip';
+
+lives_ok {
+  $row->update({ amount => undef });
+} 'updated a money value to NULL';
+
+is $rs->find($row->id)->amount, undef,'updated money value to NULL round-trip';
+
 # clean up our mess
 END {
     $dbh->do("IF OBJECT_ID('artist', 'U') IS NOT NULL DROP TABLE artist")
         if $dbh;
     $dbh->do("IF OBJECT_ID('cd', 'U') IS NOT NULL DROP TABLE cd")
         if $dbh;
+    $dbh->do("IF OBJECT_ID('money_test', 'U') IS NOT NULL DROP TABLE money_test")
+        if $dbh;
 }
index ab5b098..a3e4484 100644 (file)
@@ -21,6 +21,7 @@ __PACKAGE__->load_classes(qw/
   Year2000CDs
   Year1999CDs
   CustomSql
+  Money
   /,
   { 'DBICTest::Schema' => [qw/
     LinerNotes
diff --git a/t/lib/DBICTest/Schema/Money.pm b/t/lib/DBICTest/Schema/Money.pm
new file mode 100644 (file)
index 0000000..f4586eb
--- /dev/null
@@ -0,0 +1,21 @@
+package # hide from PAUSE 
+    DBICTest::Schema::Money;
+
+use base qw/DBICTest::BaseResult/;
+
+__PACKAGE__->table('money_test');
+
+__PACKAGE__->add_columns(
+  'id' => {
+    data_type => 'integer',
+    is_auto_increment => 1,
+  },
+  'amount' => {
+    data_type => 'money',
+    is_nullable => 1,
+  },
+);
+
+__PACKAGE__->set_primary_key('id');
+
+1;