App-Repository
view release on metacpan or search on metacpan
lib/App/Repository.pm view on Meta::CPAN
$rowchange->[$rowidx] = "";
$nrows++;
}
if ($App::DEBUG && $self->{context}->dbg(7)) {
my $context = $self->{context};
$context->dbgprint("rep->commit(): [$self->{sql}]");
$context->dbgprint(" [", join("|",@{$rows->[$rowidx]}), "]");
}
}
}
}
$self->{context}->dbgprint("rep->commit(): nrows=$nrows")
if ($App::DEBUG && $self->{context}->dbg(2));
}
#############################################################################
# rollback()
#############################################################################
=head2 rollback()
* Signature: $rep->rollback();
* Param: void
* Return: void
* Throws: App::Exception::Repository
* Since: 0.01
Sample Usage:
$rep->rollback();
=cut
sub rollback {
my $self = shift;
}
#############################################################################
# METHODS
#############################################################################
=head1 Methods: Import/Export Data From File
=cut
#############################################################################
# import_rows()
#############################################################################
=head2 import_rows()
* Signature: $rep->import_rows($table, $columns, $file);
* Signature: $rep->import_rows($table, $columns, $file, $options);
* Param: $table string
* Param: $columns ARRAY names of columns of the fields in the file
* Param: $file string
* Param: $options named
* Param: replace boolean rows should replace existing rows based on unique indexes
* Param: field_sep char character which separates the fields in the file (can by "\t")
* Param: field_quote char character which optionally encloses the fields in the file (i.e. '"')
* Param: field_escape char character which escapes the quote chars within quotes (i.e. "\")
* Return: void
* Throws: App::Exception::Repository
* Since: 0.01
Sample Usage:
$rep->import_rows("usr","usr.dat");
# root:x:0:0:root:/root:/bin/bash
$rep->import_rows("usr",
[ "username", "password", "uid", "gid", "comment", "home_directory", "shell" ],
"/etc/passwd" ,
{ field_sep => ":", });
=cut
sub import_rows {
&App::sub_entry if ($App::trace);
my ($self, $table, $columns, $file, $options) = @_;
$columns = $self->_get_default_columns($table) if (!$columns);
my $field_sep = $options->{field_sep} || ",";
my $field_quote = $options->{field_quote};
my $field_escape = $options->{field_escape};
open(App::Repository::DBI::FILE, "< $file") || die "Unable to open $file for reading: $!";
my (@row, $quoted_field_regexp, $field_regexp);
while (<App::Repository::DBI::FILE>) {
chomp;
if ($field_quote) {
@row = ();
# TODO: use the _read_rows_from_file() method
# TODO: incorporate escaping
$field_regexp = "$field_sep?$field_quote([^$field_quote]*)$field_quote";
$quoted_field_regexp = "$field_sep?([^$field_sep]*)";
while ($_) {
if ($_ =~ s/^$quoted_field_regexp//) {
push(@row, $1);
}
elsif ($_ =~ s/^$field_regexp//) {
push(@row, $1);
}
else {
die "Imported data doesn't match quoted or unquoted field [$_]";
}
}
}
else {
@row = split(/$field_sep/);
}
# TODO: use insert_rows() instead of insert_row()
$self->insert_row($table, $columns, \@row);
}
close(App::Repository::DBI::FILE);
&App::sub_exit() if ($App::trace);
}
#############################################################################
# export_rows()
#############################################################################
=head2 export_rows()
* Signature: $rep->export_rows($table, $columns, $file);
* Signature: $rep->export_rows($table, $columns, $file, $options);
* Param: $table string
* Param: $file string
* Param: $options named
* Param: columns ARRAY names of columns of the fields in the file
* Param: replace boolean rows should replace existing rows based on unique indexes
* Param: field_sep char character which separates the fields in the file (can by "\t")
* Param: field_quote char character which optionally encloses the fields in the file (i.e. '"')
* Param: field_escape char character which escapes the quote chars within quotes (i.e. "\")
* Return: void
* Throws: App::Exception::Repository
* Since: 0.01
Sample Usage:
$rep->export_rows("usr","usr.dat");
# root:x:0:0:root:/root:/bin/bash
$rep->export_rows("usr", "passwd.dat" ,{
field_sep => ":",
columns => [ "username", "password", "uid", "gid", "comment", "home_directory", "shell" ],
});
=cut
sub export_rows {
&App::sub_entry if ($App::trace);
my ($self, $table, $columns, $file, $options) = @_;
$columns = $self->_get_default_columns($table) if (!$columns);
my $rows = $self->get_rows($table, {}, $columns);
my $field_sep = $options->{field_sep} || ",";
my $field_quote = $options->{field_quote};
my $field_escape = $options->{field_escape};
open(App::Repository::DBI::FILE, "> $file") || die "Unable to open $file for writing: $!";
my ($i, $value);
foreach my $row (@$rows) {
if ($field_quote) {
for ($i = 0; $i <= $#$row; $i++) {
print App::Repository::DBI::FILE $field_sep if ($i > 0);
$value = $row->[$i];
if ($value =~ /$field_sep/) {
if ($field_escape) {
$value =~ s/$field_escape/$field_escape$field_escape/g;
$value =~ s/$field_quote/$field_escape$field_quote/g;
}
print App::Repository::DBI::FILE $field_quote, $value, $field_quote;
}
else {
print App::Repository::DBI::FILE $value;
}
}
}
else {
print App::Repository::DBI::FILE join($field_sep, @$row), "\n";
}
}
close(App::Repository::DBI::FILE);
&App::sub_exit() if ($App::trace);
}
sub _read_rows_from_file {
&App::sub_entry if ($App::trace);
my ($self, $fh, $cols, $options) = @_;
my $maxrows = $options->{maxrows};
my $null_value = $options->{null_value};
$null_value = '\N' if (!defined $null_value);
my $field_sep = $options->{field_sep} || ",";
my $field_quote = $options->{field_quote} || "";
my $field_escape = $options->{field_escape} || "";
die "TODO: field_escape not yet implemented" if ($field_escape);
my $fieldsep_regexp = ($field_sep eq "|") ? '\|' : $field_sep;
my $quoted_field_regexp = "$field_sep?$field_quote([^$field_quote]*)$field_quote";
my $field_regexp = "$field_sep?([^$field_sep]*)";
my $num_cols = $#$cols + 1;
my $rows_read = 0;
my $rows = [];
my ($num_values_read, $line, $line_remainder, $row);
while (<$fh>) {
chomp;
$line = $_;
if ($line) {
if (!$field_quote && !$field_escape) {
$row = [ map { $_ eq $null_value ? undef : $_ } split(/$fieldsep_regexp/, $line) ];
$num_values_read = $#$row + 1;
}
else {
$num_values_read = 0;
$line_remainder = $line;
$row = [];
while ($line_remainder) {
if ($line_remainder =~ s/^$quoted_field_regexp//) {
push(@$row, $1 eq $null_value ? undef : $1);
}
elsif ($line_remainder =~ s/^$field_regexp//) {
push(@$row, $1 eq $null_value ? undef : $1);
}
else {
die "Imported data [$line] doesn't match quoted or unquoted field at [$line_remainder]";
}
}
}
die "In imported data [$line], num values on line [$num_values_read] != num columns expected [$num_cols]"
if ($num_values_read != $num_cols);
push(@$rows, $row);
$rows_read ++;
if ($maxrows && $rows_read >= $maxrows) {
last;
}
}
}
&App::sub_exit($rows) if ($App::trace);
return($rows);
}
#############################################################################
# METHODS
#############################################################################
=head1 Methods: Locking (Concurrency Management)
=cut
# this is a write lock for the table
sub _lock_table {
&App::sub_entry if ($App::trace);
my ($self, $table) = @_;
if (! $self->{locked}) { # I have locked it myself, so I don't need to again
my ($name, $dbname, $context, $rlock);
$name = $self->{name};
$dbname = $self->{dbname};
$context = $self->{context};
$rlock = $context->resource_locker($name); # get the one that corresponds to this repository
$rlock->lock("db.$dbname.$table");
$self->{locked} = 1;
}
&App::sub_exit() if ($App::trace);
}
# unlocks the write lock for the table
sub _unlock_table {
&App::sub_entry if ($App::trace);
my ($self, $table) = @_;
( run in 1.034 second using v1.01-cache-2.11-cpan-39bf76dae61 )