Fix annoying warnings on innocent looking MSSQL code
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / MSSQL.pm
index 4eb090a..aed3689 100644 (file)
@@ -9,7 +9,8 @@ use base qw/
 /;
 use mro 'c3';
 
-use DBIx::Class::_Util 'dbic_internal_try';
+use Try::Tiny;
+use DBIx::Class::_Util qw( dbic_internal_try sigwarn_silencer );
 use List::Util 'first';
 use namespace::clean;
 
@@ -175,16 +176,34 @@ sub _ping {
 
   my $dbh = $self->_dbh or return 0;
 
-  local $dbh->{RaiseError} = 1;
-  local $dbh->{PrintError} = 0;
+  dbic_internal_try {
+    local $dbh->{RaiseError} = 1;
+    local $dbh->{PrintError} = 0;
 
-  (dbic_internal_try {
     $dbh->do('select 1');
     1;
-  })
-    ? 1
-    : 0
-  ;
+  }
+  catch {
+    # MSSQL is *really* annoying wrt multiple active resultsets,
+    # and this may very well be the reason why the _ping failed
+    #
+    # Proactively disconnect, while hiding annoying warnings if the case
+    #
+    # The callchain is:
+    #   < check basic retryability prerequisites (e.g. no txn) >
+    #    ->retry_handler
+    #     ->storage->connected()
+    #      ->ping
+    # So if we got here with the in_handler bit set - we won't  break
+    # anything by a disconnect
+    if( $self->{_in_do_block_retry_handler} ) {
+      local $SIG{__WARN__} = sigwarn_silencer qr/disconnect invalidates .+? active statement/;
+      $self->disconnect;
+    }
+
+    # RV of _ping itself
+    0;
+  };
 }
 
 package # hide from PAUSE