Skip to content

Commit 2528954

Browse files
Added more test cases and code coverage
1 parent d11ff0b commit 2528954

File tree

3 files changed

+105
-17
lines changed

3 files changed

+105
-17
lines changed

src/Query/UpsertQuery.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,8 @@ public function run(): mixed
134134
);
135135

136136
$lastID = $this->driver->lastInsertID();
137-
if (\is_numeric($lastID)) {
138-
return (int) $lastID;
139-
}
140137

141-
return $lastID;
138+
return \is_numeric($lastID) ? (int) $lastID : $lastID;
142139
}
143140

144141
public function getType(): int

tests/Database/Functional/Driver/Postgres/Query/UpsertQueryTest.php

Lines changed: 95 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
// phpcs:ignore
88
use Cycle\Database\Driver\Postgres\Query\PostgresUpsertQuery;
9+
use Cycle\Database\Driver\Postgres\Schema\PostgresColumn;
910
use Cycle\Database\Injection\Fragment;
1011
use Cycle\Database\Tests\Functional\Driver\Common\Query\UpsertQueryTest as CommonClass;
1112

@@ -15,9 +16,9 @@
1516
*/
1617
class UpsertQueryTest extends CommonClass
1718
{
18-
public const DRIVER = 'postgres';
19-
protected const QUERY_INSTANCE = PostgresUpsertQuery::class;
20-
protected const QUERY_WITH_FRAGMENTS_RETURNING = 'INSERT INTO {table} ({email}, {name}, {balance}, {created_at}, {updated_at}, {deleted_at}) VALUES (?, ?, ?, NOW(), datetime(\'now\'), ?) ON CONFLICT ({email}) DO UPDATE SET {email} = EXCLUDED.{email}, {name} = EXCLUDED.{name}, {balance} = EXCLUDED.{balance}, {created_at} = EXCLUDED.{created_at}, {updated_at} = EXCLUDED.{updated_at}, {deleted_at} = EXCLUDED.{deleted_at} RETURNING {balance} + 100 as {modified_balance}';
19+
public const DRIVER = 'postgres';
20+
protected const QUERY_INSTANCE = PostgresUpsertQuery::class;
21+
protected const QUERY_WITH_RETURNING_FRAGMENT = 'INSERT INTO {table} ({email}, {name}, {balance}, {created_at}, {updated_at}, {deleted_at}) VALUES (?, ?, ?, NOW(), datetime(\'now\'), ?) ON CONFLICT ({email}) DO UPDATE SET {email} = EXCLUDED.{email}, {name} = EXCLUDED.{name}, {balance} = EXCLUDED.{balance}, {created_at} = EXCLUDED.{created_at}, {updated_at} = EXCLUDED.{updated_at}, {deleted_at} = EXCLUDED.{deleted_at} RETURNING {balance} + 100 as {modified_balance}';
2122

2223
public function testQueryWithFragmentsAndReturning(): void
2324
{
@@ -32,7 +33,97 @@ public function testQueryWithFragmentsAndReturning(): void
3233
'deleted_at' => null,
3334
])->returning(new Fragment('"balance" + 100 as "modified_balance"'));
3435

