PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

PDO не хвърля изключение с необвързани параметри (и без променливи в заявката)

Това поведение може да се възпроизведе с текущия PHP (5.6.13) и заявката дори не се изпраща до сървъра.

Вашият случай е описан в документа като:

Очаква се стойност 0, дадена е стойност 1 и изразът е неуспешен, false се връща. Досега работи както е документирано.

Може да възразите, че „емитирана е грешка " би означавало, че когато ERRMODE_EXCEPTION е включено, ще бъде хвърлено изключение. Това е аргумент, но не е очевидно, че разработчиците на PDO биха се съгласили с него.

Актуализация:

Защо е SQLCode не е зададено?

Разглеждане на изходния код на PDO, по-специално static PHP_METHOD(PDOStatement, execute) който обработва PDO::execute(), можете да видите, че всички грешки се обработват от макрос: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); }

Въпросът е, че при предаване на обвързан параметър, когато PDO не очаква нищо, заявката никога не достига до SQL машината, така че SQL машината никога няма възможност да докладва грешка, придружена от SQLSTATE

Самото PDO не създава фалшив SQLSTATE сама по себе си, поне не в този случай, така чеstmt->error_code остава на PDO_ERR_NONE което е "00000" .

Разбираемо е, че бихте предпочели да бъде повдигнато изключение, но тогава трябва да предложите това на https://bugs.php. мрежа

Същото ли е и с MySQL?

Да, поведението на root е същото, с изключение на това, че с MySQL драйвера prepare се изпраща незабавно до SQL двигателя, така че ако е неправилен поради лоша колона, той се проваля по-рано и с истинска SQL грешка. От друга страна, PgSQL драйверът има различна реализация, която го кара да отлага prepare от страната на сървъра . Това конкретно поведение е обсъдено подробно в PHP Postgres PDO драйверът не поддържа подготвен оператор?

Както и да е, ето един случай с MySQL, който демонстрира моето обяснение, а именно:

  • заявката очаква параметър 0, даден е 1
  • $stmt->execute връща невярно
  • не се повдига изключение
  • PDO::errorCode е 00000

Код:

$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();
}

Резултат:

Това, което се случва под капака е, че prepare се изпраща до сървъра и е успешен, но execute стъпката е отменена от PDO поради несъответствие в параметрите.

Ето един случай, който се различава по това, че заявката препраща към несъществуваща колона. Добавям разпечатка, за да покажа, че $stmt->execute дори не се извиква, тъй като изключението се предизвиква от $stmt->prepare

Код:

$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();
}

Резултат:

Обърнете внимание, че стъпката „Изпълняваща заявка“ никога не се случва, защото това е prepare това се проваля от страна на сървъра.

Заключение

  • когато заявката е изпратена до сървъра, било то в подготви() или изпълни(), и сървърът е този, който генерира грешка, тогава можем да очакваме да бъде повдигнато PDOException.

  • когато заявката не е изпратена до сървъра за стъпка на изпълнение, тогава PDO execute() може да се провали (връща false), но не се хвърля изключение и errorCode() остава на 00000



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как Sinh() работи в PostgreSQL

  2. Как да използвате dj-database-url, докато се свързвате с postgresql в heroku с помощта на python

  3. Как да задам клеймо по подразбиране на сега () + n дни?

  4. Postgres проектиран ли е да пише в споделени хранилища за данни?

  5. PostgreSQL:Временно деактивирайте връзките