Question

I'm pretty new to Perl and I've been stumped by an error with DBI. I'm trying to query for a series of characters defined by their hex values:

my @compare = ( '\'%\'+x\'0A\'+\'%\'',
                '\'%\'+x\'92\'+\'%\'',
                '\'%\'+x\'96\'+\'%\'',
                '\'%\'+x\'A0\'+\'%\'' );

my $fetch_bad_rows = $dbh->prepare( qq{
    SELECT B.* FROM ... AS B
    WHERE B. ... LIKE ?
        OR B. ... LIKE ?
        OR B. ... LIKE ?
        OR B. ... LIKE ?
});

$fetch_bad_rows->execute(@compare)

my $counter;
for( $counter = 0; $fetch_bad_rows->fetch; $counter++ ) {};
print LOG sprintf("Found %d bad rows\n", $counter);

Executing the statement this way finds 0 rows. However, if I hard code the strings in the query, I get 437 records:

my $fetch_bad_rows = $dbh->prepare( qq{
SELECT B.* FROM ... AS B
    WHERE B. ... LIKE '%'+x'0A'+'%'
        OR B. ... LIKE '%'+x'92'+'%'
        OR B. ... LIKE '%'+x'96'+'%'
        OR B. ... LIKE '%'+x'A0'+'%'
});

$fetch_bad_rows->execute

I haven't been able to figure out what I'm doing wrong with passing in the bind values.

Anyone have any ideas? Thanks in advance.

Was it helpful?

Solution 2

Thanks for the responses. I did some more digging based on the info provided and found a way to get it working:

my @compare = ( '0A','92','96','A0' );

my $fetch_bad_rows = $dbh->prepare( qq{
    SELECT B.* FROM ... AS B
        WHERE B. ... LIKE '%' + UNHEX(?) + '%'
           OR B. ... LIKE '%' + UNHEX(?) + '%'
           OR B. ... LIKE '%' + UNHEX(?) + '%'
           OR B. ... LIKE '%' + UNHEX(?) + '%'
});

$fetch_bad_rows->execute(@compare)

I wasn't able to use 'x?' since the prepare call treated it as a table reference and complained that no table 'x' was found. The UNHEX routine turned out to be what I needed, though, since it takes a string input.

Thanks again everyone

OTHER TIPS

The ? in the prepare will make sure that everything is escaped. So if you pass in stuff that has ' it will escape the quotes:

'\'%\'+x\'0A\'+\'%\''

Which can be more easily written as:

q{'%'+x'0A'+'%'}

will turn into:

... LIKE '\'%\'+x\'0A\'+\'%\''

And thus it does not find anything.

The escaping that it's doing here is protecting you from SQL injection. Do any concatenation in the query itself, and only pass in the part that changes. For example:

my $sql = "SELECT x FROM y WHERE z LIKE '%' + x? + '%'";
my $sth = $dbh->prepare($sql);
$sth->execute("0A");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top