35-
$this->assertSameQuery(static::QUERY_WITH_FRAGMENTS_RETURNING, $upsert);
36+
$this->assertSameQuery(static::QUERY_WITH_RETURNING_FRAGMENT, $upsert);
3637
$this->assertSameParameters(['adam@email.com', 'Adam', 100, null], $upsert);
3738
}
39+
40+
public function testReturningSingleValueFromDatabase(): void
41+
{
42+
$schema = $this->schema('foo');
43+
$schema->primary('id');
44+
$schema->string('name')->nullable(false);
45+
$schema->string('email', 64)->nullable(false);
46+
$schema->integer('balance')->defaultValue(0);
47+
$schema->index(['email'])->unique(true);
48+
$schema->save();
49+
50+
$table = $this->database->table('foo');
51+
52+
$this->assertTrue($table->exists());
53+
$this->assertSame(0, $table->count());
54+
55+
$email = $table->upsert()
56+
->conflicts('email')
57+
->values([
58+
'email' => 'adam@email.com',
59+
'name' => 'Adam',
60+
'balance' => 100,
61+
])
62+
->returning('email')
63+
->run();
64+
65+
$this->assertSame('adam@email.com', $email);
66+
}
67+
68+
public function testReturningMultipleValuesFromDatabase(): void
69+
{
70+
$schema = $this->schema('foo');
71+
$schema->primary('id');
72+
$schema->string('name')->nullable(false);
73+
$schema->string('email', 64)->nullable(false);
74+
$schema->integer('balance')->defaultValue(0);
75+
$schema->index(['email'])->unique(true);
76+
$schema->save();
77+
78+
$table = $this->database->table('foo');
79+
80+
$this->assertTrue($table->exists());
81+
$this->assertSame(0, $table->count());
82+
83+
$result = $table->upsert()
84+
->conflicts('email')
85+
->values([
86+
'email' => 'adam@email.com',
87+
'name' => 'Adam',
88+
'balance' => 100,
89+
])
90+
->returning('email', 'name', 'balance')
91+
->run();
92+
93+
$this->assertSame('adam@email.com', $result['email']);
94+
$this->assertSame('Adam', $result['name']);
95+
$this->assertSame(100, $result['balance']);
96+
}
97+
98+
public function testNullReturnedWithoutPrimaryKeyAndReturningValues(): void
99+
{
100+
$schema = $this->schema('bar');
101+
$schema->string('name')->nullable(false);
102+
$schema->string('email', 64)->nullable(false);
103+
$schema->integer('balance')->defaultValue(0);
104+
$schema->index(['email'])->unique(true);
105+
$schema->save();
106+
107+
$table = $this->database->table('bar');
108+
109+
$this->assertTrue($table->exists());
110+
$this->assertSame(0, $table->count());
111+
112+
$result = $table->upsert()
113+
->conflicts('email')
114+
->values([
115+
'email' => 'adam@email.com',
116+
'name' => 'Adam',
117+
'balance' => 100,
118+
])
119+
->run();
120+
121+
$this->assertNull($result);
122+
$this->assertEquals(
123+
[
124+
['email' => 'adam@email.com', 'name' => 'Adam', 'balance' => 100],
125+
],
126+
$table->select()->fetchAll(),
127+
);
128+
}
38129
}

