PEPPLER.ORG
Michael Peppler
Sybase Consulting
Menu
Home
Sybase on Linux
Install Guide for Sybase on Linux
General Sybase Resources
General Perl Resources
Freeware
Sybperl
Sybase::Simple
DBD::Sybase
BCP Tool
Bug Tracker
Mailing List Archive
Downloads Directory
FAQs
Sybase on Linux FAQ
Sybperl FAQ
Personal
Michael Peppler's resume

sybperl-l Archive

Up    Prev    Next    

From: "W dot Phillip Moore" <wpm at ms dot com>
Subject: [PATCH] nsql() error handling made usable in subclasses of Sybase::DBlib
Date: Apr 1 1998 7:29PM

>>>>> "Michael" == Michael Peppler  writes:

Michael> I've just placed sybperl 2.09_04 on my web page (and it's
Michael> also on it's way to a CPAN server near you).

Michael> This version adds some dbreg*() calls (for calling OpenServer
Michael> registered procedures), and removes the pesky // style
Michael> comments that I inadvertently left in the code.

Here's a patch which fixes a couple of bugs in the use of nsql(), and
makes it much easier to subclass Sybase::DBlib, and still use the
nsql() interface.

[-] nsql_message_handler() attempts to use $db as a Sybase::DBlib
    object when if isn't blessed

    If the dblogin call fails, you get passed a value for $db which is 
    not yet a Sybase::DBlib object, and thus attempts to call methods
    like dbstrcpy will fail.  This method call is protected by
    checking that $db is infact a reference.

[-] dbcmd() or dbsqlexec() failure resulted in the DB_ERROR value
    being overwritten, and the message handler errors lost.

    See the patch for specifics, but I wasn't trusting the message
    handler to set DB_ERROR, and setting it myself in these cases.
    This results in better diagnostics when either of these calls
    fail.

[-] Access the error via $dbh->DB_ERROR, not $DB_ERROR

    I've been writing classes which subclass Sybase::DBlib, and
    encapsulate automated login logic (hiding username/password logic
    from some applications), and also writing classes whoise methods
    expect to be passed a Sybase::DBlib object as one of their
    arguments.

    The use of an exported variable $DB_ERROR is problematic in 2
    ways.  Since perl5 OO inheritance really only applies to methods,
    not data, subclasses have to explicitly re-export $DB_ERROR.
    Also, subroutines handed a Sybase::DBlib object can use nsql(),
    but they can't see $DB_ERROR, since it isn't necessarilt in their
    own namespace (unless the import Sybase::DBlib, which may not be
    otherwise necessary).

    A new method of the same name, DB_ERROR(), is now provided to get
    at the $DB_ERROR value, solving both of these problems.

Michael, please integrate this with your baseline for the next release 
(2.09_05?  2.10?)

W. Phillip Moore                                        Phone: (212)-762-2433
Vice President, E-Business Technology Group               FAX: (212)-762-1009
Morgan Stanley Dean Witter                                 E-mail: wpm@ms.com
750 7th Ave, NY, NY 10019

----------

diff -rc sybperl-2.09_04.orig/DBlib/DBlib.pm sybperl-2.09_04/DBlib/DBlib.pm
*** sybperl-2.09_04.orig/DBlib/DBlib.pm	Thu Mar  5 19:28:18 1998
--- sybperl-2.09_04/DBlib/DBlib.pm	Wed Apr  1 13:38:24 1998
***************
*** 383,388 ****
--- 403,410 ----
  #
  # Enhanced sql routine.
  # 
