[Melbourne-pm] Strange things about '0'

Andrew Dent sgc294 at internode.on.net
Mon Oct 27 03:37:11 PDT 2008


G'day

I have a problem with zero ('0'), and I'm hoping someone could please 
help. Sorry in advance for the long explanation.

I've written a sub called sql_engine that I would like to put into a 
module. But before I do, I have two separate problems I'd like to solve. 
One is when a scalar has the value of 0 and the other is with 
HTML::Template. The HTML::Template problem I'll put in a separate thread.

sql_engine takes a number of parameters to help control it. Its main job 
is to execute the query and return the results to the calling sub in the 
required data structure.
sql_engine can be called like this

my $data = sql_engine($entity, 'array_hash', 'asset_data', 1, $foocode);

I've put the first part of the code at the end of the email.
It calls prep_query to obtain the correct SQL code based on $query_name. 
This SQL code is stored in $query.
Some queries will be returned with a ? inside them for the where clause. 
When these queries are required, $var_num and $query_var are also 
needed, other wise the code will break at the $report->execute() line.
sql_engine is given the return type required using the $ret_type 
variable so I can select a scalar, array, hash, array of hashes etc as 
the data structure.
The database type I am connecting to is Ingres, though I'm not sure if 
this makes a difference to this problem or not.

An example of the query I see the problem with is.

select code_descr from c_table where foocode = ?

The table called c_table in an Ingres database with only two columns in 
it. Lets call them 'foocode' and 'description'. The current values of 
'foocode' are A, D, S, 0, 1..8. These codes are used in other much 
larger tables and I sometimes need to filter on those larger tables by 
using a mixture of codes from the c_table and codes from other tables.

Now, if $query_var is a 0 then the ? in the above sql there are no 
results returned from the query, but the Perl code doesn't break. The 
Ingres db system must get passed a false value.
If I change $query_var to be '0' to try and get the right string into 
the query in the $report->execute statement it doesn't work. Again the 
Perl code doesn't break, but I still don't get any results.
As the I see the Camel book mentions, Perl equates 0 and '0' both to be 
false. I think this is why there ar no results of both 0 and '0'.

The workaround is to use the ---> if ($query_var... <--- block to modify 
the SQL code in $query and replace the ? with the string '0'. This is 
fine at the moment, but if in the future I have SQL code in $query that 
has more than one ? and I want only one of them to be '0' I'll be in 
trouble.

Is there another way to approach this problem so I can deal with the 
value of foocode when it is 0, but keeping the sql_engine sub flexible 
so it can make use of any number of ? in the SQL code, and not have to 
predict in advance which ? is for foocode.

sub sql_engine {
    my $entity = shift @_;   # Used to select the database and all 
required inside the queries
    my $ret_type = shift @_; # Determines if this sub should return a 
scaler, array, hash, array of hashes etc
    my $query_name = shift @_; # A place to hold the query that will be run
    my $var_num = shift @_;
    my $query_var = shift @_; # place to put variables for the SQL query
    my $dbh = DBI->connect( "DBI:Ingres:database_$entity", 'username' );
    my $report;
    my $query = prep_query($query_name,$entity);
   
    # The disp of 0 had to be passed in as '0' because a scaler with the 
value
    # of 0 will not be passed in properly to the query
    if ($query_var eq "'0'") {
        $var_num = 0;
        $query =~ s/\?/'0'/;
    }

    $report = $dbh->prepare($query);
    unless ($var_num > 0) {
       $report->execute();
    } else {      
       $report->execute($query_var)
    }

Cheers

Andrew Dent





More information about the Melbourne-pm mailing list