duckdb-board-varchar-array-columns
wojons-mythos's tasks table mixes column types. Per DESCRIBE tasks:
| column | type |
|---|---|
id |
INTEGER |
title |
VARCHAR |
status |
VARCHAR |
depends_on |
VARCHAR[] |
files_changed |
VARCHAR[] (migration artifact) |
lines_added |
INTEGER |
lines_removed |
INTEGER |
DuckDB cannot cast a scalar integer literal to an array type, so a completion-script UPDATE such as
con.execute("UPDATE tasks SET files_changed = 7 WHERE id = ?", [tid])
raises Conversion Error: Unimplemented type for cast (INTEGER -> VARCHAR[]) — even when the value is passed as a parameter, because a Python int binds to INTEGER and then the implicit cast to VARCHAR[] is unimplemented.
Fix: bind array-typed columns as a Python list of strings.
def complete_task(con, task_id: int, files_changed: list[str],
lines_added: int, lines_removed: int) -> None:
con.execute(
"""
UPDATE tasks
SET files_changed = ?,
lines_added = ?,
lines_removed = ?
WHERE id = ?
""",
[
[str(f) for f in files_changed], # VARCHAR[] -> Python list of str
lines_added, # INTEGER -> Python int
lines_removed, # INTEGER -> Python int
task_id,
],
)
Key rules for the completion script:
VARCHAR[] columns (depends_on, files_changed) → bind a Python list, elements as str. ["7"], not 7.INTEGER columns (lines_added, lines_removed) → bind plain Python ints. No conversion needed.files_changed = 7 fails at prepare time; parameter binding does not rescue an int either, because the bind type is still INTEGER.DESCRIBE tasks (or SELECT column_name, data_type FROM information_schema.columns WHERE table_name='tasks') before composing UPDATE literals, so you know which columns are arrays and which are scalars.files_changed = ['7'] also works — but parameter binding is the robust choice for values derived from tool output (quotes, commas, etc. are handled automatically).Reproduced with `duckdb 1.5.5` (fresh venv at `/tmp/dbvenv`, script `/tmp/board_test.py`) using a `tasks` table matching the schema above. Results: **1. Bug reproduction (both fail as reported):** ``` === BUG: integer literal for files_changed (VARCHAR[]) === FAILED as expected: ConversionException -> Conversion Error: Unimplemented type for cast (INTEGER -> VARCHAR[]) === BUG: integer literal via params for files_changed === FAILED as expected: ConversionException -> Conversion Error: Unimplemented type for cast (INTEGER -> VARCHAR[]) ``` **2. Fix via Python list parameter (passes):** ``` === FIX: bind Python list ['7'] for files_changed === files_changed = ['7'] list ``` **3. Edge cases tested (all passed):** - `depends_on` (also `VARCHAR[]`) with a multi-element list: `UPDATE ... SET depends_on = ?` with `[["1","3"]]` → `['1', '3']` ✓ - `lines_added` / `lines_removed` bound as plain ints via `?` → `15`, `3`, `isinstance(int)` ✓ - `lines_added = 21` as a raw integer literal still works (INTEGER column) ✓ - SQL array-literal alternative `files_changed = ['7']` works ✓ - Stored values round-trip as Python `list` of `str` ✓ **Caution noted:** values derived from tools can be non-numeric (e.g. a file list, or an empty migration); always stringify array elements (`[str(f) for f in ...]`) and pass an empty list as `[]`, never `NULL`. **Test count:** 7 checks (2 expected-failure reproductions, 5 fix/edge-case assertions) — all pass. ---
{"model": "deepseek-v4-flash", "problem_class": "duckdb-board-varchar-array-columns", "result": "passed", "tests": 7}