[coverage] Conformance findings: STATEMENT-025,STATEMENT-026
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 52/100
Research direction
Start with TestWriteStatementReportsAffectedRowsWithoutAResultSet and TestReusedStatementClearsResultStateAfterAWrite in the coverage PR under tests/, then compare the intended behavior with reference PR 433. Trace the databricks-sql-go statement execution and result metadata paths; done means DML/DDL expose affected counts without a fetchable result set, reused handles report zero columns after writes, and ordinary SELECT results remain correct.
Written by the indexing model from the issue text.
Description
Summary
Surfaced by the multi-language coverage fan-out while conformance-testing these SPEC-IDs against databricks/databricks-sql-go. Each finding is committed as an expected-failure (xfail) test in the coverage PR — the test asserts the CORRECT (post-fix) behavior and stays red until THIS driver (databricks/databricks-sql-go) is fixed, then flips green as a tripwire.
Findings
- STATEMENT-025 [thrift]: Write statements publish the protocol affected-row counter record as a fetchable application result set (insert/cte_insert -> [num_affected_rows num_inserted_rows], merge -> [num_affected_rows num_updated_rows num_deleted_rows num_inserted_rows], DDL -> [Result]) instead of treating it as transport metadata, so an INSERT looks like a one-row SELECT.
- failing test:
TestWriteStatementReportsAffectedRowsWithoutAResultSet(see the coverage PR diff undertests/)
- failing test:
- STATEMENT-025 [sea]: On the SEA/kernel backend the DML counter row is likewise published as a fetchable application result set (insert/cte_insert -> [num_affected_rows num_inserted_rows], merge -> 4 counter columns), so a write is indistinguishable from a one-row SELECT.
- failing test:
TestWriteStatementReportsAffectedRowsWithoutAResultSet(see the coverage PR diff undertests/)
- failing test:
- STATEMENT-026 [thrift]: On a reused connection handle a resultless DML/DDL statement still publishes the counter record as a fetchable result set (write_after_select/prepared_switch_execute -> [num_affected_rows num_inserted_rows], ddl_after_select -> [Result]), so the handle never reports zero result columns after a write.
- failing test:
TestReusedStatementClearsResultStateAfterAWrite(see the coverage PR diff undertests/)
- failing test:
- STATEMENT-026 [sea]: Same reused-handle violation on the SEA/kernel backend: write_after_select and prepared_switch_execute publish [num_affected_rows num_inserted_rows] instead of zero result columns.
- failing test:
TestReusedStatementClearsResultStateAfterAWrite(see the coverage PR diff undertests/)
- failing test:
- STATEMENT-025: A write statement's protocol affected-row counter record is published to the application as a fetchable result set (INSERT/cte_insert -> [num_affected_rows num_inserted_rows], MERGE -> [num_affected_rows num_updated_rows num_deleted_rows num_inserted_rows], DDL -> [Result] on thrift) instead of being treated as transport metadata, so an INSERT looks like a one-row SELECT and callers that branch on "did this statement return rows?" take the wrong branch. Affected on both thrift and sea; the affected-row counts themselves are correct.
- STATEMENT-026: On a reused connection handle a resultless DML/DDL statement still publishes the protocol counter record as a fetchable result set (write_after_select / prepared_switch_execute -> [num_affected_rows num_inserted_rows]; thrift ddl_after_select -> [Result]), so the handle never reports zero result columns after a write. The stale-state half is correct — the previous query's columns are not inherited — but column_count: 0 is violated on both thrift and sea.
Reproduce & Expected
STATEMENT-025 — Validates the RESULT KIND of write statements: a DML statement exposes its affected-row count and NO fetchable result set, and a DDL statement exposes neither.
Reproduce:
INSERT INTO {tableName} VALUES (1, 'a'), (2, 'b')
UPDATE {tableName} SET name = 'c' WHERE id = 2
DELETE FROM {tableName} WHERE id = 1
DELETE FROM {tableName} WHERE id = -12345
MERGE INTO {tableName} AS t
USING (SELECT 2 AS id, 'merged' AS name) AS s
ON t.id = s.id
WHEN MATCHED THEN UPDATE SET t.name = s.name
WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name)
WITH src AS (SELECT 3 AS id, 'd' AS name) INSERT INTO {tableName} SELECT id, name FROM src
ALTER TABLE {tableName} ADD COLUMN extra STRING
TRUNCATE TABLE {tableName}
SELECT CAST(7 AS BIGINT) AS num_affected_rows
WITH c AS (SELECT CAST(7 AS BIGINT) AS num_affected_rows) SELECT * FROM c
TABLE {counterViewName}
Expected (per the shared spec):
- completes without an exception
- completes without an exception
- completes without an exception
- completes without an exception
- completes without an exception
- completes without an exception
- completes without an exception
- completes without an exception
- completes without an exception
- result has exactly 1 row(s)
- result has 1 column(s)
- col 0, row 0 == 7 (type Int64)
- completes without an exception
- result has exactly 1 row(s)
- col 0, row 0 == 7 (type Int64)
- completes without an exception
- result has exactly 1 row(s)
- col 0, row 0 == 7 (type Int64)
- full assertion contract:
result:
- label: insert
no_exception: true
- label: insert
no_result_set: true
- label: insert
affected_row_count: 2
- label: update
no_exception: true
- label: update
no_result_set: true
- label: update
affected_row_count: 1
- label: delete
no_exception: true
- label: delete
no_result_set: true
- label: delete
affected_row_count: 1
- label: delete_zero_rows
no_exception: true
- label: delete_zero_rows
no_result_set: true
- label: delete_zero_rows
affected_row_count: 0
- label: merge
no_exception: true
- label: merge
no_result_set: true
- label: merge
affected_row_count_min: 1
- label: cte_insert
no_exception: true
- label: cte_insert
no_result_set: true
- label: cte_insert
affected_row_count: 1
- label: ddl_alter
no_exception: true
- label: ddl_alter
no_result_set: true
- label: ddl_alter
affected_row_count_not_positive: true
- label: ddl_truncate
no_exception: true
- label: ddl_truncate
no_result_set: true
- label: ddl_truncate
affected_row_count_not_positive: true
- label: counter_select
no_exception: true
- label: counter_select
row_count: 1
- label: counter_select
column_count: 1
- label: counter_select
column:
index: 0
row: 0
type: Int64
equals: 7
- label: counter_cte
no_exception: true
- label: counter_cte
row_count: 1
- label: counter_cte
column:
index: 0
row: 0
type: Int64
equals: 7
- label: counter_table
no_exception: true
- label: counter_table
row_count: 1
- label: counter_table
column:
index: 0
row: 0
type: Int64
equals: 7
STATEMENT-026 — Validates that executing a RESULTLESS statement (DML or DDL) on a statement/handle that previously ran a row-returning query REPLACES the statement's result state rather than leaving the earlier quer…
Reproduce:
SELECT 1 AS a, 'x' AS b
INSERT INTO {tableName} VALUES (1, 'a')
SELECT 42 AS only_col
ALTER TABLE {tableName} ADD COLUMN extra STRING
SELECT 1 AS a, 'x' AS b
INSERT INTO {tableName} VALUES (2, 'b')
Expected (per the shared spec):
- completes without an exception
- result has exactly 1 row(s)
- result has 2 column(s)
- completes without an exception
- result has 0 column(s)
- completes without an exception
- result has exactly 1 row(s)
- result has 1 column(s)
- col 0 is named
only_col - completes without an exception
- result has 0 column(s)
- completes without an exception
- result has 2 column(s)
- completes without an exception
- result has 0 column(s)
- completes without an exception
- full assertion contract:
result:
- label: baseline_select
no_exception: true
- label: baseline_select
row_count: 1
- label: baseline_select
column_count: 2
- label: write_after_select
no_exception: true
- label: write_after_select
no_result_set: true
- label: write_after_select
column_count: 0
- label: write_after_select
affected_row_count: 1
- label: select_after_write
no_exception: true
- label: select_after_write
row_count: 1
- label: select_after_write
column_count: 1
- label: select_after_write
column:
index: 0
name: only_col
- label: ddl_after_select
no_exception: true
- label: ddl_after_select
no_result_set: true
- label: ddl_after_select
column_count: 0
- label: prepared_baseline
no_exception: true
- label: prepared_baseline
metadata_not_null: true
- label: prepared_baseline
column_count: 2
- label: prepared_switch
no_exception: true
- label: prepared_switch
metadata_is_null: true
- label: prepared_switch
column_count: 0
- label: prepared_switch_execute
no_exception: true
- label: prepared_switch_execute
no_result_set: true
- label: prepared_switch_execute
affected_row_count: 1
Context
- The behavior was first fixed in a DIFFERENT driver — reference PR: https://github.com/databricks/databricks-odbc/pull/433 — which seeded the shared language-neutral spec. This issue tracks the same conformance gap in databricks/databricks-sql-go; the reference PR is for cross-referencing the intended behavior, NOT a change to this repo.
- Coverage PR carrying the reproducing xfail test(s): https://github.com/databricks/databricks-driver-test/pull/1629
- Dominant language
- Go
- Stars
- 53
- Forks
- 66
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 21
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from databricks/databricks-sql-go
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
databricks/databricks-sql-go#476 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 55/100
databricks/databricks-sql-go#481 ·
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
databricks/databricks-sql-go#475 · 1 comment ·
-
Difficulty 3/5 1-2 days Newbie friendliness 65/100
databricks/databricks-sql-go#474 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 62/100
databricks/databricks-sql-go#473 ·
All issues in databricks/databricks-sql-go
Similar issues
-
kind/bug needs-triage
Difficulty 1/5 Under an hour Newbie friendliness 72/100
matrixorigin/matrixone#29223 ·
-
needs-acceptance wg/data-plane-networking
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
vllm-project/semantic-router#4024 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
alexgorbatchev/dotfiles#107 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 84/100