Skip to content

[SPARK-58876][SQL][FOLLOWUP] Map sub-microsecond Oracle TIMESTAMP to nanos NTZ - #58809

Open
aleksandar-trajkovic-db wants to merge 1 commit into
apache:masterfrom
aleksandar-trajkovic-db:timestamp-ntz-nanos
Open

aleksandar-trajkovic-db wants to merge 1 commit into
apache:masterfrom
aleksandar-trajkovic-db:timestamp-ntz-nanos

Conversation

@aleksandar-trajkovic-db

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Follow-up to SPARK-58876. That change mapped Oracle DATE/TIMESTAMP to
TimestampNTZType directly in OracleDialect.getCatalystType, which short-circuited
the shared Types.TIMESTAMP resolution in JdbcUtils that widens a sub-microsecond
column to a nanosecond-capable type.

This PR extracts that micro-vs-nanos decision into
JdbcUtils.resolveTimestampType(isTimestampNTZ, scale, preferTimestampNanos) (the
generic Types.TIMESTAMP branch now calls it) and routes Oracle's mapping through it
with isTimestampNTZ = true. Oracle DATE/TIMESTAMP therefore stays NTZ, but a
TIMESTAMP(7-9) now maps to TimestampNTZNanosType(scale) when the nanos preview is
engaged.

Why are the changes needed?

Before SPARK-58876, Oracle DATE/TIMESTAMP returned None from the dialect and fell
through to the shared resolver, so TIMESTAMP(7-9) was mapped to a nanosecond type when
the preferTimestampNanos read option and spark.sql.timestampNanosTypes.enabled were
both on. SPARK-58876 accidentally regressed this, truncating such columns to microsecond
TimestampNTZType. This restores the nanosecond precision while keeping the new
zoneless-NTZ behavior.

Does this PR introduce any user-facing change?

Yes — relative to the unreleased SPARK-58876 change, not to any released version. With
preferTimestampNanos=true and spark.sql.timestampNanosTypes.enabled=true, an Oracle
TIMESTAMP(7-9) column now reads as TimestampNTZNanos(scale) instead of microsecond
TimestampNTZType. DATE, TIMESTAMP(0-6), and the default (preview off) are
unchanged. The value is read time-zone-independently (wall-clock).

How was this patch tested?

Added a getSchema-level unit test in JDBCSuite asserting that an Oracle
TIMESTAMP(7-9) resolves to TimestampNTZNanosType(scale) only when both the
preferTimestampNanos option and the preview flag are on, and stays microsecond
TimestampNTZType for coarser scales or with either flag off. This replaces the prior
test that pinned tehavior.

build/sbt 'sql "SPARK-58876"'

Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Anthropic Claude Opus 4.8)

This is my original work and I license it to the project under the project's open source license.

…nanos NTZ

Oracle DATE/TIMESTAMP mapping short-circuited the shared TIMESTAMP resolver, regressing TIMESTAMP(7-9) to microsecond TimestampNTZType under the nanos preview. Extract the micro-vs-nanos decision into JdbcUtils.resolveTimestampType and route Oracle's NTZ mapping through it (forcing NTZ).

Co-authored-by: Isaac <no-reply@databricks.com>
@uros-b

uros-b commented Sep 15, 2026

Copy link
Copy Markdown
Member

build/sbt 'sql "SPARK-58876"'

This doesn't look like a valid test invocation. Perhaps something like build/sbt 'sql/testOnly org.apache.spark.sql.jdbc.JDBCSuite -- -z SPARK-58876'?

JdbcUtils.getSchema(mock(classOf[Connection]), rs, OracleDialect(),
preferTimestampNanos = preferNanos).fields.head.dataType
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: resolve only returns the data type. SPARK-58876 also stamps READ_TIMESTAMP_NTZ_WALL_CLOCK so a later flag flip cannot desync the microsecond NTZ read. That marker is redundant for TimestampNTZNanosType (the nanos getter already uses getObject(LocalDateTime)), but it is still part of the Oracle contract.

Consider returning the StructField (as the nearby preferTimestampNTZ test does) and asserting the marker is still present for both the nanos and microsecond outcomes, e.g. scale=9 with both flags on and scale=6 / flags off.

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.

2 participants