Author: mjevans
Date: Tue Sep  2 03:09:51 2008
New Revision: 11723

Modified:
   dbi/trunk/Driver.xst
   dbi/trunk/dbd_xsh.h
   dbi/trunk/lib/DBI/DBD.pm

Log:
Driver.xst,dbd_xsh.h:
  Add a dbd_db_login6_sv to allow drivers to get the dbname, uid and pwd as
    perl scalars and hence know if any of the strings are unicode.
DBD.pm:
  Fixed more spelling mistakes and typos
  Added mention of dbd_db_login6_sv
  Removed a couple of *FIX ME* entries for deleting driver-specific attributes
    you don't want to see via STORE and note past but in DBD_ATTRIB_DELETE
  Added TRACING section documenting trace levels, flags and macros - some minor
    omissions for pure perl drivers.


Modified: dbi/trunk/Driver.xst
==============================================================================
--- dbi/trunk/Driver.xst        (original)
+++ dbi/trunk/Driver.xst        Tue Sep  2 03:09:51 2008
@@ -84,7 +84,7 @@
 void
 _login(dbh, dbname, username, password, attribs=Nullsv)
     SV *        dbh
-    char *      dbname
+    SV *        dbname
     SV *        username
     SV *        password
     SV *        attribs
@@ -94,10 +94,12 @@
     D_imp_dbh(dbh);
     char *u = (SvOK(username)) ? SvPV(username,lna) : "";
     char *p = (SvOK(password)) ? SvPV(password,lna) : "";
-#ifdef dbd_db_login6
-    ST(0) = dbd_db_login6(dbh, imp_dbh, dbname, u, p, attribs) ? &sv_yes : 
&sv_no;
+#ifdef dbd_db_login6_sv
+    ST(0) = dbd_db_login6_sv(dbh, imp_dbh, dbname, username, password, 
attribs) ? &sv_yes : &sv_no;
+#elif defined(dbd_db_login6)
+    ST(0) = dbd_db_login6(dbh, imp_dbh, SvPV_nolen(dbname), u, p, attribs) ? 
&sv_yes : &sv_no;
 #else
-    ST(0) = dbd_db_login( dbh, imp_dbh, dbname, u, p) ? &sv_yes : &sv_no;
+    ST(0) = dbd_db_login( dbh, imp_dbh, SvPV_nolen(dbname), u, p) ? &sv_yes : 
&sv_no;
 #endif
     }
 

Modified: dbi/trunk/dbd_xsh.h
==============================================================================
--- dbi/trunk/dbd_xsh.h (original)
+++ dbi/trunk/dbd_xsh.h Tue Sep  2 03:09:51 2008
@@ -21,6 +21,7 @@
 /* function to get the list of data sources */
 AV     *dbd_dr_data_sources(SV *drh, imp_drh_t *imp_drh, SV *attrs);
 
+int      dbd_db_login6_sv _((SV *dbh, imp_dbh_t *imp_dbh, SV *dbname, SV *uid, 
SV *pwd, SV*attribs));
 int      dbd_db_login6 _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char 
*uid, char *pwd, SV*attribs));
 int      dbd_db_login  _((SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char 
*uid, char *pwd)); /* deprecated */
 /* Note: interface of dbd_db_do changed in v1.33 */

Modified: dbi/trunk/lib/DBI/DBD.pm
==============================================================================
--- dbi/trunk/lib/DBI/DBD.pm    (original)
+++ dbi/trunk/lib/DBI/DBD.pm    Tue Sep  2 03:09:51 2008
@@ -90,11 +90,11 @@
 
   http://dbi.perl.org/
 
