Listing 3. DBI implementation of program to copy user records from a source
table (uregister) to a target table (uregisternew).
use Angryman::User;
use DBI;
use Math::Random;
use strict;
use vars qw(%table $sql_field_term $insert_term %profile @ordered_fields);
$table{in} = 'uregister';
$table{out} = 'uregisternew';
# connect to database and SELECT * FROM uregister
my $dbh = DBI->connect('DBI:mysql:test', 'root') || die "$!\n";
my $sth = $dbh->prepare('SELECT * FROM uregister');
my $ret = $sth->execute;
&determine_target_database_field_order;
# because we will re-use the target table many times, we separate the
# connection and insert steps with this recordset
# iterate through the recordsets from the old table:
while (my $record = $sth->fetchrow_hashref) {
&randomize_user_profile;
&fiddle_with_my_data_to_get_it_to_work_with_the_DBI_API($record);
# INSERT
# the old table data into the new table along with
# the computed hash of profile data
my $sql =
"INSERT into $table{out}($sql_field_term) values($insert_term)";
$dbh->do($sql);
}
# Angryman::User::Profile is a hash in which each key is a reference
# to an array of profile choices. For example:
# $Angryman::User::Profile{gender} = [ 'male', 'female' ];
# $Angryman::User::Profile{age} = ['under 14', '14-19', '20-25', ... ];
# Because we don't have the actual data for the people in uregister,
# we randomly assign user profile data over a normal distribution.
# when copying it to uregisternew.
sub randomize_user_profile {
for (keys %Angryman::User::Profile) {
my @tmp = @{$Angryman::User::Profile{$_}};
$profile{$_} = random_uniform_integer(1, 0, $#tmp);
}
$profile{dob} = '1969-05-11';
}
# Hmm, I can't just give DBI my data and have it figure out the order
# of the database fields... So here we go getting the field order
# dynamically so this code doesn't break with the least little
# switch of field position.
# In DBIx::Recordset, I would just say $handle->Names()
sub determine_target_database_field_order {
my $order_sth = $dbh->prepare("SELECT * FROM $table{out} LIMIT 1");
$order_sth->execute;
@ordered_fields = @{$order_sth->{NAME}};
$sql_field_term = join ',', @{$order_sth->{NAME}};
}
# As ubiquitous as hashes are in Perl, the DBI API does not
# offer a way to directly commit hashes to databases.
sub fiddle_with_my_data_to_get_it_to_work_with_the_DBI_API {
my ($record)=@_;
my @output_data;
for (@ordered_fields) {
push @output_data, $dbh->quote
(
defined($record->{$_})
? $record->{$_}
: $profile{$_}
);
}
$insert_term = join ',', @output_data;
}