Skip to content

fix(oracle): decode TIMESTAMP, INTERVAL, and BFILE through typed paths (#965)#966

Merged
datlechin merged 1 commit intomainfrom
fix/oracle-typed-decoding
May 2, 2026
Merged

fix(oracle): decode TIMESTAMP, INTERVAL, and BFILE through typed paths (#965)#966
datlechin merged 1 commit intomainfrom
fix/oracle-typed-decoding

Conversation

@datlechin
Copy link
Copy Markdown
Member

Summary

Closes #965. Oracle TIMESTAMP, TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE, INTERVAL DAY TO SECOND, INTERVAL YEAR TO MONTH, DATE, RAW, and BLOB columns now decode through typed paths instead of reading binary bytes as UTF-8 (the source of the unreadable text in #965). Tables containing INTERVAL YEAR TO MONTH or BFILE columns previously crashed the app on row fetch via OracleNIO's fatalError/preconditionFailure for unsupported wire-protocol types — both crash sites now throw recoverable errors and the plugin renders unknown types as <unsupported: typename> placeholders without losing the rest of the row.

  • Plugin OracleConnection.decodeCell rewritten as a switch cell.dataType over OracleNIO's typed decoders. Foundation-only OracleCellFormatting extracted for testability without linking OracleNIO into the test target.
  • TIMESTAMP renders ISO-8601 UTC; TIMESTAMP WITH TIME ZONE / WITH LOCAL TIME ZONE convert to the host's local zone with explicit offset; INTERVAL DAY TO SECOND trims trailing zeros (e.g. 0 00:00:01.5, 5 03:14:00), preserving up to 9-digit nanosecond precision when present; INTERVAL YEAR TO MONTH renders as Y-MM; RAW/BLOB hex-encoded with 4 KB cap.
  • OracleNIO repointed to TableProApp/oracle-nio@f343a0d (tablepro-main branch) which adds an IntervalYM decoder, a BFILE locator-passthrough case, and replaces the two fatalError/preconditionFailure sites with thrown OraclePartialDecodingError. Upstream PR to follow.

Test plan

  • SwiftLint --strict passes on all changed files
  • OracleNIO fork builds cleanly with swift build; row/message-decoder unit tests (9 cases) pass
  • End-to-end against live Oracle 23 Free Docker (gvenzl/oracle-free:23-slim) using timestamp_repro fixture table: all four TIMESTAMP variants, both INTERVAL variants, DATE, and a 38-digit-precision NUMBER render correctly; BFILE shows <bfile> placeholder; query does not crash
  • xcodebuild -only-testing:TableProTests/Oracle\ cell\ formatting (run on your end)
  • Sanity check on a non-trivial Oracle schema (e.g. one with REF cursors or user-defined object types) — placeholder <unsupported: …> should appear without crashing

@datlechin datlechin merged commit e3e0f03 into main May 2, 2026
2 checks passed
@datlechin datlechin deleted the fix/oracle-typed-decoding branch May 2, 2026 17:53
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5381593bbb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve time when rendering Oracle DATE values

Oracle DATE stores hours/minutes/seconds, but this formatter hard-codes yyyy-MM-dd in UTC, so any non-midnight DATE value loses its time component and can even show the wrong calendar day after UTC conversion. This is a data-accuracy regression for common schemas that use DATE as a full datetime, because users will see truncated/misaligned values rather than what is stored.

Useful? React with 👍 / 👎.

@Test("TIMESTAMP local style renders an offset matching the host's current zone")
func timestampLocal() {
let result = OracleCellFormatting.formatTimestamp(Self.referenceDate, style: .local)
#expect(!result.hasSuffix("Z"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Accept Z output for UTC in timestamp offset tests

These assertions assume local/zoned formatting never ends with Z, but ISO8601DateFormatter emits Z for zero-offset time zones (e.g., UTC), so the test fails on UTC hosts. That makes the suite environment-dependent and can break CI or contributor runs where TimeZone.current is Etc/UTC.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Oracle TIMESTAMP column type reading failure

1 participant