With WDB 1.2 the Sybase specific code has been isolated into a separate Database interface package (DBI). This should make it relatively easy to port WDB to other databases like Oracle, Informix, Ingres etc. (Any database which supports standard SQL and has a Perl interface).
Currently there are interfaces to Sybase, Informix, Oracle and mSQL (a public domain database). If you want to use WDB with another database system the first thing you have to do is to get a perl interface to it. Several of these are available on the Internet. If you can't find a ready interface you have to write one your self. That's a bit more tricky, but you can always cheat and only include the few commands that WDB needs to run ( open connection, query, fetch next row, close connection). The Perl Meta-FAQ lists where you can find the perl source for various versions and also the database interfaces etc. . The Meta-FAQ is available from :
http://www.khoros.unm.edu/staff/neilb/perl/metaFAQ/metaFAQ.html
A collection of pointers to Perl reference material in general are available at :
http://www.eecs.nwu.edu/perl/perl.html
Another important factor when porting WDB to another database is of course the SQL used. Each database system seems to implement it's own flavor of SQL, but fortunately the only SQL command that WDB sends directly to the DBI is a select statement. The select statement used by wdb has the following format :
select column field, column field, ... from table where where-list and constraints and join order by order
<=
, >=
,
!=
, <
, >
, =
and like are used.
If your database does not support the column field notation described above, an alternative notation is supported. Rather than specifying the field names as column labels in the select list they can be send separately to the DBI via a function called dbi_fieldnames. WDB automatically detects if such a function is defined in the DBI and uses this second notation. See the msql_dbi.pl file for an example of its use.
To give you an idea of what it takes to write a DBI file I have included the Informix DBI file below. As you can see it is simply an encapsulation of the DBD::Informix functions.
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #.IDENTIFICATION informix_dbi.pl #.LANGUAGE DBD::Informix script # #.PURPOSE Database Interface to Informix. # # &dbi_connect( $user, $pswd, $server, $database, \$dbproc ); # &dbi_dosql( $dbproc, \$sth, "... SQL commands ..."); # %row = &dbi_nextrow( $sth, @titles ); # &dbi_countrows( $dbproc, $sth, "... SQL commands ..." ); # &dbi_disconnect( $dbproc, \$sth ); # #.AUTHOR Informix version Curtis Wong#.AUTHOR Bo Frese Rasmussen [ST-ECF] #.AUTHOR DBD::Informix/mod_perl version, Jeff Rowe # #.VERSION 1.0 22/12-1994 Creation # 16/01-1995 Informix version -ckw # 10/02-1995 make change suggested by Bo # 1.1 26/11-1996 Changed to use DBD::Informix and mod_perl #------------------------------------------------------------------------------ use strict; use DBI; #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #.PURPOSE Connects to a database. # #.REMARKS This function must be called before any of the other functions # in this package. # It logs in to the given database server and connects to a # database. # $dbproc MUST be passed in by reference, i.e.: # &dbi_connect( $user, $pswd, $server, $database, \$db_query); # #.RETURNS Dies on error ! #------------------------------------------------------------------------------ sub dbi_connect { my( $user, $pswd, $server, $database, $dbproc ) = @_; my( $drh ); ( $drh = DBI->install_driver( 'Informix' ) ) or die "Cannot install database driver: $DBI::errstr\n"; ( $$dbproc = $drh->connect( $database, 'dbuser', 'dbpass' ) ) or die "Cannot connect to database: $DBI::errstr\n"; } #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #.PURPOSE Prepares and executes an SQL statement, with error check etc. # #.REMARKS Dies on error ! # #.RETURNS An Informix statement handle #------------------------------------------------------------------------------ sub dbi_dosql { my($dbproc, $sth, $sql) = @_; $$sth = $dbproc->prepare($sql); if ( !defined $$sth ) { die "Cannot prepare handle: $DBI::errstr\n"; } $$sth->execute; } # KEEP THIS SUBROUTINE! Nothing will work without it, trust me. sub dbi_fieldnames { } #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #.PURPOSE Gets the next row from a previous select (dbi_dosql). # #.REMARKS After a dbi_dosql("select ... ") call, this function can be # called repeatetly to retrieve all rows of the query. # # Example : # &dbi_dosql("select * from mytab"); # while( %row = &dbi_nextrow ) { # print $row{'columnname'}; # ... # } # #.RETURNS An associative array (keyed on the column name) of formatted # data, based on the datatype of the corresponding columns. # Return the empty list if the fetch failed. #------------------------------------------------------------------------------ sub dbi_nextrow { my($sth, @titles) = @_; my(@trow,$i,%row); if (@trow = $sth->fetchrow) { #found a row of data for ( $i = 0 ; $i <= $#titles; ++$i) { $row{$titles[$i]} = $trow[$i]; } } else { %row = (); } return %row; } #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # #.PURPOSE Returns a count of records returned by a SQL statement. # #.REMARKS Requires a SQL statement in the form: # "select count(*) from tablename where where_clause" # #.RETURNS A number #------------------------------------------------------------------------------ sub dbi_countrows { my($dbproc, $sth, $sql) = @_; my($ch, @titles, %count_result); &dbi_dosql($dbproc, \$ch, $sql); push(@titles, "(count(*))"); %count_result = &dbi_nextrow($ch, @titles); $ch->finish; undef $ch; return $count_result{'(count(*))'}; } #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # #.PURPOSE Disconnects the current database connection # #.REMARKS After this function is called there are no current database # connection => no other function from this package can be # called before a new dbi_connect call. # #.RETURNS nothing. #------------------------------------------------------------------------------ sub dbi_disconnect { my($dbproc, $sth) = @_; if ($$sth) { $$sth->finish; undef $$sth; } if ($dbproc) { $dbproc->disconnect; } } #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #.PURPOSE Gets the next serial key value for a particular table. # #.REMARKS This is a suggested way of generating serial key values. # # Requires a table named serial_keys, and an entry in that table # for each table that has a serial key value. The value in the # table is retrieved, incremented by one, and the new value is # inserted into the serial_keys table. # Table : serial_keys # Fields: table_name, key_value # NOTE: This is only necessary for mSQL. For Informix, just # return a 0, as Informix takes care of its own serial keys. # Sybase 4.9.x might need this method also. Dunno about Oracle. # #.RETURNS The serial key value. #------------------------------------------------------------------------------ sub dbi_getnextserialkey { return 0; } 1;