On Mon, Oct 09, 2000 at 02:30:51AM -0400, Jesse wrote:
authorivan <ivan>
Mon, 9 Oct 2000 10:51:43 +0000 (10:51 +0000)
committerivan <ivan>
Mon, 9 Oct 2000 10:51:43 +0000 (10:51 +0000)
>
> DBIx::DBSchema::Column->new  Takes a large # of params in order. why not use $
> named args convention? it would make extensibility much easier. it would make$
> easier to figure out what was going on.
>
> It seems like the 'default' values aren't being quoted. this seems to not
> work so well :/
>
> DBSchema line 200. the pod says sql_string, but it's actually 'sub sql'

DBSchema.pm
DBSchema/Column.pm
DBSchema/Table.pm

index 847873d..37a3252 100644 (file)
@@ -14,7 +14,7 @@ use DBIx::DBSchema::ColGroup::Index;
 #@ISA = qw(Exporter);
 @ISA = ();
 
-$VERSION = "0.12";
+$VERSION = "0.13";
 
 =head1 NAME
 
@@ -39,7 +39,9 @@ DBIx::DBSchema - Database-independent schema objects
 
   $DBIx_DBSchema_table_object = $schema->table("table_name");
 
-  @sql = $schema->sql($dsn);
+  @sql = $schema->sql($dbh);
+  @sql = $schema->sql($dsn, $username, $password);
+  @sql = $schema->sql($dsn); #doesn't connect to database - less reliable
 
   $perl_code = $schema->pretty_print;
   %hash = eval $perl_code;
@@ -83,7 +85,7 @@ sub new {
 
 }
 
-=item new_odbc DATABASE_HANDLE || DATA_SOURCE USERNAME PASSWORD [ ATTR ]
+=item new_odbc DATABASE_HANDLE | DATA_SOURCE USERNAME PASSWORD [ ATTR ]
 
 Creates a new DBIx::DBSchema object from an existing data source, which can be
 specified by passing an open DBI database handle, or by passing the DBI data
@@ -105,7 +107,7 @@ sub new_odbc {
   );
 }
 
-=item new_native DATABASE_HANDLE || DATA_SOURCE USERNAME PASSWORD [ ATTR ]
+=item new_native DATABASE_HANDLE | DATA_SOURCE USERNAME PASSWORD [ ATTR ]
 
 Creates a new DBIx::DBSchema object from an existing data source, which can be
 specified by passing an open DBI database handle, or by passing the DBI data
@@ -189,22 +191,32 @@ sub table {
   $self->{'tables'}->{$table};
 }
 
-=item sql_string [ DATASRC ]
+=item sql [ DATABASE_HANDLE | DATA_SOURCE [ USERNAME PASSWORD [ ATTR ] ] ]
 
 Returns a list of SQL `CREATE' statements for this schema.
 
-If passed a DBI data source such as `DBI:mysql:database' or
+The data source can be specified by passing an open DBI database handle, or by
+passing the DBI data source name, username and password.  
+
+Although the username and password are optional, it is best to call this method
+with a database handle or data source including a valid username and password -
+a DBI connection will be opened and the quoting and type mapping will be more
+reliable.
+
+If passed a DBI data source (or handle) such as `DBI:mysql:database' or
 `DBI:Pg:dbname=database', will use syntax specific to that database engine.
 Currently supported databases are MySQL and PostgreSQL.
 
-If not passed a data source, or if there is no driver for the specified
-database, will attempt to use generic SQL syntax.
+If not passed a data source (or handle), or if there is no driver for the
+specified database, will attempt to use generic SQL syntax.
 
 =cut
 
 sub sql {
-  my($self, $datasrc) = @_;
-  map { $self->table($_)->sql_create_table($datasrc); } $self->tables;
+  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;
 }
 
 =item pretty_print
index 617d720..74fe039 100644 (file)
@@ -20,7 +20,20 @@ DBIx::DBSchema::Column - Column objects
   $column = new DBIx::DBSchema::Column ( $name, $sql_type, 'NULL' );
   $column = new DBIx::DBSchema::Column ( $name, $sql_type, '', $length );
   $column = new DBIx::DBSchema::Column ( $name, $sql_type, 'NULL', $length );
