PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

PDO nie zgłasza wyjątku z niezwiązanymi parametrami (i bez zmiennych w zapytaniu)

To zachowanie można odtworzyć w bieżącym PHP (5.6.13), a zapytanie nie jest nawet wysyłane do serwera.

Twoja sprawa jest opisana w dokumentacji jako:

Oczekiwana jest wartość 0, podana jest 1 wartość, a instrukcja nie powiedzie się, false zostanie zwrócony. Jak dotąd działa zgodnie z dokumentacją.

Możesz argumentować, że „wyświetlany jest błąd " oznaczałoby, że gdy ERRMODE_EXCEPTION jest włączony, zostanie zgłoszony wyjątek. To argument, ale nie jest oczywiste, że twórcy PDO się z tym zgodzą.

Aktualizacja:

Dlaczego SQLCode nie ustawiono?

Patrząc na kod źródłowy PDO, w szczególności static PHP_METHOD(PDOStatement, execute) który obsługuje PDO::execute(), widać, że wszystkie błędy są obsługiwane przez makro: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); }

Chodzi o to, że podczas przekazywania powiązanego parametru, gdy PDO nie oczekiwało żadnego, zapytanie nigdy nie trafia do silnika SQL, więc silnik SQL nigdy nie ma możliwości zgłoszenia błędu wraz ze stanem SQLSTATE

Samo PDO nie tworzy fałszywego SQLSTATE na własną rękę, przynajmniej nie w tym przypadku, więcstmt->error_code zostaje w PDO_ERR_NONE czyli "00000" .

Zrozumiałe jest, że wolisz, aby został zgłoszony wyjątek, ale powinieneś zasugerować to https://bugs.php. sieć

Czy tak samo jest z MySQL?

Tak, zachowanie roota jest takie samo, z wyjątkiem sterownika MySQL, prepare jest natychmiast wysyłana do silnika SQL, więc jeśli jest niepoprawna z powodu złej kolumny, kończy się wcześniej i z prawdziwym błędem SQL. Z drugiej strony sterownik PgSQL ma inną implementację, która sprawia, że ​​odracza prepare po stronie serwera . To szczególne zachowanie jest szczegółowo omówione w Sterownik PHP Postgres PDO nie obsługuje przygotowanego oświadczenia?

W każdym razie, oto przypadek z MySQL, który demonstruje moje wyjaśnienie, czyli:

  • zapytanie oczekuje parametru 0, podano 1
  • $stmt->execute zwraca fałsz
  • nie zgłasza się żadnego wyjątku
  • PDO::errorCode to 00000

Kod:

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

Wynik:

To, co dzieje się pod maską, polega na tym, że prepare jest wysyłany na serwer i kończy się powodzeniem, ale execute krok jest anulowany przez PDO z powodu niezgodności parametrów.

Oto przypadek, który różni się tym, że zapytanie odnosi się do nieistniejącej kolumny. Dodaję wydruk, aby pokazać, że $stmt->execute nie jest nawet wywoływana, ponieważ wyjątek jest zgłaszany przez $stmt->prepare

Kod:

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

Wynik:

Zwróć uwagę, że krok „Wykonywanie zapytania” nigdy się nie dzieje, ponieważ jest to prepare to się nie powiedzie, po stronie serwera.

Wniosek

  • kiedy zapytanie jest wysyłane do serwera, czy to w przygotowaniu(), czy w wykonywaniu(), i to serwer generuje błąd, możemy spodziewać się zgłoszenia wyjątku PDO.

  • gdy zapytanie nie jest wysyłane do serwera w celu wykonania kroku, wykonanie PDO() może zakończyć się niepowodzeniem (zwraca wartość false), ale nie zostanie zgłoszony żaden wyjątek i errorCode() zostaje w 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. Dostrajanie wydajności Postgresql i wykorzystania pamięci w przepływie pracy w Pythonie

  2. Jak utworzyć użytkownika tylko do odczytu w PostgreSQL?

  3. Jak oddzielić tekst za pomocą podciągu

  4. Rails 4 niestandardowe 404 powoduje awarię połączenia postgresql na Heroku

  5. „Zbyt wiele połączeń” utworzone w postgresie podczas tworzenia dashboardu w Pentaho