Skip to content

Fixes #28255: Pin MySQL charset and migrate Flowable tables - #33659

Open
harshach wants to merge 4 commits into
mainfrom
belo-horizonte
Open

harshach wants to merge 4 commits into
mainfrom
belo-horizonte

Conversation

@harshach

@harshach harshach commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator

Describe your changes:

Fixes #28255

Pins the OpenMetadata MySQL database default to utf8mb4 for fresh installs and upgrades. The upgrade also aligns all Flowable ACT_* tables as one foreign-key-connected set while preserving the session's FOREIGN_KEY_CHECKS, preventing legacy utf8mb3 schemas from failing during restore.

Type of change:

  • Bug fix

High-level design:

  • Set utf8mb4_unicode_ci explicitly in the MySQL bootstrap scripts and current native migration.
  • Run a MySQL-only data migration that detects charset or collation drift and converts every Flowable table to its canonical utf8mb4_0900_ai_ci collation.
  • Preserve and restore the original session foreign-key setting, leave non-Flowable tables untouched, and make aligned schemas a no-op on replay.
  • Convert the complete ACT_* family because changing only one side of a string foreign key is rejected by MySQL.

Tests:

Use cases covered

  • Fresh MySQL databases receive an explicit utf8mb4 default.
  • Existing utf8mb3 Flowable tables with foreign keys migrate successfully without weakening the constraints.
  • Replays are no-ops, partial collation drift is repaired, and non-Flowable tables remain unchanged.

Unit tests

  • I added unit tests for the new/changed logic.
  • Files added: FlowableCharsetMigrationTest.java, FlowableCharsetMigrationMySqlTest.java
  • Coverage: targeted suite passed all 9 tests; coverage was not measured separately.

Backend integration tests

  • Not applicable (no backend API changes).
  • MySQL behavior is covered by the Testcontainers regression test above.

Ingestion integration tests

  • Not applicable (no ingestion changes).

Playwright (UI) tests

  • Not applicable (no UI changes).

Manual testing performed

  1. Ran mvn -pl openmetadata-service -Dtest=IngestionPipelineMigrationEntryPointTest,FlowableCharsetMigrationTest,FlowableCharsetMigrationMySqlTest test against MySQL 8; all 9 tests passed.
  2. Ran mvn -pl openmetadata-service spotless:check, git diff --check, and make harness-check successfully.

UI screen recording / screenshots:

Not applicable.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • My PR is linked to a GitHub issue via Fixes #<issue-number> above.
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.
  • For UI changes: I attached a screen recording and/or screenshots above.
  • I have added tests (unit / integration / Playwright as applicable) and listed them above.
  • I have added a test that covers the exact scenario we are fixing.

Open workspace in Conductor

RetriggerConfidence Score: 4/5

The PR is not yet safe to merge because it still modifies an already-applied migration, so existing installations that recorded v210 will not execute the new database-default or Flowable alignment work.

Findings

  1. P1 Applied migration modified
  2. P2 Tests Assert Mock Wiring
  3. P2 Prefix matches unrelated tables
Summary

This PR pins new MySQL databases to utf8mb4_unicode_ci and adds a migration utility that converts the foreign-key-connected Flowable table family while preserving the session’s foreign-key-check setting.

  • Updates Docker MySQL bootstrap defaults.
  • Adds Flowable charset detection and conversion during the v210 data migration.
  • Adds mocked and Testcontainers-based coverage for legacy schemas, replay, drift repair, foreign keys, and session restoration.
  • The previously reported modification of an already-applied migration remains outstanding.
  • The previously reported broad ACT_ prefix selection remains outstanding.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Run v210 schema migration] --> B[Set database default to utf8mb4_unicode_ci]
  B --> C[Run v210 data migration]
  C --> D{Any ACT_* table drift?}
  D -- No --> E[No-op]
  D -- Yes --> F[Read session FOREIGN_KEY_CHECKS]
  F --> G[Disable foreign-key checks]
  G --> H[Convert selected ACT_* tables]
  H --> I[Restore original session setting]
Loading

Reviews (4) · Last reviewed commit: "Align Flowable tables with database coll..."

@harshach
harshach requested review from a team, akash-jain-10 and tutte as code owners September 20, 2026 07:19
@github-actions

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically.

Maintainers can bypass this check by adding the skip-pr-checks label.

@github-actions github-actions Bot added backend safe to test Add this label to run secure Github workflows on PRs labels Sep 20, 2026
Comment on lines +373 to +375
-- Keep future tables independent of the MySQL server default. Existing legacy Flowable tables are
-- converted by FlowableCharsetMigration while their foreign-key checks are safely suspended.
ALTER DATABASE CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Applied migration modified

This appends the database-default change to the already-applied 2.1.0 migration, violating the repository requirement that migrations are append-only and new work must use a new version. Deployments that already recorded 2.1.0 in SERVER_CHANGE_LOG will not execute this statement, leaving the legacy database default unchanged. The new v210 data-migration hook in openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v210/Migration.java:42 has the same versioning problem and should move with it.

