Author: spadkins
Date: Fri Jan 6 08:44:44 2012
New Revision: 15070
Modified:
p5ee/trunk/App-Repository/CHANGES
p5ee/trunk/App-Repository/lib/App/Repository.pm
Log:
support metadata caching on disk. (first release candidate)
Modified: p5ee/trunk/App-Repository/CHANGES
==============================================================================
--- p5ee/trunk/App-Repository/CHANGES (original)
+++ p5ee/trunk/App-Repository/CHANGES Fri Jan 6 08:44:44 2012
@@ -2,6 +2,17 @@
# CHANGE LOG
#########################################
+0.969 PRERELEASE
+ x added PrintWarn => 0 to the dbh attributes (useful for Oracle
execute_array() to suppress primary key violation warnings)
+ x support db->_do() for select statements which start with whitespace
+ x actually specify what Oracle errors a reconnect is allowed on
+ x support arbitrary DBI connection attributes to be set. (Useful for Oracle
DRCP, etc.) (e.g. {repname}.dbiattr = xyz,foo=5)
+ x support repository and table metadata caching on disk (HUGE PERFORMANCE
IMPROVEMENT)
+ Prior to this, App-Repository was built for ease-of-programming. Every time
it would connect, it would query the database
+ for a list of the tables and for the list and definition of types. Every
time it accessed a table, it would query the database
+ for the columns (and possibly also the keys/unique indexes). Now, using the
dbmetadata tool, you can extract this metadata
+ from the database and save a lot of overhead.
+
0.968
x summary_tables are now implemented
x queries which include undefined columns in the order by clause exclude
those columns and work correctly otherwise
Modified: p5ee/trunk/App-Repository/lib/App/Repository.pm
==============================================================================
--- p5ee/trunk/App-Repository/lib/App/Repository.pm (original)
+++ p5ee/trunk/App-Repository/lib/App/Repository.pm Fri Jan 6 08:44:44 2012
@@ -4228,10 +4228,32 @@
&App::sub_entry if ($App::trace);
my ($self) = @_;
- my ($table, $tables, $table_defs, $table_def, $native_table, $idx, $label,
@label);
+ my ($table, $tables, $rep_def, $table_defs, $table_def, $native_table,
$idx, $label, @label);
- # load up all possible information from the native metadata
- $self->_load_rep_metadata_from_source();
+ my $context = $self->{context};
+ my $options = $context->{options};
+ my $prefix = $options->{prefix};
+ my $rep_file = "$prefix/etc/app/Repository/$self->{name}/_META_.pl";
+ #print $self->dump();
+ #print STDERR "_load_rep_metadata(): checking $rep_file\n";
+
+ if (! $options->{force_metadata_load} && -r $rep_file) {
+ #print STDERR "_load_rep_metadata($table): checking $rep_file : found
AND {force_metadata_load}=[$options->{force_metadata_load}] is false\n";
+ $rep_def = do $rep_file;
+ if (!$rep_def) {
+ die "Error: Syntax error in $rep_file: $@" if ($@);
+ die "Error: Couldn't do $rep_file: $!" if (! defined $rep_def);
+ die "Error: Couldn't run $rep_file" if (! $rep_def);
+ }
+ App::Reference->overlay($self, $rep_def);
+ }
+ else {
+ #print STDERR "_load_rep_metadata($table): checking $rep_file : not
found OR {force_metadata_load}=[$options->{force_metadata_load}] is true\n";
+ $self->_load_rep_metadata_from_source();
+ if ($options->{force_metadata_write}) {
+ $self->_write_rep_metadata("$rep_file.new");
+ }
+ }
# start with the list of tables that was configured (or the empty list)
$tables = $self->{tables};
@@ -4318,6 +4340,32 @@
&App::sub_exit() if ($App::trace);
}
+sub _write_rep_metadata {
+ &App::sub_entry if ($App::trace);
+ my ($self, $rep_file) = @_;
+
+ open(my $fh, ">", $rep_file) || die "Can't open $rep_file for writing: $!";
+
+ my $name = $self->{name};
+ my $dump_name = "Repository__${name}";
+ my $copy = { %$self };
+ my ($key);
+ foreach $key qw(context _repository name class) {
+ delete $copy->{$key};
+ }
+ foreach $key (keys %$copy) {
+ delete $copy->{$key} if ($key =~ /^db/ || $key =~ /^$name.db/);
+ }
+
+ my $d = Data::Dumper->new([ $copy ], [ $dump_name ]);
+ $d->Indent(1);
+ $d->Purity(1);
+ print $fh $d->Dump();
+
+ close($fh);
+ &App::sub_exit() if ($App::trace);
+}
+
#############################################################################
# _load_rep_metadata_from_source()
#############################################################################
@@ -4395,25 +4443,36 @@
$table_def = $self->{table}{$table} || {};
#print STDERR "_load_table_metadata($table): table_def=[$table_def] ",
($table_def ? "{".join("|", %$table_def)."}" : "undef"), "\n";
- if (!$table_def->{column}) { # no columns are defined
- my $context = $self->{context};
- my $options = $context->{options};
- my $prefix = $options->{prefix};
- my $conf_type = $options->{conf_type} || "pl";
- my $table_file =
"$prefix/etc/app/Repository/$self->{name}/$table.$conf_type";
- #print STDERR "_load_table_metadata($table): checking $table_file\n";
- if (-r $table_file) {
- #print STDERR "_load_table_metadata($table): checking $table_file
: found\n";
- $table_def = do $table_file;
- if ($table_def->{overlay}) {
- delete $table_def->{overlay};
- # Caution. Overlays the entire conf, not just the table_def.
Use with care.
- App::Reference->overlay($self->{context}{conf}, $table_def);
- }
- else {
- # Normal. Replaces the table_def.
- $self->{table}{$table} = $table_def;
- }
+ #print STDERR $self->dump($table_def);
+
+ my $context = $self->{context};
+ my $options = $context->{options};
+ my $prefix = $options->{prefix};
+ my $table_file = "$prefix/etc/app/Repository/$self->{name}/$table.pl";
+ #print STDERR "_load_table_metadata($table): checking $table_file\n";
+ if (! $options->{force_metadata_load} && -r $table_file) {
+ #print STDERR "_load_table_metadata($table): checking $table_file :
found\n";
+ $table_def = do $table_file;
+ if (!$table_def) {
+ die "Error: Syntax error in $table_file: $@" if ($@);
+ die "Error: Couldn't do $table_file: $!" if (! defined
$table_def);
+ die "Error: Couldn't run $table_file" if (! $table_def);
+ }
+ if ($table_def->{overlay}) {
+ delete $table_def->{overlay};
+ # Caution. Overlays the entire conf, not just the table_def. Use
with care.
+ App::Reference->overlay($self->{context}{conf}, $table_def);
+ }
+ else {
+ # Normal. Replaces the table_def.
+ $self->{table}{$table} = $table_def;
+ }
+ }
+ else {
+ # load up all additional information from the native metadata
+ $self->_load_table_metadata_from_source($table);
+ if ($options->{force_metadata_write}) {
+ $self->_write_table_metadata("$table_file.new", $table);
}
}
@@ -4424,9 +4483,6 @@
return;
}
- # load up all additional information from the native metadata
- $self->_load_table_metadata_from_source($table);
-
if ($table_def->{overlay_from_table}) {
#print STDERR "load_table_metadata($table) :
OVERLAY=[$table_def->{overlay_from_table}]\n";
@@ -4596,12 +4652,41 @@
}
}
}
-
+
+ # NOTE: This must be only perl code without access to the database.
Otherwise the metadata caching doesn't work.
$self->_load_table_metadata_from_source2($table);
&App::sub_exit() if ($App::trace);
}
+sub _write_table_metadata {
+ &App::sub_entry if ($App::trace);
+ my ($self, $table_file, $table) = @_;
+
+ open(my $fh, ">", $table_file) || die "Can't open $table_file for writing:
$!";
+
+ my $name = $self->{name};
+ my $dump_name = "Repository__${name}__${table}";
+ my $table_def = $self->{table}{$table} || {};
+ my $copy = { %$table_def };
+
+ my ($key);
+ #foreach $key qw(context _repository name class) {
+ # delete $copy->{$key};
+ #}
+ #foreach $key (keys %$copy) {
+ # delete $copy->{$key} if ($key =~ /^db/ || $key =~ /^$name.db/);
+ #}
+
+ my $d = Data::Dumper->new([ $copy ], [ $dump_name ]);
+ $d->Indent(1);
+ $d->Purity(1);
+ print $fh $d->Dump();
+
+ close($fh);
+ &App::sub_exit() if ($App::trace);
+}
+
#############################################################################
# _load_table_metadata_from_source()
#############################################################################
@@ -4628,10 +4713,12 @@
=cut
+# NOTE: This generally will access the database. It does not get called if
cached metadata exists.
sub _load_table_metadata_from_source {
my ($self, $table) = @_;
}
+# NOTE: This must be only perl code without access to the database. Otherwise
the metadata caching doesn't work.
sub _load_table_metadata_from_source2 {
my ($self, $table) = @_;
}