@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('existing_businesses', function (Blueprint $table) {
|
||||
$table->foreignId('sector_id')->nullable()->constrained('sectors')->restrictOnDelete();
|
||||
$table->index('sector_id');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
if (DB::table('existing_businesses')->whereNotNull('sector_id')->exists()) {
|
||||
throw new RuntimeException('Sector associations exist; destructive rollback refused.');
|
||||
}
|
||||
Schema::table('existing_businesses', function (Blueprint $table) {
|
||||
$table->dropForeign(['sector_id']);
|
||||
$table->dropIndex(['sector_id']);
|
||||
$table->dropColumn('sector_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Support\SkillsEducationMigration;
|
||||
|
||||
return new class extends SkillsEducationMigration
|
||||
{
|
||||
protected int $block = 1;
|
||||
|
||||
protected array $tables = ['skill_details', 'occupation_details', 'occupation_skills'];
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Support\SkillsEducationMigration;
|
||||
|
||||
return new class extends SkillsEducationMigration
|
||||
{
|
||||
protected int $block = 2;
|
||||
|
||||
protected array $tables = ['professional_profiles', 'profile_contacts', 'profile_skills', 'profile_experiences', 'profile_languages', 'institutional_candidate_registrations'];
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Support\SkillsEducationMigration;
|
||||
|
||||
return new class extends SkillsEducationMigration
|
||||
{
|
||||
protected int $block = 3;
|
||||
|
||||
protected array $tables = ['profile_qualifications', 'qualification_document_details', 'consent_details', 'institutional_authorisations'];
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Support\SkillsEducationMigration;
|
||||
|
||||
return new class extends SkillsEducationMigration
|
||||
{
|
||||
protected int $block = 4;
|
||||
|
||||
protected array $tables = ['human_resource_need_details', 'human_resource_need_skills', 'human_resource_need_languages', 'human_resource_need_certifications'];
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Support\SkillsEducationMigration;
|
||||
|
||||
return new class extends SkillsEducationMigration
|
||||
{
|
||||
protected int $block = 5;
|
||||
|
||||
protected array $tables = ['program_details', 'education_program_skills', 'skill_gaps', 'educational_opportunity_details', 'educational_opportunity_skills', 'profile_need_matches'];
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Support\SkillsEducationMigration;
|
||||
|
||||
return new class extends SkillsEducationMigration
|
||||
{
|
||||
protected int $block = 6;
|
||||
|
||||
protected array $tables = ['audit_events'];
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
DB::unprepared(<<<'SQL'
|
||||
CREATE FUNCTION public.lock_project_dependency_graph() RETURNS trigger
|
||||
LANGUAGE plpgsql AS $$
|
||||
BEGIN
|
||||
IF current_setting('transaction_isolation') <> 'read committed' THEN
|
||||
RAISE EXCEPTION 'Dependency writes require READ COMMITTED isolation' USING ERRCODE='25000';
|
||||
END IF;
|
||||
PERFORM pg_advisory_xact_lock(hashtextextended('investmoz:project-dependency-graph', 0));
|
||||
RETURN NULL;
|
||||
END $$;
|
||||
CREATE FUNCTION public.check_project_dependency_graph() RETURNS trigger
|
||||
LANGUAGE plpgsql AS $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
WITH RECURSIVE edges AS (
|
||||
SELECT anchor_project_id AS origin, complementary_project_id AS destination
|
||||
FROM public.complementary_project_links
|
||||
WHERE relation_type='dependency' AND deleted_at IS NULL
|
||||
), paths(origin,destination) AS (
|
||||
SELECT origin,destination FROM edges
|
||||
UNION
|
||||
SELECT p.origin,e.destination FROM paths p JOIN edges e ON e.origin=p.destination
|
||||
) SELECT 1 FROM paths WHERE origin=destination
|
||||
) THEN
|
||||
RAISE EXCEPTION 'Project dependency cycle is not permitted' USING ERRCODE='23514';
|
||||
END IF;
|
||||
RETURN NULL;
|
||||
END $$;
|
||||
CREATE TRIGGER project_dependency_lock BEFORE INSERT OR UPDATE ON public.complementary_project_links
|
||||
FOR EACH STATEMENT EXECUTE FUNCTION public.lock_project_dependency_graph();
|
||||
CREATE TRIGGER project_dependency_check AFTER INSERT OR UPDATE ON public.complementary_project_links
|
||||
FOR EACH STATEMENT EXECUTE FUNCTION public.check_project_dependency_graph();
|
||||
-- Validate the complete existing graph, without modifying a row.
|
||||
UPDATE public.complementary_project_links SET relation_type=relation_type WHERE false;
|
||||
SQL);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
DB::unprepared(<<<'SQL'
|
||||
DROP TRIGGER project_dependency_check ON public.complementary_project_links;
|
||||
DROP TRIGGER project_dependency_lock ON public.complementary_project_links;
|
||||
DROP FUNCTION public.check_project_dependency_graph() RESTRICT;
|
||||
DROP FUNCTION public.lock_project_dependency_graph() RESTRICT;
|
||||
SQL);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user