Skip to content

Commit

Permalink
Support JSON columns in bind
Browse files Browse the repository at this point in the history
  • Loading branch information
trowski committed Dec 19, 2023
1 parent e95eee9 commit 9b590a0
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 30 deletions.
25 changes: 14 additions & 11 deletions src/Internal/ConnectionProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ public function bindParam(int $stmtId, int $paramId, string $data): void
* call of this method ...
*
* @param list<MysqlColumnDefinition> $params
* @param array<int, mixed> $prebound
* @param array<int, string> $prebound
* @param array<int, mixed> $data
*/
public function execute(int $stmtId, string $query, array $params, array $prebound, array $data = []): Future
Expand Down Expand Up @@ -463,19 +463,14 @@ public function execute(int $stmtId, string $query, array $params, array $prebou
$paramType = $params[$paramId]->getType();

if (isset($prebound[$paramId])) {
if (!$paramType->isBindable()) {
throw new SqlException("Cannot use bind with columns of type " . \strtoupper($paramType->name));
}

$types[] = MysqlDataType::encodeInt16(MysqlDataType::LongBlob->value);
$types[] = MysqlDataType::encodeInt16($this->getBindType($paramType)->value);
continue;
}

if ($paramType === MysqlDataType::Json && \is_string($param)) {
$encodedValue = MysqlEncodedValue::fromJson($param);
} else {
$encodedValue = MysqlEncodedValue::fromValue($param);
}
$encodedValue = match ($paramType) {
MysqlDataType::Json => MysqlEncodedValue::fromJson((string) $param),
default => MysqlEncodedValue::fromValue($param),
};

$types[] = MysqlDataType::encodeInt16($encodedValue->getType()->value);
$values[] = $encodedValue->getBytes();
Expand All @@ -500,6 +495,14 @@ public function execute(int $stmtId, string $query, array $params, array $prebou
return $deferred->getFuture(); // do not use $this->startCommand(), that might unexpectedly reset the seqId!
}

private function getBindType(MysqlDataType $type): MysqlDataType
{
return match ($type) {
MysqlDataType::Json => MysqlDataType::VarString,
default => $type,
};
}

/** @see 14.7.7 COM_STMT_CLOSE */
public function closeStmt(int $stmtId): void
{
Expand Down
2 changes: 2 additions & 0 deletions src/Internal/MysqlConnectionStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ final class MysqlConnectionStatement implements MysqlStatement
private readonly int $positionalParamCount;

private array $named = [];

/** @var array<string> */
private array $prebound = [];

private ?ConnectionProcessor $processor;
Expand Down
13 changes: 0 additions & 13 deletions src/MysqlDataType.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,6 @@ public function decodeText(string $bytes, int &$offset = 0, int $flags = 0): int
}
}

public function isInternal(): bool
{
return match ($this) {
self::Timestamp2, self::Datetime2, self::NewDate, self::Time2 => true,
default => false,
};
}

public function isBindable(): bool
{
return $this !== self::Json;
}

/**
* @param int<0, max> $offset
*/
Expand Down
14 changes: 8 additions & 6 deletions test/LinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use Amp\Mysql\MysqlResult;
use Amp\Sql\QueryError;
use Amp\Sql\Result;
use Amp\Sql\SqlException;
use function Amp\async;
use function Amp\delay;

Expand Down Expand Up @@ -447,12 +446,15 @@ public function testInsertSelect(): void

public function testBindJson(): void
{
$statement = $this->getLink()->prepare("SELECT CAST(? AS JSON)");
$statement->bind(0, '{"key": "value"}');
$json = '{"key": "value"}';

$this->expectException(SqlException::class);
$this->expectExceptionMessage("Cannot use bind with columns of type JSON");
$statement = $this->getLink()->prepare("SELECT CAST(? AS JSON) AS json_data");
$statement->bind(0, $json);

$statement->execute();
$result = $statement->execute();

foreach ($result as $row) {
self::assertSame($json, $row['json_data']);
}
}
}

0 comments on commit 9b590a0

Please sign in to comment.