in reply to Stringified hash

Great! Thanks all! The script is actually creating a dB query something like this. The code worked but I wasn't totally sure how. Thanks again.
use strict; use warnings; my %hash = ( A => 'a', B => 'b', C => 'c', D => 'd', E => 'e', F => 'f' ); print "@{[%hash]}"; while(my ($key, $value) = each(%hash)) { $hash{$key} = '= '.$value.' AND'; } my $query = 'SELECT row_id FROM Table WHERE '.substr("@{[%hash]}",0,-4 +); print "\n\n$query\n";

Replies are listed 'Best First'.
Re: Re: Stringified hash
by dragonchild (Archbishop) on Apr 12, 2004 at 12:32 UTC
    You'll want to rewrite that code, so that it's not obfuscated.
    my @clauses; my @params; while (my ($k, $v) = each %hash) { push @clauses, "$k = ?"; push @params, $v; } my $query = "SELECT row_id FROM Table WHERE " . join(" AND ", @clauses +);

    Then, when you execute that query using DBI, you pass @params to the execute() call. This will close a few security holes you currently have, as well as a few potential bugs. And, it's easier to read. :-)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

      This way worked out nicely for me. I guess I immediately thought of hash when an array would do. I'm not too worried about security. There is no interface, I'm processing files and loading them into a dB and I'm using ODBC. Thanks for the hand.
      use strict; use warnings; my @array = ( "A = 'a'", "B = 'b'", "C = 'c'", "D = 'd'", "E = 'e'", "F = 'f'" ); print "@array\n"; my $query = 'SELECT row_id FROM Table WHERE '.join(' AND ', @array); print "\n\n$query\n";
        You just lost the whole point of my rewrite. The idea was to use placeholders, which ODBC supports, and allow the driver to do the quoting for you.

        ------
        We are the carpenters and bricklayers of the Information Age.

        Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

      See, I personally find this much easier to read, but I tend to find each loops generally hard to read. (I recognize that they're sometimes necessary for efficiency reasons, but still consider them ugly) Maybe it's just me.
      my @fields = keys(%hash); my @params = @hash{@fields}; my $query = "SELECT row_id FROM Table WHERE " . join(" AND ", map {"$_ = ?"} @fields);
      If for some reason the interface you have won't accomodate the extra separate @params parameter, you could also do this, though this depends on having the DBI handle available when you're forming the query:
      my @fields = keys(%hash); my $query = "SELECT row_id FROM Table WHERE " . join(" AND ", map {"$_ = " . $dbh->quote($hash{$_})} @fields);
      However, I'd still go with the first, assuming that passing along the @params list is doable.