sql >> Database >  >> RDS >> PostgreSQL

PDO genereert geen uitzondering met ongebonden parameters (en geen variabelen in query)

Dat gedrag is reproduceerbaar met de huidige PHP (5.6.13) en de query wordt niet eens naar de server gestuurd.

Uw geval wordt beschreven in het document als:

0 waarde wordt verwacht, 1 waarde wordt gegeven, en de instructie mislukt, false wordt teruggestuurd. Werkt tot nu toe zoals gedocumenteerd.

Je zou kunnen beweren dat "er een fout is verzonden " zou impliceren dat wanneer ERRMODE_EXCEPTION is ingeschakeld, zou er een uitzondering worden gegenereerd. Dat is een argument, maar het ligt niet voor de hand dat de PDO-ontwikkelaars het daarmee eens zijn.

Bijwerken:

Waarom is SQLCode niet ingesteld?

Kijken naar de PDO-broncode, met name static PHP_METHOD(PDOStatement, execute) die PDO::execute() afhandelt, kunt u zien dat alle fouten worden afgehandeld door een 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); }

Het punt is dat, wanneer een gebonden parameter wordt doorgegeven terwijl PDO er geen verwachtte, de query nooit de SQL-engine bereikt, dus de SQL-engine heeft nooit de mogelijkheid om een ​​fout te rapporteren die vergezeld gaat van een SQLSTATE

PDO maakt zelf geen nep SQLSTATE op zichzelf, althans niet in dat geval, dusstmt->error_code blijft bij PDO_ERR_NONE dat is "00000" .

Het is begrijpelijk dat u er de voorkeur aan geeft dat er een uitzondering wordt gemaakt, maar dan moet u voorstellen aan https://bugs.php. netto

Is het hetzelfde met MySQL?

Ja, het rootgedrag is hetzelfde, behalve dat met het MySQL-stuurprogramma de prepare wordt onmiddellijk naar de SQL-engine gestuurd, dus als het onjuist is vanwege een slechte kolom, mislukt het eerder en met een echte SQL-fout. Aan de andere kant heeft het PgSQL-stuurprogramma een andere implementatie waardoor het de server-side prepare uitstelt . Dit specifieke gedrag wordt in detail besproken op PHP Postgres PDO-stuurprogramma ondersteunt geen voorbereide verklaring?

Hoe dan ook, hier is een geval met MySQL dat mijn uitleg demonstreert, namelijk:

  • de query verwacht parameter 0, 1 wordt gegeven
  • $stmt->execute geeft false terug
  • er wordt geen uitzondering gemaakt
  • PDO::errorCode is 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();
}

Resultaat:

Wat er onder de motorkap gebeurt, is dat de prepare wordt naar de server gestuurd en slaagt, maar de execute stap is geannuleerd door PDO vanwege de mismatch in parameters.

Hier is een geval dat verschilt in het feit dat de query verwijst naar een niet-bestaande kolom. Ik voeg een afdruk toe om te laten zien dat $stmt->execute wordt niet eens aangeroepen, omdat de uitzondering wordt gemaakt door $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();
}

Resultaat:

Merk op dat de stap "query uitvoeren" nooit gebeurt, omdat het de prepare is dat mislukt, server-side.

Conclusie

  • wanneer de query naar de server wordt verzonden, hetzij in prepare() of execute(), en het is de server die een fout genereert, dan kunnen we verwachten dat een PDOException wordt gegenereerd.

  • wanneer de query niet naar de server wordt verzonden voor een uitvoeringsstap, kan PDO execute() mislukken (retourneert false) maar er wordt geen uitzondering gegenereerd en errorCode() blijft bij 00000



  1. Django DateRangeField-probleem

  2. ASCII() Voorbeelden – MySQL

  3. Reader.Read() kan rijen niet lezen, ook al heeft het rijen

  4. Wrapping uitschakelen in Psql-uitvoer