-  $column = new DBIx::DBSchema::Column ( $name, $sql_type, 'NULL', $length, $default, $local );
+
+  #named params with a hashref (preferred)
+  $column = new DBIx::DBSchema::Column ( {
+    'name'    => 'column_name',
+    'type'    => 'varchar'
+    'null'    => 'NOT NULL',
+    'length'  => 64,
+    'default' => '
+    'local'   => '',
+  } );
+
+  #list
+  $column = new DBIx::DBSchema::Column ( $name, $sql_type, $nullability, $length, $default, $local );
+
 
   $name = $column->name;
   $column->name( 'name' );
@@ -52,33 +65,35 @@ L<DBIx::DBSchema::Table>).
 
 =over 4
 
-=item new [ NAME [ , SQL_TYPE [ , NULL [ , LENGTH  [ , DEFAULT [ , LOCAL ] ] ] ] ] ]
+=item new HASHREF
+
+=item new [ name [ , type [ , null [ , length  [ , default [ , local ] ] ] ] ] ]
 
-Creates a new DBIx::DBSchema::Column object.  NAME is the name of the column.
-SQL_TYPE is the SQL data type.  NULL is the nullability of the column (the
-empty string is equivalent to `NOT NULL').  LENGTH is the SQL length of the
-column.  DEFAULT is the default value of the column.  LOCAL is reserved for
-database-specific information.
+Creates a new DBIx::DBSchema::Column object.  Takes a hashref of named
+parameters, or a list.  B<name> is the name of the column.  B<type> is the SQL
+data type.  B<null> is the nullability of the column (intrepreted using Perl's
+rules for truth, with one exception: `NOT NULL' is false).  B<length> is the
+SQL length of the column.  B<default> is the default value of the column.
+B<local> is reserved for database-specific information.
 
 =cut
 
 sub new {
-  my($proto,$name,$type,$null,$length,$default,$local)=@_;
+  my $proto = shift;
+  my $class = ref($proto) || $proto;
 
-  #croak "Illegal name: $name" if grep $name eq $_, @reserved_words;
+  my $self;
+  if ( ref($_[0]) ) {
+    $self = shift;
+  } else {
+    $self = { map { $_ => shift } qw(name type null length default local) };
+  }
 
-  $null =~ s/^NOT NULL$//i;
-  $null = 'NULL' if $null;
+  #croak "Illegal name: ". $self->{'name'}
+  #  if grep $self->{'name'} eq $_, @reserved_words;
 
-  my $class = ref($proto) || $proto;
-  my $self = {
-    'name'    => $name,
-    'type'    => $type,
-    'null'    => $null,
-    'length'  => $length,
-    'default' => $default,
-    'local'   => $local,
-  };
+  $self->{'null'} =~ s/^NOT NULL$//i;
+  $self->{'null'} = 'NULL' if $self->{'null'};
 
   bless ($self, $class);
 
@@ -179,11 +194,19 @@ sub local {
   }
 }
 
-=item line [ $datasrc ]
+=item line [ DATABASE_HANDLE | DATA_SOURCE [ USERNAME PASSWORD [ ATTR ] ] ]
 
 Returns an SQL column definition.
 
-If passed a DBI data source such as `DBI:mysql:database' or
+The data source can be specified by passing an open DBI database handle, or by
+passing the DBI data source name, username and password.  
+
+Although the username and password are optional, it is best to call this method
+with a database handle or data source including a valid username and password -
+a DBI connection will be opened and the quoting and type mapping will be more
+reliable.
+
+If passed a DBI data source (or handle) such as `DBI:mysql:database' or
 `DBI:Pg:dbname=database', will use syntax specific to that database engine.
 Currently supported databases are MySQL and PostgreSQL.  Non-standard syntax
 for other engines (if applicable) may also be supported in the future.
@@ -191,20 +214,34 @@ for other engines (if applicable) may also be supported in the future.
 =cut
 
 sub line {
-  my($self,$datasrc)=@_;
+  my($self,$dbh)=@_;
   
-  my $driver = DBIx::DBSchema::_load_driver($datasrc);
-  my %typemap = eval "\%DBIx::DBSchema::DBD::${driver}::typemap";
+  my $driver = DBIx::DBSchema::_load_driver($dbh);
+  my %typemap;
+  %typemap = eval "\%DBIx::DBSchema::DBD::${driver}::typemap" if $driver;
   my $type = defined( $typemap{uc($self->type)} )
     ? $typemap{uc($self->type)}
     : $self->type;
 
-  my($null)=$self->null;
+  my $null = $self->null;
+
+  my $default = $self->default;
+  if ( defined($default) && default ne ''
+       && ref($dbh)
+       # false laziness: nicked from FS::Record::_quote
+       && ( $default !~ /^\-?\d+(\.\d+)?$/
+            || $type =~ /(char|binary|blob|text)$/i
+          )
+  ) {
+    $default = $dbh->quote($self->default);
+  } else {
+    $default = $self->default;
+  }
 
-  if ( $datasrc =~ /^dbi:mysql:/i ) { #yucky mysql hack
+  #this should be a callback into the driver
+  if ( $driver eq 'mysql' ) { #yucky mysql hack
     $null ||= "NOT NULL"
-  }
-  if ( $datasrc =~ /^dbi:pg/i ) { #yucky Pg hack
+  } elsif ( $driver eq 'Pg' ) { #yucky Pg hack
     $null ||= "NOT NULL";
     $null =~ s/^NULL$//;
   }
@@ -213,11 +250,11 @@ sub line {
     $self->name,
     $type. ( $self->length ? '('.$self->length.')' : '' ),
     $null,
-    ( ( defined($self->default) && $self->default ne '' )
-      ? 'DEFAULT '. $self->default
+    ( ( defined($default) && $default ne '' )
+      ? 'DEFAULT '. $default
       : ''
     ),
-    ( ( $datasrc =~ /^dbi:mysql:/i )
+    ( ( $driver eq 'mysql' )
       ? $self->local
       : ''
     ),
index 6919331..f647ab9 100644 (file)
@@ -45,8 +45,13 @@ DBIx::DBSchema::Table - Table objects
 
   $dbix_dbschema_column_object = $table->column("column");
 
-  @sql_statements = $table->sql_create_table;
+  #preferred
+  @sql_statements = $table->sql_create_table $dbh;
+  @sql_statements = $table->sql_create_table $datasrc, $username, $password;
+
+  #possible problems
   @sql_statements = $table->sql_create_table $datasrc;
+  @sql_statements = $table->sql_create_table;
 
 =head1 DESCRIPTION
 
@@ -279,11 +284,19 @@ sub column {
   $self->{'columns'}->{$column};
 }
 
-=item sql_create_table [ DATASRC ]
+=item sql_create_table [ DATABASE_HANDLE | DATA_SOURCE [ USERNAME PASSWORD [ ATTR ] ] ]
 
 Returns a list of SQL statments to create this table.
 
-If passed a DBI data source such as `DBI:mysql:database', will use
+The data source can be specified by passing an open DBI database handle, or by
+passing the DBI data source name, username and password.  
+
+Although the username and password are optional, it is best to call this method
+with a database handle or data source including a valid username and password -
+a DBI connection will be opened and the quoting and type mapping will be more
+reliable.
+
+If passed a DBI data source (or handle) such as `DBI:mysql:database', will use
 MySQL-specific syntax.  PostgreSQL is also supported (requires no special
 syntax).  Non-standard syntax for other engines (if applicable) may also be
 supported in the future.
@@ -291,11 +304,25 @@ supported in the future.
 =cut
 
 sub sql_create_table { 
-  my($self,$datasrc)=@_;
-  my(@columns)=map { $self->column($_)->line($datasrc) } $self->columns;
+  my($self, $dbh) = (shift, shift);
+  $dbh = DBI->connect( $dbh, @_ ) or die $DBI::errstr
+    unless ref($dbh) || ! @_;
+
+  #false laziness: nicked from DBSchema::_load_driver
+  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";
+  }
+  #eofalse
+
+  my(@columns)=map { $self->column($_)->line($dbh) } $self->columns;
   push @columns, "PRIMARY KEY (". $self->primary_key. ")"
     if $self->primary_key;
-  if ( $datasrc =~ /^dbi:mysql:/i ) { #yucky mysql hack
+  if ( $driver eq 'mysql' ) { #yucky mysql hack
     push @columns, map "UNIQUE ($_)", $self->unique->sql_list;
     push @columns, map "INDEX ($_)", $self->index->sql_list;
   }