diff --git a/CHANGELOG.md b/CHANGELOG.md index 9774875..6ce00a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ -# v8.1.0 (2024-04-16) +# v8.1.0 (Not released yet) Added - Request and Transaction tagging support (#206) +- Support for `INSERT OR IGNORE` (#207) # v8.0.0 (2024-04-11) diff --git a/compose.yaml b/compose.yaml index ff5a760..242d8d7 100644 --- a/compose.yaml +++ b/compose.yaml @@ -8,4 +8,4 @@ services: depends_on: - emulator emulator: - image: gcr.io/cloud-spanner-emulator/emulator + image: "gcr.io/cloud-spanner-emulator/emulator:1.5.17" diff --git a/src/Query/Grammar.php b/src/Query/Grammar.php index ee59be0..10aef95 100644 --- a/src/Query/Grammar.php +++ b/src/Query/Grammar.php @@ -30,6 +30,14 @@ class Grammar extends BaseGrammar use MarksAsNotSupported; use SharedGrammarCalls; + /** + * @inheritDoc + */ + public function compileInsertOrIgnore(Builder $query, array $values) + { + return Str::replaceFirst('insert', 'insert or ignore', $this->compileInsert($query, $values)); + } + /** * @inheritDoc */ diff --git a/tests/Query/BuilderTest.php b/tests/Query/BuilderTest.php index b9264e0..b6f18d0 100644 --- a/tests/Query/BuilderTest.php +++ b/tests/Query/BuilderTest.php @@ -25,6 +25,7 @@ use Google\Cloud\Core\Exception\ConflictException; use Google\Cloud\Spanner\Bytes; use Google\Cloud\Spanner\Duration; +use Illuminate\Database\Events\QueryExecuted; use Illuminate\Database\QueryException; use Illuminate\Support\Carbon; use LogicException; @@ -496,7 +497,7 @@ public function test_ignoreIndex(): void ->toSql(); } - public function testInterleaveTable(): void + public function test_interleaved_table(): void { $conn = $this->getDefaultConnection(); @@ -558,7 +559,7 @@ public function test_insert_numeric_types(): void $this->assertNull($insertedRow['nullableNumericTest']); } - public function testInsertDatetime(): void + public function test_insert_datetime_object(): void { date_default_timezone_set('Asia/Tokyo'); @@ -577,6 +578,34 @@ public function testInsertDatetime(): void $this->assertSame($carbonMax->getTimestamp(), $insertedTimestamp->getTimestamp()); } + public function test_insertOrIgnore(): void + { + $table = __FUNCTION__; + $conn = $this->getDefaultConnection(); + $sb = $conn->getSchemaBuilder(); + + $sb->create($table, function (Blueprint $table) { + $table->integer('id')->nullable()->primary(); + $table->string('s', 1)->nullable(); + }); + + $query = $conn->table($table); + $query->truncate(); + $this->assertSame(1, $query->insertOrIgnore(['id' => 1, 's' => 'a'])); + $this->assertSame(2, $query->insertOrIgnore([ + ['id' => 1, 's' => 'b'], + ['id' => 2, 's' => 'c'], + ['id' => 3, 's' => 'd'], + ])); + + $this->assertSame([ + ['id' => 1, 's' => 'a'], + ['id' => 2, 's' => 'c'], + ['id' => 3, 's' => 'd'], + ], $query->get()->sortBy('id')->values()->all()); + + } + public function test_upsert_single_row(): void { $table = __FUNCTION__; @@ -649,7 +678,7 @@ public function test_upsert_throw_error(): void $this->assertSame(0, $query->count()); } - public function testWhereDatetime(): void + public function test_where_with_datetime(): void { date_default_timezone_set('Asia/Tokyo'); @@ -670,7 +699,7 @@ public function testWhereDatetime(): void /** * null ではない列を null で上書きできるか */ - public function testUpdateWithNull(): void + public function test_update_with_null(): void { $conn = $this->getDefaultConnection(); $tableName = self::TABLE_NAME_TEST; @@ -696,10 +725,10 @@ public function testUpdateWithNull(): void ->where('testId', $insertRow['testId']) ->first(); - $this->assertSame(null, $afterRow['nullableStringTest']); + $this->assertNull($afterRow['nullableStringTest']); } - public function testUpdateOrInsert(): void + public function test_updateOrInsert(): void { $conn = $this->getDefaultConnection(); $tableName = self::TABLE_NAME_TEST; @@ -724,7 +753,7 @@ public function testUpdateOrInsert(): void $this->assertSame('updated', $record['stringTest']); } - public function testDeleteOnCascase(): void + public function test_delete_with_cascading_interleaves(): void { $conn = $this->getDefaultConnection(); @@ -767,7 +796,7 @@ public function testDeleteOnCascase(): void $this->assertDatabaseMissing($tableName, $userItems[1]); } - public function testInsertBytes(): void + public function test_insert_bytes(): void { $conn = $this->getDefaultConnection(); $tableName = self::TABLE_NAME_TEST; @@ -784,7 +813,7 @@ public function testInsertBytes(): void $this->assertSame($bytes->formatAsString(), $insertedBytes->formatAsString()); } - public function testWhereBytes(): void + public function test_Where_with_bytes(): void { $conn = $this->getDefaultConnection(); $tableName = self::TABLE_NAME_TEST; @@ -799,7 +828,7 @@ public function testWhereBytes(): void $this->assertSame(0, $qb->where('bytesTest', '=', new Bytes("\x00\x01"))->count()); } - public function testWhereIn(): void + public function test_whereIn(): void { $conn = $this->getDefaultConnection(); $tableName = self::TABLE_NAME_TEST; @@ -895,7 +924,7 @@ public function test_whereLike(): void } } - public function testEscapeCharacter(): void + public function test_escapeCharacter(): void { $conn = $this->getDefaultConnection(); $tableName = self::TABLE_NAME_USER; @@ -920,7 +949,7 @@ public function testEscapeCharacter(): void } } - public function testStaleReads(): void + public function test_stale_reads(): void { $conn = $this->getDefaultConnection(); $tableName = self::TABLE_NAME_USER; @@ -935,7 +964,7 @@ public function testStaleReads(): void $this->assertEmpty($stalenessRow); } - public function testTruncate(): void + public function test_truncate(): void { $conn = $this->getDefaultConnection(); $tableName = self::TABLE_NAME_USER;