mirror of
https://github.com/danog/postgres.git
synced 2024-11-26 12:04:50 +01:00
Provide SQL query to QueryError
This was an oversight when QueryExecutionError was added some time ago. Closes #26.
This commit is contained in:
parent
54186c9d26
commit
13ac10a086
@ -34,6 +34,17 @@ final class PgSqlCommandResult implements CommandResult
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This is not meant to be used to get the last insertion ID. Use `INSERT ... RETURNING column_name`
|
||||
* to get the last auto-increment ID.
|
||||
*
|
||||
* $sql = "INSERT INTO person (lastname, firstname) VALUES (?, ?) RETURNING id;"
|
||||
* $statement = yield $pool->prepare($sql);
|
||||
* $result = yield $statement->execute(['Doe', 'John']);
|
||||
* if (!yield $result->advance()) {
|
||||
* throw new \RuntimeException("Insertion failed");
|
||||
* }
|
||||
* $id = $result->getCurrent()['id'];
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLastOid(): string
|
||||
|
@ -241,13 +241,14 @@ final class PgSqlHandle implements Handle
|
||||
|
||||
/**
|
||||
* @param resource $result PostgreSQL result resource.
|
||||
* @param string $sql Query SQL.
|
||||
*
|
||||
* @return \Amp\Sql\CommandResult|ResultSet
|
||||
*
|
||||
* @throws FailureException
|
||||
* @throws QueryError
|
||||
*/
|
||||
private function createResult($result)
|
||||
private function createResult($result, string $sql)
|
||||
{
|
||||
switch (\pg_result_status($result, \PGSQL_STATUS_LONG)) {
|
||||
case \PGSQL_EMPTY_QUERY:
|
||||
@ -265,7 +266,7 @@ final class PgSqlHandle implements Handle
|
||||
foreach (self::DIAGNOSTIC_CODES as $fieldCode => $desciption) {
|
||||
$diagnostics[$desciption] = \pg_result_error_field($result, $fieldCode);
|
||||
}
|
||||
throw new QueryExecutionError(\pg_result_error($result), $diagnostics);
|
||||
throw new QueryExecutionError(\pg_result_error($result), $diagnostics, null, $sql);
|
||||
|
||||
case \PGSQL_BAD_RESPONSE:
|
||||
throw new FailureException(\pg_result_error($result));
|
||||
@ -286,7 +287,8 @@ final class PgSqlHandle implements Handle
|
||||
public function statementExecute(string $name, array $params): Promise
|
||||
{
|
||||
return call(function () use ($name, $params) {
|
||||
return $this->createResult(yield from $this->send("pg_send_execute", $name, $params));
|
||||
\assert(isset($this->statements[$name]), "Named statement not found when executing");
|
||||
return $this->createResult(yield from $this->send("pg_send_execute", $name, $params), $this->statements[$name]->sql);
|
||||
});
|
||||
}
|
||||
|
||||
@ -326,7 +328,7 @@ final class PgSqlHandle implements Handle
|
||||
}
|
||||
|
||||
return call(function () use ($sql) {
|
||||
return $this->createResult(yield from $this->send("pg_send_query", $sql));
|
||||
return $this->createResult(yield from $this->send("pg_send_query", $sql), $sql);
|
||||
});
|
||||
}
|
||||
|
||||
@ -343,7 +345,7 @@ final class PgSqlHandle implements Handle
|
||||
$params = Internal\replaceNamedParams($params, $names);
|
||||
|
||||
return call(function () use ($sql, $params) {
|
||||
return $this->createResult(yield from $this->send("pg_send_query_params", $sql, $params));
|
||||
return $this->createResult(yield from $this->send("pg_send_query_params", $sql, $params), $sql);
|
||||
});
|
||||
}
|
||||
|
||||
@ -378,12 +380,15 @@ final class PgSqlHandle implements Handle
|
||||
use Struct;
|
||||
public $refCount = 1;
|
||||
public $promise;
|
||||
public $sql;
|
||||
};
|
||||
|
||||
$storage->sql = $sql;
|
||||
|
||||
$this->statements[$name] = $storage;
|
||||
|
||||
try {
|
||||
yield ($storage->promise = call(function () use ($name, $modifiedSql) {
|
||||
yield ($storage->promise = call(function () use ($name, $modifiedSql, $sql) {
|
||||
$result = yield from $this->send("pg_send_prepare", $name, $modifiedSql);
|
||||
|
||||
switch (\pg_result_status($result, \PGSQL_STATUS_LONG)) {
|
||||
@ -396,7 +401,7 @@ final class PgSqlHandle implements Handle
|
||||
foreach (self::DIAGNOSTIC_CODES as $fieldCode => $description) {
|
||||
$diagnostics[$description] = \pg_result_error_field($result, $fieldCode);
|
||||
}
|
||||
throw new QueryExecutionError(\pg_result_error($result), $diagnostics);
|
||||
throw new QueryExecutionError(\pg_result_error($result), $diagnostics, null, $sql);
|
||||
|
||||
case \PGSQL_BAD_RESPONSE:
|
||||
throw new FailureException(\pg_result_error($result));
|
||||
|
@ -163,6 +163,7 @@ final class PqHandle implements Handle
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null Query SQL or null if not related.
|
||||
* @param callable $method Method to execute.
|
||||
* @param mixed ...$args Arguments to pass to function.
|
||||
*
|
||||
@ -172,7 +173,7 @@ final class PqHandle implements Handle
|
||||
*
|
||||
* @throws FailureException
|
||||
*/
|
||||
private function send(callable $method, ...$args): \Generator
|
||||
private function send(?string $sql, callable $method, ...$args): \Generator
|
||||
{
|
||||
while ($this->busy) {
|
||||
try {
|
||||
@ -232,7 +233,7 @@ final class PqHandle implements Handle
|
||||
|
||||
case pq\Result::NONFATAL_ERROR:
|
||||
case pq\Result::FATAL_ERROR:
|
||||
throw new QueryExecutionError($result->errorMessage, $result->diag);
|
||||
throw new QueryExecutionError($result->errorMessage, $result->diag, null, $sql ?? '');
|
||||
|
||||
case pq\Result::BAD_RESPONSE:
|
||||
throw new FailureException($result->errorMessage);
|
||||
@ -306,7 +307,7 @@ final class PqHandle implements Handle
|
||||
|
||||
\assert($storage->statement instanceof pq\Statement, "Statement storage in invalid state");
|
||||
|
||||
return new Coroutine($this->send([$storage->statement, "execAsync"], $params));
|
||||
return new Coroutine($this->send($storage->sql, [$storage->statement, "execAsync"], $params));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -334,7 +335,7 @@ final class PqHandle implements Handle
|
||||
|
||||
\assert($storage->statement instanceof pq\Statement, "Statement storage in invalid state");
|
||||
|
||||
return new Coroutine($this->send([$storage->statement, "deallocateAsync"]));
|
||||
return new Coroutine($this->send(null, [$storage->statement, "deallocateAsync"]));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -346,7 +347,7 @@ final class PqHandle implements Handle
|
||||
throw new \Error("The connection to the database has been closed");
|
||||
}
|
||||
|
||||
return new Coroutine($this->send([$this->handle, "execAsync"], $sql));
|
||||
return new Coroutine($this->send($sql, [$this->handle, "execAsync"], $sql));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -361,7 +362,7 @@ final class PqHandle implements Handle
|
||||
$sql = Internal\parseNamedParams($sql, $names);
|
||||
$params = Internal\replaceNamedParams($params, $names);
|
||||
|
||||
return new Coroutine($this->send([$this->handle, "execParamsAsync"], $sql, $params));
|
||||
return new Coroutine($this->send($sql, [$this->handle, "execParamsAsync"], $sql, $params));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -396,13 +397,16 @@ final class PqHandle implements Handle
|
||||
public $refCount = 1;
|
||||
public $promise;
|
||||
public $statement;
|
||||
public $sql;
|
||||
};
|
||||
|
||||
$storage->sql = $sql;
|
||||
|
||||
$this->statements[$name] = $storage;
|
||||
|
||||
try {
|
||||
$storage->statement = yield (
|
||||
$storage->promise = new Coroutine($this->send([$this->handle, "prepareAsync"], $name, $modifiedSql))
|
||||
$storage->promise = new Coroutine($this->send($sql, [$this->handle, "prepareAsync"], $name, $modifiedSql))
|
||||
);
|
||||
} catch (\Throwable $exception) {
|
||||
unset($this->statements[$name]);
|
||||
@ -420,7 +424,7 @@ final class PqHandle implements Handle
|
||||
*/
|
||||
public function notify(string $channel, string $payload = ""): Promise
|
||||
{
|
||||
return new Coroutine($this->send([$this->handle, "notifyAsync"], $channel, $payload));
|
||||
return new Coroutine($this->send(null, [$this->handle, "notifyAsync"], $channel, $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -437,6 +441,7 @@ final class PqHandle implements Handle
|
||||
|
||||
try {
|
||||
yield from $this->send(
|
||||
null,
|
||||
[$this->handle, "listenAsync"],
|
||||
$channel,
|
||||
static function (string $channel, string $message, int $pid) use ($emitter) {
|
||||
@ -474,7 +479,7 @@ final class PqHandle implements Handle
|
||||
if (!$this->handle) {
|
||||
$promise = new Success; // Connection already closed.
|
||||
} else {
|
||||
$promise = new Coroutine($this->send([$this->handle, "unlistenAsync"], $channel));
|
||||
$promise = new Coroutine($this->send(null, [$this->handle, "unlistenAsync"], $channel));
|
||||
}
|
||||
|
||||
$promise->onResolve([$emitter, "complete"]);
|
||||
|
@ -9,9 +9,9 @@ class QueryExecutionError extends QueryError
|
||||
/** @var mixed[] */
|
||||
private $diagnostics;
|
||||
|
||||
public function __construct(string $message, array $diagnostics, \Throwable $previous = null)
|
||||
public function __construct(string $message, array $diagnostics, \Throwable $previous = null, string $query = '')
|
||||
{
|
||||
parent::__construct($message, 0, $previous);
|
||||
parent::__construct($message, $query, $previous);
|
||||
$this->diagnostics = $diagnostics;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user