| SPOPS documentation | Contained in the SPOPS distribution. |
SPOPS::Import::DBI::Table - Import a DBI table structure
#!/usr/bin/perl
use strict;
use SPOPS::Import;
{
my $table_import = SPOPS::Import->new( 'table' );
$table_import->database_type( 'sybase' );
$table_import->read_table_from_fh( \*DATA );
$table_import->print_only( 1 );
$table_import->transforms([ \&table_login ]);
$table_import->run;
}
sub table_login {
my ( $transformer, $sql, $importer ) = @_;
$$sql =~ s/%%LOGIN%%/varchar(25)/g;
}
__DATA__
CREATE TABLE sys_user (
user_id %%INCREMENT%%,
login_name %%LOGIN%% not null,
password varchar(30) not null,
last_login datetime null,
num_logins int null,
theme_id %%INCREMENT_TYPE%% default 1,
first_name varchar(50) null,
last_name varchar(50) null,
title varchar(50) null,
email varchar(100) not null,
language char(2) default 'en',
notes text null,
removal_date %%DATETIME%% null,
primary key ( user_id ),
unique ( login_name )
)
Output:
CREATE TABLE sys_user (
user_id NUMERIC( 10, 0 ) IDENTITY NOT NULL,
login_name varchar(25) not null,
password varchar(30) not null,
last_login datetime null,
num_logins int null,
theme_id NUMERIC( 10, 0 ) default 1,
first_name varchar(50) null,
last_name varchar(50) null,
title varchar(50) null,
email varchar(100) not null,
language char(2) default 'en',
notes text null,
removal_date datetime null,
primary key ( user_id ),
unique ( login_name )
)
This class allows you to transform and import (or simply display) a DBI table structure.
Transformations are done via two means. The first is the database-specific classes and the standard modifications provided by SPOPS::Import::DBI::TableTransform. The second is custom code that you can write.
database_type ($)
Type of database to generate a table for. See SPOPS::Import::DBI::TableTransform for the listing and types to use.
transforms (\@ of \&, or \&)
Register with the import object one or more code references that will get called to modify a SQL statement. See CUSTOM TRANSFORMATIONS below.
print_only (boolean)
If set to true, the final table will be printed to STDOUT rather than sent to a database.
return_only (boolean)
If set to true, the final table will be returned from run() rather
than sent to a database.
As the example in SYNOPSIS indicates, you can register perl code to modify the contents of a table before it is displayed or sent to a database. When called the code will get three arguments:
Most of the transformation code will be very simple, along the lines of:
sub my_transform {
my ( $self, $sql, $importer ) = @_;
$$sql =~ s/%%THIS_KEY%%/THAT SQL EXPRESSION/g;
}
These are the built-in transformations:
increment
Key: %%INCREMENT%%
Replaces the key with an expression to generate a unique ID value with every INSERT. Some databases accomplish this with a sequence, others with an auto-incrementing value.
increment_type
Key: %%INCREMENT_TYPE%%
Datatype of the increment field specified by %%INCREMENT%%. This is necessary when you are creating foreign keys (logical or enforced) and need to know the datatype of the ID you are referencing.
datetime
Key: %%DATETIME%%
Datatype of the field that holds a date and time value. This should not be automatically set with every insert/update (as it is with MySQL).
None known.
Nothing known.
SPOPS::Manual::ImportExport (SPOPS::Manual::ImportExport)
Copyright (c) 2001-2004 intes.net, inc.. All rights reserved.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Chris Winters <chris@cwinters.com>
| SPOPS documentation | Contained in the SPOPS distribution. |
package SPOPS::Import::DBI::Table; # $Id: Table.pm,v 3.7 2004/06/02 00:48:23 lachoy Exp $ use strict; use base qw( SPOPS::Import ); use Data::Dumper qw( Dumper ); use SPOPS::Exception; use SPOPS::Import::DBI::TableTransform; $SPOPS::Import::DBI::Table::VERSION = sprintf("%d.%02d", q$Revision: 3.7 $ =~ /(\d+)\.(\d+)/); my @FIELDS = qw( database_type transforms print_only return_only ); SPOPS::Import::DBI::Table->mk_accessors( @FIELDS ); ######################################## # CORE API sub get_fields { return ( $_[0]->SUPER::get_fields(), @FIELDS ) } sub run { my ( $self ) = @_; unless ( $self->data ) { my $m = "Cannot import a table without data\n" . "Please set it using \$table_import->data( \$table_sql )\n" . "or \$table_import->read_table_from_file( '/path/to/mytable.sql' )\n" . "or \$table_import->read_table_from_fh( \$filehandle )"; SPOPS::Exception->throw( $m ); } unless ( $self->database_type ) { my $m = "Cannot import a table without specifying a database type.\n" . "Please set the database type using:\n" . "\$table_import->database_type( 'dbtype' )"; SPOPS::Exception->throw( $m ); } my $table_sql = $self->transform_table; if ( $self->print_only ) { print $table_sql; return; } if ( $self->return_only ) { return $table_sql; } my $object_class = $self->object_class; unless ( $object_class ) { my $m = "Cannot retrieve a database handle without an object class being\n" . "defined. Please set it using \$table_import->object_class( 'My::Class' )\n" . "so I know what to use."; SPOPS::Exception->throw( $m ); } my $db = $object_class->global_datasource_handle; unless ( $db ) { my $m = "No datasource defined for ($object_class) -- please ensure that\n" . "when I call \$object_class->global_datasource_handle() I get a\n" . "DBI database handle back.\n"; SPOPS::Exception->throw( $m ); } eval { $db->do( $table_sql ) }; return [ undef, $table_sql, $@ ] if ( $@ ); return [ 1, $table_sql, undef ]; } ######################################## # TABLE TRANSFORMATIONS sub transform_table { my ( $self ) = @_; # Make a copy of 'data' so that it will remain in the # untransformed state my $table_sql = $self->data; # Create a new transformer my $transformer = SPOPS::Import::DBI::TableTransform->new( $self->database_type ); # These are the built-ins (facade to all of them) $transformer->transform( \$table_sql ); # Run the custom transformations my $transforms = $self->transforms; my $transforms_list = ( ref $transforms eq 'ARRAY' ) ? $transforms : [ $transforms ]; foreach my $transform_sub ( @{ $transforms_list } ) { next unless ( ref $transform_sub eq 'CODE' ); $transform_sub->( $transformer, \$table_sql, $self ); } return $table_sql; } ######################################## # I/O sub read_table_from_file { my ( $self, $filename ) = @_; $self->data( $self->read_file( $filename ) ); } sub read_table_from_fh { my ( $self, $fh ) = @_; $self->data( $self->read_fh( $fh ) ); } 1; __END__