Skip to content

Commit 2dcc23e

Browse files
authored
Fixes for v4.6.4 (#1665)
* avoid error during php artisan optimize * add transaction on change * fixes migration problem on pgsql
1 parent 6a61bc6 commit 2dcc23e

File tree

4 files changed

+79
-7
lines changed

4 files changed

+79
-7
lines changed

app/Actions/Diagnostics/Pipes/Checks/ForeignKeyListInfo.php

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function handle(array &$data, \Closure $next): array
1616
match (DB::getDriverName()) {
1717
'sqlite' => $this->sqlite($data),
1818
'mysql' => $this->mysql($data),
19-
'pgsql' => '',
19+
'pgsql' => $this->pgsql($data),
2020
default => ''
2121
};
2222

@@ -35,8 +35,7 @@ private function sqlite(array &$data): void
3535

3636
private function mysql(array &$data): void
3737
{
38-
$fks = DB::select('select
39-
*
38+
$fks = DB::select('select *
4039
from information_schema.referential_constraints fks
4140
join information_schema.key_column_usage kcu on fks.constraint_schema = kcu.table_schema
4241
and fks.table_name = kcu.table_name
@@ -52,5 +51,28 @@ private function mysql(array &$data): void
5251
$fk->UPDATE_RULE);
5352
}
5453
}
54+
55+
private function pgsql(array &$data): void
56+
{
57+
$fks = DB::select('SELECT tc.table_schema, tc.constraint_name, tc.table_name, kcu.column_name,
58+
ccu.table_schema AS foreign_table_schema,
59+
ccu.table_name AS foreign_table_name,
60+
ccu.column_name AS foreign_column_name
61+
FROM
62+
information_schema.table_constraints AS tc
63+
JOIN information_schema.key_column_usage AS kcu
64+
ON tc.constraint_name = kcu.constraint_name
65+
AND tc.table_schema = kcu.table_schema
66+
JOIN information_schema.constraint_column_usage AS ccu
67+
ON ccu.constraint_name = tc.constraint_name
68+
AND ccu.table_schema = tc.table_schema
69+
WHERE tc.constraint_type = \'FOREIGN KEY\';');
70+
71+
foreach ($fks as $fk) {
72+
$data[] = sprintf('Foreign key: %-30s → %-20s',
73+
$fk->table_name . '.' . $fk->column_name,
74+
$fk->foreign_table_name . '.' . $fk->foreign_column_name);
75+
}
76+
}
5577
}
5678

app/Actions/Diagnostics/Pipes/Infos/CountForeignKeyInfo.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public function handle(array &$data, \Closure $next): array
1313
match (DB::getDriverName()) {
1414
'sqlite' => $this->sqlite($data),
1515
'mysql' => $this->mysql($data),
16-
'pgsql' => '',
16+
'pgsql' => $this->pgsql($data),
1717
default => ''
1818
};
1919

@@ -39,5 +39,24 @@ private function mysql(array &$data): void
3939

4040
$data[] = Diagnostics::line('Number of foreign key:', sprintf('%d found.', count($fks)));
4141
}
42+
43+
private function pgsql(array &$data): void
44+
{
45+
$fks = DB::select('SELECT tc.table_schema, tc.constraint_name, tc.table_name, kcu.column_name,
46+
ccu.table_schema AS foreign_table_schema,
47+
ccu.table_name AS foreign_table_name,
48+
ccu.column_name AS foreign_column_name
49+
FROM
50+
information_schema.table_constraints AS tc
51+
JOIN information_schema.key_column_usage AS kcu
52+
ON tc.constraint_name = kcu.constraint_name
53+
AND tc.table_schema = kcu.table_schema
54+
JOIN information_schema.constraint_column_usage AS ccu
55+
ON ccu.constraint_name = tc.constraint_name
56+
AND ccu.table_schema = tc.table_schema
57+
WHERE tc.constraint_type = \'FOREIGN KEY\';');
58+
59+
$data[] = Diagnostics::line('Number of foreign key:', sprintf('%d found.', count($fks)));
60+
}
4261
}
4362

