X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FRecord.pm;h=7f76d99885e9ccfd962169ed79419d81ac23c5c1;hb=3cbdd85a96348a287623e3b97c937c7749e99392;hp=b2ab713f0aa5595dcebef0c68164f4d8af7f5a23;hpb=49a6b0927001edb259a858841dd529e42fa58880;p=freeside.git diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index b2ab713f0..7f76d9988 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -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; @@ -66,8 +66,8 @@ FS::UID->install_callback( sub { $conf = FS::Conf->new; $conf_encryption = $conf->exists('encryption'); $conf_encryptionmodule = $conf->config('encryptionmodule'); - $conf_encryptionpublickey = $conf->config('encryptionpublickey'); - $conf_encryptionprivatekey = $conf->config('encryptionprivatekey'); + $conf_encryptionpublickey = join("\n",$conf->config('encryptionpublickey')); + $conf_encryptionprivatekey = join("\n",$conf->config('encryptionprivatekey')); $money_char = $conf->config('money_char') || '$'; my $nw_coords = $conf->exists('geocode-require_nw_coordinates'); $lat_lower = $nw_coords ? 1 : -90; @@ -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(); } ); @@ -201,6 +199,7 @@ sub new { $self->{'modified'} = 0; + $self->_simplecache($self->{'Hash'}) if $self->can('_simplecache'); $self->_cache($self->{'Hash'}, shift) if $self->can('_cache') && @_; $self; @@ -527,6 +526,7 @@ sub qsearch { # Check for encrypted fields and decrypt them. ## only in the local copy, not the cached object + no warnings 'deprecated'; # XXX silence the warning for now if ( $conf_encryption && eval '@FS::'. $table . '::encrypted_fields' ) { foreach my $record (@return) { @@ -987,7 +987,7 @@ sub exists { exists($self->{Hash}->{$field}); } -=item AUTLOADED METHODS +=item AUTOLOADED METHODS $record->column is a synonym for $record->get('column'); @@ -1009,10 +1009,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}; @@ -1055,6 +1053,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" if $DEBUG; + foreach my $table ( dbdef->tables ) { + $fk_method_cache{$table} = fk_methods($table); + } +} + sub fk_methods { my $table = shift; @@ -1092,11 +1121,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) @@ -1119,9 +1152,6 @@ sub fk_methods { } } - - } - } \%hash; @@ -1299,8 +1329,7 @@ sub insert { my $table = $self->table; # Encrypt before the database - if ( defined(eval '@FS::'. $table . '::encrypted_fields') - && scalar( eval '@FS::'. $table . '::encrypted_fields') + if ( scalar( eval '@FS::'. $table . '::encrypted_fields') && $conf_encryption ) { foreach my $field (eval '@FS::'. $table . '::encrypted_fields') { @@ -1542,9 +1571,8 @@ sub replace { # Encrypt for replace my $saved = {}; - if ( $conf_encryption - && defined(eval '@FS::'. $new->table . '::encrypted_fields') - && scalar( eval '@FS::'. $new->table . '::encrypted_fields') + if ( scalar( eval '@FS::'. $new->table . '::encrypted_fields') + && $conf_encryption ) { foreach my $field (eval '@FS::'. $new->table . '::encrypted_fields') { next if $field eq 'payinfo' @@ -2124,6 +2152,7 @@ sub batch_import { #my $job = $param->{job}; my $line; my $imported = 0; + my $unique_skip = 0; #lines skipped because they're already in the system my( $last, $min_sec ) = ( time, 5 ); #progressbar foo while (1) { @@ -2226,6 +2255,7 @@ sub batch_import { } last if exists( $param->{skiprow} ); } + $unique_skip++ if $param->{unique_skip}; #line is already in the system next if exists( $param->{skiprow} ); if ( $preinsert_callback ) { @@ -2271,7 +2301,8 @@ sub batch_import { unless ( $imported || $param->{empty_ok} ) { $dbh->rollback if $oldAutoCommit; - return "Empty file!"; + # freeside-cdr-conexiant-import is sensitive to the text of this message + return $unique_skip ? "All records in file were previously imported" : "Empty file!"; } $dbh->commit or die $dbh->errstr if $oldAutoCommit; @@ -2976,7 +3007,6 @@ May not be null. sub ut_name { my( $self, $field ) = @_; -# warn "ut_name allowed alphanumerics: +(sort grep /\w/, map { chr() } 0..255), "\n"; $self->getfield($field) =~ /^([\p{Word} \,\.\-\']+)$/ or return gettext('illegal_name'). " $field: ". $self->getfield($field); my $name = $1; @@ -3293,14 +3323,12 @@ sub loadRSA { } # Initialize Encryption if ($conf_encryptionpublickey && $conf_encryptionpublickey ne '') { - my $public_key = join("\n",$conf_encryptionpublickey); - $rsa_encrypt = $rsa_module->new_public_key($public_key); + $rsa_encrypt = $rsa_module->new_public_key($conf_encryptionpublickey); } # Intitalize Decryption if ($conf_encryptionprivatekey && $conf_encryptionprivatekey ne '') { - my $private_key = join("\n",$conf_encryptionprivatekey); - $rsa_decrypt = $rsa_module->new_private_key($private_key); + $rsa_decrypt = $rsa_module->new_private_key($conf_encryptionprivatekey); } }