Skip to content

driver-sql (oracle): bind uuid text to RAW(16) through HEXTORAW, so a lookup over a SYS_GUID key filters and writes by its uuid string, and type-compat can lift the pairing from lossy to compatible #31390

Closed

Description

@objectstack-fleet

epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
Filing gate: ③ should-fix 3 of the CONTRACT_REVIEW_TIER record on PR #31351 (#31328). That PR marks RAW(16) against lookup/master_detail as 'lossy' for oracle. The binding is this follow-up.
Ruling-ref: ADR-0015 §4.6
Dedupe (open AND closed): "HEXTORAW", "RAW(16) uuid", "SYS_GUID lookup" → none.
Blocked-by: #31328
Reader: the epic PM dispatches it after #31328 lands.
type: Feature

维护者速读

  • 做什么: Oracle 老库常用 SYS_GUID() 生成 RAW(16) 主键。目前平台读这类主键时显示为 uuid 字符串,但不能用 uuid 字符串去过滤或写入,所以基于它的查找关系只能读、不能筛选。补上绑定后,这类主键可以像普通 uuid 一样使用。
  • 需要您做的: 无。

Task

  • driver-sql oracle dialect: a comparand or written value for a RAW(16) column typed as uuid binds through HEXTORAW(?) with dashes stripped, and the read side stays RAWTOHEX dashed. The column type must be known at bind time; read it from the introspected/declared column type, never guess it from the value.
  • Malformed uuid text is refused with a typed INVALID_FILTER, not sent.
  • type-compat.ts: lift the RAW(16) → lookup/master_detail pairing for oracle from 'lossy' to compatible, and update the pin. That touches the spec, so a CONTRACT_REVIEW_TIER review is owed.
  • Live pins in the Oracle cell (OS_TEST_ORACLE_URL): filter eq/in, write, and a lookup round-trip over a SYS_GUID key.

Clause-②: yes (widening) expected · Metadata-protocol: none.

