Merge 'mssql_top_fixes' into 'trunk'
Peter Rabbitson [Fri, 3 Jul 2009 18:20:42 +0000 (18:20 +0000)]
r6554@Thesaurus (orig r6553):  frew | 2009-06-09 00:06:42 +0200
branch for mssql top issues
r6572@Thesaurus (orig r6571):  frew | 2009-06-09 23:18:46 +0200
more tests for SQL Server!
r6573@Thesaurus (orig r6572):  frew | 2009-06-09 23:49:10 +0200
Added AmbiguousGlob.pm for silly servers like mssql and mysql.  See docs for more info
r6574@Thesaurus (orig r6573):  frew | 2009-06-09 23:55:22 +0200
fix plan
r6602@Thesaurus (orig r6601):  frew | 2009-06-10 17:03:30 +0200
more failing tests
r6608@Thesaurus (orig r6607):  frew | 2009-06-10 20:05:53 +0200
don't use eval!
r6610@Thesaurus (orig r6609):  frew | 2009-06-10 20:07:49 +0200
beginning of DWIM for IDENTITY_INSERT
r6628@Thesaurus (orig r6627):  frew | 2009-06-11 18:13:02 +0200
still busted :-(
r6631@Thesaurus (orig r6630):  frew | 2009-06-11 19:39:00 +0200
general function to go from column names and ident to result source
r6632@Thesaurus (orig r6631):  frew | 2009-06-11 19:40:11 +0200
Use new _resolve_column_sources method and begin insert_bulk method
r6635@Thesaurus (orig r6634):  frew | 2009-06-11 20:12:38 +0200
updated _resolve_column_source to _resolve_column_info as per ribasushi's suggestion
r6650@Thesaurus (orig r6649):  frew | 2009-06-12 17:13:32 +0200
Now I just need to check if the actual values are set...
r6651@Thesaurus (orig r6650):  frew | 2009-06-12 17:26:53 +0200
Insert Identity works!
r6652@Thesaurus (orig r6651):  frew | 2009-06-12 17:34:13 +0200
silly warns.
r6684@Thesaurus (orig r6683):  frew | 2009-06-15 16:49:00 +0200
failing test
r6686@Thesaurus (orig r6685):  ribasushi | 2009-06-15 18:10:26 +0200
make all resolved attrs visible to sqla
r6698@Thesaurus (orig r6697):  ribasushi | 2009-06-17 02:31:37 +0200
Half way working stuff, needs a LOT of tweaking still
r6729@Thesaurus (orig r6728):  ribasushi | 2009-06-19 19:49:27 +0200
Merge badness
r6730@Thesaurus (orig r6729):  ribasushi | 2009-06-19 19:49:40 +0200
fix eol
r6731@Thesaurus (orig r6730):  ribasushi | 2009-06-19 19:55:47 +0200
augment inheritance
r6735@Thesaurus (orig r6734):  ribasushi | 2009-06-20 10:34:42 +0200
Maybe I've nailed it
r6746@Thesaurus (orig r6745):  ribasushi | 2009-06-20 23:53:55 +0200
Test and merge fixes
r6747@Thesaurus (orig r6746):  ribasushi | 2009-06-21 00:01:09 +0200
Really fix tests
r6748@Thesaurus (orig r6747):  ribasushi | 2009-06-21 00:01:54 +0200
Really fix tests
r6749@Thesaurus (orig r6748):  ribasushi | 2009-06-21 00:18:33 +0200
Now really final
r6750@Thesaurus (orig r6749):  ribasushi | 2009-06-21 00:22:23 +0200
whoops
r6751@Thesaurus (orig r6750):  ribasushi | 2009-06-21 00:42:18 +0200
That should be all
r6752@Thesaurus (orig r6751):  ribasushi | 2009-06-21 08:54:00 +0200
Make sure quoting works
r6755@Thesaurus (orig r6754):  ribasushi | 2009-06-21 15:21:23 +0200
Groundwork for sanification of the toplimit test
r6863@Thesaurus (orig r6862):  ribasushi | 2009-06-30 01:13:49 +0200
Make sure storage classes use c3, just like the rest of dbic (tested on 5.8 as well)
r6869@Thesaurus (orig r6868):  ribasushi | 2009-06-30 09:53:27 +0200
Some fixes after review
r6874@Thesaurus (orig r6873):  ribasushi | 2009-06-30 11:54:34 +0200
Fix borked next invocation
r6896@Thesaurus (orig r6895):  frew | 2009-06-30 21:38:26 +0200
silly misspells and trailing whitespace
r6955@Thesaurus (orig r6954):  ribasushi | 2009-07-03 01:21:28 +0200
Some hack consolidation
r6962@Thesaurus (orig r6961):  ribasushi | 2009-07-03 12:06:57 +0200
Fix some mssql shortcommings when confronted with the new subequeried prefetch sql
r6963@Thesaurus (orig r6962):  ribasushi | 2009-07-03 12:47:57 +0200
Ask for newer DBD::Pg in author mode, suggest the newer version otherwise (proper array support). Make test more resilient as well
r6964@Thesaurus (orig r6963):  ribasushi | 2009-07-03 12:49:16 +0200
Switch to C3 mro throughout the ::Storage hierarchy (DBIx::Class brings in MRO::Compat, and all ::Storage's are based on it, tested on 5.8
r6969@Thesaurus (orig r6968):  ribasushi | 2009-07-03 19:54:04 +0200
Duh
r6970@Thesaurus (orig r6969):  frew | 2009-07-03 19:59:48 +0200
fix tests for new codez
r6971@Thesaurus (orig r6970):  ribasushi | 2009-07-03 20:18:53 +0200
detabify
r6972@Thesaurus (orig r6971):  ribasushi | 2009-07-03 20:20:07 +0200
changes

Changes
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/Storage/DBI/mysql.pm
t/71mysql.t
t/lib/DBICTest/Schema/Artwork.pm
t/lib/DBICTest/Schema/CD.pm
t/multi_create/multilev_might_have_PKeqFK.t [deleted file]
t/multi_create/multilev_single_PKeqFK.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index 443a8b4..fe80b31 100644 (file)
--- a/Changes
+++ b/Changes
@@ -6,6 +6,12 @@ Revision history for DBIx::Class
         - New resultsed method count_rs, returns a ::ResultSetColumn
           which in turn returns a single count value
         - Even better support of count with limit
+        - New on_connect_call/on_disconnect_call functionality (check
+          POD of Storage::DBI)
+        - Automatic datetime handling environment/session setup for
+          Oracle via connect_call_datetime_setup()
+        - MySQL can now be turned into a sane database by adding
+          { on_connect_call => 'set_ansi_mode' } to the connect() call
         - count/all on related left-joined empty resultsets now correctly
           returns 0/()
         - Fixed regression when both page and offset are specified on
index fae8f01..3ffec5c 100644 (file)
@@ -2233,12 +2233,15 @@ store. If the appropriate relationships are set up, foreign key fields
 can also be passed an object representing the foreign row, and the
 value will be set to its primary key.
 
-To create related objects, pass a hashref for the value if the related
-item is a foreign key relationship (L<DBIx::Class::Relationship/belongs_to>),
-and use the name of the relationship as the key. (NOT the name of the field,
-necessarily). For C<has_many> and C<has_one> relationships, pass an arrayref
-of hashrefs containing the data for each of the rows to create in the foreign
-tables, again using the relationship name as the key.
+To create related objects, pass a hashref of related-object column values
+B<keyed on the relationship name>. If the relationship is of type C<multi>
+(L<DBIx::Class::Relationship/has_many>) - pass an arrayref of hashrefs.
+The process will correctly identify columns holding foreign keys, and will
+transparrently populate them from the keys of the corresponding relation.
+This can be applied recursively, and will work correctly for a structure
+with an arbitrary depth and width, as long as the relationships actually
+exists and the correct column data has been supplied.
+
 
 Instead of hashrefs of plain related data (key/value pairs), you may
 also pass new or inserted objects. New objects (not inserted yet, see
index 0eb53d2..aa1530b 100644 (file)
@@ -15,15 +15,15 @@ __PACKAGE__->sql_maker_class('DBIx::Class::SQLAHacks::MySQL');
 sub with_deferred_fk_checks {
   my ($self, $sub) = @_;
 
-  $self->dbh->do('SET foreign_key_checks=0');
+  $self->_do_query('SET FOREIGN_KEY_CHECKS = 0');
   $sub->();
-  $self->dbh->do('SET foreign_key_checks=1');
+  $self->_do_query('SET FOREIGN_KEY_CHECKS = 1');
 }
 
 sub connect_call_set_ansi_mode {
   my $self = shift;
-  $self->dbh->do(q|SET sql_mode = 'ANSI,TRADITIONAL'|);
-  $self->dbh->do(q|SET sql_mode = 'ANSI,TRADITIONAL'|);
+  $self->_do_query(q|SET SQL_MODE = 'ANSI,TRADITIONAL'|);
+  $self->_do_query(q|SET SQL_AUTO_IS_NULL = 0|);
 }
 
 sub _dbh_last_insert_id {
index 88d6ea2..836c846 100644 (file)
@@ -155,41 +155,36 @@ SKIP: {
     is_deeply($type_info, $test_type_info, 'columns_info_for - column data types');
 }
 
+my $cd = $schema->resultset ('CD')->create ({});
+my $producer = $schema->resultset ('Producer')->create ({});
+lives_ok { $cd->set_producers ([ $producer ]) } 'set_relationship doesnt die';
+
+
 ## Can we properly deal with the null search problem?
 ##
 ## Only way is to do a SET SQL_AUTO_IS_NULL = 0; on connect
 ## But I'm not sure if we should do this or not (Ash, 2008/06/03)
+#
+# There is now a built-in function to do this, test that everything works
+# with it (ribasushi, 2009/07/03)
 
 NULLINSEARCH: {
-    
-    ok my $artist1_rs = $schema->resultset('Artist')->search({artistid=>6666})
-    => 'Created an artist resultset of 6666';
-    
+    my $ansi_schema = DBICTest::Schema->connect ($dsn, $user, $pass, { on_connect_call => 'set_ansi_mode' });
+
+    ok my $artist1_rs = $ansi_schema->resultset('Artist')->search({artistid=>6666})
+      => 'Created an artist resultset of 6666';
+
     is $artist1_rs->count, 0
-    => 'Got no returned rows';
-    
-    ok my $artist2_rs = $schema->resultset('Artist')->search({artistid=>undef})
-    => 'Created an artist resultset of undef';
-    
-    TODO: {
-       local $TODO = "need to fix the row count =1 when select * from table where pk IS NULL problem";
-           is $artist2_rs->count, 0
-           => 'got no rows';           
-    }
+      => 'Got no returned rows';
 
-    my $artist = $artist2_rs->single;
-    
-    is $artist => undef
-    => 'Nothing Found!';
-}
-    
-my $cd = $schema->resultset ('CD')->create ({});
+    ok my $artist2_rs = $ansi_schema->resultset('Artist')->search({artistid=>undef})
+      => 'Created an artist resultset of undef';
 
-my $producer = $schema->resultset ('Producer')->create ({});
+    is $artist2_rs->count, 0
+      => 'got no rows';
 
-lives_ok { $cd->set_producers ([ $producer ]) } 'set_relationship doesnt die';
+    my $artist = $artist2_rs->single;
 
-# clean up our mess
-END {
-    #$dbh->do("DROP TABLE artist") if $dbh;
+    is $artist => undef
+      => 'Nothing Found!';
 }
index 849096b..4eecef5 100644 (file)
@@ -7,6 +7,7 @@ __PACKAGE__->table('cd_artwork');
 __PACKAGE__->add_columns(
   'cd_id' => {
     data_type => 'integer',
+    is_nullable => 0,
   },
 );
 __PACKAGE__->set_primary_key('cd_id');
index ec6ab24..80af1df 100644 (file)
@@ -56,6 +56,7 @@ __PACKAGE__->might_have(
     { proxy => [ qw/notes/ ] },
 );
 __PACKAGE__->might_have(artwork => 'DBICTest::Schema::Artwork', 'cd_id');
+__PACKAGE__->has_one(mandatory_artwork => 'DBICTest::Schema::Artwork', 'cd_id');
 
 __PACKAGE__->many_to_many( producers => cd_to_producer => 'producer' );
 __PACKAGE__->many_to_many(
diff --git a/t/multi_create/multilev_might_have_PKeqFK.t b/t/multi_create/multilev_might_have_PKeqFK.t
deleted file mode 100644 (file)
index 702ffba..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-use strict;
-use warnings;
-
-use Test::More;
-use Test::Exception;
-use lib qw(t/lib);
-use DBICTest;
-
-sub mc_diag { diag (@_) if $ENV{DBIC_MULTICREATE_DEBUG} };
-
-plan tests => 8;
-
-my $schema = DBICTest->init_schema();
-
-mc_diag (<<'DG');
-* Test a multilevel might-have with a PK == FK in the might_have/has_many table
-
-CD -> might have -> Artwork
-                       \
-                        \-> has_many \
-                                      --> Artwork_to_Artist
-                        /-> has_many /
-                       /
-                     Artist
-DG
-
-lives_ok (sub {
-  my $someartist = $schema->resultset('Artist')->first;
-  my $cd = $schema->resultset('CD')->create ({
-    artist => $someartist,
-    title => 'Music to code by until the cows come home',
-    year => 2008,
-    artwork => {
-      artwork_to_artist => [
-        { artist => { name => 'cowboy joe' } },
-        { artist => { name => 'billy the kid' } },
-      ],
-    },
-  });
-
-  isa_ok ($cd, 'DBICTest::CD', 'Main CD object created');
-  is ($cd->title, 'Music to code by until the cows come home', 'Correct CD title');
-
-  my $art_obj = $cd->artwork;
-  ok ($art_obj->has_column_loaded ('cd_id'), 'PK/FK present on artwork object');
-  is ($art_obj->artists->count, 2, 'Correct artwork creator count via the new object');
-  is_deeply (
-    [ sort $art_obj->artists->get_column ('name')->all ],
-    [ 'billy the kid', 'cowboy joe' ],
-    'Artists named correctly when queried via object',
-  );
-
-  my $artwork = $schema->resultset('Artwork')->search (
-    { 'cd.title' => 'Music to code by until the cows come home' },
-    { join => 'cd' },
-  )->single;
-  is ($artwork->artists->count, 2, 'Correct artwork creator count via a new search');
-  is_deeply (
-    [ sort $artwork->artists->get_column ('name')->all ],
-    [ 'billy the kid', 'cowboy joe' ],
-    'Artists named correctly queried via a new search',
-  );
-}, 'multilevel might-have with a PK == FK in the might_have/has_many table ok');
-
-1;
diff --git a/t/multi_create/multilev_single_PKeqFK.t b/t/multi_create/multilev_single_PKeqFK.t
new file mode 100644 (file)
index 0000000..07101a2
--- /dev/null
@@ -0,0 +1,105 @@
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+use lib qw(t/lib);
+use DBICTest;
+
+sub mc_diag { diag (@_) if $ENV{DBIC_MULTICREATE_DEBUG} };
+
+plan tests => 26;
+
+my $schema = DBICTest->init_schema();
+
+mc_diag (<<'DG');
+* Test a multilevel might-have/has_one with a PK == FK in the mid-table
+
+CD -> might have -> Artwork
+    \- has_one -/     \
+                       \
+                        \-> has_many \
+                                      --> Artwork_to_Artist
+                        /-> has_many /
+                       /
+                     Artist
+DG
+
+my $rels = {
+  has_one => 'mandatory_artwork',
+  might_have => 'artwork',
+};
+
+for my $type (qw/has_one might_have/) {
+
+  lives_ok (sub {
+
+    my $rel = $rels->{$type};
+    my $cd_title = "Simple test $type cd";
+
+    my $cd = $schema->resultset('CD')->create ({
+      artist => 1,
+      title => $cd_title,
+      year => 2008,
+      $rel => {},
+    });
+
+    isa_ok ($cd, 'DBICTest::CD', 'Main CD object created');
+    is ($cd->title, $cd_title, 'Correct CD title');
+
+    isa_ok ($cd->$rel, 'DBICTest::Artwork', 'Related artwork present');
+    ok ($cd->$rel->in_storage, 'And in storage');
+
+  }, "Simple $type creation");
+}
+
+my $artist_rs = $schema->resultset('Artist');
+for my $type (qw/has_one might_have/) {
+
+  my $rel = $rels->{$type};
+
+  my $cd_title = "Test $type cd";
+  my $artist_names = [ map { "Artist via $type $_" } (1, 2) ];
+
+  my $someartist = $artist_rs->next;
+
+  lives_ok (sub {
+    my $cd = $schema->resultset('CD')->create ({
+      artist => $someartist,
+      title => $cd_title,
+      year => 2008,
+      $rel => {
+      artwork_to_artist => [ map {
+            { artist => { name => $_ } }
+          } (@$artist_names)
+        ]
+      },
+    });
+
+
+    isa_ok ($cd, 'DBICTest::CD', 'Main CD object created');
+    is ($cd->title, $cd_title, 'Correct CD title');
+
+    my $art_obj = $cd->$rel;
+    ok ($art_obj->has_column_loaded ('cd_id'), 'PK/FK present on artwork object');
+    is ($art_obj->artists->count, 2, 'Correct artwork creator count via the new object');
+    is_deeply (
+      [ sort $art_obj->artists->get_column ('name')->all ],
+      $artist_names,
+      'Artists named correctly when queried via object',
+    );
+
+    my $artwork = $schema->resultset('Artwork')->search (
+      { 'cd.title' => $cd_title },
+      { join => 'cd' },
+    )->single;
+    is ($artwork->artists->count, 2, 'Correct artwork creator count via a new search');
+    is_deeply (
+        [ sort $artwork->artists->get_column ('name')->all ],
+      $artist_names,
+      'Artists named correctly queried via a new search',
+    );
+  }, "multilevel $type with a PK == FK in the $type/has_many table ok");
+}
+
+1;