Merge branch 'master' of git.freeside.biz:/home/git/freeside
authorIvan Kohler <ivan@freeside.biz>
Mon, 23 Nov 2015 22:56:43 +0000 (14:56 -0800)
committerIvan Kohler <ivan@freeside.biz>
Mon, 23 Nov 2015 22:56:43 +0000 (14:56 -0800)
FS/FS/Record.pm
FS/FS/UID.pm
htetc/handler.pl

index d27a614..18198d8 100644 (file)
@@ -3,7 +3,7 @@ use base qw( Exporter );
 
 use strict;
 use vars qw( $AUTOLOAD
-             %virtual_fields_cache %fk_method_cache
+             %virtual_fields_cache %fk_method_cache $fk_table_cache
              $money_char $lat_lower $lon_upper
            );
 use Carp qw(carp cluck croak confess);
@@ -34,7 +34,7 @@ our @EXPORT_OK = qw(
   dbh fields hfields qsearch qsearchs dbdef jsearch
   str2time_sql str2time_sql_closing regexp_sql not_regexp_sql
   concat_sql group_concat_sql
-  midnight_sql
+  midnight_sql fk_methods_init
 );
 
 our $DEBUG = 0;
@@ -82,9 +82,7 @@ FS::UID->install_callback( sub {
     eval "sub PG_BYTEA { die 'guru meditation #9: calling PG_BYTEA when not running Pg?'; }";
   }
 
-  foreach my $table ( dbdef->tables ) {
-    $fk_method_cache{$table} = fk_methods($table);
-  }
+  #fk_methods_init();
 
 } );
 
@@ -988,7 +986,7 @@ sub exists {
   exists($self->{Hash}->{$field});
 }
 
-=item AUTLOADED METHODS
+=item AUTOLOADED METHODS
 
 $record->column is a synonym for $record->get('column');
 
@@ -1010,10 +1008,8 @@ sub AUTOLOAD {
   confess "errant AUTOLOAD $field for $self (arg $value)"
     unless blessed($self) && $self->can('setfield');
 
-  #$fk_method_cache{$self->table} ||= fk_methods($self->table);
-  if ( exists($fk_method_cache{$self->table}->{$field}) ) {
+  if ( my $fk_info = get_fk_method($self->table, $field) ) {
 
-    my $fk_info = $fk_method_cache{$self->table}->{$field};
     my $method = $fk_info->{method} || 'qsearchs';
     my $table = $fk_info->{table} || $field;
     my $column = $fk_info->{column};
@@ -1056,6 +1052,37 @@ sub AUTOLOAD {
 #  }    
 #}
 
+# get_fk_method(TABLE, FIELD)
+# Internal subroutine for fetching the foreign key descriptor for TABLE.FIELD
+# if there is one. If not, returns undef.
+# This will initialize fk_method_cache if it hasn't happened yet. It is the
+# _only_ allowed way to access the contents of %fk_method_cache.
+
+# if we wanted to be even more efficient we'd create the fk methods in the
+# symbol table instead of relying on AUTOLOAD every time
+
+sub get_fk_method {
+  my ($table, $field) = @_;
+
+  # maybe should only load one table at a time?
+  fk_methods_init() unless exists($fk_method_cache{$table});
+
+  if ( exists($fk_method_cache{$table}) and
+       exists($fk_method_cache{$table}{$field}) ) {
+    return $fk_method_cache{$table}{$field};
+  } else {
+    return undef;
+  }
+
+}
+
+sub fk_methods_init {
+  warn "[fk_methods_init]\n";
+  foreach my $table ( dbdef->tables ) {
+    $fk_method_cache{$table} = fk_methods($table);
+  }
+}
+
 sub fk_methods {
   my $table = shift;
 
@@ -1093,11 +1120,15 @@ sub fk_methods {
   #  (alas.  why we're cached.  still, might this loop better be done once at
   #   schema load time insetad of every time we AUTOLOAD a method on a new
   #   class?)
-  foreach my $f_table ( dbdef->tables ) {
-    foreach my $fk (dbdef->table($f_table)->foreign_keys) {
-
-      next unless $fk->table eq $table;
-
+  if (! defined $fk_table_cache) {
+    foreach my $f_table ( dbdef->tables ) {
+      foreach my $fk (dbdef->table($f_table)->foreign_keys) {
+        push @{$fk_table_cache->{$fk->table}},[$f_table,$fk];
+      }
+    }
+  }
+  foreach my $fks (@{$fk_table_cache->{$table}}) {
+      my ($f_table,$fk) = @$fks;
       my $method = '';
       if ( scalar( @{$fk->columns} ) == 1 ) {
         if (    ! defined($fk->references)
@@ -1120,9 +1151,6 @@ sub fk_methods {
         }
 
       }
-
-    }
-
   }
 
   \%hash;
index c725f03..50a9178 100644 (file)
@@ -14,7 +14,7 @@ use IO::File;
 use FS::CurrentUser;
 
 @EXPORT_OK = qw( checkeuid checkruid cgi setcgi adminsuidsetup forksuidsetup
-                 preuser_setup
+                 preuser_setup load_schema
                  getotaker dbh datasrc getsecrets driver_name myconnect
                );
 
@@ -113,6 +113,14 @@ sub env_setup {
 
 }
 
+sub load_schema {
+  warn "$me loading schema\n" if $DEBUG;
+  getsecrets() unless $datasrc;
+  use FS::Schema qw(reload_dbdef dbdef);
+  reload_dbdef("$conf_dir/dbdef.$datasrc")
+    unless $FS::Schema::setup_hack;
+}
+
 sub db_setup {
   croak "Not running uid freeside (\$>=$>, \$<=$<)\n" unless checkeuid();
 
@@ -121,10 +129,7 @@ sub db_setup {
 
   warn "$me forksuidsetup connected to database with handle $dbh\n" if $DEBUG;
 
-  warn "$me forksuidsetup loading schema\n" if $DEBUG;
-  use FS::Schema qw(reload_dbdef dbdef);
-  reload_dbdef("$conf_dir/dbdef.$datasrc")
-    unless $FS::Schema::setup_hack;
+  load_schema();
 
   warn "$me forksuidsetup deciding upon config system to use\n" if $DEBUG;
 
index 416ea69..4bb214c 100644 (file)
@@ -10,6 +10,12 @@ use FS::Conf;
 
 $FS::Conf::conf_cache_enabled = 1; # enable FS::Conf caching for performance
 
+# Preload to share in mod_perl parent for performance
+use FS::UID qw(load_schema);
+load_schema();
+use FS::Record qw(fk_methods_init);
+fk_methods_init;
+
 if ( %%%RT_ENABLED%%% ) {
 
   require RT;