Hacker News new | past | comments | ask | show | jobs | submit login

The query in question is using an IN clause which takes a tuple of values.

I don't think bindParam will allow you to bind an array into a tuple , the only way to pass the tuple is by forming it as a string and adding that to the query string.




It's awful how poorly IN-clauses are supported (in lots of places, not just PHP) considering how often they're used and how useful they are. I mean basic stuff like being able to use them securely or making programmers write their own checks to prevent SQL-errors on empty lists.


Not many people here will care, but SQL Server with .NET do support binding table valued parameters in lowlevel System.Data (SqlCommand).

I'm using a Micro ORM (Insight Database, https://github.com/jonwagner/Insight.Database) that takes advantage of this. It maps a parameter of type IEnumerable<SomeType> automatically to a TVP. This ORM works brilliantly when you want to get everything out of SQL.


No, it doesn't. PHP can handle it fine and we've undergone multiple attacks and security audits [both daily automated ones and professionals by hand]. :/

The problem here was a mistake someone made, not a fundamental support problem with the language.

This is precisely why people mock PHP developers. :/ So many don't even understand how the language f'n works.


I never said it was a problem with the language. I said it was poorly supported in a lot of platforms including PHP and I stand by that.

It has nothing to do with passing security audits or withstanding attacks, there's not a security flauw in the way PHP handles this because PHP or specifically the PDO framework relies on the user to implement this themself. There obviously can't be a security flaw in something which does not exist.

A quick Google search suggests it is not at all obvious to many how to do a parametrised query with an IN-clause using PDO. The highest ranking answer is this SO post: http://stackoverflow.com/a/1586650

Having to iterate the array yourself adding the right amount of placeholders and binding individual values is secure but a lot of boilerplate. Escaping values in PHP and concatting them in the old fashioned way ought to be safe but everyone switched to parametrised queries for a reason: in practice it's often fucked up which leads to security vulnerabilities. The last one, the find_in_set trick, is a clever kludge but a kludge nonetheless.

People shouldn't need to roll their own way to do this because that's where unnecessary mistakes get made.


> A quick Google search suggests it is not at all obvious to many how to do a parametrised query with an IN-clause using PDO.

Alot of programmers can't do FizzBuzz either. If you can't figure out how to iterate and count an array on your own...

I'm sorry but I have 0 sympathy.


Just as I have no sympathy for programmers forgetting to always call mysql_real_escape_string and setting their encodings right in the old MySQL driver, it's not difficult to get right, but tons of people didn't and it made the web a worse place for everyone.

Plus, they might be able to figure out how to iterate and count an array but they might also figure out how to use implode instead which is less code and programmers tend to be lazy. And suddenly they've opened their app up to SQL injection because they forgot or are unaware they now need to do escaping despite using prepared statements.

And since their app might contain my data, I care about this and not just think "those idiots brought it upon themselves".


Java has this issue as well for IN clauses.


JDBC 4, released in Java 6 in 2006 supports setArray. However, that doesn't mean that your database driver supports it safely.


You can write a function for it using ?'s being generated inside your code only. Its perfectly safe to do it that want and allows you to bind parameters.

The only explanation for not doing that is ignorance and/or incompetence. Mistakes happen but to claim its a language problem is incorrect.

http://php.net/manual/en/pdostatement.bindparam.php

<?php /* Execute a prepared statement by binding PHP variables */ $calories = 150; $colour = 'red'; $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ?'); $sth->bindParam(1, $calories, PDO::PARAM_INT); $sth->bindParam(2, $colour, PDO::PARAM_STR, 12); $sth->execute(); ?>

So what you do is you write a function to convert the array to a series of ?'s for the IN clause/tuple and then iterate through the array to bind the parameters.


> You can write a function for it using ?'s being generated inside your code only. Its perfectly safe to do it that want and allows you to bind parameters.

Of course you can. Everyone here is saying you shouldn't have to. This is the perfect type of thing to move into the db library. That makes it much safer because you don't have to hand-roll the same stupid code in 50,000 places (and possibly fat-finger it once).


It belongs in an ORM, not the language.


I don't think that would work in this case, because there is no way to bind a PHP array to an SQL tuple. Available param types includes string , int , bool but no array or tuple type.

http://php.net/manual/en/pdo.constants.php

You can write "SELECT calories FROM fruit WHERE name IN (? , ?, ?)" and then bind the parameters as strings but this will only work in cases where the length of the tuple is known and fixed. If you need to allow for a variable length tuple then you will need to concatenate the query string yourself.


Just use a placeholder like (??) and flatten everything out. Translate (??) and array(1,2,3) into (?,?,?) with 1, 2, 3 as the binds.


Then what do you do if the passed tuple has zero length?

Dynamically rewriting the SQL isn't going to be tractable in all cases - doing `IN (NULL)` might be a valid value - and throwing an exception is poor form for an actually valid case.


Check for bad inputs? I'm not saying this is a cure all, but it's a lot better than not being able to use arrays at all.


I don't think PDO supports this AFAIK.


I had to implement it manually, but it works. FWIW, I'm using a custom wrapper around MySQLi though.


You count the length of the array. You create the tuple with the appropriate number of ?'s. You then bind parameters.

No user input involved.


...

What part of you needed to write a function was unclear? o.O

Counting an array is a safe operation.


You need to count the array at runtime and convert to a tuple, the only way this can be done using PDO (AFAIK) is by appending the tuple to the string itself because PDO provides no tuple type.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: