* fix(labels): enforce per-tenant uniqueness on NormalizedName
Finish the unused Label.NormalizedName contract the same way Secrets
does: unique (TenantId, NormalizedName) in EF, fail-closed Memory saves,
and keep NormalizedName in sync with Name.
Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com>
* fix(labels): clone Memory label reads so a rejected rename cannot persist
Find/List handed out live store refs. Labels.Update mutates Name (and
NormalizedName) on that instance before Save; a uniqueness rejection
then left the stored row already renamed. Clone-on-read matches Memory
identity stores from #8108.
Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com>
* fix(labels): stamp null TenantId, fail-loud on leftover duplicates, cap names at 255
Follow the Architect steer for Greptile P1s: do not auto-delete duplicate
labels; UPDATE Labels SET TenantId = '' WHERE TenantId IS NULL on every
provider before CreateIndex; keep SQL Server/Oracle filtered unique
indexes; HasMaxLength(255) on Name and NormalizedName with no silent
truncate.
Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com>
* fix(labels): fail-loud preflight for leftover keys and over-length names
No silent dedupe: every provider lists leftover (TenantId, NormalizedName)
keys and aborts before CreateIndex. SQL Server/Oracle keep their filtered
unique indexes. PostgreSQL/SQLite keep provider column types. Providers
that narrow Name/NormalizedName to 255 preflight over-length Ids first.
Memory uniqueness semantics are unchanged.
Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com>
* test(labels): match Oracle filtered-index escape in migration assertion
Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
* fix(efcore-oracle): migrate LOB columns in V3_6 without in-place datatype alteration
Both Oracle V3_6 migrations were generated as in-place `ALTER TABLE ... MODIFY`
statements that change a column's datatype to or from a LOB type: NCLOB to JSON
for `WorkflowDefinitions.StringData`, and NVARCHAR2(450) to NCLOB for
`ActivityNodeId` on `WorkflowExecutionLogRecords` and `ActivityExecutionRecords`.
Oracle refuses both (ORA-22858 / ORA-22859), so neither migration could ever
apply and the reported ORA-22858 was unavoidable.
Convert the columns the way the ORA-22858 message prescribes instead: add a
temporary column of the target type, copy the values across, drop the original
and rename the temporary one. Because Oracle commits DDL implicitly, a run that
fails partway leaves its earlier statements applied - the reporter's already
committed `OriginalSource` column is exactly that - so every step is guarded
against the state a previous attempt can have left behind. The conversion block
derives what still needs doing from `ALL_TAB_COLUMNS`, skips a conversion that
already completed (including one applied by hand), and raises rather than copy
out of and drop a column whose datatype it does not recognize.
Add an offline regression test that generates the Oracle Management and Runtime
V3_6 scripts through `IMigrator.GenerateScript` without a connection and asserts
that no in-place datatype `MODIFY` is emitted for either column, that the
add/copy/drop/rename sequence appears in order, and that the re-run guards are
present. All 19 cases fail against the previous migrations.
Refs #8011
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* refactor(efcore-oracle): tighten migration helper visibility and index guard, share the script-generation test harness
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* test(efcore-oracle): brace the foreach bodies in the V3_6 migration tests
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix(efcore-oracle): refuse to truncate node IDs on downgrade and validate same-named indexes
The Runtime V3_6 downgrade converted ActivityNodeId from NCLOB back to
NVARCHAR2(450) by copying DBMS_LOB.SUBSTR(..., 450, 1), silently
truncating any value the upgraded schema had allowed to grow past 450
characters. EnsureLobLengthAtMost now checks for oversized values while
the column is still a LOB and raises before any data is copied.
CreateIndexIfMissing also treated any index with a matching name as
already done. It now validates the existing index's table, uniqueness
and ordered column list against ALL_INDEXES/ALL_IND_COLUMNS so a
same-named index left behind by schema drift or manual recovery is not
mistaken for the one the migration means to create.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* docs(efcore-oracle): correct the dynamic SQL rationale on the LOB length guard
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix(efcore-oracle): preflight both tables before downgrading and escape schema names in migration SQL
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix(efcore-oracle): copy every row NULL-preservingly so retries reproduce the current source
The filtered copy `WHERE "<column>" IS NOT NULL` skipped rows whose
nullable source had since become NULL. If a prior conversion committed
the copy and then failed before dropping the source column, an
operator clearing a value before retrying would find the predicate
skip that row, and the stale converted value would be renamed into
place. Replace the filtered UPDATE with an unconditional, NULL-
preserving CASE expression so a retry always reproduces the current
source exactly.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
* fix(efcore): terminate raw SQL statements in the PostgreSQL and SQLite Runtime V3_6 migrations
The V3_6 Runtime migration's two DROP INDEX statements were emitted without a
trailing semicolon on PostgreSQL and SQLite, so `dotnet ef migrations script`
produced syntactically invalid SQL (an unterminated statement inside the
idempotent DO $EF$ block, and unseparated statements in the plain script).
MigrateAsync() was unaffected because EF executes each Sql() call individually.
Add the missing terminators and a regression test that generates the Runtime
migration script offline for both providers (idempotent and plain forms) and
asserts the DROP INDEX statements are properly terminated.
Refs #7912
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* test(efcore): share migration-script setup and cover the schema-prefixed statements
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* test(efcore): cover schema-prefixed migration statements without static state
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>