Skip to content

fix(core): UPDATE to work with bind variables for TIMESTAMP columns#6510

Merged
bluestreak01 merged 8 commits intomasterfrom
ia_ts_update_fix
Dec 17, 2025
Merged

fix(core): UPDATE to work with bind variables for TIMESTAMP columns#6510
bluestreak01 merged 8 commits intomasterfrom
ia_ts_update_fix

Conversation

@glasstiger
Copy link
Copy Markdown
Contributor

Fix the UPDATE statement to handle TIMESTAMP columns correctly when bind variables used.


When attempted to update a TIMESTAMP column using bind variables, the following error was returned:

bind variable cannot be used [contextType=unknown, index=1]

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Dec 6, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The pull request modifies timestamp column update handling in SQL code generation and bind variable services. It qualifies a QUERY constant, updates metadata construction for timestamp columns during updates, and changes error message formatting to use numeric type codes. A new test class validates timestamp updates through PostgreSQL wire protocol APIs.

Changes

Cohort / File(s) Change Summary
SQL Code Generation
core/src/main/java/io/questdb/griffin/SqlCodeGenerator.java
Qualifies QUERY constant import, updates timestamp column metadata construction for update paths with new branch for STRING/VARCHAR types, and simplifies update target type handling by removing conditional timestamp-precision preservation logic
Error Reporting
core/src/main/java/io/questdb/griffin/engine/functions/bind/BindVariableServiceImpl.java
Changes error message formatting in define() and setLong0() methods to use numeric type codes instead of type names via ColumnType.nameOf()
Test Coverage
core/src/test/java/io/questdb/test/cutlass/pgwire/PGTimestampUpdateTest.java
Introduces new test class validating TIMESTAMP and TIMESTAMP_NS column updates via PostgreSQL wire protocol using setLong, setString, and setTimestamp APIs with nanos precision handling

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • SqlCodeGenerator timestamp metadata logic: Review the new branch for STRING/VARCHAR type handling and implications of removing timestamp-precision preservation check
  • Impact of error message format changes: Verify that numeric type codes are appropriate for all error paths and don't reduce debugging clarity
  • Test coverage completeness: Ensure new tests adequately validate timestamp update scenarios across different precision types and setter APIs

Suggested labels

Bug, SQL

Suggested reviewers

  • bluestreak01
  • nwoolmer

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing UPDATE statements to work with bind variables for TIMESTAMP columns, which matches the changeset's core purpose.
Description check ✅ Passed The description is directly related to the changeset, explaining the bug being fixed (UPDATE with bind variables on TIMESTAMP columns) and showing the error message that was reproduced.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@glasstiger
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Dec 6, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
core/src/main/java/io/questdb/griffin/SqlCodeGenerator.java (1)

5394-5469: TIMESTAMP + bind-variable update handling looks good; consider documenting invariants

The updated block in generateSelectVirtualWithSubQuery does what we want for UPDATEs:

  • For update models, unresolved functions (e.g. bind vars) are now typed via assignType(targetColumnType, ...), so a TIMESTAMP column will drive the bind-variable type instead of staying UNDEFINED.
  • When the logical target type is TIMESTAMP but the underlying expression function remains STRING/VARCHAR, the special-case columnType == TIMESTAMP && (function.getType() == STRING || function.getType() == VARCHAR) and metadata construction using function.getType() let the metadata reflect the string-y representation the client actually sends, which should address the previous “contextType=unknown” failure for timestamp updates.

Two small, non-blocking suggestions:

  • The columnIndex from updateTableColumnNames().indexOf(column.getAlias()) is assumed to be non‑negative; that invariant already exists in generateSelectChoose, but an assert columnIndex >= 0 (or a brief comment) here would make it explicit and future‑proof against additional non‑SET projection columns being added to update models.
  • The TIMESTAMP/STRING/VARCHAR branch relies on columnType potentially diverging from function.getType() (after the widening/implicit-cast logic). A short comment explaining that this is intentional—metadata should describe the physical bind type while the engine still treats the target as TIMESTAMP—would help avoid accidental “cleanup” of this subtle logic later.

Functionally though, the change is coherent with the existing update/type-casting flow.

core/src/test/java/io/questdb/test/cutlass/pgwire/PGTimestampUpdateTest.java (1)

106-142: Consider deduplicating the SQLException‑wrapping lambdas

The helper method is well‑structured: it validates the initial row, performs the UPDATE via bind variables, drains the WAL, and re‑asserts the final state, all under assertWithPgServer. One minor improvement would be to reduce the repeated try { … } catch (SQLException e) { throw new RuntimeException(e); } blocks in each test by introducing a small helper (e.g., a ThrowingSqlConsumer functional interface plus an adapter to Consumer<PreparedStatement>), but this is purely cosmetic and can be deferred.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 606aace and f7560fd.

📒 Files selected for processing (3)
  • core/src/main/java/io/questdb/griffin/SqlCodeGenerator.java (3 hunks)
  • core/src/main/java/io/questdb/griffin/engine/functions/bind/BindVariableServiceImpl.java (2 hunks)
  • core/src/test/java/io/questdb/test/cutlass/pgwire/PGTimestampUpdateTest.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (34)
  • GitHub Check: New pull request (Hosted Running tests on windows-other-2)
  • GitHub Check: New pull request (Hosted Running tests on windows-other-1)
  • GitHub Check: New pull request (Hosted Running tests on windows-pgwire)
  • GitHub Check: New pull request (Hosted Running tests on windows-cairo-2)
  • GitHub Check: New pull request (Hosted Running tests on windows-cairo-1)
  • GitHub Check: New pull request (Hosted Running tests on windows-fuzz2)
  • GitHub Check: New pull request (Hosted Running tests on windows-fuzz1)
  • GitHub Check: New pull request (SelfHosted Running tests with cover on linux-other)
  • GitHub Check: New pull request (Hosted Running tests on windows-griffin-sub)
  • GitHub Check: New pull request (SelfHosted Running tests with cover on linux-pgwire)
  • GitHub Check: New pull request (Hosted Running tests on windows-griffin-base)
  • GitHub Check: New pull request (SelfHosted Running tests with cover on linux-cairo-sub)
  • GitHub Check: New pull request (Hosted Running tests on mac-other)
  • GitHub Check: New pull request (SelfHosted Running tests with cover on linux-cairo-root)
  • GitHub Check: New pull request (Hosted Running tests on mac-pgwire)
  • GitHub Check: New pull request (SelfHosted Running tests with cover on linux-fuzz2)
  • GitHub Check: New pull request (Hosted Running tests on mac-cairo-fuzz)
  • GitHub Check: New pull request (SelfHosted Running tests with cover on linux-fuzz1)
  • GitHub Check: New pull request (SelfHosted Running tests with cover on linux-griffin-sub)
  • GitHub Check: New pull request (Hosted Running tests on mac-cairo)
  • GitHub Check: New pull request (SelfHosted Running tests with cover on linux-griffin-root)
  • GitHub Check: New pull request (Hosted Running tests on mac-griffin)
  • GitHub Check: New pull request (SelfHosted Other tests on linux-arm64)
  • GitHub Check: New pull request (SelfHosted Other tests on linux-x86-graal)
  • GitHub Check: New pull request (Rust Test and Lint on linux-jdk17)
  • GitHub Check: New pull request (SelfHosted Other tests on linux-x64-zfs)
  • GitHub Check: New pull request (SelfHosted Griffin tests on linux-x86-graal)
  • GitHub Check: New pull request (SelfHosted Griffin tests on linux-x64-zfs)
  • GitHub Check: New pull request (SelfHosted Griffin tests on linux-arm64)
  • GitHub Check: New pull request (SelfHosted Cairo tests on linux-x86-graal)
  • GitHub Check: New pull request (Trigger Enterprise CI Trigger Enterprise Pipeline)
  • GitHub Check: New pull request (SelfHosted Cairo tests on linux-x64-zfs)
  • GitHub Check: New pull request (SelfHosted Cairo tests on linux-arm64)
  • GitHub Check: New pull request (Check Changes Check changes)
🔇 Additional comments (6)
core/src/main/java/io/questdb/griffin/engine/functions/bind/BindVariableServiceImpl.java (2)

214-215: Error message in define default branch now better reflects raw context type

Switching to .put(type) instead of ColumnType.nameOf(type) makes the error expose the exact encoded type value, which addresses the previous "contextType=unknown" issue and is safe since this path is already exceptional-only.


1208-1210: setLong0 now reports LONG as the source type, consistent with other setters

Passing ColumnType.LONG into reportError correctly identifies the bound value’s logical type (LONG) and aligns with the patterns in setInt0, setShort0, etc., improving diagnostic clarity without changing binding behavior.

core/src/main/java/io/questdb/griffin/SqlCodeGenerator.java (1)

648-656: Explain wrapper condition remains correct

Using QueryModel.QUERY here keeps the explain-behaviour identical while avoiding reliance on the unqualified constant; no functional or safety concerns.

core/src/test/java/io/questdb/test/cutlass/pgwire/PGTimestampUpdateTest.java (3)

36-38: Test class setup and annotations look correct

Extending BasePGTest and using the SqlNoDataSourceInspection suppression is consistent with other PG wire tests; class scaffolding is fine and ready to integrate with the existing test harness.


39-70: Micros TIMESTAMP tests cover all relevant binder variants

The three TIMESTAMP tests (setLong, setString, setTimestamp) nicely exercise the different binder paths, and the epoch/expected strings are internally consistent (1764863925s → 2025-12-04T15:58:45, with the fractional parts matching the chosen microsecond values). These should reliably guard the regression around UPDATE + bind variables for microsecond timestamps.


72-104: Nanos TIMESTAMP_NS tests correctly validate nano vs micro precision behavior

The TIMESTAMP_NS tests mirror the micros ones and explicitly check:

  • setLong as nanoseconds since epoch,
  • string parsing with 9‑digit fractional seconds, and
  • setTimestamp only transferring micro precision (4242ns000004000).

The expectations (.000000042 and .000004000) align with typical QuestDB semantics, and the explicit comment on micro‑only transfer makes the intent clear. This is a solid coverage matrix for the nano path.

@glasstiger
Copy link
Copy Markdown
Contributor Author

[PR Coverage check]

😍 pass : 8 / 9 (88.89%)

file detail

path covered line new line coverage
🔵 io/questdb/griffin/engine/functions/bind/BindVariableServiceImpl.java 1 2 50.00%
🔵 io/questdb/griffin/SqlCodeGenerator.java 7 7 100.00%

@bluestreak01 bluestreak01 merged commit 40367ef into master Dec 17, 2025
43 checks passed
@bluestreak01 bluestreak01 deleted the ia_ts_update_fix branch December 17, 2025 16:45
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