tests/Database/Functional/Driver/SQLServer/Query/UpsertQueryTest.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
final class UpsertQueryTest extends CommonClass
1616
{
1717
public const DRIVER = 'sqlserver';
18-
protected const QUERY_REQUIRES_CONFLICTS = true;
19-
protected const QUERY_WITH_VALUES = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?) ) AS [source] ([email], [name]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name] WHEN NOT MATCHED THEN INSERT ([email], [name]) VALUES ([source].[email], [source].[name]);';
20-
protected const QUERY_WITH_STATES_VALUES = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?) ) AS [source] ([email], [name]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name] WHEN NOT MATCHED THEN INSERT ([email], [name]) VALUES ([source].[email], [source].[name]);';
21-
protected const QUERY_WITH_MULTIPLE_ROWS = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?), (?, ?) ) AS [source] ([email], [name]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name] WHEN NOT MATCHED THEN INSERT ([email], [name]) VALUES ([source].[email], [source].[name]);';
22-
protected const QUERY_WITH_EXPRESSIONS = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?, NOW(), NOW(), ?) ) AS [source] ([email], [name], [created_at], [updated_at], [deleted_at]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name], [target].[created_at] = [source].[created_at], [target].[updated_at] = [source].[updated_at], [target].[deleted_at] = [source].[deleted_at] WHEN NOT MATCHED THEN INSERT ([email], [name], [created_at], [updated_at], [deleted_at]) VALUES ([source].[email], [source].[name], [source].[created_at], [source].[updated_at], [source].[deleted_at]);';
23-
protected const QUERY_WITH_FRAGMENTS = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?, NOW(), datetime(\'now\'), ?) ) AS [source] ([email], [name], [created_at], [updated_at], [deleted_at]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name], [target].[created_at] = [source].[created_at], [target].[updated_at] = [source].[updated_at], [target].[deleted_at] = [source].[deleted_at] WHEN NOT MATCHED THEN INSERT ([email], [name], [created_at], [updated_at], [deleted_at]) VALUES ([source].[email], [source].[name], [source].[created_at], [source].[updated_at], [source].[deleted_at]);';
24-
protected const QUERY_WITH_CUSTOM_FRAGMENT = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?, NOW()) ) AS [source] ([email], [name], [expired_at]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name], [target].[expired_at] = [source].[expired_at] WHEN NOT MATCHED THEN INSERT ([email], [name], [expired_at]) VALUES ([source].[email], [source].[name], [source].[expired_at]);';
25-
protected const QUERY_WITH_FRAGMENTS_RETURNING = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?, ?, NOW(), datetime(\'now\'), ?) ) AS [source] ([email], [name], [balance], [created_at], [updated_at], [deleted_at]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name], [target].[balance] = [source].[balance], [target].[created_at] = [source].[created_at], [target].[updated_at] = [source].[updated_at], [target].[deleted_at] = [source].[deleted_at] WHEN NOT MATCHED THEN INSERT ([email], [name], [balance], [created_at], [updated_at], [deleted_at]) VALUES ([source].[email], [source].[name], [source].[balance], [source].[created_at], [source].[updated_at], [source].[deleted_at]) OUTPUT INSERTED.[email], {balance} + 100 AS {modified_balance};';
18+
protected const QUERY_REQUIRES_CONFLICTS = true;
19+
protected const QUERY_WITH_VALUES = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?) ) AS [source] ([email], [name]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name] WHEN NOT MATCHED THEN INSERT ([email], [name]) VALUES ([source].[email], [source].[name]);';
20+
protected const QUERY_WITH_STATES_VALUES = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?) ) AS [source] ([email], [name]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name] WHEN NOT MATCHED THEN INSERT ([email], [name]) VALUES ([source].[email], [source].[name]);';
21+
protected const QUERY_WITH_MULTIPLE_ROWS = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?), (?, ?) ) AS [source] ([email], [name]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name] WHEN NOT MATCHED THEN INSERT ([email], [name]) VALUES ([source].[email], [source].[name]);';
22+
protected const QUERY_WITH_EXPRESSIONS = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?, NOW(), NOW(), ?) ) AS [source] ([email], [name], [created_at], [updated_at], [deleted_at]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name], [target].[created_at] = [source].[created_at], [target].[updated_at] = [source].[updated_at], [target].[deleted_at] = [source].[deleted_at] WHEN NOT MATCHED THEN INSERT ([email], [name], [created_at], [updated_at], [deleted_at]) VALUES ([source].[email], [source].[name], [source].[created_at], [source].[updated_at], [source].[deleted_at]);';
23+
protected const QUERY_WITH_FRAGMENTS = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?, NOW(), datetime(\'now\'), ?) ) AS [source] ([email], [name], [created_at], [updated_at], [deleted_at]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name], [target].[created_at] = [source].[created_at], [target].[updated_at] = [source].[updated_at], [target].[deleted_at] = [source].[deleted_at] WHEN NOT MATCHED THEN INSERT ([email], [name], [created_at], [updated_at], [deleted_at]) VALUES ([source].[email], [source].[name], [source].[created_at], [source].[updated_at], [source].[deleted_at]);';
24+
protected const QUERY_WITH_CUSTOM_FRAGMENT = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?, NOW()) ) AS [source] ([email], [name], [expired_at]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name], [target].[expired_at] = [source].[expired_at] WHEN NOT MATCHED THEN INSERT ([email], [name], [expired_at]) VALUES ([source].[email], [source].[name], [source].[expired_at]);';
25+
protected const QUERY_WITH_RETURNING_FRAGMENT = 'MERGE INTO [table] WITH (holdlock) AS [target] USING ( VALUES (?, ?, ?, NOW(), datetime(\'now\'), ?) ) AS [source] ([email], [name], [balance], [created_at], [updated_at], [deleted_at]) ON [target].[email] = [source].[email] WHEN MATCHED THEN UPDATE SET [target].[email] = [source].[email], [target].[name] = [source].[name], [target].[balance] = [source].[balance], [target].[created_at] = [source].[created_at], [target].[updated_at] = [source].[updated_at], [target].[deleted_at] = [source].[deleted_at] WHEN NOT MATCHED THEN INSERT ([email], [name], [balance], [created_at], [updated_at], [deleted_at]) VALUES ([source].[email], [source].[name], [source].[balance], [source].[created_at], [source].[updated_at], [source].[deleted_at]) OUTPUT INSERTED.[email], {balance} + 100 AS {modified_balance};';
2626

2727
public function testQueryWithFragmentsAndReturning(): void
2828
{
@@ -37,7 +37,7 @@ public function testQueryWithFragmentsAndReturning(): void
3737
'deleted_at' => null,
3838
])->returning('email', new Fragment('[balance] + 100 AS [modified_balance]'));
3939

40-
$this->assertSameQuery(static::QUERY_WITH_FRAGMENTS_RETURNING, $upsert);
40+
$this->assertSameQuery(static::QUERY_WITH_RETURNING_FRAGMENT, $upsert);
4141
$this->assertSameParameters(['adam@email.com', 'Adam', 100, null], $upsert);
4242
}
4343
}

0 commit comments

Comments
 (0)