Skip to content
Merged
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
1 change: 1 addition & 0 deletions apps/dav/lib/Migration/Version1034Date20250605132605.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
'notnull' => true,
'length' => 255,
]);
/** @psalm-suppress InvalidArgument legacy column */
$federatedCalendarsTable->addColumn('remote_Url', Types::STRING, [
'notnull' => true,
'length' => 255,
Expand Down
5 changes: 3 additions & 2 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,11 @@
'OCP\\DB\\QueryBuilder\\IQueryFunction' => $baseDir . '/lib/public/DB/QueryBuilder/IQueryFunction.php',
'OCP\\DB\\QueryBuilder\\ITypedQueryBuilder' => $baseDir . '/lib/public/DB/QueryBuilder/ITypedQueryBuilder.php',
'OCP\\DB\\QueryBuilder\\Sharded\\IShardMapper' => $baseDir . '/lib/public/DB/QueryBuilder/Sharded/IShardMapper.php',
'OCP\\DB\\Schema\\ColumnType' => $baseDir . '/lib/public/DB/Schema/ColumnType.php',
'OCP\\DB\\Schema\\IColumn' => $baseDir . '/lib/public/DB/Schema/IColumn.php',
'OCP\\DB\\Schema\\IForeignKeyConstraint' => $baseDir . '/lib/public/DB/Schema/IForeignKeyConstraint.php',
'OCP\\DB\\Schema\\IIndex' => $baseDir . '/lib/public/DB/Schema/IIndex.php',
'OCP\\DB\\Schema\\ITable' => $baseDir . '/lib/public/DB/Schema/ITable.php',
'OCP\\DB\\Schema\\IType' => $baseDir . '/lib/public/DB/Schema/IType.php',
'OCP\\DB\\Schema\\SchemaException' => $baseDir . '/lib/public/DB/Schema/SchemaException.php',
'OCP\\DB\\Types' => $baseDir . '/lib/public/DB/Types.php',
'OCP\\Dashboard\\IAPIWidget' => $baseDir . '/lib/public/Dashboard/IAPIWidget.php',
Expand Down Expand Up @@ -1785,9 +1786,9 @@
'OC\\DB\\SQLiteSessionInit' => $baseDir . '/lib/private/DB/SQLiteSessionInit.php',
'OC\\DB\\SchemaWrapper' => $baseDir . '/lib/private/DB/SchemaWrapper.php',
'OC\\DB\\Schema\\Column' => $baseDir . '/lib/private/DB/Schema/Column.php',
'OC\\DB\\Schema\\ForeignKeyConstraint' => $baseDir . '/lib/private/DB/Schema/ForeignKeyConstraint.php',
'OC\\DB\\Schema\\Index' => $baseDir . '/lib/private/DB/Schema/Index.php',
'OC\\DB\\Schema\\Table' => $baseDir . '/lib/private/DB/Schema/Table.php',
'OC\\DB\\Schema\\Type' => $baseDir . '/lib/private/DB/Schema/Type.php',
'OC\\DB\\SetTransactionIsolationLevel' => $baseDir . '/lib/private/DB/SetTransactionIsolationLevel.php',
'OC\\Dashboard\\Manager' => $baseDir . '/lib/private/Dashboard/Manager.php',
'OC\\DatabaseException' => $baseDir . '/lib/private/DatabaseException.php',
Expand Down
5 changes: 3 additions & 2 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -413,10 +413,11 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\DB\\QueryBuilder\\IQueryFunction' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IQueryFunction.php',
'OCP\\DB\\QueryBuilder\\ITypedQueryBuilder' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/ITypedQueryBuilder.php',
'OCP\\DB\\QueryBuilder\\Sharded\\IShardMapper' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/Sharded/IShardMapper.php',
'OCP\\DB\\Schema\\ColumnType' => __DIR__ . '/../../..' . '/lib/public/DB/Schema/ColumnType.php',
'OCP\\DB\\Schema\\IColumn' => __DIR__ . '/../../..' . '/lib/public/DB/Schema/IColumn.php',
'OCP\\DB\\Schema\\IForeignKeyConstraint' => __DIR__ . '/../../..' . '/lib/public/DB/Schema/IForeignKeyConstraint.php',
'OCP\\DB\\Schema\\IIndex' => __DIR__ . '/../../..' . '/lib/public/DB/Schema/IIndex.php',
'OCP\\DB\\Schema\\ITable' => __DIR__ . '/../../..' . '/lib/public/DB/Schema/ITable.php',
'OCP\\DB\\Schema\\IType' => __DIR__ . '/../../..' . '/lib/public/DB/Schema/IType.php',
'OCP\\DB\\Schema\\SchemaException' => __DIR__ . '/../../..' . '/lib/public/DB/Schema/SchemaException.php',
'OCP\\DB\\Types' => __DIR__ . '/../../..' . '/lib/public/DB/Types.php',
'OCP\\Dashboard\\IAPIWidget' => __DIR__ . '/../../..' . '/lib/public/Dashboard/IAPIWidget.php',
Expand Down Expand Up @@ -1826,9 +1827,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\DB\\SQLiteSessionInit' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteSessionInit.php',
'OC\\DB\\SchemaWrapper' => __DIR__ . '/../../..' . '/lib/private/DB/SchemaWrapper.php',
'OC\\DB\\Schema\\Column' => __DIR__ . '/../../..' . '/lib/private/DB/Schema/Column.php',
'OC\\DB\\Schema\\ForeignKeyConstraint' => __DIR__ . '/../../..' . '/lib/private/DB/Schema/ForeignKeyConstraint.php',
'OC\\DB\\Schema\\Index' => __DIR__ . '/../../..' . '/lib/private/DB/Schema/Index.php',
'OC\\DB\\Schema\\Table' => __DIR__ . '/../../..' . '/lib/private/DB/Schema/Table.php',
'OC\\DB\\Schema\\Type' => __DIR__ . '/../../..' . '/lib/private/DB/Schema/Type.php',
'OC\\DB\\SetTransactionIsolationLevel' => __DIR__ . '/../../..' . '/lib/private/DB/SetTransactionIsolationLevel.php',
'OC\\Dashboard\\Manager' => __DIR__ . '/../../..' . '/lib/private/Dashboard/Manager.php',
'OC\\DatabaseException' => __DIR__ . '/../../..' . '/lib/private/DatabaseException.php',
Expand Down
14 changes: 7 additions & 7 deletions lib/private/DB/Schema/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@
use Doctrine\DBAL\Schema\Column as DBALColumn;
use Doctrine\DBAL\Schema\SchemaException as DBALSchemaException;
use Doctrine\DBAL\Types\Type as DBALType;
use OCP\DB\Schema\ColumnType;
use OCP\DB\Schema\IColumn;
use OCP\DB\Schema\IType;
use OCP\DB\Schema\SchemaException;

/**
* Object representation of a column, wrapping a Doctrine DBAL Column.
*/
class Column implements IColumn {
public function __construct(
private DBALColumn $column,
private readonly DBALColumn $column,
) {
}

Expand All @@ -33,9 +33,9 @@ public function getWrappedColumn(): DBALColumn {
}

#[\Override]
public function setType(string|IType|DBALType $type): self {
if ($type instanceof IType) {
$type = $type->getName();
public function setType(string|DBALType|ColumnType $type): self {
if ($type instanceof ColumnType) {
$type = $type->value;
}

$this->column->setType($type instanceof DBALType ? $type : DBALType::getType($type));
Expand Down Expand Up @@ -93,8 +93,8 @@ public function setDefault(mixed $default): self {
}

#[\Override]
public function getType(): IType {
return new Type($this->column->getType());
public function getType(): ColumnType {
return ColumnType::from(DBALType::lookupName($this->column->getType()));
}

#[\Override]
Expand Down
29 changes: 29 additions & 0 deletions lib/private/DB/Schema/ForeignKeyConstraint.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OC\DB\Schema;

use Doctrine\DBAL\Schema\ForeignKeyConstraint as DBALForeignKeyConstraint;
use OCP\DB\Schema\IForeignKeyConstraint;
use Override;

class ForeignKeyConstraint implements IForeignKeyConstraint {

public function __construct(
private readonly DBALForeignKeyConstraint $keyConstraint,
) {
}

#[Override]
public function getName(): string {
/** @var non-empty-string $value */
$value = $this->keyConstraint->getName();
return $value;
}
}
5 changes: 5 additions & 0 deletions lib/private/DB/Schema/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public function isSimpleIndex(): bool {
return $this->index->isSimpleIndex();
}

#[\Override]
public function hasColumnAtPosition(string $name, int $position = 0): bool {
return $this->index->hasColumnAtPosition($name, $position);
}

/**
* Forwards any method not declared on IIndex to the wrapped Doctrine
* DBAL index, e.g. mutators like `addFlag()` or `removeFlag()` that are
Expand Down
33 changes: 29 additions & 4 deletions lib/private/DB/Schema/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@
namespace OC\DB\Schema;

use Doctrine\DBAL\Schema\Column as DBALColumn;
use Doctrine\DBAL\Schema\ForeignKeyConstraint as DBALForeignKeyConstraint;
use Doctrine\DBAL\Schema\Index as DBALIndex;
use Doctrine\DBAL\Schema\SchemaException as DBALSchemaException;
use Doctrine\DBAL\Schema\Table as DBALTable;
use Doctrine\DBAL\Types\Type as DBALType;
use OCP\DB\Schema\ColumnType;
use OCP\DB\Schema\IColumn;
use OCP\DB\Schema\IForeignKeyConstraint;
use OCP\DB\Schema\IIndex;
use OCP\DB\Schema\ITable;
use OCP\DB\Schema\SchemaException;
Expand All @@ -36,7 +40,9 @@ public function getWrappedTable(): DBALTable {

#[\Override]
public function getName(): string {
return $this->table->getName();
/** @var non-empty-lowercase-string $name */
$name = $this->table->getName();
return $name;
}

#[\Override]
Expand Down Expand Up @@ -134,8 +140,11 @@ public function renameIndex(string $oldName, ?string $newName = null): self {
}

#[\Override]
public function addColumn(string $name, string $typeName, array $options = []): IColumn {
public function addColumn(string $name, string|ColumnType $typeName, array $options = []): IColumn {
try {
if ($typeName instanceof ColumnType) {
$typeName = $typeName->value;
}
return new Column($this->table->addColumn($name, $typeName, $options));
} catch (DBALSchemaException $e) {
throw new SchemaException($e->getMessage(), $e->getCode(), $e);
Expand All @@ -145,6 +154,14 @@ public function addColumn(string $name, string $typeName, array $options = []):
#[\Override]
public function modifyColumn(string $name, array $options): self {
try {
if (isset($options['type'])) {
if ($options['type'] instanceof ColumnType) {
$options['type'] = $options['type']->value;
}
if (is_string($options['type'])) {
$options['type'] = DBALType::getType($options['type']);
}
}
$this->table->modifyColumn($name, $options);
} catch (DBALSchemaException $e) {
throw new SchemaException($e->getMessage(), $e->getCode(), $e);
Expand Down Expand Up @@ -210,8 +227,8 @@ public function __call(string $name, array $arguments): mixed {
}

#[\Override]
public function hasColumn(string $string): bool {
return $this->table->hasColumn($string);
public function hasColumn(string $name): bool {
return $this->table->hasColumn($name);
}

#[\Override]
Expand All @@ -238,4 +255,12 @@ public function getIndexes(): array {
$this->table->getIndexes(),
));
}

#[\Override]
public function getForeignKeys(): array {
return array_values(array_map(
static fn (DBALForeignKeyConstraint $keyConstraint): IForeignKeyConstraint => new ForeignKeyConstraint($keyConstraint),
$this->table->getForeignKeys(),
));
}
}
42 changes: 0 additions & 42 deletions lib/private/DB/Schema/Type.php

This file was deleted.

60 changes: 33 additions & 27 deletions lib/public/AppFramework/Db/Entity.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace OCP\AppFramework\Db;

use OCP\DB\Schema\ColumnType;
use OCP\DB\Types;
use function lcfirst;
use function substr;
Expand All @@ -23,8 +24,8 @@ abstract class Entity {
public $id;
/** @var array<string, true> $_updatedFields */
private array $_updatedFields = [];
/** @var array<string, Types::*> $_fieldTypes */
protected array $_fieldTypes = ['id' => 'integer'];
/** @var array<string, ColumnType> $_fieldTypes */
protected array $_fieldTypes = ['id' => ColumnType::Integer];

/**
* Simple alternative constructor for building entities from a request
Expand Down Expand Up @@ -66,7 +67,7 @@ public static function fromRow(array $row): static {
* @since 7.0.0
*/
public function getFieldTypes(): array {
return $this->_fieldTypes;
return array_map(fn (ColumnType $type) => $type->value, $this->_fieldTypes);
}

/**
Expand Down Expand Up @@ -98,47 +99,47 @@ protected function setter(string $name, array $args): void {
// if type definition exists, cast to correct type
if ($args[0] !== null && array_key_exists($name, $this->_fieldTypes)) {
$type = $this->_fieldTypes[$name];
if ($type === Types::BLOB) {
if ($type === ColumnType::Blob) {
// (B)LOB is treated as string when we read from the DB
if (is_resource($args[0])) {
$args[0] = stream_get_contents($args[0]);
}
$type = Types::STRING;
$type = ColumnType::String;
}

switch ($type) {
case Types::BIGINT:
case Types::SMALLINT:
case ColumnType::Bigint:
case ColumnType::Smallint:
settype($args[0], Types::INTEGER);
break;
case Types::BINARY:
case Types::DECIMAL:
case Types::TEXT:
case ColumnType::Binary:
case ColumnType::Decimal:
case ColumnType::Text:
settype($args[0], Types::STRING);
break;
case Types::TIME:
case Types::DATE:
case Types::DATETIME:
case Types::DATETIME_TZ:
case ColumnType::Time:
case ColumnType::Date:
case ColumnType::Datetime:
case ColumnType::DatetimeTz:
if (!$args[0] instanceof \DateTime) {
$args[0] = new \DateTime($args[0]);
}
break;
case Types::TIME_IMMUTABLE:
case Types::DATE_IMMUTABLE:
case Types::DATETIME_IMMUTABLE:
case Types::DATETIME_TZ_IMMUTABLE:
case ColumnType::TimeImmutable:
case ColumnType::DateImmutable:
case ColumnType::DatetimeImmutable:
case ColumnType::DatetimeTzImmutable:
if (!$args[0] instanceof \DateTimeImmutable) {
$args[0] = new \DateTimeImmutable($args[0]);
}
break;
case Types::JSON:
case ColumnType::Json:
if (!is_array($args[0])) {
$args[0] = json_decode($args[0], true);
}
break;
default:
settype($args[0], $type);
settype($args[0], $type->value);
}
}
$this->$name = $args[0];
Expand Down Expand Up @@ -187,7 +188,7 @@ public function __call(string $methodName, array $args) {
protected function isGetterForBoolProperty(string $methodName): bool {
if (str_starts_with($methodName, 'is')) {
$fieldName = lcfirst(substr($methodName, 2));
return isset($this->_fieldTypes[$fieldName]) && str_starts_with($this->_fieldTypes[$fieldName], 'bool');
return isset($this->_fieldTypes[$fieldName]) && str_starts_with($this->_fieldTypes[$fieldName]->value, 'bool');
}
return false;
}
Expand Down Expand Up @@ -258,23 +259,28 @@ public function getUpdatedFields(): array {
* that value once its being returned from the database
*
* @param string $fieldName the name of the attribute
* @param Types::* $type the type which will be used to match a cast
* @param Types::*|ColumnType $type the type which will be used to match a cast
* @since 31.0.0 Parameter $type is now restricted to {@see Types} constants. The formerly accidentally supported types 'int'|'bool'|'double' are mapped to Types::INTEGER|Types::BOOLEAN|Types::FLOAT accordingly.
* @since 35.0.0 Parameter $type now prefers using one of the {@see ColumnType} enum values.
* @since 7.0.0
*/
protected function addType(string $fieldName, string $type): void {
protected function addType(string $fieldName, string|ColumnType $type): void {
/** @psalm-suppress TypeDoesNotContainType */
if (in_array($type, ['bool', 'double', 'int', 'array', 'object'], true)) {
// Mapping legacy strings to the actual types
$type = match ($type) {
'int' => Types::INTEGER,
'bool' => Types::BOOLEAN,
'double' => Types::FLOAT,
'int' => ColumnType::Integer,
'bool' => ColumnType::Boolean,
'double' => ColumnType::Float,
'array',
'object' => Types::STRING,
'object' => ColumnType::String,
};
}

if (is_string($type)) {
$type = ColumnType::from($type);
}

$this->_fieldTypes[$fieldName] = $type;
}

Expand Down
Loading
Loading