+ sub DB_ERROR { return $DB_ERROR; }
+ 
  sub nsql {
      my ($db,$sql,$type) = @_;
      my (@res,@data,%data);
***************
*** 396,410 ****
  
      undef $DB_ERROR;
   
!     unless ( $db->dbcmd($sql) ) {
!       $DB_ERROR = "Unable to submit SQL to Sybase server.";
!       return undef;
!     }
  
!     unless ( $db->dbsqlexec ) {
!       $DB_ERROR = "Error executing SQL.";
!       return undef;
!     }
  
      while ( $db->dbresults != $db->NO_MORE_RESULTS ) {
        if ( ref $type eq "HASH" || $type eq "HASH" ) {
--- 418,426 ----
  
      undef $DB_ERROR;
   
!     return unless $db->dbcmd($sql);
  
!     return unless $db->dbsqlexec;
  
      while ( $db->dbresults != $db->NO_MORE_RESULTS ) {
        if ( ref $type eq "HASH" || $type eq "HASH" ) {
***************
*** 430,436 ****
      #
      # If we picked any sort of error, then don't feed the data back.
      #
!     return ( $DB_ERROR ? undef : @res );
  
  }
  
--- 446,452 ----
      #
      # If we picked any sort of error, then don't feed the data back.
      #
!     return ( $DB_ERROR ? () : @res );
  
  }
  
***************
*** 443,449 ****
        $DB_ERROR .= "OS Error: $os_error_msg\n" if defined $os_error_msg;
      }
  
!     $db->INT_CANCEL;
  }
  
  sub nsql_message_handler {
--- 459,465 ----
        $DB_ERROR .= "OS Error: $os_error_msg\n" if defined $os_error_msg;
      }
  
!     $db->INT_CANCEL if ref $db;
  }
  
  sub nsql_message_handler {
***************
*** 458,463 ****
--- 474,481 ----
        $DB_ERROR .= "Line: $line\n" if defined $line;
        $DB_ERROR .= "Text: $text\n";
        
+       return unless ref $db;
+ 
        my ($lineno) = 1;
        my $row;
        foreach $row ( split(/\n/,$db->dbstrcpy) ) {
diff -rc sybperl-2.09_04.orig/pod/sybperl.pod sybperl-2.09_04/pod/sybperl.pod
*** sybperl-2.09_04.orig/pod/sybperl.pod	Thu Mar 26 17:07:52 1998
--- sybperl-2.09_04/pod/sybperl.pod	Wed Apr  1 13:49:53 1998
***************
*** 792,821 ****
        print "col1 = $ret\n";
      }
  
! The nsql() routine will return success or failure in the exported
! variable DB_ERROR, and a pair of Sybase message/error handler routines
! are also provided which will use DB_ERROR for the Sybase messages and
! errors as well.  However, these must be installed by the client
! application:
  
      dbmsghandle("Sybase::DBlib::nsql_message_handler");
      dberrhandle("Sybase::DBlib::nsql_error_handler");
  
- Success of failure of an nsql() call cannot necessarily be judged
- based on the value of the return code, as an emtpy array may be a
- perfectly valid result for certain sql code.
- 
  The following code is the proper method for handling errors with use
  of nsql.
  
      @ret = $dbh->nsql("select stuff from table where stuff = 'nothing'","ARRAY");
!     if ( $DB_ERROR ) {
!       # error handling code goes here
      }
  
! NOTE: This routine was contributed by W. Phillip Moore.
!   
  
  =back
  
  B
--- 792,828 ----
        print "col1 = $ret\n";
      }
  
! Success of failure of an nsql() call cannot necessarily be judged
! based on the value of the return code, as an empty array may be a
! perfectly valid result for certain sql code.
  
+ The nsql() routine will maintain the success or failure state in a
+ variable $DB_ERROR, accessed by the method of the same name, and a
+ pair of Sybase message/error handler routines are also provided which
+ will use $DB_ERROR for the Sybase messages and errors as well.
+ However, these must be installed by the client application:
+ 
      dbmsghandle("Sybase::DBlib::nsql_message_handler");
      dberrhandle("Sybase::DBlib::nsql_error_handler");
  
  The following code is the proper method for handling errors with use
  of nsql.
  
      @ret = $dbh->nsql("select stuff from table where stuff = 'nothing'","ARRAY");
!     if ( $dbh->DB_ERROR() ) {
!       # error handling code goes here, perhaps:
!       die "Unable to get stuff from table:" . $dbh->DB_ERROR() . "\n";
      }
  
! For compatibility with older release, the error variable $DB_ERROR is
! still exported, however, direct use of this variable makes it
! difficult to pass the Sybase::DBlib object around and use the nsql()
! method for queries, since the subroutine using the object will not
! necessarily have $DB_ERROR in its namespace.  The method will always
! be available.
  
+ NOTE: This routine was contributed by W. Phillip Moore .
+   
  =back
  
  B