Context Used: CLAUDE.md (source)

AND LEFT(UPPER(flowable_table.TABLE_NAME), 4) = 'ACT_'
AND EXISTS (
SELECT 1
FROM information_schema.TABLES AS candidate_table

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Prefix matches unrelated tables

The name-prefix test treats every base table beginning with ACT_ as a Flowable table. If the OpenMetadata database contains a customer or extension table such as ACT_AUDIT, drift in any matching table causes it to be forcibly converted to utf8mb4_0900_ai_ci, even though non-Flowable tables are intended to remain untouched. Use the canonical Flowable table set or otherwise verify ownership instead of relying only on the prefix.

Comment thread bootstrap/sql/migrations/native/2.1.0/mysql/schemaChanges.sql
@gitar-bot

gitar-bot Bot commented Sep 21, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 1 closed / 1 findings

🔴 High risk

Pins MySQL charset to utf8mb4 for fresh installs and upgrades, and migrates all Flowable ACT_* tables to aligned utf8mb4_0900_ai_ci collation while preserving foreign-key constraints. Addresses the DB default collation divergence from Flowable table collation. Comprehensive unit tests added and manual verification completed.

✅ 1 closed
Quality: DB default collation diverges from Flowable table collation

📄 bootstrap/sql/migrations/native/2.1.0/mysql/schemaChanges.sql:375 📄 openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v210/FlowableCharsetMigration.java:24 📄 openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v210/FlowableCharsetMigration.java:52 📄 docker/mysql/mysql-script.sql:1
This PR pins the openmetadata_db default to utf8mb4_unicode_ci (bootstrap scripts and the ALTER DATABASE in schemaChanges.sql) but the migration forces every ACT_* table to utf8mb4_0900_ai_ci. Because the two collations differ, any ACT_* table Flowable creates later (e.g. during a Flowable engine schema upgrade) inherits the database default utf8mb4_unicode_ci and diverges from the already-converted 0900_ai_ci tables; the one-shot data migration will not re-run to repair it, so a new string foreign key between an old and new ACT_* table could be rejected by MySQL — the exact failure mode this PR set out to fix. Consider converting Flowable tables to utf8mb4_unicode_ci to match the pinned database default, or documenting why 0900_ai_ci is deliberately chosen for the ACT_* family despite the divergent database default.

Review coverage

Rules No rules evaluated

Functional validation Not enabled · Set up

Auto-approval Not enabled · Set up

Options

Display: compact → Counting what did not apply, without listing it.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

Comment on lines +68 to +112

final int converted = FlowableCharsetMigration.alignFlowableTableCharsets(handle);

assertEquals(2, converted);
final InOrder statements = inOrder(handle);
statements.verify(handle).execute("SET SESSION FOREIGN_KEY_CHECKS = 0");
statements.verify(handle).execute(conversionStatement("ACT_GE_BYTEARRAY"));
statements.verify(handle).execute(conversionStatement("ACT_RE_DEPLOYMENT"));
statements.verify(handle).execute("SET SESSION FOREIGN_KEY_CHECKS = 1");
}

@Test
void restoresTheOriginalForeignKeySettingWhenConversionFails() {
final Handle handle = handleWithTables(List.of("ACT_GE_BYTEARRAY"), 1);
when(handle.execute(conversionStatement("ACT_GE_BYTEARRAY")))
.thenThrow(new IllegalStateException("conversion failed"));

assertThrows(
IllegalStateException.class,
() -> FlowableCharsetMigration.alignFlowableTableCharsets(handle));

verify(handle).execute("SET SESSION FOREIGN_KEY_CHECKS = 1");
}

@Test
void preservesAnAlreadyDisabledForeignKeySetting() {
final Handle handle = handleWithTables(List.of("ACT_GE_BYTEARRAY"), 0);

FlowableCharsetMigration.alignFlowableTableCharsets(handle);

verify(handle, times(2)).execute("SET SESSION FOREIGN_KEY_CHECKS = 0");
}

@Test
void skipsSessionChangesWhenEveryFlowableTableIsAlreadyUtf8mb4() {
final Handle handle = handleWithTables(List.of(), 1);

assertEquals(0, FlowableCharsetMigration.alignFlowableTableCharsets(handle));

verify(handle, never()).execute(anyString());
}

private static Handle handleWithTables(
final List<String> tableNames, final int foreignKeyChecks) {
final Handle handle = mock(Handle.class, RETURNS_DEEP_STUBS);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Tests Assert Mock Wiring

These tests assert Mockito interaction order, exact SQL calls, and invocation counts instead of observable database outcomes. This violates the repository directive to test real behavior and avoid internal verify() assertions. The requirement must be satisfied before merging because these checks can pass even when the migration leaves the schema, constraints, or session setting in the wrong state.

Context Used: CLAUDE.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MySQL: openmetadata_db should be created with explicit utf8mb4 charset to prevent FK incompatibility on upgraded instances

1 participant