Activity

  1. added
    enhancementNew feature or request
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Nov 8, 2026
  2. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p3 · domain:server · blocked · 2026-11-08T05:55Z

    ⛔ Not a claim.

    • Oracle RAW(16) keys from SYS_GUID() read as uuid strings, but they cannot be filtered or written by uuid, so lookups on them are read-only. The fix binds through HEXTORAW. It is an ADR-0015 §4.6 federation follow-up.
    • p3, lane domain:server, area:data. pm:blocked: the body carries Blocked-by: #31328, which the unlock sweep reads. finding removed.

    Generated by Claude Code

  3. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmPF1skfu2kx89BEXZi

    Unblocked · re-verified · 2026-11-08T16:06Z (idle chore ①, execution-duties.md)

  4. added
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    pm:queueReady for the PM dispatch loop
    on Nov 8, 2026
  5. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-steve · session_01ADHkmP8JJo4zF2sjTBRwnX

    Claim: PM loop round 1 · #31390 (items 1, 2 and 4; item 3 is split out to #31592) · 2026-11-08T16:18Z
    Session: session_01ADHkmP8JJo4zF2sjTBRwnX (seat); dev = card thread session_01ADHkmQ9H84XNocJ8waPS1P
    Account: os-steve
    Branch: claude/project-thread-py8ur5
    Worktree: the card thread's checkout of objectstack-ai/objectstack
    Domain: domain:server
    Seat: domain:server#4
    File surface: packages/drivers/driver-sql/src/** (the oracle dialect's uuid bind and its filter/write compile only; other dialects' compiled output byte-identical), its tests incl. the Oracle live cell (sql-driver-oracle-*.test.ts, live-dialect-matrix.testkit.ts); prose only: the demoteExact JSDoc in packages/spec/src/data/type-compat.ts may be left for #31592; .changeset/31390-*.md (stop on breach; ⛔ no type-compat pairing value change)
    Container & model: S–M, mode:thread, model: default tier (dispatch-gates --tier on driver-sql: no path-derived mandate). The Clause-② widening is reviewed at CONTRACT_REVIEW_TIER before the queue, effort: high
    Clause-②: yes (widening)
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6723782323
    Premise: holds (Blocked-by: #31328 closed completed; re-verified by 6723782323: no HEXTORAW bind on main)
    Serial constraints cleared: #31395 (domain:server#1, mssql uniqueidentifier substring operators) also edits the driver-sql filter emitter; dialects disjoint, so ordinary concurrency: merge origin/main before the PR and again after #31395 lands; the later lander resolves. Split note: item 3 (type-compat.ts lossy → compatible) is #31592, Blocked-by: #31390, spec lane.

  6. added
    pm:blockingDerived cache from the Blocked-by reverse index: open card with open dependents — never hand-set
    on Nov 8, 2026
  7. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-steve · session_01ADHkmQ9H84XNocJ8waPS1P
    os-dev-report

    {
      "issue": 31390,
      "status": "done",
      "branch": "claude/project-thread-py8ur5",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/31642",
      "session": "session_01ADHkmQ9H84XNocJ8waPS1P",
      "premise_still_valid": true,
      "summary": "On the Oracle dialect a federated object's RAW(16) columns are read once per object from ALL_TAB_COLUMNS, and a comparison comparand, a written value or a by-id key for those columns binds as HEXTORAW(?) over the uuid's 32 hex digits; reads keep RAWTOHEX dashed. The column type decides, never the value (a VARCHAR2 uuid column binds text). Non-uuid text is refused before anything is sent: INVALID_FILTER / 400 through the withheld-filter seam for comparands, VALIDATION_ERROR / 400 for written values. A failed catalog read binds text as before; other dialects are byte-identical. Card item 3 is carried by #31592.",
      "tests": "Head a535d018 (suites on aed364b6; a535d018 only types 9 test query bags, and the oracle dialect file, eslint and the erasure gate were re-run on it). driver-sql: build 0, typecheck 0, eslint --no-inline-config 0, full test 245 files passed / 13 skipped, 4147 tests passed / 222 skipped, VERDICT command-exit 0. objectql: 570/570 files, 11571/11571 tests, typecheck 0, VERDICT 0. Oracle dialect file 71 tests (41 on main). Live Oracle cell (OS_TEST_ORACLE_URL): NOT MEASURED, unset here and in CI. Ablations via scripts/ablation-replace.mjs, every one restored to blob == HEAD with an empty git diff: B1 comparand refusal 10 red (incl. 4 seam rows); B2 write refusal 1 red; C1 filter-site + binding Oracle guards 4 red (pg, mysql2, mssql, sqlite pins); C2 formatInput + binding guards 4 red; C3 binding guard alone 1 red (sqlite door pin); C4 column judged by value 6 red incl. both controls; C5 failed read recorded 1 red; D1 once-per-object cache 2 red; E1 re-registration 1 red. Other-dialect pins pass on base source. Conformance before 66 covered / 6 DEBT; after 66 covered / 6 DEBT / 0 exempt.",
      "gates": "dispatch-gates --commands derived 71 families; all 71 ran, exit codes captured before any pipe, final 71 x exit 0. First-run non-zero: check-plugin-teardown-shape --self-test exit 3 (fixture commit 621a4876 absent; fetched, re-run 0), check:type-check-debt exit 3 (verify-lock queue-timeout behind dogfood; re-run under the lock 0), check:query-options-erasure exit 1 (9 new any-cast query bags in the new test grew the test surface 236 to 245; typed in a535d018, re-run 0 at 236). --ran reconciliation: 71 derived, 71 run, 0 NOT-MEASURED, 0 UNRUN. Earlier rounds: check:facade-delegation-only and check:keyed-text-bounds went red on SqlDriver stubs holding bodies; the priming and binding moved into the facets, both now 0. PR check-runs: in_progress at report time, not waited on.",
      "dogfood_battery": "aed364b6 · os-verify-lock: VERDICT command-exit 0, held the lock 2191s · Test Files 440 passed / 3 skipped (443) · Tests 3633 passed / 41 skipped (3674) · no failures",
      "mcp_calls": "4 — mcp__github__issue_read x3 (get, get_comments x2), mcp__github__pull_request_read x1 (get); no write tool",
      "api_writes": "2 — fleet-write relay POST /repos/objectstack-ai/objectstack/dispatches (op pr_create, PR #31642), and this comment through post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/31390/comments); git push is not counted",
      "open_questions": [
        {
          "question": "A comparand or written value that is not uuid text (valid hex of another length, other text) reached Oracle on main and is now refused before it is sent. Is that narrowing acceptable as the card requires?",
          "options": [
            "A keep the refusal, as the card asks",
            "B bind such values as text again"
          ],
          "recommendation": "A, because the card mandates the refusal and Oracle refused text against RAW anyway; whether implicit conversion ever answered such a value is NOT MEASURED"
        },
        {
          "question": "create() mints a nanoid when no id is given, so a RAW(16)-keyed object now answers VALIDATION_ERROR / 400 instead of an Oracle error. Should a later card let such an object take its DEFAULT SYS_GUID() id?",
          "options": [
            "A separate card for a database-default id",
            "B leave as is"
          ],
          "recommendation": "A, because it is new behaviour outside this card's three items"
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [],
      "files_changed": "17: changeset; driver-sql src sql-driver.ts, -oracle-dialect.ts, -filter-helpers.ts, -sqlite-serialisation.ts, -field-mapping.ts, -schema-sync.ts, -crud.ts, -sequence-semantics.ts, -bulk-operations.ts, -aggregation.ts, -distinct.ts, -window-functions.ts, -query-plan.ts; tests -oracle-dialect.test.ts, -oracle-federation-conformance.test.ts, -compile-refusal-seam.test.ts (forced: one DOORS row for the new seam builder)",
      "line_budget": "+853 / -31 against main; tests +434, source and changeset +419",
      "deviations": "No second merge of origin/main before the PR: the 10 commits main gained after the aed364b6 merge touch no driver-sql file, and merging would have left the PR head unverified; the merge after #31395 lands is still owed. textMatchPredicate untouched; packages/spec untouched."
    }

    Stamped 2026-11-08T18:15Z.

  8. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-steve · session_01ADHkmP8JJo4zF2sjTBRwnX

    Landed · #31390 · 2026-11-08T21:53Z

    Probe Reading
    PR #31642 merged through the queue 2026-11-08T21:42:55Z as 836d408f07; head ee1c0183fa (ACCEPT 6727176997; contract review PASS 6725408036 on a535d018, round 2 PASS 6727162827 on the merge head)
    #31390 closed by Fixes #31390

    State change: pm:dispatched removed and os-steve unassigned in this stroke. Card item 3 (pattern operators over RAW(16)) stays with #31592 (spec). The seven review nits stay as recorded deviations in the ACCEPT; no follow-up card is owed for them.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:datadomain:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpm:blockingDerived cache from the Blocked-by reverse index: open card with open dependents — never hand-setpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions