views:

61

answers:

3

PLEASE READ THE QUESTION CAREFULLY. It is not usual silly "my code doesn't work!!!" question.

When I run this code with intended error

try {
  $sth = $dbh->prepare("SELECT id FROM users WHERE name INN(?,?) ");
  $sth->execute(array("I'm","d'Artagnan"));
} catch (PDOException $e) {
    echo $e->getMessage();
}

I get this error message

You have an error in your SQL syntax ... near 'INN('I\'m','d\'Artagnan')' at line 1

But I thought for years that query and data being sent to the server separately and never interfere. Thus I have some questions (though I doubt anyone got an answer...)

  1. Where does it get such a familiar string representation - quoted and escaped? Is it being made especially to report an error or is it a part of actual query?
  2. How does it work in real? Does it substitute a placeholder with data or not?
  3. Is there a way to get whole query, not only little bit of it, for debugging purposes?

Update

mysqli does it as expected: it throws an error says near 'INN(?,?)'

+3  A: 

Oh boy, what a day Cassy has the right answer and I'm going to bed...

DrColossos
-1 this doesn't answer the question ...
Cassy
now I'm tempted to vote you up simply because you're agreeing ;-)
Cassy
+5  A: 

I'm not sure about all the details, but I will try to answer.

  1. The quotation happens on the database side. The database escapes and sanitizes all values (see bullet 2) it receives so that it gets interpreted correctly. The moment the error is thrown, the database (in this case MySQL) prints out the query it tried to run. This wouldn't be so helpful if it just showed the prepared part.

  2. No, it doesn't. At preparation time the query gets compiled on the server side. When a query is executed with values, only the values are transmitted. This is pretty much the same as calling PREPARE and EXECUTE on the database directly.

  3. This depends on the database you're using. MySQL for example can log all queries to a log file (check my.cnf settings for that). But you can also use debugDumpParams() on PHP side.

I hope this was a bit helpful.

Cassy
Thanks for the sensible response. I can't tie 1 and 2 together. Does it mean that at the end it's the same quoting/escaping but just made on the server side?
Col. Shrapnel
+1 for answering the actual question(s) and not focusing on the IN/INN thing.. since the first sentence explains that the syntax error is *intentional*
Jake
@Col. Shrapnel: For the database 1 and 2 are two distinct commands. The first "registers" a query (metaphorically as a function if you wish), the second passes parameters to it. In this approach the database exactly knows which part of the query it can/must/should quote. It couldn't do this on a combined query.
Cassy
I see. I thought after preparing it is not being a query anymore but become a set of commands with parameters, thus, no need to escape.
Col. Shrapnel
oh man. mysqli doing it as expected - ??s in the error message
Col. Shrapnel
LOL. Looks like PDO just fake proper parametrizing :) see update
Col. Shrapnel
Upon research I was humbled to learn that while PDO will handle the prepared statement in a conventional manner with most databases (IE caching the compiled query, and passing in parameters dynamically from then on) that with database drivers that don't actually support that behavior, it will emulate it client-side. So the actual end behavior may depend on your specific environment.
Jake
+2  A: 

try adding

$dbh->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

;)

stereofrog
Bingo! I was about to write another update, exactly on this topic, pointing to the second paragraph on this man page http://php.net/manual/en/ref.pdo-mysql.php and ask if there is a way to test what mode is on. Just tested your code and it worked. no escaped string in the error message
Col. Shrapnel
you have actually solved my other question too :)
Col. Shrapnel
glad to hear that, @Col ;))))
stereofrog