Skip to content

fix: reset vector class to FLAT in ResetWithSameType to fix prepared stmt null json panic#23864

Merged
mergify[bot] merged 6 commits intomatrixorigin:mainfrom
ck89119:issue-23859
Mar 17, 2026
Merged

fix: reset vector class to FLAT in ResetWithSameType to fix prepared stmt null json panic#23864
mergify[bot] merged 6 commits intomatrixorigin:mainfrom
ck89119:issue-23859

Conversation

@ck89119
Copy link
Copy Markdown
Contributor

@ck89119 ck89119 commented Mar 17, 2026

What type of PR is this?

  • API-change
  • BUG
  • Improvement
  • Documentation
  • Feature
  • Test and CI
  • Code Refactoring

Which issue(s) this PR fixes:

issue #23859

What this PR does / why we need it:

When a prepared statement inserts NULL into a JSON column multiple times, the second execution causes a panic during SELECT:

panic runtime error: index out of range [0] with length 0
  ByteJson.Unmarshal (bytejson.go:96)
  DecodeJson (encoding.go:93)
  ColumnSlices.GetStringBased (output.go:538)

Reproduce:

CREATE TABLE test_ps (id INT, meta JSON);
PREPARE stmt FROM 'INSERT INTO test_ps (id, meta) VALUES (?, ?)';
SET @a=1, @b=NULL; EXECUTE stmt USING @a, @b;
SET @a=2, @b=NULL; EXECUTE stmt USING @a, @b;
DEALLOCATE PREPARE stmt;
SELECT meta FROM test_ps where id = 1;  -- ok
SELECT meta FROM test_ps where id = 2;  -- panic

Root cause: FunctionExpressionExecutor.doFold() calls ToConst() on the result vector after constant folding. On the second execution, PreExtendAndReset() calls ResetWithSameType() which clears nsp (null bitmap) but preserves the CONSTANT class. When FunctionResult.AppendBytes(nil, true) is called on a CONSTANT vector, it skips setting the null marker entirely, resulting in a non-null empty byte slice being stored instead of NULL.

Fix: Reset vector class to FLAT in ResetWithSameType(), so the vector is in a clean state for re-population. doFold() will call ToConst() again after evaluation if needed.

@matrix-meow matrix-meow added the size/S Denotes a PR that changes [10,99] lines label Mar 17, 2026
@mergify mergify Bot added the kind/bug Something isn't working label Mar 17, 2026
…stmt null json panic (matrixorigin#23859)

When a prepared statement inserts NULL into a JSON column multiple times,
the second execution panics with 'index out of range [0] with length 0'
in ByteJson.Unmarshal during SELECT.

Root cause: FunctionExpressionExecutor.doFold() calls ToConst() on the
result vector after constant folding. On the second execution,
PreExtendAndReset() calls ResetWithSameType() which clears nsp but
preserves the CONSTANT class. When FunctionResult.AppendBytes(nil, true)
is called on a CONSTANT vector, it skips setting the null marker,
resulting in a non-null empty byte slice being stored instead of NULL.

Fix: Reset vector class to FLAT in ResetWithSameType(), so the vector
is in a clean state for re-population. doFold() will call ToConst()
again after evaluation if needed.
@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented Mar 17, 2026

Merge Queue Status

  • Entered queue2026-03-17 14:32 UTC · Rule: main
  • Checks passed · in-place
  • Merged2026-03-17 21:44 UTC · at 2a169aaceb6806abd7dba0435fcdb34bafb9ffb4

This pull request spent 7 hours 11 minutes 12 seconds in the queue, including 5 hours 43 minutes 10 seconds running CI.

Required conditions to merge
  • #approved-reviews-by >= 1 [🛡 GitHub branch protection]
  • #changes-requested-reviews-by = 0 [🛡 GitHub branch protection]
  • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
  • branch-protection-review-decision = APPROVED [🛡 GitHub branch protection]
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
    • check-neutral = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
    • check-skipped = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
    • check-neutral = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
    • check-skipped = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / SCA Test on Ubuntu/x86
    • check-neutral = Matrixone CI / SCA Test on Ubuntu/x86
    • check-skipped = Matrixone CI / SCA Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
    • check-neutral = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
    • check-skipped = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
    • check-neutral = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
    • check-skipped = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Utils CI / Coverage
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage

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

Labels

kind/bug Something isn't working size/M Denotes a PR that changes [100,499] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants