Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# v8.2.0 (2024-06-17)

Added
- New method `Query/Builder::whereInEmbedded` to allow for querying without parameterizing queries (#221)
# v8.1.1 (2024-06-03)

Fixed
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ Please note that the following are not required, but are strongly recommended fo
### SQL Mode
Currently only supports Spanner running GoogleSQL (PostgreSQL mode is not supported).

### Query
- [Binding more than 950 parameters in a single query will result in an error](https://cloud.google.com/spanner/quotas#query-limits)
by the server. You may by-pass this limitation by using `Query\Builder::whereInEmbedded(...)` method to embed the
values instead of using query parameters. Using this method may have [negative impact on performance and security](https://cloud.google.com/spanner/docs/sql-best-practices#query-parameters).
Please ensure to review the security practices when using this method, especially regarding SQL injection risks.
### Eloquent
If you use interleaved keys, you MUST define them in the `interleaveKeys` property, or else you won't be able to save.
For more detailed instructions, see `Colopl\Spanner\Tests\Eloquent\ModelTest`.
Expand Down
13 changes: 13 additions & 0 deletions src/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,19 @@ public function whereInUnnest(string $column, $values, string $boolean = 'and')
return $this;
}

/**
* @param string $column
* @param iterable<array-key, scalar> $values
* @return $this
*/
public function whereInEmbedded(string $column, iterable $values): static
{
$rawColumn = $this->getGrammar()->wrap($column);
$rawValues = implode(', ', array_map($this->connection->escape(...), iterator_to_array($values)));
$this->whereRaw("{$rawColumn} in ({$rawValues})");
return $this;
}

/**
* @param array<array-key, mixed> $values
* @return array<int, mixed>
Expand Down
15 changes: 15 additions & 0 deletions tests/Query/BuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Google\Cloud\Spanner\Duration;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Database\QueryException;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use LogicException;

Expand Down Expand Up @@ -850,6 +851,20 @@ public function test_whereIn(): void
$this->assertSame(2, $conn->table($tableName)->whereIn('bytesTest', [new Bytes(chr(10)), new Bytes(chr(20))])->count());
}

public function test_whereInEmbedded_can_do_more_than_950_parameters(): void
{
$conn = $this->getDefaultConnection();
$tableName = self::TABLE_NAME_USER;
$qb = $conn->table($tableName);
$id1 = $this->generateUuid();
$id2 = $this->generateUuid();
$dummyIds = array_map($this->generateUuid(...), range(0, 950));

$qb->insert([['userId' => $id1, 'name' => 't1'], ['userId' => $id2, 'name' => 't2']]);
$ids = $qb->whereInEmbedded('userId', [$id1, $id2, ...$dummyIds])->pluck('userId');
$this->assertEquals([$id1, $id2], $ids->all());
}
Comment on lines +854 to +866
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding more robust assertions to ensure the correctness of whereInEmbedded.

The test verifies that the IDs match, but it could be enhanced by checking that no additional IDs are returned and that the exact expected IDs are present in the correct order. This would make the test more robust against potential modifications that could alter the behavior of whereInEmbedded.


public function test_partitionedDml(): void
{
$conn = $this->getDefaultConnection();
Expand Down