Streamline BYTEA (binary) Pg optdeps using the new augmentation system
Peter Rabbitson [Mon, 19 Jan 2015 14:00:42 +0000 (15:00 +0100)]
Read under -w

lib/DBIx/Class/Optional/Dependencies.pm
lib/DBIx/Class/Storage/DBI/Pg.pm
t/72pg_bytea.t
xt/extra/internals/optional_deps.t

index 946cb7a..43ce063 100644 (file)
@@ -235,6 +235,17 @@ my $dbic_reqs = {
     },
   },
 
+  binary_data => {
+    pod => {
+      title => 'Binary datatype support (certain RDBMS)',
+      desc =>
+        'Some RDBMS engines require specific versions of the respective DBD '
+      . 'driver for binary data support. Note that this group does not '
+      . 'require anything on its own, but instead is augmented by various '
+      . 'RDBMS-specific groups. See the documentation of each rbms_* group '
+      . 'for details',
+    },
+  },
 
   # this is just for completeness as SQLite
   # is a core dep of DBIC for testing
@@ -274,13 +285,19 @@ my $dbic_reqs = {
   rdbms_pg => {
     include => '_ic_dt_pg_base',
     req => {
-      # when changing this list make sure to adjust xt/optional_deps.t
       'DBD::Pg' => 0,
     },
     pod => {
       title => 'PostgreSQL support',
       desc => 'Modules required to connect to PostgreSQL',
     },
+    augment => {
+      binary_data => {
+        req => {
+          'DBD::Pg' => '2.009002'
+        },
+      }
+    },
   },
 
   _rdbms_mssql_common => {
@@ -507,13 +524,6 @@ my $dbic_reqs = {
       DBICTEST_PG_USER => 0,
       DBICTEST_PG_PASS => 0,
     ],
-    req => {
-      # the order does matter because the rdbms support group might require
-      # a different version that the test group
-      #
-      # when changing this list make sure to adjust xt/optional_deps.t
-      'DBD::Pg' => '2.009002',  # specific version to test bytea
-    },
   },
 
   test_rdbms_mssql_odbc => {
index 7c20330..ded6d06 100644 (file)
@@ -8,7 +8,7 @@ use base qw/DBIx::Class::Storage::DBI/;
 use Scope::Guard ();
 use Context::Preserve 'preserve_context';
 use DBIx::Class::Carp;
-use Try::Tiny;
+use DBIx::Class::_Util 'modver_gt_or_eq';
 use namespace::clean;
 
 __PACKAGE__->sql_limit_dialect ('LimitOffset');
@@ -168,19 +168,27 @@ sub bind_attribute_by_data_type {
   if ($self->_is_binary_lob_type($data_type)) {
     # this is a hot-ish codepath, use an escape flag to minimize
     # amount of function/method calls
-    # additionally version.pm is cock, and memleaks on multiple
-    # ->VERSION calls
     # the flag is stored in the DBD namespace, so that Class::Unload
     # will work (unlikely, but still)
-    unless ($DBD::Pg::__DBIC_DBD_VERSION_CHECK_DONE__) {
-      if ($self->_server_info->{normalized_dbms_version} >= 9.0) {
-        try { DBD::Pg->VERSION('2.17.2'); 1 } or carp (
-          __PACKAGE__.': BYTEA columns are known to not work on Pg >= 9.0 with DBD::Pg < 2.17.2'
+    unless (
+      modver_gt_or_eq( 'DBD::Pg', '2.17.2' )
+        or
+      $DBD::Pg::__DBIC_DBD_VERSION_CHECK_DONE__
+    ) {
+      if ( $self->_server_info->{normalized_dbms_version} >= 9.0 ) {
+        $self->throw_exception(
+          'BYTEA columns are known to not work on Pg >= 9.0 with DBD::Pg < 2.17.2'
         );
       }
-      elsif (not try { DBD::Pg->VERSION('2.9.2'); 1 } ) { carp (
-        __PACKAGE__.': DBD::Pg 2.9.2 or greater is strongly recommended for BYTEA column support'
-      )}
+      elsif (
+        my $missing = DBIx::Class::Optional::Dependencies->req_missing_for([qw( rdbms_pg binary_data )])
+      ) {
+        # FIXME - perhaps this needs to be an exception too...?
+        # too old to test sensibly...
+        carp (
+          __PACKAGE__ . ": BYTEA column support strongly recommends $missing"
+        )
+      }
 
       $DBD::Pg::__DBIC_DBD_VERSION_CHECK_DONE__ = 1;
     }
index bf577a9..7049b31 100644 (file)
@@ -1,10 +1,11 @@
-use DBIx::Class::Optional::Dependencies -skip_all_without => 'test_rdbms_pg';
+use DBIx::Class::Optional::Dependencies -skip_all_without => qw(test_rdbms_pg binary_data);
 
 use strict;
 use warnings;
 
 use Test::More;
-use Try::Tiny;
+use DBIx::Class::_Util 'modver_gt_or_eq';
+
 use lib qw(t/lib);
 use DBICTest;
 
@@ -12,16 +13,11 @@ my ($dsn, $dbuser, $dbpass) = @ENV{map { "DBICTEST_PG_${_}" } qw/DSN USER PASS/}
 
 my $schema = DBICTest::Schema->connect($dsn, $dbuser, $dbpass, { AutoCommit => 1 });
 
-if ($schema->storage->_server_info->{normalized_dbms_version} >= 9.0) {
-  if (not try { DBD::Pg->VERSION('2.17.2') }) {
-    plan skip_all =>
-      'DBD::Pg < 2.17.2 does not work with Pg >= 9.0 BYTEA columns';
-  }
-}
-elsif (not try { DBD::Pg->VERSION('2.9.2') }) {
-  plan skip_all =>
-    'DBD::Pg < 2.9.2 does not work with BYTEA columns';
-}
+plan skip_all => 'DBD::Pg < 2.17.2 does not work with Pg >= 9.0 BYTEA columns' if (
+  ! modver_gt_or_eq('DBD::Pg', '2.17.2')
+    and
+  $schema->storage->_server_info->{normalized_dbms_version} >= 9.0
+);
 
 my $dbh = $schema->storage->dbh;
 
index a227476..7da1cc4 100644 (file)
@@ -137,13 +137,13 @@ is_deeply (
 
 # regular
   is_deeply(
-    DBIx::Class::Optional::Dependencies->modreq_list_for('test_rdbms_pg'),
+    DBIx::Class::Optional::Dependencies->modreq_list_for([shuffle qw( test_rdbms_pg binary_data )]),
     { 'DBD::Pg' => '2.009002' },
     'optional dependencies list for testing Postgres without envvar',
   );
 
   is_deeply(
-    DBIx::Class::Optional::Dependencies->req_list_for('test_rdbms_pg'),
+    DBIx::Class::Optional::Dependencies->req_list_for([shuffle qw( test_rdbms_pg binary_data )]),
     undef,
     'optional dependencies list for testing Postgres without envvar',
   );
@@ -168,26 +168,26 @@ is_deeply (
   );
 
   is(
-    DBIx::Class::Optional::Dependencies->req_missing_for([qw( rdbms_pg test_rdbms_pg )]),
+    DBIx::Class::Optional::Dependencies->req_missing_for([shuffle qw( rdbms_pg test_rdbms_pg binary_data )]),
     'DBD::Pg~2.009002 as well as the following group(s) of environment variables: DBICTEST_PG_DSN/..._USER/..._PASS',
     'optional dependencies for testing Postgres without envvar'
   );
 
   is(
-    DBIx::Class::Optional::Dependencies->req_missing_for([shuffle qw( test_rdbms_mysql test_rdbms_pg )]),
+    DBIx::Class::Optional::Dependencies->req_missing_for([shuffle qw( test_rdbms_mysql test_rdbms_pg binary_data)]),
     'DBD::mysql DBD::Pg~2.009002 as well as the following group(s) of environment variables: DBICTEST_MYSQL_DSN/..._USER/..._PASS and DBICTEST_PG_DSN/..._USER/..._PASS',
     'optional dependencies for testing Postgres+MySQL without envvars'
   );
 
   $ENV{DBICTEST_PG_DSN} = 'boo';
   is_deeply (
-    DBIx::Class::Optional::Dependencies->modreq_list_for([shuffle qw( rdbms_pg test_rdbms_pg )]),
+    DBIx::Class::Optional::Dependencies->modreq_list_for([shuffle qw( rdbms_pg test_rdbms_pg binary_data)]),
     { 'DBD::Pg' => '2.009002' },
     'optional module dependencies list for testing Postgres matches with envvar',
   );
 
   is(
-    DBIx::Class::Optional::Dependencies->req_missing_for([shuffle qw( rdbms_pg test_rdbms_pg )]),
+    DBIx::Class::Optional::Dependencies->req_missing_for([shuffle qw( rdbms_pg test_rdbms_pg binary_data )]),
     'DBD::Pg~2.009002',
     'optional dependencies error text for testing Postgres matches with evvar',
   );