Fix RT#58554 (make sure FOR X is always the last part of a select)
[dbsrgits/DBIx-Class.git] / t / 72pg.t
index f3ad48e..10ef8b2 100644 (file)
--- a/t/72pg.t
+++ b/t/72pg.t
@@ -3,6 +3,7 @@ use warnings;
 
 use Test::More;
 use Test::Exception;
+use Sub::Name;
 use lib qw(t/lib);
 use DBICTest;
 
@@ -23,15 +24,6 @@ EOM
 our @test_classes; #< array that will be pushed into by test classes defined in this file
 DBICTest::Schema->load_classes( map {s/.+:://;$_} @test_classes ) if @test_classes;
 
-my $schema;
-
-for my $use_insert_returning (0..1) {
-  no warnings qw/redefine once/;
-  require DBIx::Class::Storage::DBI::Pg;
-  local *DBIx::Class::Storage::DBI::Pg::can_insert_returning = sub {
-    $use_insert_returning
-  };
-
 ###  pre-connect tests (keep each test separate as to make sure rebless() runs)
   {
     my $s = DBICTest::Schema->connect($dsn, $user, $pass);
@@ -52,6 +44,7 @@ for my $use_insert_returning (0..1) {
 
     ok (!$s->storage->_dbh, 'still not connected');
   }
+
   {
     my $s = DBICTest::Schema->connect($dsn, $user, $pass);
     # make sure sqlt_type overrides work (::Storage::DBI::Pg does this)
@@ -60,9 +53,84 @@ for my $use_insert_returning (0..1) {
     ok (!$s->storage->_dbh, 'still not connected');
   }
 
+# test LIMIT support
+{
+  my $schema = DBICTest::Schema->connect($dsn, $user, $pass);
+  drop_test_schema($schema);
+  create_test_schema($schema);
+  for (1..6) {
+    $schema->resultset('Artist')->create({ name => 'Artist ' . $_ });
+  }
+  my $it = $schema->resultset('Artist')->search( {},
+    { rows => 3,
+      offset => 2,
+      order_by => 'artistid' }
+  );
+  is( $it->count, 3, "LIMIT count ok" );  # ask for 3 rows out of 6 artists
+  is( $it->next->name, "Artist 3", "iterator->next ok" );
+  $it->next;
+  $it->next;
+  $it->next;
+  is( $it->next, undef, "next past end of resultset ok" );
+
+  # Limit with select-lock
+  lives_ok {
+    $schema->txn_do (sub {
+      isa_ok (
+        $schema->resultset('Artist')->find({artistid => 1}, {for => 'update', rows => 1}),
+        'DBICTest::Schema::Artist',
+      );
+    });
+  } 'Limited FOR UPDATE select works';
+}
+
+# check if we indeed do support stuff
+my $test_server_supports_insert_returning = do {
+  my $v = DBICTest::Schema->connect($dsn, $user, $pass)
+                   ->storage
+                    ->_get_dbh
+                     ->get_info(18);
+  $v =~ /^(\d+)\.(\d+)/
+    or die "Unparseable Pg server version: $v\n";
+
+  ( sprintf ('%d.%d', $1, $2) >= 8.2 ) ? 1 : 0;
+};
+is (
+  DBICTest::Schema->connect($dsn, $user, $pass)->storage->_use_insert_returning,
+  $test_server_supports_insert_returning,
+  'insert returning capability guessed correctly'
+);
+
+my $schema;
+for my $use_insert_returning ($test_server_supports_insert_returning
+  ? (0,1)
+  : (0)
+) {
+
+  no warnings qw/once/;
+  local *DBICTest::Schema::connection = subname 'DBICTest::Schema::connection' => sub {
+    my $s = shift->next::method (@_);
+    $s->storage->_use_insert_returning ($use_insert_returning);
+    $s;
+  };
+
+### test capability override
+  {
+    my $s = DBICTest::Schema->connect($dsn, $user, $pass);
+
+    ok (!$s->storage->_dbh, 'definitely not connected');
+
+    ok (
+      ! ($s->storage->_use_insert_returning xor $use_insert_returning),
+      'insert returning capability set correctly',
+    );
+    ok (!$s->storage->_dbh, 'still not connected (capability override works)');
+  }
+
 ### connect, create postgres-specific test schema
 
   $schema = DBICTest::Schema->connect($dsn, $user, $pass);
+  $schema->storage->ensure_connected;
 
   drop_test_schema($schema);
   create_test_schema($schema);
@@ -192,6 +260,15 @@ for my $use_insert_returning (0..1) {
   is( $uc_name_info->{size}, 3, "Case insensitive matching info for 'uc_name'" );
 
 
+## Test ResultSet->update
+my $artist = $schema->resultset('Artist')->first;
+my $cds = $artist->cds_unordered->search({
+    year => { '!=' => 2010 }
+}, { prefetch => 'liner_notes' });
+TODO: {
+    todo_skip 'update resultset with a prefetch over a might_have rel', 1;
+    $cds->update({ year => '2010' });
+}
 
 
 ## Test SELECT ... FOR UPDATE
@@ -229,12 +306,15 @@ for my $use_insert_returning (0..1) {
         $schema2->source("Artist")->name("dbic_t_schema.artist");
 
         $schema->txn_do( sub {
-          my $artist = $schema->resultset('Artist')->search(
+          my $rs = $schema->resultset('Artist')->search(
               {
                   artistid => 1
               },
               $t->{update_lock} ? { for => 'update' } : {}
-          )->first;
+          );
+          ok ($rs->count, 'Count works');
+
+          my $artist = $rs->next;
           is($artist->artistid, 1, "select returns artistid = 1");
 
           $timed_out = 0;
@@ -269,7 +349,7 @@ for my $use_insert_returning (0..1) {
 
 ######## test non-serial auto-pk
 
-  if ($schema->storage->can_insert_returning) {
+  if ($schema->storage->_use_insert_returning) {
     $schema->source('TimestampPrimaryKey')->name('dbic_t_schema.timestamp_primary_key_test');
     my $row = $schema->resultset('TimestampPrimaryKey')->create({});
     ok $row->id;