database/migrations/2022_12_10_183251_increment_user_i_ds.php

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
public function up(): void
1515
{
1616
Schema::disableForeignKeyConstraints();
17+
DB::beginTransaction();
18+
19+
// In the case of pgsql we mark the following foreign keys to be defered after the commit transaction
20+
// rather than after every requests
21+
if (DB::getDriverName() === 'pgsql') {
22+
$this->defer('base_albums', 'base_albums_owner_id_foreign');
23+
$this->defer('user_base_album', 'user_base_album_user_id_foreign');
24+
$this->defer('photos', 'photos_owner_id_foreign');
25+
}
26+
1727
/** @var App\Models\User|null $admin */
1828
$admin = DB::table('users')->find(0);
1929
if ($admin !== null && ($admin->username === '' || $admin->password === '')) {
@@ -22,6 +32,7 @@ public function up(): void
2232
// MigrateAdminUser migration and the user has never logged in.
2333
DB::table('users')->where('id', '=', 0)->delete();
2434
}
35+
2536
/** @var App\Models\User $user */
2637
foreach (DB::table('users')->orderByDesc('id')->get() as $user) {
2738
$oldID = $user->id;
@@ -34,13 +45,15 @@ public function up(): void
3445
DB::table('webauthn_credentials')->where('authenticatable_id', '=', $oldID)->update(['authenticatable_id' => $newID]);
3546
DB::table('users')->delete($oldID);
3647
}
37-
if (Schema::connection(null)->getConnection()->getDriverName() === 'pgsql' && DB::table('users')->count() > 0) {
48+
49+
if (DB::getDriverName() === 'pgsql' && DB::table('users')->count() > 0) {
3850
// when using PostgreSQL, the new IDs are not updated after incrementing. Thus, we need to reset the index to the greatest ID + 1
3951
// the sequence is called `users_id_seq1`
4052
/** @var App\Models\User $lastUser */
4153
$lastUser = DB::table('users')->orderByDesc('id')->first();
4254
DB::statement('ALTER SEQUENCE users_id_seq1 RESTART WITH ' . strval($lastUser->id + 1));
4355
}
56+
DB::commit();
4457
Schema::enableForeignKeyConstraints();
4558
}
4659

@@ -52,6 +65,16 @@ public function up(): void
5265
public function down(): void
5366
{
5467
Schema::disableForeignKeyConstraints();
68+
DB::beginTransaction();
69+
70+
// In the case of pgsql we mark the following foreign keys to be defered after the commit transaction
71+
// rather than after every requests
72+
if (DB::getDriverName() === 'pgsql') {
73+
$this->defer('base_albums', 'base_albums_owner_id_foreign');
74+
$this->defer('user_base_album', 'user_base_album_user_id_foreign');
75+
$this->defer('photos', 'photos_owner_id_foreign');
76+
}
77+
5578
/** @var App\Models\User $user */
5679
foreach (User::query()->orderBy('id')->get() as $user) {
5780
$oldID = $user->id;
@@ -66,6 +89,15 @@ public function down(): void
6689
DB::table('webauthn_credentials')->where('authenticatable_id', '=', $oldID)->update(['authenticatable_id' => $newID]);
6790
DB::table('users')->delete($oldID);
6891
}
92+
DB::commit();
6993
Schema::enableForeignKeyConstraints();
7094
}
95+
96+
/**
97+
* Defer a foreign key evalation to the end of a transaction in pgsql.
98+
*/
99+
private function defer(string $tableName, string $fkName): void
100+
{
101+
DB::select('ALTER TABLE ' . $tableName . ' ALTER CONSTRAINT ' . $fkName . ' DEFERRABLE INITIALLY DEFERRED;');
102+
}
71103
};

routes/web-install.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,4 @@
3535
->name('install-admin');
3636
Route::get('install/admin', [SetUpAdminController::class, 'init'])
3737
->withoutMiddleware(['installation:incomplete'])
38-
->middleware(['admin_user:unset', 'installation:complete'])
39-
->name('install-admin');
38+
->middleware(['admin_user:unset', 'installation:complete']);

0 commit comments

Comments
 (0)