-There are two main and one auxilliary mailing lists for people working
+There are two main and one auxiliary mailing lists for people working
 with B<DBI>.  The primary lists are I<[EMAIL PROTECTED]> for general users
 of B<DBI> and B<DBD> drivers, and I<[EMAIL PROTECTED]> mainly for B<DBD> driver
 writers (don't join the I<dbi-dev> list unless you have a good reason).
-The auxilliary list is I<[EMAIL PROTECTED]> for announcing new
+The auxiliary list is I<[EMAIL PROTECTED]> for announcing new
 releases of B<DBI> or B<DBD> drivers.
 
 You can join these lists by accessing the web-site L<http://dbi.perl.org/>.
@@ -465,7 +465,7 @@
 If your driver depends upon external software (it usually will), you
 will need to add code to ensure that your environment is workable
 before the call to C<WriteMakefile()>. If you need to check for the
-existance of an external library and perhaps modify I<INC> to include
+existence of an external library and perhaps modify I<INC> to include
 the paths to where the external library header files are located and
 you cannot find the library or header files make sure you output a
 message saying they cannot be found but C<exit 0> (success) B<before>
@@ -474,7 +474,7 @@
 
 A full-fledged I<Makefile.PL> can be quite large (for example, the
 files for B<DBD::Oracle> and B<DBD::Informix> are both over 1000 lines
-long, and the Informix one uses - and creates - auxilliary modules
+long, and the Informix one uses - and creates - auxiliary modules
 too).
 
 See also L<ExtUtils::MakeMaker> and L<ExtUtils::MM_Unix>. Consider using
@@ -815,7 +815,7 @@
 =head4 The CLONE special subroutine
 
 Also needed here, in the B<DBD::Driver> package, is a C<CLONE()> method
-that will be called by perl when an intrepreter is cloned. All your
+that will be called by perl when an interpreter is cloned. All your
 C<CLONE()> method needs to do, currently, is clear the cached I<$drh> so
 the new interpreter won't start using the cached I<$drh> from the old
 interpreter:
@@ -1370,7 +1370,7 @@
 number of elements in the row buffer array (C<DBIc_FIELDS_AV(imp_sth)>)
 to match the new result set. Fill any new values with newSV(0) not &sv_undef.
 Alternatively you could free DBIc_FIELDS_AV(imp_sth) and set it to null,
-but that would mean bind_columns() woudn't work across result sets.
+but that would mean bind_columns() wouldn't work across result sets.
 
 
 =head4 Statement attributes
@@ -1594,17 +1594,28 @@
   }
 
 This is mostly the same as in the pure Perl case, the exception being
-the use of the private C<_login()> callback, which is the function that
-will really connect to the database. It is implemented in F<Driver.xst>
-(you should not implement it) and calls C<dbd_db_login6()> from
-F<dbdimp.c>. See below for details.
+the use of the private C<_login()> callback, which is the function
+that will really connect to the database. It is implemented in
+F<Driver.xst> (you should not implement it) and calls
+C<dbd_db_login6()> or C<dbd_db_login6_sv> from F<dbdimp.c>. See below
+for details.
 
- *FIX ME* Discuss removing attributes from hash reference as an optimization
- to skip later calls to $dbh->STORE made by DBI->connect.
+If your driver has driver-specific attributes which may be passed in the
+connect method and hence end up in C<$attr> in C<dbd_db_login6> then it
+is best to delete any you process so DBI does not send them again
+via STORE after connect. You can do this in C like this:
+
+  DBD_ATTRIB_DELETE(attr, "my_attribute_name",
+                    strlen("my_attribute_name"));
+
+However, prior to DBI subversion version 11605 (and fixed post 1.607)
+DBD_ATTRIB_DELETE segfaulted so if you cannot guarantee the DBI version
+will be post 1.607 you need to use:
 
- *FIX ME* Discuss removing attributes in Perl code.
+  hv_delete((HV*)SvRV(attr), "my_attribute_name",
+                     strlen("my_attribute_name"), G_DISCARD);
 
- *FIX ME* Discuss removing attributes in C code.
+ *FIX ME* Discuss removing attributes in Perl code.
 
 =head3 The disconnect_all method
 
@@ -1724,14 +1735,14 @@
 The F<DBIXS.h> header defines most of the interesting information that
 the writer of a driver needs.
 
-The file F<dbd_xsh.h> header provides prototype declarations for the
-C functions that you might decide to implement. Note that you should
-normally only define one of C<dbd_db_login()> and C<dbd_db_login6()>
-unless you are intent on supporting really old versions of B<DBI>
-(prior to B<DBI> 1.06) as well as modern versions. The only standard,
-B<DBI>-mandated functions that you need write are those specified in the
-F<dbd_xsh.h> header. You might also add extra driver-specific functions
-in F<Driver.xs>.
+The file F<dbd_xsh.h> header provides prototype declarations for the C
+functions that you might decide to implement. Note that you should
+normally only define one of C<dbd_db_login()>, C<dbd_db_login6()> or
+C<dbd_db_login6_sv> unless you are intent on supporting really old
+versions of B<DBI> (prior to B<DBI> 1.06) as well as modern
+versions. The only standard, B<DBI>-mandated functions that you need
+write are those specified in the F<dbd_xsh.h> header. You might also
+add extra driver-specific functions in F<Driver.xs>.
 
 The F<dbivport.h> file should be I<copied> from the latest B<DBI> release
 into your distribution each time you modify your driver. Its job is to
@@ -1802,6 +1813,12 @@
 with 6 arguments), it will be used instead with the attribute hash
 passed as the sixth argument.
 
+Since B<DBI> post v1.607, if a C<dbd_db_login6_sv()> macro is defined (for
+a function like dbd_db_login6 but with scalar pointers for the dbname,
+username and password), it will be used instead. This will allow your
+login6 function to see if there are any unicode characters in the
+dbname.
+
 People used to just pick Oracle's F<dbdimp.c> and use the same names,
 structures and types. I strongly recommend against that. At first glance
 this saves time, but your implementation will be less readable. It was
@@ -1833,9 +1850,9 @@
 
   /*  Rename functions for avoiding name clashes; prototypes are  */
   /*  in dbd_xst.h                                                */
-  #define dbd_init         drv_dr_init
-  #define dbd_db_login6    drv_db_login
-  #define dbd_db_do        drv_db_do
+  #define dbd_init            drv_dr_init
+  #define dbd_db_login6_sv    drv_db_login_sv
+  #define dbd_db_do           drv_db_do
   ... many more here ...
 
 These structures implement your private part of the handles.
@@ -1879,12 +1896,13 @@
 between drivers and eases discussions on the I<dbi-dev> mailing list.
 The majority of the code fragments here will use the unmapped names.
 
-Ultimately, you should provide implementations for most fo the functions
-listed in the F<dbd_xsh.h> header. The exceptions are optional functions
-(such as C<dbd_st_rows()>) and those functions with alternative
-signatures, such as C<dbd_db_login6()> and I<dbd_db_login()>. Then you
-should only implement one of the alternatives, and generally the newer
-one of the alternatives.
+Ultimately, you should provide implementations for most of the
+functions listed in the F<dbd_xsh.h> header. The exceptions are
+optional functions (such as C<dbd_st_rows()>) and those functions with
+alternative signatures, such as C<dbd_db_login6_sv>,
+C<dbd_db_login6()> and I<dbd_db_login()>. Then you should only
+implement one of the alternatives, and generally the newer one of the
+alternatives.
 
 =head3 The dbd_init method
 
@@ -2018,6 +2036,11 @@
 
 =head3 The dbd_db_login6 method
 
+  int dbd_db_login6_sv(SV* dbh, imp_dbh_t* imp_dbh, SV* dbname,
+                       SV* user, SV* auth, SV *attr);
+
+  or
+
   int dbd_db_login6(SV* dbh, imp_dbh_t* imp_dbh, char* dbname,
                    char* user, char* auth, SV *attr);
 
@@ -2053,7 +2076,7 @@
 is at best redundant for attributes you have already processed.
 
 B<Note: Until revision 11605 (post DBI 1.607), there was a problem with
-DBD_ATRRIBUTE_DELETE so unless you require a DBI version after 1.607
+DBD_ATTRIBUTE_DELETE so unless you require a DBI version after 1.607
 you need to replace each DBD_ATTRIBUTE_DELETE call with:>
 
   hv_delete((HV*)SvRV(attr), key, key_len, G_DISCARD)
@@ -2109,6 +2132,8 @@
 C<dbd_db_login()> instead of C<dbd_db_login6()>. The missing argument is
 the attributes. There are ways to work around the missing attributes,
 but they are ungainly; it is much better to use the 6-argument form.
+Even later drivers will use C<dbd_db_login6_sv()> which provides the
+dbname, username and password as SVs.
 
 =head3 The dbd_db_commit and dbd_db_rollback methods
 
@@ -2427,7 +2452,7 @@
 
 The from_destroy parameter is true if C<dbd_st_finish3()> is being called
 from C<DESTROY()> - and so the statement is about to be destroyed.
-For many drivers there's no point in doing anything more than turing of
+For many drivers there is no point in doing anything more than turning off
 the I<Active> flag in this case.
 
 The function returns I<TRUE> for success, I<FALSE> otherwise, but there isn't
@@ -2664,7 +2689,7 @@
 
     perldoc DBI::DBD::Metadata
 
-The setup is exactly analogous to the mechanism descibed in
+The setup is exactly analogous to the mechanism described in
 L</Generating the get_info method>.
 
 With the pre-requisites in place, you might type:
@@ -2866,6 +2891,99 @@
 This sample implementation also ignores the single-argument variant of
 the method.
 
+=head1 TRACING
+
+Tracing in DBI is controlled with a combination of a trace level and a
+set of flags which together are known as the trace settings. The trace
+settings are stored in a single integer and divided into levels and
+flags by a set of masks (C<DBIc_TRACE_LEVEL_MASK> and
+C<DBIc_TRACE_FLAGS_MASK>).
+
+Each handle has it's own trace settings and so does the DBI. When you
+call a method the DBI merges the handles settings into its own for the
+duration of the call: the trace flags of the handle are OR'd into the
+trace flags of the DBI, and if the handle has a higher trace level
+then the DBI trace level is raised to match it. The previous DBI trace
+setings are restored when the called method returns.
+
+=head2 Trace Level
+
+The trace level is the first 4 bits of the trace settings (masked by
+C<DBIc_TRACE_FLAGS_MASK>) and represents trace levels of 1 to 15. Do
+not output anything at trace levels less than 3 as they are reserved
+for DBI.
+
+For advice on what to output at each level see "Trace Levels" in
+L<DBI>.
+
+To test for a trace level you can use the C<DBIc_TRACE_LEVEL> macro
+like this:
+
+  if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) {
+      PerlIO_printf(DBIc_LOGPIO(imp_xxh), "foobar");
+  }
+
+Also B<note> the use of PerlIO_printf which you should always use for
+tracing and never the C C<stdio.h> I/O functions.
+
+=head2 Trace Flags
+
+Trace flags are used to enable tracing of specific activities within
+the DBI and drivers. The DBI defines some trace flags and drivers can
+define others. DBI trace flag names begin with a capital letter and
+driver specific names begin with a lowercase letter. For a list of DBI
+defined trace flags see "Trace Flags" in L<DBI>.
+
+If you want to use private trace flags you'll probably want to be able
+to set them by name. Drivers are expected to override the
+parse_trace_flag (note the singular) and check if $trace_flag_name is
+a driver specific trace flags and, if not, then call the DBIs default
+parse_trace_flag(). To do that you'll need to define a
+parse_trace_flag() method like this:
+
+  sub parse_trace_flag {
+      my ($h, $name) = @_;
+      return 0x01000000 if $name eq 'foo';
+      return 0x02000000 if $name eq 'bar';
+      return 0x04000000 if $name eq 'baz';
+      return 0x08000000 if $name eq 'boo';
+      return 0x10000000 if $name eq 'bop';
+      return $h->SUPER::parse_trace_flag($name);
+  }
+
+All private flag names must be lowercase, and all private flags must
+be in the top 8 of the 32 bits of C<DBIc_TRACE_FLAGS(imp)> i.e.,
+0xFF000000.
+
+If you've defined a parse_trace_flag() method in ::db you'll also want
+it in ::st, so just alias it in:
+
+  *parse_trace_flag = \&DBD::foo:db::parse_trace_flag;
+
+You may want to act on the current 'SQL' trace flag that DBI defines
+to output SQL prepared/executed as DBI currently does not do SQL
+tracing.
+
+=head2 Trace Macros
+
+Access to the trace level and trace flags is via a set of macros.
+
+  DBIc_TRACE_SETTINGS(imp) returns the trace settings
+  DBIc_TRACE_LEVEL(imp) returns the trace level
+  DBIc_TRACE_FLAGS(imp) returns the trace flags
+  DBIc_TRACE(imp, flags, flaglevel, level)
+
+  e.g.,
+
+  DBIc_TRACE(imp, 0, 0, 4)
+    if level >= 4
+
+  DBIc_TRACE(imp, DBDtf_FOO, 2, 4)
+    if tracing DBDtf_FOO & level>=2 or level>=4
+
+  DBIc_TRACE(imp, DBDtf_FOO, 2, 0)
+    as above but never trace just due to level
+
 =head1 WRITING AN EMULATION LAYER FOR AN OLD PERL INTERFACE
 
 Study F<Oraperl.pm> (supplied with B<DBD::Oracle>) and F<Ingperl.pm> (supplied

Reply via email to