Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  specify next release
  CS
  Revert "remove ability to use joins when updating or deleting as it is not supported by sqlite"
  fix support of aliased table when deleting
  remove sqlite support
  fix tests
  fix applying a moreThanOrEqual or lessThanOrEqual when the columns are different
  • Loading branch information
Baptouuuu committed Jul 14, 2024
2 parents e71b05f + 317dedf commit 0283177
Show file tree
Hide file tree
Showing 15 changed files with 365 additions and 78 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/composer.lock
/vendor
/.cache
/tmp
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 4.0.0 - 2024-07-14

### Added

- `Formal\AccessLayer\Query\Delete::join()`

### Removed

- `Formal\AccessLayer\Driver::sqlite`

### Fixed

- Support for aliased table names when using `Formal\AccessLayer\Query\Delete`

## 3.0.0 - 2024-07-14

### Added
Expand Down
8 changes: 0 additions & 8 deletions documentation/connections/pdo.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@ To build an instance of it you only need the dsn to your database:
);
```

=== "SQLite"
```php
use Formal\AccessLayer\Connection\PDO;
use Innmind\Url\Url;

$connection = PDO::of(Url::of('sqlite:///path/to/database/file.sq3'));
```

When executing a [query](../queries/sql.md) through this connection it will return a [deferred `Sequence`](http://innmind.github.io/Immutable/structures/sequence/#defer) of rows. This means that the rows returned from the database are only loaded once you iterate over the sequence. (Queries with the named constructor `::onDemand()` will return a lazy `Sequence`).

!!! note ""
Expand Down
100 changes: 74 additions & 26 deletions proofs/connection/pdo.php
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,6 @@ static function($assert) use ($driver) {
$assert->same(
match ($driver) {
Driver::mysql => 'CONSTRAINT `FK_foo` FOREIGN KEY (`parent`) REFERENCES `parent_table`(`id`)',
Driver::sqlite => 'CONSTRAINT "FK_foo" FOREIGN KEY ("parent") REFERENCES "parent_table"("id")',
Driver::postgres => 'CONSTRAINT "FK_foo" FOREIGN KEY ("parent") REFERENCES "parent_table"("id")',
},
ForeignKey::of(Column\Name::of('parent'), $parent, Column\Name::of('id'))
Expand All @@ -405,6 +404,79 @@ static function($assert) use ($driver) {
},
);

yield test(
"Delete join({$driver->name})",
static function($assert) use ($connection) {
$parent = Table\Name::of('test_join_delete_parent')->as('parent');
$child = Table\Name::of('test_join_delete_child')->as('child');
$connection(CreateTable::ifNotExists(
$child->name(),
Column::of(
Column\Name::of('id'),
Column\Type::int(),
),
)->primaryKey(Column\Name::of('id')));
$connection(
CreateTable::ifNotExists(
$parent->name(),
Column::of(
Column\Name::of('id'),
Column\Type::int(),
),
Column::of(
Column\Name::of('child'),
Column\Type::int(),
),
)
->primaryKey(Column\Name::of('id'))
->foreignKey(
Column\Name::of('child'),
$child->name(),
Column\Name::of('id'),
),
);
$connection(Delete::from($parent->name()));
$connection(Delete::from($child->name()));
$connection(Insert::into(
$child->name(),
Row::of([
'id' => 2,
]),
));
$connection(Insert::into(
$parent->name(),
Row::of([
'id' => 1,
'child' => 2,
]),
));

$connection(
Delete::from($parent)
->join(
Join::left($child)->on(
Column\Name::of('child')->in($parent),
Column\Name::of('id')->in($child),
),
)
->where(Comparator\Property::of(
'child.id',
Sign::equality,
2,
)),
);

$rows = $connection(Select::from($child));
$assert->count(1, $rows);

$rows = $connection(Select::from($parent));
$assert->count(0, $rows);

$connection(DropTable::named($parent->name()));
$connection(DropTable::named($child->name()));
},
);

yield proof(
"Unique constraint({$driver->name})",
given(Set\Integers::between(0, 1_000_000)),
Expand Down Expand Up @@ -449,30 +521,13 @@ static function($assert, $int) use ($connection) {
},
);

$filter = match ($driver) {
Driver::sqlite => static fn($ensure) => \count(
\array_filter(
$ensure->properties(),
static fn($property) => $property instanceof Properties\MustThrowWhenValueDoesntFitTheSchema,
)
) === 0,
default => static fn() => true,
};

yield properties(
"PDO properties({$driver->name})",
Properties::any()->filter($filter),
Properties::any(),
$connections,
);

foreach (Properties::list() as $property) {
if (
$driver === Driver::sqlite &&
$property === Properties\MustThrowWhenValueDoesntFitTheSchema::class
) {
continue;
}

yield property(
$property,
$connections,
Expand All @@ -488,13 +543,6 @@ static function($assert, $int) use ($connection) {
Driver::mysql,
);

$tmp = \getcwd().'/tmp';

yield from $proofs(
Url::of("sqlite:$tmp/formal.sq3"),
Driver::sqlite,
);

$port = \getenv('POSTGRES_DB_PORT') ?: '5432';

yield from $proofs(
Expand Down
72 changes: 72 additions & 0 deletions proofs/query/where.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,42 @@ static function($assert, $column, $value) {
},
);

yield proof(
'Where less than or equal comparator on different columns',
given(
Column::any(),
Column::any(),
Set\Strings::any(),
),
static function($assert, $column1, $column2, $value) {
$lessThan = Property::of(
$column1->name()->toString(),
Sign::lessThan,
$value,
);
$equal = Property::of(
$column2->name()->toString(),
Sign::equality,
$value,
);
$where = Where::of($lessThan->or($equal));

$assert->same(
"WHERE ({$column1->name()->sql(Driver::mysql)} < ? OR {$column2->name()->sql(Driver::mysql)} = ?)",
$where->sql(Driver::mysql),
);
$assert->count(2, $where->parameters());
$assert->same($value, $where->parameters()->first()->match(
static fn($parameter) => $parameter->value(),
static fn() => null,
));
$assert->same($value, $where->parameters()->last()->match(
static fn($parameter) => $parameter->value(),
static fn() => null,
));
},
);

yield proof(
'Where more than comparator',
given(
Expand Down Expand Up @@ -169,6 +205,42 @@ static function($assert, $column, $value) {
},
);

yield proof(
'Where more than or equal comparator on different columns',
given(
Column::any(),
Column::any(),
Set\Strings::any(),
),
static function($assert, $column1, $column2, $value) {
$moreThan = Property::of(
$column1->name()->toString(),
Sign::moreThan,
$value,
);
$equal = Property::of(
$column2->name()->toString(),
Sign::equality,
$value,
);
$where = Where::of($moreThan->or($equal));

$assert->same(
"WHERE ({$column1->name()->sql(Driver::mysql)} > ? OR {$column2->name()->sql(Driver::mysql)} = ?)",
$where->sql(Driver::mysql),
);
$assert->count(2, $where->parameters());
$assert->same($value, $where->parameters()->first()->match(
static fn($parameter) => $parameter->value(),
static fn() => null,
));
$assert->same($value, $where->parameters()->last()->match(
static fn($parameter) => $parameter->value(),
static fn() => null,
));
},
);

yield proof(
'Where is null comparator',
given(Column::any()),
Expand Down
1 change: 1 addition & 0 deletions properties/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public static function list(): array
Connection\Update::class,
Connection\UpdateSpecificRow::class,
Connection\Delete::class,
Connection\DeleteWithAlias::class,
Connection\DeleteSpecificRow::class,
];
}
Expand Down
4 changes: 2 additions & 2 deletions properties/Connection/DeleteSpecificRow.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ public function ensureHeldBy(Assert $assert, object $connection): object
]),
)));

$delete = Query\Delete::from(Table\Name::of('test'))->where(
$delete = Query\Delete::from(Table\Name::of('test')->as('alias'))->where(
Comparator\Property::of(
'id',
'alias.id',
Sign::equality,
$this->uuid1,
),
Expand Down
65 changes: 65 additions & 0 deletions properties/Connection/DeleteWithAlias.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
declare(strict_types = 1);

namespace Properties\Formal\AccessLayer\Connection;

use Formal\AccessLayer\{
Query\SQL,
Query,
Table,
Row,
Connection,
};
use Innmind\BlackBox\{
Property,
Set,
Runner\Assert,
};

/**
* @implements Property<Connection>
*/
final class DeleteWithAlias implements Property
{
private string $uuid;

public function __construct(string $uuid)
{
$this->uuid = $uuid;
}

public static function any(): Set
{
return Set\Uuid::any()->map(static fn($uuid) => new self($uuid));
}

public function applicableTo(object $connection): bool
{
return true;
}

public function ensureHeldBy(Assert $assert, object $connection): object
{
$select = SQL::of('SELECT * FROM test');
$connection(Query\Insert::into(
Table\Name::of('test'),
Row::of([
'id' => $this->uuid,
'username' => 'foo',
'registerNumber' => 42,
]),
));

$sequence = $connection(Query\Delete::from(
Table\Name::of('test')->as('alias'),
));

$assert->count(0, $sequence);

$rows = $connection($select);

$assert->count(0, $rows);

return $connection;
}
}
27 changes: 8 additions & 19 deletions src/Connection/PDO.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ private function __construct(Url $dsn, array $options = [])
}

$this->driver = match ($dsn->scheme()->toString()) {
'sqlite' => Driver::sqlite,
'mysql' => Driver::mysql,
'pgsql' => Driver::postgres,
};
Expand All @@ -59,26 +58,16 @@ private function __construct(Url $dsn, array $options = [])
}
}

$pdoDsn = match ($this->driver) {
Driver::sqlite => \sprintf(
'sqlite:%s',
$dsn->path()->toString(),
),
default => \sprintf(
'%s:host=%s;port=%s;dbname=%s%s',
$dsn->scheme()->toString(),
$dsn->authority()->host()->toString(),
$dsn->authority()->port()->toString(),
\substr($dsn->path()->toString(), 1), // substring to remove leading '/'
$charset,
),
};
$pdoDsn = \sprintf(
'%s:host=%s;port=%s;dbname=%s%s',
$dsn->scheme()->toString(),
$dsn->authority()->host()->toString(),
$dsn->authority()->port()->toString(),
\substr($dsn->path()->toString(), 1), // substring to remove leading '/'
$charset,
);

$this->pdo = new \PDO($pdoDsn, $user, $password, $options);

if ($this->driver === Driver::sqlite) {
$this->pdo->query('PRAGMA foreign_keys = ON');
}
}

public function __invoke(Query $query): Sequence
Expand Down
Loading

0 comments on commit 0283177

Please sign in to comment.