Используя PostgreSQL 9.6 и PHP 7.2, я создаю соединение PDO, готовлю запрос INSERT, связываю параметры, затем выполняю подготовленный запрос.У меня ATTR_ERRMODE
установлено значение ERRMODE_EXCEPTION
, и фактически он может вызвать исключение при выполнении, если, например, подготовленный запрос имеет 4 параметра, но я ограничен только 3.
Ноесли мой подготовленный запрос не содержит поле с ограничением NOT NULL, то выполнение будет зависать, возможно, на 20 секунд, а затем в браузере отобразится «соединение было сброшено».В журнале Postgres написано:
ERROR: null value in column "fullname" violates not-null constraint
DETAIL: Failing row contains (345, fredf, fredf@bedrock.net, yabadabadoo, null, Bedrock, none, user).
STATEMENT: INSERT INTO users (username, password, location, description, email, role) VALUES ($1, $2, $3, $4, $5, $6)
LOG: could not receive data from client: An existing connection was forcibly closed by the remote host.
Эти 4 записи журнала повторяются в общей сложности 10 раз.
Я понимаю, что эта ситуация действительно является проблемой программирования - запрос должен соответствовать требованиямдизайна базы данных.Но мне бы очень хотелось, чтобы драйвер Postgres PDO объяснил мне, в чем была ошибка, а не копался в журналах.
Пример кода
/*
Sample code to demonstrate failure of prepared query execute()
to throw an exception when the prepared query omits a field
with a NOT NULL constraint.
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username varchar(50) NOT NULL,
email varchar(100) NOT NULL,
password varchar(255) NOT NULL,
fullname varchar(100) NOT NULL,
location varchar(100) NOT NULL,
description text NOT NULL,
role varchar(50) NOT NULL DEFAULT ''
);
*/
$host = "localhost";
$user = "postgres";
$pass = "password";
$dbname = "database";
/**
* Initialize the PDO connection.
*/
$dsn = 'pgsql:host=' . $host . ';dbname=' . $dbname;
$options = [
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
];
try {
$handler = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
echo $e->getMessage();
die();
}
/**
* Demonstrate failure of execute() to return an error or throw an exception
* Error condition omits the fullname field from the INSERT query, which has a
* "not null" constraint.
*/
$demonstrateProblem = 1;
$badQuery = "INSERT INTO users (username, password, location, description, email, role) " .
"VALUES (:username, :password, :location, :description, :email, :role)";
$goodQuery = "INSERT INTO users (username, password, fullname, location, description, email, role) " .
"VALUES (:username, :password, :fullname, :location, :description, :email, :role)";
if ($demonstrateProblem == 1) {
$query = $badQuery;
} else {
$query = $goodQuery;
}
$stmt = $handler->prepare($query);
if (!$stmt) {
echo "Error in prepare, errorInfo():<br>";
print_r($handler->errorInfo());
}
/**
* Bind the variables
*/
$username = "fredf";
$password = "yabadabadoo";
$fullname = "Fred Flintstone";
$location = "Bedrock";
$description = "none";
$email = "fredf@bedrock.net";
$role = "user";
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password);
if ($demonstrateProblem == 0) {
$stmt->bindParam(':fullname', $fullname);
} else {
// nothing to do, :fullname is not in the prepared query!
}
$stmt->bindParam(':location', $location);
$stmt->bindParam(':description', $description);
$stmt->bindParam(':email', $email);
$stmt->bindParam(':role', $role);
/**
* Execute a prepared statement.
*/
echo "Executing prepared query...<br>";
try {
$res = $stmt->execute(); // <-- this statement hangs when the query prepare is bad.
if ($res) {
echo "execute returns true<br> ";
} else {
echo "execute returns false<br> ";
}
} catch (PDOException $e) {
echo "execute error " . $e->getMessage(); // <-- this never appears
}
PostgreSQLlog (последовательность повторяется 10 раз)
ERROR: null value in column "fullname" violates not-null constraint
DETAIL: Failing row contains (345, fredf, fredf@bedrock.net, yabadabadoo, null, Bedrock, none, user).
STATEMENT: INSERT INTO users (username, password, location, description, email, role) VALUES ($1, $2, $3, $4, $5, $6)
LOG: could not receive data from client: An existing connection was forcibly closed by the remote host.