In this node, I posted some code for review. I also asked (both in the node and in CB) for advice on transforming it to use an Object-Oriented style. (Please note that this was primarily an exercise in using OOP for what -- to me -- did not seem like a good candiate for OOP.)
After getting a little direction from various monks, here is my first draft Thanks to jeffa for helping me get started, and demerphq for warning me off of this project. :-)
In focussing on the OO structure, I did not include all of the functionality of the original version. There are also some things that I've already noticed that I need to work on (such as commenting, error handling and the possibly unnecessary connection between the two objects), but I wanted to get feedback as quickly as possible.
As before, please feel free to criticize style, efficiency, etc. Thanks in advance for anything you can do to help me improve my programming skills and knowledge.
#!/usr/bin/perl -w # db_import.plx # by Brad Smithart (AKA Impossible Robot) # OOP version # $Revision: 1.5 $ # Uses tab-separated data file with header column use strict; my $exh = new Data::Reader( filename => 'myfile.txt', _debug => 1 ); $exh->connect() or croak $exh->error; print "Columns: ",join(', ', $exh->columns), "\n"; print "# of Cols: ", scalar($exh->columns), "\n"; my $imp = new Data::Import( reader => $exh, dsn => 'DBI:mysql:exhibit:localhost', username => 'user', password => 'pass', _debug => 1 ); $imp->connect() or die $imp->error; my @values; while (@values = $exh->row) { $imp->insert(@values); } $exh->disconnect(); $imp->disconnect(); exit; ###################################################################### # Classes ###################################################################### package Data::Reader; use Carp; sub new { my $pkg = shift; bless { _error => 'No error', _connected => 0, _debug => 0, @_ }, $pkg; } sub connect { my $self = shift; my %attr = @_; # Connect string params can override constructer params for (keys %attr) { $self->{$_} = $attr{$_}; } print "Data::Reader Connect:\n" if $self->{_debug}; eval { # Open file open(FILE, $self->{filename}) or croak "Data::Reader couldn't connect: $!"; print " Filename: ", $self->{filename},"\n" if $self->{_debug}; $self->{_handle} = *FILE; # Get field names from header chomp(my $header = readline($self->{_handle})); $header =~ tr/"//d; $self->{_fieldnames} = [ split(/\t/, $header) ]; @{ $self->{_fieldnames} } or croak "Data::Reader - No valid header"; $self->{_connected} = 1; }; if ( $@ ) { $self->{_error} = $@; $self->{_connected} = 0; return 0; } return 1; } sub disconnect { my $self = shift; close(FILE) or return 0; $self->{_connected} = 0; print "Data::Reader Disconnect.\n" if $self->{_debug}; return 1; } # Accessor methods sub columns { my $self = shift; unless ($self->{_connected}) { carp ("Data::Reader - No connection\n"); return; } return @{ $self->{_fieldnames} }; } sub row { my $self = shift; my $row = readline($self->{_handle}); return unless $row; chomp($row); $row =~ tr/"//d; my @values = split(/\t/, $row); return @values; } sub connected { my $self =shift; $self->{_connected}; } sub error { my $self = shift; $self->{_error}; } sub filename { my $self = shift; if (@_) { $self->{filename} = shift }; return $self->{filename}; } ###################################################################### package Data::Import; use DBI; use Carp; sub new { my $pkg = shift; bless { dsn => "DBI:mysql:database:localhost", username => 'root', password => '', table => 'exhibit', reader => undef, _error => 'No error', _debug => 0, @_ }, $pkg; } sub connect { my $self = shift; my %attr = @_; for (keys %attr) { $self->{$_} = $attr{$_}; } print "Import Connect:\n" if $self->{_debug}; eval { $self->{dsn} or croak "Data::Import - No DSN"; my $dsn = $self->{dsn}; my $username = $self->{username}; my $password = $self->{password}; $self->{_database} = DBI->connect($dsn, $username, $password ) or croak $DBI::errstr; print " Connect string: ", $self->{dsn}, ',', $self->{username}, ',', $self->{password}, "\n" if $self->{_debug}; $self->{reader} or croak "Data::Import - No Reader"; my $reader = $self->{reader}; unless ($reader->{_connected}) { $reader->connect() or croak $exh->error; } my $insert_fields = join(', ', $reader->columns); my $placeholders = join(', ', ('?') x $reader->columns); my $table = $self->{table}; my $query = <<"EOQ"; INSERT INTO $table ( $insert_fields ) VALUES ( $placeholders ) EOQ $query =~ tr/\r\n//d; $query =~ s/\s{2,}/ /g; $query =~ s/^\s|\s$/ /g; print " Query: $query\n" if $self->{_debug}; $self->{_query} = $self->{_database}->prepare($query); }; if ( $@ ) { $self->{_error} = $@; return 0; } return 1; } sub disconnect { my $self = shift; $self->{_database}->disconnect(); print "Import Disconnect.\n" if $self->{_debug}; } sub DESTROY { shift->disconnect(); } sub insert { my $self = shift; $self->{_query}->execute(@_); print "Execute: ", join(',', @_), "\n" if $self->{_debug}; } # Accessor methods sub dsn { my $self = shift; if (@_) { $self->{dsn} = shift }; return $self->{dsn}; } sub username { my $self = shift; if (@_) { $self->{username} = shift }; return $self->{username}; } sub password { my $self = shift; if (@_) { $self->{password} = shift }; return $self->{password}; } sub table { my $self = shift; if (@_) { $self->{table} = shift }; return $self->{table}; } sub error { my $self = shift; $self->{_error}; }
In reply to For Review: OOP DB Import by impossiblerobot
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |