brainfart! 0.30
[DBIx-DBSchema.git] / DBSchema.pm
index 37a3252..9595c42 100644 (file)
@@ -3,9 +3,9 @@ package DBIx::DBSchema;
 use strict;
 use vars qw(@ISA $VERSION);
 #use Exporter;
-#use Carp qw(verbose);
 use DBI;
-use FreezeThaw qw(freeze thaw cmpStr);
+use Storable;
+use DBIx::DBSchema::_util qw(_load_driver);
 use DBIx::DBSchema::Table;
 use DBIx::DBSchema::Column;
 use DBIx::DBSchema::ColGroup::Unique;
@@ -14,7 +14,7 @@ use DBIx::DBSchema::ColGroup::Index;
 #@ISA = qw(Exporter);
 @ISA = ();
 
-$VERSION = "0.13";
+$VERSION = "0.30";
 
 =head1 NAME
 
@@ -58,9 +58,10 @@ schema from an existing database.  You can save the schema to disk and restore
 it a different process.  Most importantly, DBIx::DBSchema can write SQL
 CREATE statements statements for different databases from a single source.
 
-Currently supported databases are MySQL and PostgreSQL.  DBIx::DBSchema will
-attempt to use generic SQL syntax for other databases.  Assistance adding
-support for other databases is welcomed.
+Currently supported databases are MySQL and PostgreSQL.  Sybase support is
+partially implemented.  DBIx::DBSchema will attempt to use generic SQL syntax
+for other databases.  Assistance adding support for other databases is
+welcomed.  See L<DBIx::DBSchema::DBD>, "Driver Writer's Guide and Base Class".
 
 =head1 METHODS
 
@@ -95,7 +96,9 @@ closely correspond to any non-portable column types.  Use this to import a
 schema that you wish to use with many different database engines.  Although
 primary key and (unique) index information will only be read from databases
 with DBIx::DBSchema::DBD drivers (currently MySQL and PostgreSQL), import of
-column names and attributes *should* work for any database.
+column names and attributes *should* work for any database.  Note that this
+method only uses "ODBC" column types; it does not require or use an ODBC
+driver.
 
 =cut
 
@@ -133,12 +136,23 @@ Loads a DBIx::DBSchema object from a file.
 
 sub load {
   my($proto,$file)=@_; #use $proto ?
-  open(FILE,"<$file") or die "Can't open $file: $!";
-  my($string)=join('',<FILE>); #can $string have newlines?  pry not?
-  close FILE or die "Can't close $file: $!";
-  my($self)=thaw $string;
-  #no bless needed?
+
+  my $self;
+
+  #first try Storable
+  eval { $self = Storable::retrieve($file); };
+
+  if ( $@ && $@ =~ /not.*storable/i ) { #then try FreezeThaw
+    eval "use FreezeThaw;";
+    die $@ if $@;
+    open(FILE,"<$file") or die "Can't open $file: $!";
+    my $string = join('',<FILE>);
+    close FILE or die "Can't close $file: $!";
+    ($self) = FreezeThaw::thaw($string);
+  }
+
   $self;
+
 }
 
 =item save FILENAME
@@ -148,14 +162,8 @@ Saves a DBIx::DBSchema object to a file.
 =cut
 
 sub save {
-  my($self,$file)=@_;
-  my($string)=freeze $self;
-  open(FILE,">$file") or die "Can't open $file: $!";
-  print FILE $string;
-  close FILE or die "Can't close file: $!";
-  my($check_self)=thaw $string;
-  die "Verify error: Can't freeze and thaw dbdef $self"
-    if (cmpStr($self,$check_self));
+  #my($self, $file) = @_;
+  Storable::nstore(@_);
 }
 
 =item addtable TABLE_OBJECT
@@ -214,9 +222,14 @@ specified database, will attempt to use generic SQL syntax.
 
 sub sql {
   my($self, $dbh) = (shift, shift);
-  $dbh = DBI->connect( $dbh, @_ ) or die $DBI::errstr
-    unless ref($dbh) || ! @_;
-  map { $self->table($_)->sql_create_table($dbh); } $self->tables;
+  my $created_dbh = 0;
+  unless ( ref($dbh) || ! @_ ) {
+    $dbh = DBI->connect( $dbh, @_ ) or die $DBI::errstr;
+    $created_dbh = 1;
+  }
+  my @r = map { $self->table($_)->sql_create_table($dbh); } $self->tables;
+  $dbh->disconnect if $created_dbh;
+  @r;
 }
 
 =item pretty_print
