From a875043efcdcd5f56956a3015660b3167dfeb7c0 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 9 Oct 2000 10:51:43 +0000 Subject: [PATCH] On Mon, Oct 09, 2000 at 02:30:51AM -0400, Jesse wrote: > > 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 | 32 +++++++++++------ DBSchema/Column.pm | 101 ++++++++++++++++++++++++++++++++++++----------------- DBSchema/Table.pm | 39 +++++++++++++++++---- 3 files changed, 124 insertions(+), 48 deletions(-) diff --git a/DBSchema.pm b/DBSchema.pm index 847873d..37a3252 100644 --- a/DBSchema.pm +++ b/DBSchema.pm @@ -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 diff --git a/DBSchema/Column.pm b/DBSchema/Column.pm index 617d720..74fe039 100644 --- a/DBSchema/Column.pm +++ b/DBSchema/Column.pm @@ -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). =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 is the name of the column. B is the SQL +data type. B is the nullability of the column (intrepreted using Perl's +rules for truth, with one exception: `NOT NULL' is false). B is the +SQL length of the column. B is the default value of the column. +B 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 : '' ), diff --git a/DBSchema/Table.pm b/DBSchema/Table.pm index 6919331..f647ab9 100644 --- a/DBSchema/Table.pm +++ b/DBSchema/Table.pm @@ -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; } -- 2.11.0