Cache column and primary/foreign/unique key info fewer-queries
Dagfinn Ilmari Mannsåker [Sun, 13 Sep 2015 13:17:12 +0000 (14:17 +0100)]
Changes
Makefile.PL
lib/DBIx/Class/Schema/Loader/DBI.pm

diff --git a/Changes b/Changes
index f93c43e..57a25be 100644 (file)
--- a/Changes
+++ b/Changes
@@ -2,6 +2,7 @@ Revision history for Perl extension DBIx::Class::Schema::Loader
 
         - Fix Pg date/time types with zero fractional second digits
         - Reduce the number of queries by caching the list of tables
+          and their columns and primary/foreign/unique keys
 
 0.07043  2015-05-13
         - Fix many_to_many bridges with overlapping foreign keys
index dae8d9d..eb0db45 100644 (file)
@@ -42,6 +42,7 @@ requires 'Carp::Clan'                  => 0;
 requires 'Class::Accessor::Grouped'    => '0.10008';
 requires 'Class::C3::Componentised'    => '1.0008';
 requires 'Class::Inspector'            => '1.27';
+requires 'Class::Method::Modifiers'    => '1.05';
 requires 'Class::Unload'               => '0.07';
 requires 'Data::Dump'                  => '1.06';
 requires 'DBIx::Class'                 => '0.08127';
index 47e4248..5dcc71a 100644 (file)
@@ -5,8 +5,11 @@ use warnings;
 use base qw/DBIx::Class::Schema::Loader::Base/;
 use mro 'c3';
 use Try::Tiny;
+use Scalar::Util 'blessed';
 use List::Util 'any';
 use Carp::Clan qw/^DBIx::Class/;
+use Class::Method::Modifiers 'install_modifier';
+
 use namespace::clean;
 use DBIx::Class::Schema::Loader::Table ();
 
@@ -94,7 +97,31 @@ sub _build_name_sep {
 }
 
 # Override this in vendor modules to do things at the end of ->new()
-sub _setup { }
+sub _setup {
+    my ($self) = @_;
+
+    for my $method (qw(
+        _columns_info_for _table_columns
+        _table_pk_info _table_fk_info _table_uniq_info
+    )) {
+        $self->_setup_per_table_cache($method);
+    }
+}
+
+{
+    my %has_cache_setup;
+    sub _setup_per_table_cache {
+        my ($self, $method) = @_;
+        my $class = blessed($self);
+
+        return if $has_cache_setup{$class}{$method}++;
+
+        install_modifier($class, around => $method => sub {
+            my ($orig, $self, $table) = @_;
+            $self->{_cache}{$method}{$table->sql_name} ||= $self->$orig($table);
+        });
+    }
+}
 
 # Override this in vendor module to load a subclass if necessary
 sub _rebless { }