Skip to content

getGeneratedKeys returns 0 after batch failure with rewriteBatchedStatements in text protocol, historical regression expects 2 #1279

Description

@cms-cms

Environment

  • OceanBase Version (SeekDB): 5.7.25-OceanBase seekdb-v
  • Observer Revision: 1-f84169fbd80d020887d038cdb0892703e28833f3
  • Observer Build Time: Aug 10 2026 10:45:34
  • Observer Build Flags: RelWithDebInfo
  • JDBC Driver: com.oceanbase:oceanbase-client:2.4.16-SERVER_LITE-SNAPSHOT
  • Test Pipeline: [INTERNAL_URL]
  • Test Job: [INTERNAL_URL]
  • seekdb_test SHA: a1a3df9543b0a778bad60a0e4574d522fc473c4e
  • oceanbase-lite SHA: f84169fbd80d020887d038cdb0892703e28833f3

Description

When running the objdbctest GeneratedKeysTest.testBatchedError on SeekDB 1.3, the test fails only in text protocol.

Test Scenario Configuration:

  • useServerPrepStmts=false
  • rewriteBatchedStatements=true
  • allowMultiQueries=true
  • continueBatchOnError=false
  • Statement.RETURN_GENERATED_KEYS

A batch of 5 inserts is executed. The third item intentionally writes the string "a" into an INT column to trigger a type conversion error. After executeLargeBatch throws a BatchUpdateException, ps.getGeneratedKeys() returns 0 rows, while the existing historical regression test case expects it to return 2 keys (for the first two successful inserts).

The test annotation references a historical issue: "When an error occurs in the middle of a JDBC multi-statement insert with batched_multi_statement enabled, the returned last_insert_id is incorrect" (workItemId=2024080100104016016). Therefore, the expectation of "2" is likely an intentional regression check.

Steps to Reproduce

  1. Create the test table:
    CREATE TABLE t_br (
      id INT AUTO_INCREMENT PRIMARY KEY,
      n INT
    );
  2. Use a JDBC connection with the parameters listed above.
  3. Prepare a statement:
    PreparedStatement ps = conn.prepareStatement(
        "INSERT INTO t_br (n) VALUES (?)",
        Statement.RETURN_GENERATED_KEYS);
  4. Add batch parameters in order: 1, 2, "a", 4, 5.
  5. Execute: ps.executeLargeBatch(); (This throws a BatchUpdateException).
  6. Call: ps.getGeneratedKeys();

Actual Results:

  • BatchUpdateException.getLargeUpdateCounts() outputs: [-3, -3, -3, -3]
  • getGeneratedKeys() returns row count: 0
  • Test assertion fails: java.lang.AssertionError: expected:<0> but was:<2> (Note: The test is written as assertEquals(num, 2), so the correct interpretation is num=0 but the test requires num=2).

Protocol Comparison:

Protocol useServerPrepStmts Test Result GeneratedKeys Expectation
prepare_execute_protocol true PASS Test explicitly expects empty
prepare_protocol true PASS Test explicitly expects empty
text_protocol false FAIL Historical test expects 2, actual 0

Other related tests (testRewriteBatched, testStmtGetGeneratedKeys, testPrepStmtGeneratedKeys) in the same run pass, so not all GeneratedKeys functionality is broken.

Impact

This issue blocks the complete physical regression of the SeekDB Linux objdbctest.

Analysis & Questions for Developers

Key observations from the database state after failure:

  • SHOW CREATE TABLE t_br shows: AUTO_INCREMENT = 6
  • SELECT COUNT(*) FROM t_br; returns: 0

This suggests:

  • 5 auto-increment values have been allocated.
  • No records were committed from the entire statement.
  • JDBC getGeneratedKeys returns 0 rows.

This behavior is closer to "a single multi-value INSERT that fails atomically", while the historical test expectation is closer to "multi-statement where the first two succeed and two keys are returned".

Questions for JDBC/Connector developers (priority) and database kernel:

  1. In OceanBase JDBC with text protocol + rewriteBatchedStatements=true, is the above batch ultimately sent as:
    a) A single multi-value INSERT statement, or
    b) A multi-statement composed of multiple INSERTs?
    This determines whether 0 or 2 GeneratedKeys is the correct compatible behavior.

  2. With continueBatchOnError=false and the third item failing, what is the MySQL-compatible semantic?
    a) The entire batch fails atomically, getGeneratedKeys returns 0; or
    b) The first two items succeed, getGeneratedKeys returns 2?

  3. Are the error packet, affected rows, and last_insert_id returned by the server sufficient for the driver to correctly generate the GeneratedKeys?

  4. Why does getLargeUpdateCounts for a five-item batch only return four -3 values?

  5. Please perform a control test using the same driver version on MySQL to confirm the compatibility baseline.

Proposed Solution / Acceptance Criteria

Before simply changing the test expectation from 2 to 0, the compatible semantics for the above scenario must be clearly defined. It is recommended to supplement regression tests for the following matrix:

  • useServerPrepStmts=true/false
  • rewriteBatchedStatements=true/false
  • continueBatchOnError=true/false
  • Error located at the beginning, middle, or end of the batch
  • Validate updateCounts, GeneratedKeys, table records, and AUTO_INCREMENT values.

Logs & Evidence

  • Failure Time: 2026-08-10 10:54:17.483 - 10:54:17.510
  • Server Trace ID: YB427F000001-000658A860426632-0-0
  • Server Error Codes: ob_error=-4226, client error=1366
  • Server Transaction Log Indicates: context.exec_error_=-4226, context.is_rollback_=true, rollback=true, need_rollback=true, trans_result.touched_storage=false
  • Corresponding Error Packet: sending error packet( ob_error=-4226, client error=1366 )

Log Locations:

  • Workload complete log: /obdata/data/hudson/seekdb-gitlab/objdbctest/runs/pipeline-189961-job-919123/singlejob-logs/objdbctest-cycle-1-text_protocol.log
  • Observer log: /obdata/data/hudson/seekdb-gitlab/objdbctest/log/pipeline-189961-job-919123/seekdb.log.20260810110209777 (precise lines: 233317-233320)
  • Database data directory: /obdata/data/hudson/seekdb-gitlab/objdbctest/data/pipeline-189961-job-919123
  • Clog directory: /obdata/data/hudson/seekdb-gitlab/objdbctest/clog/pipeline-189961-job-919123
  • Database PID: 2187220

Database Connection Info (Preserved):

  • CLI: obclient -h -P5044 -uroot@sys -Dtest (password is empty)
  • JDBC: jdbc:oceanbase://:5044/test?user=root@sys&password=&useServerPrepStmts=false&rewriteBatchedStatements=true&allowMultiQueries=true&continueBatchOnError=false&useAffectedRows=true

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions