sql >> Databáze >  >> RDS >> PostgreSQL

PDO nevyvolává výjimku s nesvázanými parametry (a bez proměnných v dotazu)

Toto chování je reprodukovatelné s aktuálním PHP (5.6.13) a dotaz není ani odeslán na server.

Váš případ je popsán v dokumentu jako:

Očekává se 0 hodnota, je zadána hodnota 1 a příkaz selže, false vracení. Zatím funguje tak, jak je zdokumentováno.

Můžete namítnout, že „je generována chyba " by znamenalo, že když ERRMODE_EXCEPTION je zapnutá, bude vyvolána výjimka. To je argument, ale není zřejmé, že by s ním vývojáři PDO souhlasili.

Aktualizace:

Proč je SQLCode není nastaveno?

Podívejte se na zdrojový kód PDO, konkrétně static PHP_METHOD(PDOStatement, execute) který zpracovává PDO::execute(), můžete vidět, že všechny chyby zpracovává 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); }

Jde o to, že při předávání vázaného parametru, když PDO neočekává žádné, se dotaz nikdy nedostane k enginu SQL, takže stroj SQL nikdy nemá příležitost ohlásit chybu spolu s SQLSTATE

PDO samo o sobě nevytváří falešný SQLSTATE sám o sobě, alespoň ne v tomto případě, takžestmt->error_code zůstává na PDO_ERR_NONE což je "00000" .

Je pochopitelné, že byste preferovali vznesení výjimky, ale pak byste měli navrhnout, aby https://bugs.php. síť

Je to stejné s MySQL?

Ano, kořenové chování je stejné až na to, že s ovladačem MySQL prepare je okamžitě odeslána do SQL motoru, takže pokud je nesprávná kvůli špatnému sloupci, selže dříve a se skutečnou chybou SQL. Na druhou stranu má ovladač PgSQL jinou implementaci, díky které odkládá prepare na straně serveru . Toto konkrétní chování je podrobně diskutováno na stránce PHP Postgres PDO ovladač nepodporuje připravené prohlášení?

Každopádně zde je případ s MySQL, který demonstruje mé vysvětlení, tedy:

  • dotaz očekává parametr 0, je uvedena 1
  • $stmt->execute vrací false
  • nebude vznesena žádná výjimka
  • PDO::errorCode je 00000

Kód:

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

Výsledek:

Co se děje pod kapotou, je to, že se prepare je odeslána na server a uspěje, ale execute krok je zrušen PDO z důvodu neshody v parametrech.

Zde je případ, který se liší tím, že dotaz odkazuje na neexistující sloupec. Přidávám tisk, abych ukázal, že $stmt->execute se ani nezavolá, protože výjimku vyvolá $stmt->prepare

Kód:

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

Výsledek:

Všimněte si, že krok „Provádění dotazu“ nikdy nenastane, protože je to prepare který selže na straně serveru.

Závěr

  • když je dotaz odeslán na server, ať už je to v Prepare() nebo execute(), a je to server, který generuje chybu, pak můžeme očekávat vyvolání výjimky PDOException.

  • když dotaz není odeslán na server pro provedení kroku, pak PDO execute() může selhat (vrací hodnotu false), ale není vyvolána žádná výjimka a errorCode() zůstane na 00000



  1. Jak vypsat PGresult pro příkazy jiné než SELECT

  2. Jak implementovat priority v SQL (postgres)

  3. SQL:vložte řádky se souhrnnými hodnotami

  4. Funkce řetězce SQL Server (úplný seznam)