php - PDO not throwing exception with unbound parameters (and no variables in query) -


so have no idea what's going on here

$link = new pdo('pgsql:dbname=' . $name . ';host=' . $host, $user, $password); $link->setattribute(pdo::attr_emulate_prepares, false); $link->setattribute(pdo::attr_errmode, pdo::errmode_exception);  try {     $stmt = $link->prepare("select s.*, d.invalid_column students s order s.student_id");     $stmt->execute(array(1)); } catch (pdoexception $e) {     print $e->getmessage(); } 

when run little code example, expect exception thrown (as d.invalid_column not real column , i'm passing in parameters cannot bound), thing happens execute returns false , nothing else. additionally $stmt->errorinfo() blank , code 00000 makes hard add proper exception throw beyond super generic nothing else logs assist me in tracking errors down when end user reports error.

if add single '?' somewhere query, proper execution thrown (that d.invalid_column not valid column), if add more parameters don't bind anything.

so ways query error:
1) rid parameters
2) add '?' query

is bug in pdo or what?

edit: setups throw exception (invalid column):

    $stmt = $link->prepare("select s.*, d.invalid_column, ? students s order s.student_id");     $stmt->execute(array(1));      $stmt = $link->prepare("select s.*, d.invalid_column, ? students s order s.student_id");     $stmt->execute(array(1,2,3));      $stmt = $link->prepare("select s.*, d.invalid_column, ? students s order s.student_id");     $stmt->execute();      $stmt = $link->prepare("select s.*, d.invalid_column students s order s.student_id");     $stmt->execute(); 

it's when have no ? in query , pass execute() things fail silently , no explanation pdo.

that behavior reproducible current php (5.6.13), , query not sent server.

your case described in the doc as:

you cannot bind more values specified; if more keys exist in input_parameters in sql specified in pdo::prepare(), statement fail , error emitted.

0 value expected, 1 value given, , statement fails, false being returned. far, works documented.

you may argue "an error emitted" imply when errmode_exception on, exception thrown. that's argument, it's not obvious pdo developers agree it.

update:

why sqlcode not set?

looking @ pdo source code, static php_method(pdostatement, execute) handles pdo::execute(), can see errors handled macro: pdo_handle_stmt_err()

#define pdo_handle_stmt_err()   if (strcmp(stmt->error_code, pdo_err_none)) { pdo_handle_error(stmt->dbh, stmt tsrmls_cc); } 

the point that, when passing bound parameter when pdo expected none, query never makes sql engine, sql engine never has opportunity report error accompanied sqlstate

pdo not create fake sqlstate on own, @ least no in case, sostmt->error_code stays @ pdo_err_none "00000".

it's understandable prefer exception raised, should suggest https://bugs.php.net

is same mysql ?

yes, root behavior same except mysql driver, prepare sent sql engine if it's incorrect because of bad column, fails earlier , real sql error. on other hand, pgsql driver has different implementation makes defer server-side prepare. particular behavior discussed in detail @ php postgres pdo driver not support prepared statement?

anyway, here's case mysql demonstrates explanation, is:

  • the query expects 0 parameter, 1 given
  • $stmt->execute returns false
  • no exception gets raised
  • pdo::errorcode 00000

code:

$link = new pdo('mysql:dbname=' . $name . ';host=' . $host, $user, $password); $link->setattribute(pdo::attr_emulate_prepares, false); $link->setattribute(pdo::attr_errmode, pdo::errmode_exception);  try {     $stmt = $link->prepare("select 1");     $rc=$stmt->execute(array(1));    if ($rc===false)     echo "query failed, errorcode=", $link->errorcode(), "\n";    else     echo "query succeeded, errorcode=", $link->errorcode(), "\n"; } catch (pdoexception $e) {     print "a pdoexception has occurred";     print $e->getmessage(); } 

result:

query failed, errorcode=00000

what happens under hood prepare sent server , succeeds, execute step cancelled pdo due mismatch in parameters.

here's case differs in fact query refers non-existing column. i'm adding print show $stmt->execute not called, exception raised $stmt->prepare

code:

$link = new pdo('mysql:dbname=' . $name . ';host=' . $host, $user, $password); $link->setattribute(pdo::attr_emulate_prepares, false); $link->setattribute(pdo::attr_errmode, pdo::errmode_exception);  try {     $stmt = $link->prepare("select nonexisting");     echo "executing query\n";     $rc=$stmt->execute(array(1));    if ($rc===false)     echo "query failed, errorcode=", $link->errorcode(), "\n";    else     echo "query succeeded, errorcode=", $link->errorcode(), "\n"; } catch (pdoexception $e) {   print "a pdoexception has occurred";     print $e->getmessage(); } 

result:

a pdoexception has occurredsqlstate[42s22]: column not found: 1054 unknown column 'nonexisting' in 'field list'

note how "executing query" step never happens, because it's prepare fails, server-side.

conclusion

  • when query sent server, in prepare() or execute(), , it's server generates error, can expect pdoexception raised.

  • when query not sent server execution step, pdo execute() can fail (returns false) no exception thrown , errorcode() stays @ 00000


Comments