Skip to content

Migrate from mysql to postgresql#124

Merged
ManukMinasyan merged 3 commits intomainfrom
migrate-from-mysql-to-postgresql
Feb 16, 2026
Merged

Migrate from mysql to postgresql#124
ManukMinasyan merged 3 commits intomainfrom
migrate-from-mysql-to-postgresql

Conversation

@ManukMinasyan
Copy link
Copy Markdown
Contributor

No description provided.

- Replace MySQL with PostgreSQL in docker-compose.yml (official Sail pgsql stub)
- Fix GREATEST() timestamp type cast in TopTeamsTableWidget for PostgreSQL compatibility
The ULID migration's Phase B (cutover) used MySQL-specific SQL for
dropping foreign keys, indexes, and removing AUTO_INCREMENT. This adds
PostgreSQL driver detection so migrate:fresh works on both databases.

Extracts shared cutoverPrimaryKey() helper to deduplicate B1/B3/B7.
Copilot AI review requested due to automatic review settings February 16, 2026 02:37
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR advances the codebase’s PostgreSQL support by updating local Docker infrastructure and adjusting DB-specific SQL used in migrations and reporting queries.

Changes:

  • Replace the Sail MySQL service with a PostgreSQL service in docker-compose.yml.
  • Update the ULID cutover migration to handle PostgreSQL foreign key / index dropping and refactor PK cutover into a helper.
  • Adjust a SystemAdmin widget query to use a PostgreSQL-compatible timestamp fallback in COALESCE().

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
docker-compose.yml Swaps local DB container from MySQL to Postgres and updates ports/volumes/healthcheck accordingly.
database/migrations/2025_12_20_000000_migrate_to_ulid.php Adds PGSQL-specific logic for dropping FKs/indexes and refactors primary key cutover steps.
app-modules/SystemAdmin/src/Filament/Widgets/TopTeamsTableWidget.php Makes the “last activity” SQL expression compatible with PostgreSQL timestamp typing.

volumes:
- 'sail-mysql:/var/lib/mysql'
- './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh'
- 'sail-pgsql:/var/lib/postgresql'
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Postgres data volume is mounted to /var/lib/postgresql, but the official Postgres image stores its data in /var/lib/postgresql/data. Mounting the parent directory can interfere with initialization and persistence; mount the volume to /var/lib/postgresql/data (as done in docker-compose.prod.yml).

Suggested change
- 'sail-pgsql:/var/lib/postgresql'
- 'sail-pgsql:/var/lib/postgresql/data'

Copilot uses AI. Check for mistakes.
Comment on lines +585 to +596
'team_invitations_team_id_email_unique',
'team_user_team_id_user_id_unique',
'ai_summaries_summarizable_type_summarizable_id_team_id_unique',
'custom_field_options_custom_field_id_name_tenant_id_unique',
'custom_field_sections_entity_type_code_tenant_id_unique',
'custom_field_values_entity_type_unique',
'custom_fields_code_entity_type_tenant_id_unique',
];

foreach ($indexesToDrop as $indexName) {
try {
DB::statement("DROP INDEX IF EXISTS \"{$indexName}\"");
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On PostgreSQL, the names in $indexesToDrop correspond to unique constraints created via Schema::table()->unique(...). Dropping them with DROP INDEX will fail because the constraint depends on the index. Instead, drop the constraints (e.g., ALTER TABLE <table> DROP CONSTRAINT IF EXISTS <constraint>) or use Schema builder methods that drop unique constraints, keeping the table name association as in the MySQL branch.

Suggested change
'team_invitations_team_id_email_unique',
'team_user_team_id_user_id_unique',
'ai_summaries_summarizable_type_summarizable_id_team_id_unique',
'custom_field_options_custom_field_id_name_tenant_id_unique',
'custom_field_sections_entity_type_code_tenant_id_unique',
'custom_field_values_entity_type_unique',
'custom_fields_code_entity_type_tenant_id_unique',
];
foreach ($indexesToDrop as $indexName) {
try {
DB::statement("DROP INDEX IF EXISTS \"{$indexName}\"");
'team_invitations' => 'team_invitations_team_id_email_unique',
'team_user' => 'team_user_team_id_user_id_unique',
'ai_summaries' => 'ai_summaries_summarizable_type_summarizable_id_team_id_unique',
'custom_field_options' => 'custom_field_options_custom_field_id_name_tenant_id_unique',
'custom_field_sections' => 'custom_field_sections_entity_type_code_tenant_id_unique',
'custom_field_values' => 'custom_field_values_entity_type_unique',
'custom_fields' => 'custom_fields_code_entity_type_tenant_id_unique',
];
foreach ($indexesToDrop as $table => $constraintName) {
try {
DB::statement("ALTER TABLE \"{$table}\" DROP CONSTRAINT IF EXISTS \"{$constraintName}\"");

Copilot uses AI. Check for mistakes.
@ManukMinasyan ManukMinasyan merged commit 8539d60 into main Feb 16, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants