---
phase: 21-error-location-reporting
plan: 02
type: execute
wave: 2
depends_on: ["21-01"]
files_modified:
  - test/sql/phase21_error_reporting.test
  - test/sql/TEST_LIST
autonomous: true
requirements: [ERR-01, ERR-02, ERR-03]

must_haves:
  truths:
    - "Malformed DDL through the loaded extension shows clause-level error messages"
    - "Error output from DuckDB includes a caret (^) pointing at the error location in the original DDL text"
    - "Near-miss DDL prefix typos produce 'Did you mean' suggestions through the extension"
    - "All existing tests still pass (no regressions from the validation layer)"
  artifacts:
    - path: "test/sql/phase21_error_reporting.test"
      provides: "sqllogictest integration tests for error reporting through full extension pipeline"
      min_lines: 40
  key_links:
    - from: "test/sql/phase21_error_reporting.test"
      to: "cpp/src/shim.cpp"
      via: "DuckDB extension load -> parser hook -> sv_validate_ddl_rust -> DISPLAY_EXTENSION_ERROR"
      pattern: "require semantic_views"
    - from: "test/sql/phase21_error_reporting.test"
      to: "src/parse.rs"
      via: "Validation functions called from sv_parse_stub through FFI"
      pattern: "statement error"
---

<objective>
Create integration tests that verify error messages render correctly through the full DuckDB extension load pipeline, including caret position rendering. Run the complete test suite to confirm no regressions.

Purpose: Unit tests (Plan 01) verify logic in isolation. This plan proves the errors flow correctly through DuckDB's parser extension error path and render carets in sqllogictest output.
Output: New test/sql/phase21_error_reporting.test file, all tests green via `just test-all`.
</objective>

<execution_context>
@/Users/paul/.claude/get-shit-done/workflows/execute-plan.md
@/Users/paul/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/21-error-location-reporting/21-CONTEXT.md
@.planning/phases/21-error-location-reporting/21-RESEARCH.md
@.planning/phases/21-error-location-reporting/21-01-SUMMARY.md

<interfaces>
<!-- Patterns from existing sqllogictest files for error testing -->

From test/sql/phase20_extended_ddl.test (error test pattern):
```sql
# Error testing pattern in sqllogictest:
statement error
DROP SEMANTIC VIEW sv_nonexistent;
----
does not exist

# The text after ---- is a substring match against the error message.
# DuckDB includes the error message text; the caret line is part of the output.
```

From DuckDB error rendering (confirmed in RESEARCH.md):
```
# When error_location is set, DuckDB renders:
# Error: <message>
# LINE 1: <original query>
#          ^
# The caret (^) points at the byte offset specified by error_location.
```

From RESEARCH.md (key constraint):
```
# sqllogictest `statement error` matches a SUBSTRING of the error message.
# It does NOT match the caret line or LINE marker.
# So tests should match on the error message text, not on caret position.
# Caret rendering verification needs manual spot-checking or a custom test.
```
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Integration test file for error reporting through extension load</name>
  <files>test/sql/phase21_error_reporting.test, test/sql/TEST_LIST</files>
  <action>
Create `test/sql/phase21_error_reporting.test` with sqllogictest format testing all error scenarios through the full extension pipeline.

Structure the test file with these sections:

```
# Phase 21: Error location reporting integration tests
# Verifies error messages flow through DuckDB's parser extension error path
# with clause-level hints (ERR-01), character positions (ERR-02), and
# "did you mean" suggestions (ERR-03).

require semantic_views
```

**Section 1: ERR-01 -- Clause-level error hints**

Test missing required clauses in CREATE body:
```sql
# Missing tables clause
statement error
CREATE SEMANTIC VIEW err_test (
    dimensions := [{'name': 'x', 'expr': 'x', 'source_table': 'y'}]
);
----
tables

# Empty body
statement error
CREATE SEMANTIC VIEW err_test ();
----
Expected clause definitions

# Missing dimensions/metrics (only tables present)
statement error
CREATE SEMANTIC VIEW err_test (
    tables := [{'alias': 't', 'table': 't'}]
);
----
dimensions
```

Test misspelled clause keyword:
```sql
# Typo in clause name
statement error
CREATE SEMANTIC VIEW err_test (
    tbles := [{'alias': 't', 'table': 't'}],
    dimensions := [{'name': 'x', 'expr': 'x', 'source_table': 't'}]
);
----
Did you mean
```

**Section 2: ERR-02 -- Character position (caret rendering)**

Caret rendering is difficult to assert in sqllogictest (it matches error message substring, not full output). But we can verify that positioned errors don't crash and produce the expected message text. The caret rendering itself is a DuckDB framework feature that works if error_location is set correctly (verified by unit tests in Plan 01).

```sql
# Structural error: missing opening paren
statement error
CREATE SEMANTIC VIEW err_test tables := [];
----
Expected '('
```

**Section 3: ERR-03 -- "Did you mean" suggestions**

Test near-miss DDL prefix:
```sql
# Typo in DDL prefix
statement error
CREAT SEMANTIC VIEW test_view (tables := []);
----
Did you mean

# Another near-miss
statement error
DROP SEMANTC VIEW some_view;
----
Did you mean
```

**Section 4: Non-interference -- normal SQL and valid DDL still work**

```sql
# Setup table for valid DDL test
statement ok
CREATE TABLE err_source (id INT, val DOUBLE);

# Valid CREATE still works
statement ok
CREATE SEMANTIC VIEW err_valid (
    tables := [{'alias': 'err_source', 'table': 'err_source'}],
    dimensions := [{'name': 'id', 'expr': 'id', 'source_table': 'err_source'}],
    metrics := [{'name': 'total', 'expr': 'SUM(val)', 'source_table': 'err_source'}]
);

# Valid DESCRIBE still works
query TTTTTT
DESCRIBE SEMANTIC VIEW err_valid;
----
(verify it returns the expected 6-column row)

# Normal SQL unaffected
query I
SELECT 42;
----
42

# Cleanup
statement ok
DROP SEMANTIC VIEW err_valid;

statement ok
DROP TABLE err_source;
```

Add `test/sql/phase21_error_reporting.test` to `test/sql/TEST_LIST` (append to the list, maintaining alphabetical order or existing convention).

IMPORTANT: The exact error message substrings in the `----` lines must match the actual error messages produced by the Rust validation code from Plan 01. After writing the test file, run `just build && just test-sql` and adjust the substring matches if needed to match the actual error output. The sqllogictest runner matches the text after `----` as a case-sensitive substring of the error message.

IMPORTANT: Build first with `just build` before running `just test-sql` -- sqllogictest requires the compiled extension binary.
  </action>
  <verify>
    <automated>cd /Users/paul/Documents/Dev/Personal/duckdb-semantic-views && just build && just test-all 2>&1 | tail -30</automated>
  </verify>
  <done>phase21_error_reporting.test exists and passes via `just test-sql`. All existing tests pass (cargo test, just test-sql, just test-ducklake-ci). The full `just test-all` suite is green. Error messages for malformed DDL are confirmed to flow through the extension pipeline with clause-level hints and suggestions.</done>
</task>

</tasks>

<verification>
```bash
# Full test suite (quality gate per CLAUDE.md)
cd /Users/paul/Documents/Dev/Personal/duckdb-semantic-views && just test-all
```
</verification>

<success_criteria>
- test/sql/phase21_error_reporting.test exists with tests for all 3 ERR requirements
- Missing clause errors produce clause-level hints through extension load
- Misspelled clause keywords produce "Did you mean" suggestions through extension load
- Near-miss DDL prefix typos produce suggestions through extension load
- Valid DDL and normal SQL are unaffected (no regressions)
- `just test-all` passes (cargo test + sqllogictest + DuckLake CI)
</success_criteria>

<output>
After completion, create `.planning/phases/21-error-location-reporting/21-02-SUMMARY.md`
</output>