@@ -260,7 +273,7 @@ sub pretty_print {
           ). " ],\n"
         #"  'index' => [ ".    " ],\n"
     } $self->tables
-  ), "}\n";
+  ). "}\n";
 }
 
 =cut
@@ -293,25 +306,15 @@ sub pretty_read {
 
 # private subroutines
 
-sub _load_driver {
-  my($dbh) = @_;
-  my $driver;
-  if ( ref($dbh) ) {
-    $driver = $dbh->{Driver}->{Name};
-  } else {
-    $dbh =~ s/^dbi:(\w*?)(?:\((.*?)\))?://i #nicked from DBI->connect
-                        or '' =~ /()/; # ensure $1 etc are empty if match fails
-    $driver = $1 or die "can't parse data source: $dbh";
-  }
-
-  #require "DBIx/DBSchema/DBD/$driver.pm";
-  #$driver;
-  eval 'require "DBIx/DBSchema/DBD/$driver.pm"' and $driver;
-}
-
 sub _tables_from_dbh {
   my($dbh) = @_;
-  my $sth = $dbh->table_info or die $dbh->errstr;
+  my $driver = _load_driver($dbh);
+  my $db_catalog =
+    scalar(eval "DBIx::DBSchema::DBD::$driver->default_db_catalog");
+  my $db_schema  =
+    scalar(eval "DBIx::DBSchema::DBD::$driver->default_db_schema");
+  my $sth = $dbh->table_info($db_catalog, $db_schema, '', 'TABLE')
+    or die $dbh->errstr;
   #map { $_->{TABLE_NAME} } grep { $_->{TABLE_TYPE} eq 'TABLE' }
   #  @{ $sth->fetchall_arrayref({ TABLE_NAME=>1, TABLE_TYPE=>1}) };
   map { $_->[0] } grep { $_->[1] =~ /^TABLE$/i }
@@ -320,13 +323,25 @@ sub _tables_from_dbh {
 
 =back
 
-=head1 AUTHOR
+=head1 AUTHORS
 
 Ivan Kohler <ivan-dbix-dbschema@420.am>
 
+Charles Shapiro <charles.shapiro@numethods.com> and Mitchell Friedman
+<mitchell.friedman@numethods.com> contributed the start of a Sybase driver.
+
+Daniel Hanks <hanksdc@about-inc.com> contributed the Oracle driver.
+
+Jesse Vincent contributed the SQLite driver.
+
+=head1 CONTRIBUTIONS
+
+Contributions are welcome!  I'm especially keen on any interest in the first
+three items/projects below under BUGS.
+
 =head1 COPYRIGHT
 
-Copyright (c) 2000 Ivan Kohler
+Copyright (c) 2000-2006 Ivan Kohler
 Copyright (c) 2000 Mail Abuse Prevention System LLC
 All rights reserved.
 This program is free software; you can redistribute it and/or modify it under
@@ -334,6 +349,18 @@ the same terms as Perl itself.
 
 =head1 BUGS
 
+Indices are not stored by name.  Index representation could use an overhaul.
+
+Multiple primary keys are not yet supported.
+
+Foreign keys and other constraints are not yet supported.
+
+Eventually it would be nice to have additional transformations (deleted,
+modified columns, added/modified/indices (probably need em named first),
+added/deleted tables
+
+Need to port and test with additional databases
+
 Each DBIx::DBSchema object should have a name which corresponds to its name
 within the SQL database engine (DBI data source).
 
@@ -342,12 +369,17 @@ pretty_print is actually pretty ugly.
 Perhaps pretty_read should eval column types so that we can use DBI
 qw(:sql_types) here instead of externally.
 
+sql CREATE TABLE output should convert integers
+(i.e. use DBI qw(:sql_types);) to local types using DBI->type_info plus a hash
+to fudge things
+
 =head1 SEE ALSO
 
 L<DBIx::DBSchema::Table>, L<DBIx::DBSchema::ColGroup>,
 L<DBIx::DBSchema::ColGroup::Unique>, L<DBIx::DBSchema::ColGroup::Index>,
-L<DBIx::DBSchema::Column>, L<DBIx::DBSchema::DBD>, L<DBIx::DBSchema::mysql>,
-L<DBIx::DBSchema::Pg>, L<FS::Record>, L<DBI>
+L<DBIx::DBSchema::Column>, L<DBIx::DBSchema::DBD>,
+L<DBIx::DBSchema::DBD::mysql>, L<DBIx::DBSchema::DBD::Pg>, L<FS::Record>,
+L<DBI>
 
 =cut