Skip to content

fix(db): convert oc_jobs.argument to CLOB out of place on Oracle - #64935

Draft
moodyjmz wants to merge 2 commits into
masterfrom
fix/oracle-jobs-argument-clob
Draft

moodyjmz wants to merge 2 commits into
masterfrom
fix/oracle-jobs-argument-clob

Conversation

@moodyjmz

@moodyjmz moodyjmz commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

occ upgrade aborts on Oracle at Version34000Date20260318095645: VARCHAR2(4000) → CLOB cannot be done in place (ORA-22858), even on an empty table. Affects v32.0.7+, v33.0.1+ and all of 34.x on Oracle. On Oracle the migration now converts oc_jobs.argument out of place in preSchemaChange, then changeSchema sees TEXT and no-ops. Other platforms are unchanged.

Details

Cause

changeSchema calls setType(TEXT) on jobs.argument. Doctrine emits that as ALTER TABLE ... MODIFY, which Oracle rejects for VARCHAR2 → CLOB. Doctrine's OraclePlatform also restates the type in every MODIFY, and on Oracle 23 any MODIFY naming a type on a LOB column fails (ORA-22296 with DEFAULT '' NOT NULL, ORA-22859 for a bare type), so the schema API can't restore NOT NULL afterwards. MODIFY ("argument" NOT NULL) without the type is legal, which is what the fix uses.

Fix

Oracle only, in preSchemaChange:

  1. ADD ("argument_copy" CLOB)
  2. UPDATE ... SET "argument_copy" = "argument", then count mismatches (DBMS_LOB.COMPARE plus NULL checks); any mismatch throws with the original column untouched
  3. MODIFY ("argument_copy" NOT NULL) if the original was NOT NULL
  4. DROP COLUMN "argument"
  5. RENAME COLUMN "argument_copy" TO "argument"

Each step is chosen from the columns found in all_tab_columns, so an interrupted run resumes where it stopped. An argument_copy that isn't a CLOB copy of a VARCHAR2 argument throws rather than guessing. Installs already converted by hand (CLOB, nullable or not) are left alone.

The fix modifies the released class rather than adding a new one, because a new migration dated after it would never get to run on instances stuck on it. Fresh installs go through migrateSchemaOnly(), which skips preSchemaChange and creates the column as CLOB directly.

Between the copy and the drop, a job written only to the old column should fail on the NOT NULL copy rather than lose its argument. Upgrades run in maintenance mode, so no writers are expected.

Tests

Test Covers
MigratorTest::testChangeStringToTextEmptyTableFailsOnOracle in-place string → text raises ORA-22858 on an empty table (from #61912)
Version34000Date20260318095645Test::testInstalledSchemaHasTextColumn fresh install path: TEXT, no leftover copy
Version34000Date20260318095645Test::testMigrationKeepsConvertedColumn all platforms: migration is a no-op on the installed schema, data intact
Version34000Date20260318095645Test::testMigrationConvertsOracleColumn Oracle: never upgraded, converted by hand (NOT NULL / nullable), interrupted after add, before drop, before rename; data including multibyte survives, new inserts work

The Oracle-only tests skip on other platforms and run in the DB group, so phpunit-oci covers Oracle 18 and 23.

Known limitation

On a compressed oc_jobs, DROP COLUMN fails on Oracle 19 per Oracle's documentation, and on 23 it silently turns into SET UNUSED. Neither is checked by the migration.

Backports

Master's guard differs from stable32/33/34 since #63013 (getType()->getName() vs Type::getType()), so backportbot won't apply this cleanly; the stable branches need their own PRs.

TODO

  • phpunit-oci green on Oracle 18 and 23
  • Backport PRs for stable32, stable33, stable34

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

🤖 Generated with Claude Code

moodyjmz and others added 2 commits September 30, 2026 15:13
Adds testChangeStringToTextEmptyTableFailsOnOracle to MigratorTest: an
in-place string to text migration on an empty Oracle table raises
ORA-22858. Skipped on other platforms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: James Manuel <moodyjmz@users.noreply.github.com>
Assisted-by: ClaudeCode:claude-opus-5-5
On Oracle, preSchemaChange adds a CLOB copy of jobs.argument, copies and
verifies the data, sets the copy NOT NULL if the original was, drops the
original and renames the copy. changeSchema then sees TEXT and returns null.
Each step is picked from the columns found, so an interrupted run resumes.
Other platforms are unchanged. The new test runs the migration through
MigrationService for each state oc_jobs can be in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: James Manuel <moodyjmz@users.noreply.github.com>
Assisted-by: ClaudeCode:claude-opus-5-5

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

occ upgrade fails on Oracle: core migration Version34000Date20260318095645 cannot convert oc_jobs.argument to TEXT (ORA-22858)

2 participants