Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
d069366
Added upsert functionality for MySQL, Postgres, SQLite and SQLServer
puzzledpolymath Jul 11, 2025
6007e53
Added upsert test cases for MySQL, Postgres, SQLite and SQLServer
puzzledpolymath Jul 11, 2025
db1a012
Merge statement must be terminated by a semicolon
puzzledpolymath Jul 11, 2025
2b4d727
Updated upsertOne and upsertMultiple methods to accept conflicts argu…
puzzledpolymath Jul 11, 2025
71ef04e
Includes upsertOne and upsertMultiple for common table test
puzzledpolymath Jul 11, 2025
802d24f
Includes overridden test case given Postgres sequence handling
puzzledpolymath Jul 11, 2025
e831289
Updated test as SQLServer does require conflicts defined
puzzledpolymath Jul 11, 2025
224aae6
Improved test coverage for Postgres when returning with Fragment
puzzledpolymath Jul 11, 2025
6e0001b
Added additional composer utilities for testing and code coverage
puzzledpolymath Jul 11, 2025
9c2fc52
Added support for returning values/fragments whilst upserting with sq…
puzzledpolymath Jul 11, 2025
d11ff0b
Tweaked formatting
puzzledpolymath Jul 11, 2025
2528954
Added more test cases and code coverage
puzzledpolymath Jul 11, 2025
9a2285a
Added more test cases and code coverage
puzzledpolymath Jul 11, 2025
776239d
Introduced ULID type via annotations and added column mapping for eac…
puzzledpolymath Jul 14, 2025
7818f55
Add test coverage for newly introduced ULID type
puzzledpolymath Jul 14, 2025
5801734
Psalm baseline has not been updated recently
puzzledpolymath Jul 14, 2025
c37e0c0
style(php-cs-fixer): fix coding standards
Jul 14, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/.idea/
/.report/
/.dolt/
/runtime/
/vendor/
Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@
"cs:fix": "php-cs-fixer fix -v",
"psalm": "psalm",
"psalm:baseline": "psalm --set-baseline=psalm-baseline.xml",
"test": "phpunit --color=always"
"test": "phpunit --color=always",
"test:coverage": "phpunit --colors=always --coverage-text",
"test:report": "phpunit --do-not-cache-result --log-junit=.report/phpunit.xml --coverage-clover=.report/coverage-clover.xml --coverage-cobertura=.report/coverage-cobertura.xml --coverage-text --colors=never"
}
}
128 changes: 125 additions & 3 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,14 @@
<code><![CDATA[$param]]></code>
<code><![CDATA[$param]]></code>
<code><![CDATA[$param]]></code>
<code><![CDATA[$tokens['alias']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['conflicts']]]></code>
<code><![CDATA[$tokens['conflicts']]]></code>
<code><![CDATA[$tokens['distinct']]]></code>
<code><![CDATA[$tokens['except']]]></code>
<code><![CDATA[$tokens['expression']]]></code>
Expand Down Expand Up @@ -366,6 +372,7 @@
<code><![CDATA[$value]]></code>
<code><![CDATA[$value]]></code>
<code><![CDATA[$value]]></code>
<code><![CDATA[$value]]></code>
<code><![CDATA[[$boolean, $context]]]></code>
</MixedAssignment>
<MixedOperand>
Expand All @@ -379,8 +386,11 @@
<code><![CDATA[$identifier]]></code>
</MoreSpecificImplementedParamType>
<PossiblyUndefinedStringArrayOffset>
<code><![CDATA[$tokens['alias']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['conflicts']]]></code>
<code><![CDATA[$tokens['distinct']]]></code>
<code><![CDATA[$tokens['except']]]></code>
<code><![CDATA[$tokens['expression']]]></code>
Expand All @@ -405,9 +415,11 @@
<code><![CDATA[$tokens['table']]]></code>
<code><![CDATA[$tokens['table']]]></code>
<code><![CDATA[$tokens['table']]]></code>
<code><![CDATA[$tokens['table']]]></code>
<code><![CDATA[$tokens['union']]]></code>
<code><![CDATA[$tokens['values']]]></code>
<code><![CDATA[$tokens['values']]]></code>
<code><![CDATA[$tokens['values']]]></code>
<code><![CDATA[$tokens['where']]]></code>
<code><![CDATA[$tokens['where']]]></code>
<code><![CDATA[$tokens['where']]]></code>
Expand Down Expand Up @@ -770,9 +782,23 @@
<ClassMustBeFinal>
<code><![CDATA[MySQLCompiler]]></code>
</ClassMustBeFinal>
<MissingClosureParamType>
<code><![CDATA[$column]]></code>
</MissingClosureParamType>
<MixedArgument>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
</MixedArgument>
<MixedAssignment>
<code><![CDATA[$value]]></code>
</MixedAssignment>
<PossiblyUndefinedStringArrayOffset>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['table']]]></code>
<code><![CDATA[$tokens['table']]]></code>
<code><![CDATA[$tokens['values']]]></code>
</PossiblyUndefinedStringArrayOffset>
</file>
<file src="src/Driver/MySQL/MySQLDriver.php">
Expand All @@ -793,6 +819,7 @@
new QueryBuilder(
new MySQLSelectQuery(),
new InsertQuery(),
new UpsertQuery(),
new MySQLUpdateQuery(),
new MySQLDeleteQuery(),
),
Expand Down Expand Up @@ -901,19 +928,20 @@
</MixedAssignment>
<PossiblyUndefinedStringArrayOffset>
<code><![CDATA[$matches['type']]]></code>
<code><![CDATA[$schema['Comment']]]></code>
<code><![CDATA[$schema['Default']]]></code>
<code><![CDATA[$schema['Extra']]]></code>
<code><![CDATA[$schema['Field']]]></code>
<code><![CDATA[$schema['Null']]]></code>
<code><![CDATA[$schema['Type']]]></code>
<code><![CDATA[$schema['Comment']]]></code>
</PossiblyUndefinedStringArrayOffset>
<RiskyTruthyFalsyComparison>
<code><![CDATA[empty($matches['attr'])]]></code>
<code><![CDATA[empty($matches['options'])]]></code>
</RiskyTruthyFalsyComparison>
<UndefinedInterfaceMethod>
<code><![CDATA[identifier]]></code>
<code><![CDATA[identifier]]></code>
</UndefinedInterfaceMethod>
</file>
<file src="src/Driver/MySQL/Schema/MySQLForeignKey.php">
Expand Down Expand Up @@ -1097,6 +1125,7 @@
<ArgumentTypeCoercion>
<code><![CDATA[$path]]></code>
<code><![CDATA[$return]]></code>
<code><![CDATA[$return]]></code>
</ArgumentTypeCoercion>
<ClassMustBeFinal>
<code><![CDATA[PostgresCompiler]]></code>
Expand All @@ -1106,9 +1135,11 @@
</InvalidClassConstantType>
<MixedArgument>
<code><![CDATA[$tokens['return']]]></code>
<code><![CDATA[$tokens['return']]]></code>
</MixedArgument>
<PossiblyNullArgument>
<code><![CDATA[$return]]></code>
<code><![CDATA[$return]]></code>
</PossiblyNullArgument>
</file>
<file src="src/Driver/Postgres/PostgresDriver.php">
Expand Down Expand Up @@ -1145,6 +1176,7 @@
new QueryBuilder(
new PostgresSelectQuery(),
new PostgresInsertQuery(),
new PostgresUpsertQuery(),
new PostgresUpdateQuery(),
new PostgresDeleteQuery(),
),
Expand Down Expand Up @@ -1234,6 +1266,31 @@
<code><![CDATA[PostgresUpdateQuery]]></code>
</ClassMustBeFinal>
</file>
<file src="src/Driver/Postgres/Query/PostgresUpsertQuery.php">
<ClassMustBeFinal>
<code><![CDATA[PostgresUpsertQuery]]></code>
</ClassMustBeFinal>
<DeprecatedProperty>
<code><![CDATA[$this->returning]]></code>
</DeprecatedProperty>
<MixedReturnStatement>
<code><![CDATA[$result->fetch(StatementInterface::FETCH_ASSOC)]]></code>
<code><![CDATA[$result->fetchColumn()]]></code>
<code><![CDATA[$result->fetchColumn()]]></code>
</MixedReturnStatement>
<NonInvariantDocblockPropertyType>
<code><![CDATA[$driver]]></code>
</NonInvariantDocblockPropertyType>
<PossiblyNullArgument>
<code><![CDATA[$this->prefix]]></code>
</PossiblyNullArgument>
<PossiblyNullReference>
<code><![CDATA[isReadonly]]></code>
</PossiblyNullReference>
<PropertyTypeCoercion>
<code><![CDATA[\array_values($columns)]]></code>
</PropertyTypeCoercion>
</file>
<file src="src/Driver/Postgres/Query/Traits/WhereJsonTrait.php">
<MixedArgument>
<code><![CDATA[$params['encode']]]></code>
Expand Down Expand Up @@ -1303,10 +1360,10 @@
<code><![CDATA[$identifier]]></code>
<code><![CDATA[$identifier]]></code>
<code><![CDATA[$range]]></code>
<code><![CDATA[$tableName]]></code>
<code><![CDATA[$value]]></code>
<code><![CDATA[$value]]></code>
<code><![CDATA[$value]]></code>
<code><![CDATA[$tableName]]></code>
</MixedAssignment>
<MixedOperand>
<code><![CDATA[$schema['dtd_identifier']]]></code>
Expand All @@ -1321,6 +1378,7 @@
<code><![CDATA[$schema['column_name']]]></code>
<code><![CDATA[$schema['data_type']]]></code>
<code><![CDATA[$schema['datetime_precision']]]></code>
<code><![CDATA[$schema['description']]]></code>
<code><![CDATA[$schema['dtd_identifier']]]></code>
<code><![CDATA[$schema['interval_type']]]></code>
<code><![CDATA[$schema['is_nullable']]]></code>
Expand All @@ -1330,7 +1388,6 @@
<code><![CDATA[$schema['tableOID']]]></code>
<code><![CDATA[$schema['typname']]]></code>
<code><![CDATA[$schema['typtype']]]></code>
<code><![CDATA[$schema['description']]]></code>
</PossiblyUndefinedStringArrayOffset>
<RedundantCast>
<code><![CDATA[(bool) (
Expand Down Expand Up @@ -1580,6 +1637,24 @@
<code><![CDATA[SQLServerUpdateQuery]]></code>
</ClassMustBeFinal>
</file>
<file src="src/Driver/SQLServer/Query/SQLServerUpsertQuery.php">
<ClassMustBeFinal>
<code><![CDATA[SQLServerUpsertQuery]]></code>
</ClassMustBeFinal>
<MixedReturnStatement>
<code><![CDATA[$result->fetch(StatementInterface::FETCH_ASSOC)]]></code>
<code><![CDATA[$result->fetchColumn()]]></code>
</MixedReturnStatement>
<NonInvariantDocblockPropertyType>
<code><![CDATA[$driver]]></code>
</NonInvariantDocblockPropertyType>
<PossiblyNullReference>
<code><![CDATA[isReadonly]]></code>
</PossiblyNullReference>
<PropertyTypeCoercion>
<code><![CDATA[\array_values($columns)]]></code>
</PropertyTypeCoercion>
</file>
<file src="src/Driver/SQLServer/Query/Traits/WhereJsonTrait.php">
<MethodSignatureMismatch>
<code><![CDATA[public function orWhereJson(string $column, mixed $value): static]]></code>
Expand Down Expand Up @@ -1652,6 +1727,13 @@
<code><![CDATA[$offset]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['conflicts']]]></code>
<code><![CDATA[$tokens['conflicts']]]></code>
<code><![CDATA[$tokens['distinct']]]></code>
<code><![CDATA[$tokens['except']]]></code>
<code><![CDATA[$tokens['groupBy']]]></code>
Expand All @@ -1662,6 +1744,7 @@
<code><![CDATA[$tokens['offset']]]></code>
<code><![CDATA[$tokens['orderBy']]]></code>
<code><![CDATA[$tokens['return']]]></code>
<code><![CDATA[$tokens['return']]]></code>
<code><![CDATA[$tokens['union']]]></code>
<code><![CDATA[$tokens['where']]]></code>
</MixedArgument>
Expand All @@ -1678,6 +1761,7 @@
<code><![CDATA[$offset]]></code>
<code><![CDATA[$table]]></code>
<code><![CDATA[$value]]></code>
<code><![CDATA[$value]]></code>
</MixedAssignment>
<MixedReturnStatement>
<code><![CDATA[\call_user_func_array([$this, 'baseSelect'], \func_get_args())]]></code>
Expand All @@ -1691,6 +1775,8 @@
<PossiblyUndefinedStringArrayOffset>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['columns']]]></code>
<code><![CDATA[$tokens['conflicts']]]></code>
<code><![CDATA[$tokens['distinct']]]></code>
<code><![CDATA[$tokens['except']]]></code>
<code><![CDATA[$tokens['forUpdate']]]></code>
Expand All @@ -1708,8 +1794,10 @@
<code><![CDATA[$tokens['orderBy']]]></code>
<code><![CDATA[$tokens['table']]]></code>
<code><![CDATA[$tokens['table']]]></code>
<code><![CDATA[$tokens['table']]]></code>
<code><![CDATA[$tokens['union']]]></code>
<code><![CDATA[$tokens['values']]]></code>
<code><![CDATA[$tokens['values']]]></code>
<code><![CDATA[$tokens['where']]]></code>
</PossiblyUndefinedStringArrayOffset>
</file>
Expand Down Expand Up @@ -1746,6 +1834,7 @@
new QueryBuilder(
new SQLServerSelectQuery(),
new SQLServerInsertQuery(),
new SQLServerUpsertQuery(),
new SQLServerUpdateQuery(),
new SQLServerDeleteQuery(),
),
Expand Down Expand Up @@ -2059,6 +2148,7 @@
new QueryBuilder(
new SQLiteSelectQuery(),
new InsertQuery(),
new UpsertQuery(),
new SQLiteUpdateQuery(),
new SQLiteDeleteQuery(),
),
Expand Down Expand Up @@ -2424,6 +2514,14 @@
<code><![CDATA[$value]]></code>
</PropertyNotSetInConstructor>
</file>
<file src="src/Injection/SubQuery.php">
<ClassMustBeFinal>
<code><![CDATA[SubQuery]]></code>
</ClassMustBeFinal>
<MixedPropertyTypeCoercion>
<code><![CDATA[$parameters->getParameters()]]></code>
</MixedPropertyTypeCoercion>
</file>
<file src="src/Query/ActiveQuery.php">
<PossiblyNullArgument>
<code><![CDATA[$this->prefix]]></code>
Expand Down Expand Up @@ -2521,6 +2619,7 @@
<code><![CDATA[from]]></code>
<code><![CDATA[in]]></code>
<code><![CDATA[into]]></code>
<code><![CDATA[into]]></code>
<code><![CDATA[where]]></code>
<code><![CDATA[where]]></code>
</UndefinedMethod>
Expand Down Expand Up @@ -2656,6 +2755,23 @@
<code><![CDATA[execute]]></code>
</PossiblyNullReference>
</file>
<file src="src/Query/UpsertQuery.php">
<MixedArgument>
<code><![CDATA[$rowsets[\key($rowsets)]]]></code>
<code><![CDATA[$values]]></code>
</MixedArgument>
<MixedAssignment>
<code><![CDATA[$lastID]]></code>
<code><![CDATA[$values]]></code>
</MixedAssignment>
<MixedReturnStatement>
<code><![CDATA[\is_numeric($lastID) ? (int) $lastID : $lastID]]></code>
<code><![CDATA[\is_numeric($lastID) ? (int) $lastID : $lastID]]></code>
</MixedReturnStatement>
<PossiblyNullReference>
<code><![CDATA[execute]]></code>
</PossiblyNullReference>
</file>
<file src="src/Schema/AbstractColumn.php">
<ArgumentTypeCoercion>
<code><![CDATA[$this->getAbstractType()]]></code>
Expand Down Expand Up @@ -2930,9 +3046,15 @@
->insert($this->name)
->values($rowset)
->run()]]></code>
<code><![CDATA[$this->database
->upsert($this->name)
->conflicts($conflicts)
->values($rowset)
->run()]]></code>
</InvalidReturnStatement>
<InvalidReturnType>
<code><![CDATA[int|string|null]]></code>
<code><![CDATA[int|string|null]]></code>
</InvalidReturnType>
<MissingTemplateParam>
<code><![CDATA[\IteratorAggregate]]></code>
Expand Down
8 changes: 8 additions & 0 deletions src/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Cycle\Database\Query\InsertQuery;
use Cycle\Database\Query\SelectQuery;
use Cycle\Database\Query\UpdateQuery;
use Cycle\Database\Query\UpsertQuery;

/**
* Database class is high level abstraction at top of Driver. Databases usually linked to real
Expand Down Expand Up @@ -139,6 +140,13 @@ public function insert(?string $table = null): InsertQuery
->insertQuery($this->prefix, $table);
}

public function upsert(?string $table = null): UpsertQuery
{
return $this->getDriver(self::WRITE)
->getQueryBuilder()
->upsertQuery($this->prefix, $table);
}

public function update(?string $table = null, array $values = [], array $where = []): UpdateQuery
{
return $this->getDriver(self::WRITE)
Expand Down
Loading
Loading