X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FRecord.pm;h=5269ab8cb8dc351056945e8af142f05654bae102;hb=34f8c7273c726b62f6a0031b7adf788bfb81e35e;hp=6bf124b4a8ad0abb1b870d51c5f5b76a6122cd99;hpb=fb53325987efe2e57ea4ba23483e0091527bc803;p=freeside.git diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index 6bf124b4a..5269ab8cb 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -211,6 +211,7 @@ The preferred usage is to pass a hash reference of named parameters: #these are optional... 'select' => '*', 'extra_sql' => 'AND field ', + 'order_by' => 'ORDER BY something', #'cache_obj' => '', #optional 'addl_from' => 'LEFT JOIN othtable USING ( field )', } @@ -233,13 +234,14 @@ fine in the common case where there are only two parameters: =cut sub qsearch { - my($stable, $record, $select, $extra_sql, $cache, $addl_from ); + my($stable, $record, $select, $extra_sql, $order_by, $cache, $addl_from ); if ( ref($_[0]) ) { #hashref for now, eventually maybe accept a list too my $opt = shift; $stable = $opt->{'table'} or die "table name is required"; $record = $opt->{'hashref'} || {}; $select = $opt->{'select'} || '*'; $extra_sql = $opt->{'extra_sql'} || ''; + $order_by = $opt->{'order_by'} || ''; $cache = $opt->{'cache_obj'} || ''; $addl_from = $opt->{'addl_from'} || ''; } else { @@ -272,94 +274,13 @@ sub qsearch { $statement .= " $addl_from" if $addl_from; if ( @real_fields or @virtual_fields ) { $statement .= ' WHERE '. join(' AND ', - ( map { - - my $op = '='; - my $column = $_; - if ( ref($record->{$_}) ) { - $op = $record->{$_}{'op'} if $record->{$_}{'op'}; - #$op = 'LIKE' if $op =~ /^ILIKE$/i && driver_name ne 'Pg'; - if ( uc($op) eq 'ILIKE' ) { - $op = 'LIKE'; - $record->{$_}{'value'} = lc($record->{$_}{'value'}); - $column = "LOWER($_)"; - } - $record->{$_} = $record->{$_}{'value'} - } - - if ( ! defined( $record->{$_} ) || $record->{$_} eq '' ) { - if ( $op eq '=' ) { - if ( driver_name eq 'Pg' ) { - my $type = dbdef->table($table)->column($column)->type; - if ( $type =~ /(int|(big)?serial)/i ) { - qq-( $column IS NULL )-; - } else { - qq-( $column IS NULL OR $column = '' )-; - } - } else { - qq-( $column IS NULL OR $column = "" )-; - } - } elsif ( $op eq '!=' ) { - if ( driver_name eq 'Pg' ) { - my $type = dbdef->table($table)->column($column)->type; - if ( $type =~ /(int|(big)?serial)/i ) { - qq-( $column IS NOT NULL )-; - } else { - qq-( $column IS NOT NULL AND $column != '' )-; - } - } else { - qq-( $column IS NOT NULL AND $column != "" )-; - } - } else { - if ( driver_name eq 'Pg' ) { - qq-( $column $op '' )-; - } else { - qq-( $column $op "" )-; - } - } - } else { - "$column $op ?"; - } - } @real_fields ), - ( map { - my $op = '='; - my $column = $_; - if ( ref($record->{$_}) ) { - $op = $record->{$_}{'op'} if $record->{$_}{'op'}; - if ( uc($op) eq 'ILIKE' ) { - $op = 'LIKE'; - $record->{$_}{'value'} = lc($record->{$_}{'value'}); - $column = "LOWER($_)"; - } - $record->{$_} = $record->{$_}{'value'}; - } - - # ... EXISTS ( SELECT name, value FROM part_virtual_field - # JOIN virtual_field - # ON part_virtual_field.vfieldpart = virtual_field.vfieldpart - # WHERE recnum = svc_acct.svcnum - # AND (name, value) = ('egad', 'brain') ) - - my $value = $record->{$_}; - - my $subq; - - $subq = ($value ? 'EXISTS ' : 'NOT EXISTS ') . - "( SELECT part_virtual_field.name, virtual_field.value ". - "FROM part_virtual_field JOIN virtual_field ". - "ON part_virtual_field.vfieldpart = virtual_field.vfieldpart ". - "WHERE virtual_field.recnum = ${table}.${pkey} ". - "AND part_virtual_field.name = '${column}'". - ($value ? - " AND virtual_field.value ${op} '${value}'" - : "") . ")"; - $subq; - - } @virtual_fields ) ); - + get_real_fields($table, $record, \@real_fields) , + get_virtual_fields($table, $pkey, $record, \@virtual_fields), + ); } $statement .= " $extra_sql" if defined($extra_sql); + $statement .= " $order_by" if defined($order_by); warn "[debug]$me $statement\n" if $DEBUG > 1; my $sth = $dbh->prepare($statement) @@ -468,6 +389,110 @@ sub qsearch { return @return; } +## makes this easier to read + +sub get_virtual_fields { + my $table = shift; + my $pkey = shift; + my $record = shift; + my $virtual_fields = shift; + + return + ( map { + my $op = '='; + my $column = $_; + if ( ref($record->{$_}) ) { + $op = $record->{$_}{'op'} if $record->{$_}{'op'}; + if ( uc($op) eq 'ILIKE' ) { + $op = 'LIKE'; + $record->{$_}{'value'} = lc($record->{$_}{'value'}); + $column = "LOWER($_)"; + } + $record->{$_} = $record->{$_}{'value'}; + } + + # ... EXISTS ( SELECT name, value FROM part_virtual_field + # JOIN virtual_field + # ON part_virtual_field.vfieldpart = virtual_field.vfieldpart + # WHERE recnum = svc_acct.svcnum + # AND (name, value) = ('egad', 'brain') ) + + my $value = $record->{$_}; + + my $subq; + + $subq = ($value ? 'EXISTS ' : 'NOT EXISTS ') . + "( SELECT part_virtual_field.name, virtual_field.value ". + "FROM part_virtual_field JOIN virtual_field ". + "ON part_virtual_field.vfieldpart = virtual_field.vfieldpart ". + "WHERE virtual_field.recnum = ${table}.${pkey} ". + "AND part_virtual_field.name = '${column}'". + ($value ? + " AND virtual_field.value ${op} '${value}'" + : "") . ")"; + $subq; + + } @{ $virtual_fields } ) ; +} + +sub get_real_fields { + my $table = shift; + my $record = shift; + my $real_fields = shift; + + ## this huge map was previously inline, just broke it out to help read the qsearch method, should be optimized for readability + return ( + map { + + my $op = '='; + my $column = $_; + if ( ref($record->{$_}) ) { + $op = $record->{$_}{'op'} if $record->{$_}{'op'}; + #$op = 'LIKE' if $op =~ /^ILIKE$/i && driver_name ne 'Pg'; + if ( uc($op) eq 'ILIKE' ) { + $op = 'LIKE'; + $record->{$_}{'value'} = lc($record->{$_}{'value'}); + $column = "LOWER($_)"; + } + $record->{$_} = $record->{$_}{'value'} + } + + if ( ! defined( $record->{$_} ) || $record->{$_} eq '' ) { + if ( $op eq '=' ) { + if ( driver_name eq 'Pg' ) { + my $type = dbdef->table($table)->column($column)->type; + if ( $type =~ /(int|(big)?serial)/i ) { + qq-( $column IS NULL )-; + } else { + qq-( $column IS NULL OR $column = '' )-; + } + } else { + qq-( $column IS NULL OR $column = "" )-; + } + } elsif ( $op eq '!=' ) { + if ( driver_name eq 'Pg' ) { + my $type = dbdef->table($table)->column($column)->type; + if ( $type =~ /(int|(big)?serial)/i ) { + qq-( $column IS NOT NULL )-; + } else { + qq-( $column IS NOT NULL AND $column != '' )-; + } + } else { + qq-( $column IS NOT NULL AND $column != "" )-; + } + } else { + if ( driver_name eq 'Pg' ) { + qq-( $column $op '' )-; + } else { + qq-( $column $op "" )-; + } + } + } else { + "$column $op ?"; + } + } @{ $real_fields } ); +} + =item by_key PRIMARY_KEY_VALUE This is a class method that returns the record with the given primary key @@ -725,7 +750,7 @@ sub insert { #single-field unique keys are given a value if false #(like MySQL's AUTO_INCREMENT or Pg SERIAL) - foreach ( $self->dbdef_table->unique_singles ) { + foreach ( $self->dbdef_table->unique_singles) { $self->unique($_) unless $self->getfield($_); } @@ -752,6 +777,7 @@ sub insert { # Encrypt before the database + my $conf = new FS::Conf; if ($conf->exists('encryption') && defined(eval '@FS::'. $table . '::encrypted_fields')) { foreach my $field (eval '@FS::'. $table . '::encrypted_fields') { $self->{'saved'} = $self->getfield($field); @@ -1249,6 +1275,7 @@ sub _h_statement { # If we're encrypting then don't ever store the payinfo or CVV2 in the history.... # You can see if it changed by the paymask... + my $conf = new FS::Conf; if ($conf->exists('encryption') ) { @fields = grep $_ ne 'payinfo' && $_ ne 'cvv2', @fields; } @@ -2136,7 +2163,7 @@ sub loadRSA { $rsa_module = 'Crypt::OpenSSL::RSA'; # The Default my $conf = new FS::Conf; - if ($conf->exists('encryptionmodule') && $conf->config('encryptionmodule') ne '') { + if ($conf->exists('encryptionmodule') && $conf->config_binary('encryptionmodule') ne '') { $rsa_module = $conf->config('encryptionmodule'); } @@ -2145,13 +2172,13 @@ sub loadRSA { $rsa_loaded++; } # Initialize Encryption - if ($conf->exists('encryptionpublickey') && $conf->config('encryptionpublickey') ne '') { + if ($conf->exists('encryptionpublickey') && $conf->config_binary('encryptionpublickey') ne '') { my $public_key = join("\n",$conf->config('encryptionpublickey')); $rsa_encrypt = $rsa_module->new_public_key($public_key); } # Intitalize Decryption - if ($conf->exists('encryptionprivatekey') && $conf->config('encryptionprivatekey') ne '') { + if ($conf->exists('encryptionprivatekey') && $conf->config_binary('encryptionprivatekey') ne '') { my $private_key = join("\n",$conf->config('encryptionprivatekey')); $rsa_decrypt = $rsa_module->new_private_key($private_key); }