"The Perl DBI Database Driver Writer's Guide" introduces attribute
handling in the following way:

  Note the use of the STORE method for setting the dbh attributes.
  That's because within the driver code, the handle object you have is
  the 'inner' handle of a tied hash, not the outer handle that the
  users of your driver have.

  Because you have the inner handle, tie magic doesn't get invoked
  when you get or set values in the hash. This is often very handy for
  speed when you want to get or set simple non-special driver-specific
  attributes.

All well, nothing to criticise.
However, it's placed below the connect() method:

  
<http://search.cpan.org/~timb/DBI-1.46/lib/DBI/DBD.pm#The_database_handle_constructor>

where we have an outer handle by way of an exception!
Instead of changing the nice description, I'd rather change the
example code (see attached patch). Advantages that accrued:

 - Now, we have the inner handle the text speaks about.
 - The example is shorter.
 - The example shows both, the STORE method and direct hash access.
 - The example shows a realistic DBI attribute ('Active') instead of
   whatever gets extracted from DSN (and may cause troubles in STORE).
 - The example shows a realistic driver specific attribute.
 - The examples are more consistent ($dbh is always the inner handle).


Steffen
Index: lib/DBI/DBD.pm
===================================================================
--- lib/DBI/DBD.pm      (revision 629)
+++ lib/DBI/DBD.pm      (working copy)
@@ -696,21 +696,18 @@
       # environment variables to be set; this could be where you
       # validate that they are set, or default them if they are not set.

+      # Assume you can attach to your database via drv_connect:
+      my $connection = drv_connect($dbname, $user, $auth);
+      return $drh->set_err(1,'Connection refused') unless $connection;
+
       # create a 'blank' dbh (call superclass constructor)
-      my $dbh = DBI::_new_dbh($drh, {
-              'Name'         => $dbname,
-          })
-          or return undef;
+      my ($outer, $dbh) = DBI::_new_dbh($drh, { Name => $dbname });

-      # Process attributes from the DSN; we assume ODBC syntax
-      # here, that is, the DSN looks like var1=val1;...;varN=valN
-      foreach my $var (split(/;/, $dbname)) {
-          if ($var =~ m/(.*?)=(,*)/) {
-              # Not !!! $dbh->{$var} = $val;
-              $dbh->STORE($var, $val);
-          }
-      }
-      $dbh;
+      $dbh->STORE('Active', 1 );
+
+      $dbh->{drv_connection} = $connection;
+
+      return $outer;
   }

 The Name attribute is a standard DBI attribute.
@@ -721,11 +718,13 @@
 The constructor _new_dbh is called, returning a database handle.
 The constructor's prototype is:

-  $dbh = DBI::_new_dbh($drh, $public_attr, $private_attr);
+  ($outer, $inner) = DBI::_new_dbh($drh, $public_attr, $private_attr);

 with similar arguments to those in the I<driver handle constructor>,
 except that the C<$class> is replaced by C<$drh>.

+In scalar context, only the outer handle is returned.
+
 Note the use of the I<STORE> method for setting the dbh attributes.
 That's because within the driver code, the handle object you have is
 the 'inner' handle of a tied hash, not the outer handle that the
@@ -807,19 +806,18 @@
       my ($dbh, $statement, @attribs) = @_;

       # create a 'blank' sth
-      my $sth = DBI::_new_sth($dbh, {
-          'Statement' => $statement,
-          });
+      my ($outer, $sth) = DBI::_new_sth($dbh, { Statement => $statement });

-      # Setup module specific data
-      $sth->STORE('drv_params', []);
       $sth->STORE('NUM_OF_PARAMS', ($statement =~ tr/?//));

-      $sth;
+      $sth->{drv_params} = [];
+
+      return $outer;
   }

 This is still the same: check the arguments and call the super class
 constructor I<DBI::_new_sth>.
+Again, in scalar context, only the outer handle is returned.
 The C<Statement> attribute should be cached as shown.
 Note the prefix I<drv_> in the attribute names: it is required that
 your private attributes are lowercased and use such a prefix.

Reply via email to