->req_list_for([qw( rdbms_oracle icdt )]) bringing in the Oracle
specific DateTime::Format dependencies
+ * Fixes
+ - Ensure failing on_connect* / on_disconnect* are dealt with properly,
+ notably on_connect* failures now properly abort the entire connect
+
* Misc
- Skip tests in a way more intelligent and speedy manner when optional
dependencies are missing
# this confuses CXSA: https://rt.cpan.org/Ticket/Display.html?id=103296
$self->_dbh_details->{info} || do {
+ # this guarantees that problematic conninfo won't be hidden
+ # by the try{} below
+ $self->ensure_connected;
+
my $info = {};
my $server_version = try {
sub _do_connection_actions {
my ($self, $method_prefix, $call, @args) = @_;
+ try {
if (not ref($call)) {
my $method = $method_prefix . $call;
$self->$method(@args);
else {
$self->throw_exception (sprintf ("Don't know how to process conection actions of type '%s'", ref($call)) );
}
+ }
+ catch {
+ if ( $method_prefix =~ /^connect/ ) {
+ # this is an on_connect cycle - we can't just throw while leaving
+ # a handle in an undefined state in our storage object
+ # kill it with fire and rethrow
+ $self->_dbh(undef);
+ $self->throw_exception( $_[0] );
+ }
+ else {
+ carp "Disconnect action failed: $_[0]";
+ }
+ };
return $self;
}
use lib qw(t/lib);
use DBICTest;
+for my $conn_args (
+ [ on_connect_do => "_NOPE_" ],
+ [ on_connect_call => sub { shift->_dbh->do("_NOPE_") } ],
+ [ on_connect_call => "_NOPE_" ],
+) {
+ for my $method (qw( ensure_connected _server_info _get_server_version _get_dbh )) {
+
+ my $s = DBICTest->init_schema(
+ no_deploy => 1,
+ on_disconnect_call => sub { fail 'Disconnector should not be invoked' },
+ @$conn_args
+ );
+
+ my $storage = $s->storage;
+ $storage = $storage->master if $ENV{DBICTEST_VIA_REPLICATED};
+
+ ok( ! $storage->connected, 'Starting unconnected' );
+
+ my $desc = "calling $method with broken on_connect action @{[ explain $conn_args ]}";
+
+ throws_ok { $storage->$method }
+ qr/ _NOPE_ \b/x,
+ "Throwing correctly when $desc";
+
+ ok( ! $storage->connected, "Still not connected after $desc" );
+
+ # this checks that the on_disconect_call FAIL won't trigger
+ $storage->disconnect;
+ }
+}
+
+for my $conn_args (
+ [ on_disconnect_do => "_NOPE_" ],
+ [ on_disconnect_call => sub { shift->_dbh->do("_NOPE_") } ],
+ [ on_disconnect_call => "_NOPE_" ],
+) {
+ my $s = DBICTest->init_schema( no_deploy => 1, @$conn_args );
+
+ my $storage = $s->storage;
+ $storage = $storage->master if $ENV{DBICTEST_VIA_REPLICATED};
+
+ my $desc = "broken on_disconnect action @{[ explain $conn_args ]}";
+
+ # connect + ping
+ my $dbh = $storage->dbh;
+
+ ok ($dbh->FETCH('Active'), 'Freshly connected DBI handle is healthy');
+
+ warnings_exist { eval { $storage->disconnect } } [
+ qr/\QDisconnect action failed\E .+ _NOPE_ \b/x
+ ], "Found warning of failed $desc";
+
+ ok (! $dbh->FETCH('Active'), "Actual DBI disconnect was not prevented by $desc" );
+}
+
my $schema = DBICTest->init_schema;
warnings_are ( sub {