Repository navigation
Backport #37184 to 2.0: align entity_extension.extension with its table's collation on MySQL - #37186
Conversation
❌ PR checklist incompleteThis 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 |
| * Puts {@code entity_extension.extension} back on its table's default character set and collation | ||
| * on MySQL. Until #37167, the 2.0.3 migration switched the column to {@code ascii_bin}, so databases | ||
| * upgraded through 2.0.3 to 2.0.7 differ from the rest of the table and from databases that never | ||
| * ran that statement. The target is the table's own default: OpenMetadata never set a collation, so | ||
| * each table carries the server default of the day it was created. | ||
| * |
There was a problem hiding this comment.
⚠️ Bug: 2.0 branch still runs the 2.0.3 ascii_bin ALTER, so the table is copied twice
The class Javadoc says the ascii_bin conversion happened "until #37167", but on this 2.0 branch bootstrap/sql/migrations/native/2.0.3/mysql/schemaChanges.sql:15-16 still runs MODIFY COLUMN extension VARCHAR(512) CHARACTER SET ascii COLLATE ascii_bin NOT NULL. So every fresh install, and every upgrade that starts below 2.0.3, first converts the column to ascii_bin (a full table copy that blocks writes), and then the new 2.0.8 step converts it back (a second full copy, after a GROUP BY scan for collisions). On large entity_extension tables this doubles the hours of write-blocking downtime that this PR is trying to keep down. Backport #37167 together with this PR, so the 2.0.3 statement keeps the table default (VARCHAR(512) NOT NULL with no charset). That way the 2.0.8 step only runs on databases that really went through the old 2.0.3.
Backport #37167's 2.0.3 change to the 2.0 branch (bootstrap/sql/migrations/native/2.0.3/mysql/schemaChanges.sql):
ALTER TABLE entity_extension
MODIFY COLUMN extension VARCHAR(512) NOT NULL;
Was this helpful? React with 👍 / 👎
| * <p>2.1.0 runs it again, because a database that recorded 2.0.8 before this step existed reruns | ||
| * 2.0.8 for its SQL only. |
There was a problem hiding this comment.
💡 Quality: Javadoc says 2.1.0 reruns the step, but 2.0 has no 2.1.0 migration
The Javadoc says that 2.1.0 runs the step again for databases that recorded 2.0.8 before this step existed. The PR description says 2.0 has no 2.1.0 migration, so on this branch nothing reruns the step. That comment is copied from main and is wrong here. It also hides the fact that a 2.0.x database that already applied 2.0.8 will not be aligned by this branch. Remove or reword that paragraph for the 2.0 backport.
Was this helpful? React with 👍 / 👎
Code Review
|
| Compact |
|
Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source
…37162) * fix(sql): bind names in the prefix-rename statements The FQN prefix renames, the tag-usage prefix rewrites and the thread-link rename bind every value; only the table name stays a template attribute. A guard test fails on any DAO statement that is a bare template attribute. Tag lists count usage with the bound per-tag query. ListFilter.escapeForMySqlRegexReplacement stays, deprecated, for extensions. * fix(auth): resolve our own tokens to the account they name A token verified against OpenMetadata's own signing key, on a request or a WebSocket connection, resolves to the user name it was minted for instead of the configured principal claims, whose email local part can belong to another account. SecurityUtil.getUserName uses the principal name whole. * fix(sessions): logout retires the request's token; password changes end sign-ins Logout denylists the verified bearer token of the request, not a token named in the body. Denylist entries are keyed by a digest of the token's signed part, hold only who signed out and when, and are capped. A new password, from a reset link, the user, an admin or the reset-password command, ends the user's refresh tokens, live sessions and MCP grants; personal access tokens and bot tokens stay. * fix(sessions): replace a refresh token in one update A refresh replaces its refresh token with the new one in a single UPDATE keyed by the old token, for basic and LDAP sign-ins. Only the request whose update changed the row gets new tokens; a token deleted while the request ran is not renewed. * fix(sso): a SAML login completes in the browser that started it The login keeps its AuthnRequest id, and the ACS accepts only a response whose signed assertion answers it. The ACS no longer signs anyone in: it attaches the account to the pending login and redirects to /api/v1/saml/complete on the login's own origin with a one-time code. Completing the login needs both the browser's session cookie and that code, read from the session store. * fix(input): bound parsing of names, patches and descriptions The email pattern matches in linear time and accepts the same addresses. The message parser's entity-link pattern cannot backtrack across unclosed links. JSON Patch bodies are read with Jackson limits and an operation cap, and a patch on the document root is refused. Description placeholders are restored in one pass, in text positions only. * fix(users): keep account restore, deletion and role changes with admins A PUT naming the caller's own account refuses a deleted self with 404 and treats an unknown self as a sign-up, allowed only when self sign-up is. Deleting your own account needs an admin. A role list that differs from the stored one, in either direction, is an admin change, and a non-admin PUT keeps the stored admin and bot flags and, when omitted, the stored roles. A non-admin CSV row fails for a stored admin or bot. * fix(policies): reviewers, disabled and owner-team policies, RBAC writes Rules of a disabled policy no longer apply. An owning team's policies give their allow rules to its members only. A reviewer is matched by user id. Startup no longer rewrites seeded policies. Impersonated requests cannot write policies or roles, and BotNonAdminImpersonationPolicy denies bot targets, added to stored copies by the 2.0.8 migration. A soft-deleted team or role keeps the policy conditions that name it; only a hard delete rewrites them. * fix(patch-authz): authorize every location a patch touches A JSON Patch is authorized at every location it touches, the from location of a move or copy included. Narrow edit operations apply only at real fields of the entity; tag changes are compared with their location, and an operation beside a tag change keeps that change's tag operation. The user PATCH guards and the domain check read the same locations. A patch's copies are bounded in size, and a date field refuses an object or array. * fix(users): decide team membership and self-delete on the stored result; refuse impersonated team grants A user's team changes are decided on the patched result, whatever shape the PATCH operations take, and joining or leaving a closed team needs an admin; a non-admin PUT that omits teams keeps the stored ones. The by-name self-delete check resolves the user and compares ids. Team writes that change default roles or policies, and team CSV imports, refuse impersonated requests. * fix(ui): offer Join and Leave team only where the user may change the membership The team page shows Join and Leave only on a joinable team, or to an admin, as the server allows joining and leaving a closed team only for admins. * fix(create-put): authorize creates and PUTs against the stored entity - On create, hasDomain() needs a domain of the stored container and every domain the request names. - A root parent reference without an id is loaded by name and a missing one fails the request; TagMapper resolves the classification by name. - A tag's parent must belong to the tag's classification. - PUT contexts see soft-deleted entities, as the write does. - A system tag's fully qualified name cannot change through its parent or classification either. ADR:2026-11-03-a-create-is-authorized-against-its-stored-container * fix(delete): a hard delete removes only rows of the deleted entity - The FQN-prefix cleanup of field relationships runs only for taggable types and for types, whose custom property definitions live under their name; tag labels are removed by FQN prefix only for taggable types. - Custom property definitions are removed only when their type is deleted. - The tag-FQN label delete without a source is removed; tags and glossary terms keep removing their own source-bound labels. ADR:2026-11-03-a-hard-delete-removes-only-rows-of-the-deleted-entity * fix(reads): read handlers authorize like the entity reads they mirror - Tasks read by id, and their versions, also need ViewBasic on the entity they are about. - Activity by entity link matches the link's entity type as well as its FQN. - Team hierarchy, task counts, domain hierarchy and the type custom-property reads need ViewBasic on their type; the team hierarchy still serves joinable teams to someone signing up. The role list uses the standard listing. - The global profiler setting is always authorized on tables. ADR:2026-11-03-read-handlers-authorize-like-the-entity-reads-they-mirror * test(mcp): give create_entity's root parent a repository in the tool test CreateResourceContext now loads the root parent a create names (a glossary term's glossary) and no longer swallows a failed load, so the test's static Entity stub has to answer for that parent's repository. * test(sessions): fit the session ITs to 2.0's authenticator and tokens 2.0's BasicAuthenticator reads the authorizer configuration at init, so PasswordChangeIT gives it one. 2.0 tokens carry no jti, so the logout test mints its two tokens with different expiries; two tokens minted in the same second would otherwise be the same token. * docs(decisions): name only the patch guards 2.0 has The 2.0 record no longer mentions the connection and sourceConfig copy guard, context-file sharing or conversations, which 2.0 does not have. * test(migrations): mock the collation step in the v208 entry-point test #37186 added EntityExtensionCollationAlignment to the 2.0.8 MySQL data migration without the matching change to WorkflowRedeployEntryPointTest, so the test's mocked Handle reached the step's query. This is the test change main made in #37184.
Fixes #37180
Backport of PR #37184 to
2.0. Same step: on MySQL, the 2.0.8 Java migration putsentity_extension.extensionback on its table's default character set and collation when the old 2.0.3 statement left it onascii_bin. It does nothing when the column already matches its table, and it stops before copying, naming the keys, if two keys of one entity would become equal under the table's collation.Differences from
main:2.0has no 2.1.0 migration, so only the 2.0.8 migration runs the step.2.0also hasLifeCycleCreatedSentinelMigrationas its first step. The alignment runs before it, as onmain.Tests
EntityExtensionCollationAlignmentTest(6 cases on a real MySQL 8.0 container) andMigrationWorkflowTest(40 tests) pass on this branch.