use strict;
use vars qw( $AUTOLOAD @ISA @EXPORT_OK $DEBUG
- $conf $me
+ $conf $conf_encryption $me
%virtual_fields_cache
$nowarn_identical $no_update_diff $no_check_foreign
);
my $rsa_encrypt;
my $rsa_decrypt;
+$conf = '';
+$conf_encryption = '';
FS::UID->install_callback( sub {
eval "use FS::Conf;";
die $@ if $@;
$conf = FS::Conf->new;
+ $conf_encryption = $conf->exists('encryption');
$File::CounterFile::DEFAULT_DIR = $conf->base_dir . "/counters.". datasrc;
} );
my %TYPE = (); #for debugging
+sub _is_fs_float {
+ my ($type, $value) = @_;
+ if ( ( $type =~ /(numeric)/i && $value =~ /^[+-]?\d+(\.\d+)?$/ ) ||
+ ( $type =~ /(real|float4)/i && $value =~ /[-+]?\d*\.?\d+([eE][-+]?\d+)?/)
+ ) {
+ return 1;
+ }
+ '';
+}
+
sub qsearch {
my($stable, $record, $select, $extra_sql, $order_by, $cache, $addl_from );
my $debug = '';
) {
my $value = $record->{$field};
+ my $op = (ref($value) && $value->{op}) ? $value->{op} : '=';
$value = $value->{'value'} if ref($value);
my $type = dbdef->table($table)->column($field)->type;
$TYPE = SQL_INTEGER;
#DBD::Pg 1.49: Cannot bind ... unknown sql_type 6 with SQL_FLOAT
- } elsif ( ( $type =~ /(numeric)/i && $value =~ /^[+-]?\d+(\.\d+)?$/)
- || ( $type =~ /(real|float4)/i
- && $value =~ /[-+]?\d*\.?\d+([eE][-+]?\d+)?/
- )
- ) {
+ #fixed by DBD::Pg 2.11.8
+ #can change back to SQL_FLOAT in early-mid 2010, once everyone's upgraded
+ } elsif ( _is_fs_float( $type, $value ) ) {
$TYPE = SQL_DECIMAL;
}
warn " bind_param $bind (for field $field), $value, TYPE $TYPE{$TYPE}\n";
}
- $sth->bind_param($bind++, $value, { TYPE => $TYPE } );
+ #if this needs to be re-enabled, it needs to use a custom op like
+ #"APPROX=" or something (better name?, not '=', to avoid affecting other
+ # searches
+ #if ($TYPE eq SQL_DECIMAL && $op eq 'APPROX=' ) {
+ # # these values are arbitrary; better (faster?) ones welcome
+ # $sth->bind_param($bind++, $value*1.00001, { TYPE => $TYPE } );
+ # $sth->bind_param($bind++, $value*.99999, { TYPE => $TYPE } );
+ #} else {
+ $sth->bind_param($bind++, $value, { TYPE => $TYPE } );
+ #}
}
# Check for encrypted fields and decrypt them.
## only in the local copy, not the cached object
- if ( $conf && $conf->exists('encryption') # $conf doesn't exist when doing
- # the initial search for
- # access_user
- && eval 'defined(@FS::'. $table . '::encrypted_fields)') {
+ if ( $conf_encryption
+ && eval 'defined(@FS::'. $table . '::encrypted_fields)' ) {
foreach my $record (@return) {
foreach my $field (eval '@FS::'. $table . '::encrypted_fields') {
# Set it directly... This may cause a problem in the future...
my $op = '=';
my $column = $_;
+ my $type = dbdef->table($table)->column($column)->type;
+ my $value = $record->{$column};
+ $value = $value->{'value'} if ref($value);
if ( ref($record->{$_}) ) {
$op = $record->{$_}{'op'} if $record->{$_}{'op'};
#$op = 'LIKE' if $op =~ /^ILIKE$/i && driver_name ne 'Pg';
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 ) {
+ if ( $type =~ /(int|numeric|real|float4|(big)?serial)/i ) {
qq-( $column IS NULL )-;
} 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 ) {
+ if ( $type =~ /(int|numeric|real|float4|(big)?serial)/i ) {
qq-( $column IS NOT NULL )-;
} else {
qq-( $column IS NOT NULL AND $column != '' )-;
qq-( $column $op "" )-;
}
}
+ #if this needs to be re-enabled, it needs to use a custom op like
+ #"APPROX=" or something (better name?, not '=', to avoid affecting other
+ # searches
+ #} elsif ( $op eq 'APPROX=' && _is_fs_float( $type, $value ) ) {
+ # ( "$column <= ?", "$column >= ?" );
} else {
"$column $op ?";
}
: '';
}
-=item ut_agentnum_acl
+=item ut_agentnum_acl COLUMN [ NULL_RIGHT | NULL_RIGHT_LISTREF ]
Checks this column as an agentnum, taking into account the current users's
-ACLs.
+ACLs. NULL_RIGHT or NULL_RIGHT_LISTREF, if specified, indicates the access
+right or rights allowing no agentnum.
=cut
sub ut_agentnum_acl {
- my( $self, $field, $null_acl ) = @_;
+ my( $self, $field ) = (shift, shift);
+ my $null_acl = scalar(@_) ? shift : [];
+ $null_acl = [ $null_acl ] unless ref($null_acl);
my $error = $self->ut_foreign_keyn($field, 'agent', 'agentnum');
return "Illegal agentnum: $error" if $error;
} else {
return "Access denied"
- unless $curuser->access_right($null_acl);
+ unless grep $curuser->access_right($_), @$null_acl;
}