---
phase: quick
plan: 260322-s2y
type: execute
wave: 1
depends_on: []
files_modified:
  - src/parse.rs
  - test/sql/phase34_1_1_show_filtering.test
autonomous: true
must_haves:
  truths:
    - "SHOW SEMANTIC VIEWS LIKE '%pattern%' filters views by name (case-insensitive)"
    - "SHOW SEMANTIC VIEWS STARTS WITH 'prefix' filters views by name prefix (case-sensitive)"
    - "SHOW SEMANTIC VIEWS LIMIT N returns at most N rows"
    - "All three clauses compose: LIKE + STARTS WITH + LIMIT"
    - "Unfiltered SHOW SEMANTIC VIEWS still works (no regression)"
  artifacts:
    - path: "src/parse.rs"
      provides: "Filter clause parsing for DdlKind::Show"
      contains: "DdlKind::Show =>"
    - path: "test/sql/phase34_1_1_show_filtering.test"
      provides: "sqllogictest cases for SHOW SEMANTIC VIEWS filtering"
      contains: "SHOW SEMANTIC VIEWS LIKE"
  key_links:
    - from: "src/parse.rs rewrite_ddl DdlKind::Show arm"
      to: "parse_show_filter_clauses + build_filter_suffix"
      via: "clause parsing and SQL suffix injection"
      pattern: "build_filter_suffix"
---

<objective>
Add LIKE, STARTS WITH, and LIMIT filtering to SHOW SEMANTIC VIEWS.

Purpose: Complete Snowflake parity -- the other three SHOW commands (DIMENSIONS, METRICS, FACTS) already support these clauses but SHOW SEMANTIC VIEWS was left as a bare no-args rewrite.

Output: Updated parse.rs with filter support for DdlKind::Show, new unit tests, new sqllogictest cases appended to the existing filtering test file.
</objective>

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

<context>
@.planning/STATE.md
@src/parse.rs
@test/sql/phase34_1_1_show_filtering.test

<interfaces>
<!-- Key functions and types the executor needs. Extracted from src/parse.rs. -->

From src/parse.rs (lines 267-290) -- fully reusable, no changes needed:
```rust
fn build_filter_suffix(
    like_pattern: Option<&str>,
    starts_with: Option<&str>,
    limit: Option<u64>,
) -> String
```

From src/parse.rs (lines 292-427) -- needs DdlKind::Show added to its match:
```rust
struct ShowClauses<'a> {
    like_pattern: Option<String>,
    in_view: Option<&'a str>,
    for_metric: Option<&'a str>,
    starts_with: Option<String>,
    limit: Option<u64>,
}

fn parse_show_filter_clauses<'a>(
    after_prefix: &'a str,
    kind: DdlKind,
) -> Result<ShowClauses<'a>, String>
```

Current DdlKind::Show arm (line 457) -- this is what we replace:
```rust
DdlKind::Show => Ok(format!("SELECT * FROM {fn_name}()")),
```

The VTab `list_semantic_views()` returns columns: `(name VARCHAR, base_table VARCHAR)`.
The `name` column is what LIKE/STARTS WITH filters target (same as other SHOW commands).
</interfaces>
</context>

<tasks>

<task type="auto" tdd="true">
  <name>Task 1: Extend parse_show_filter_clauses and rewrite_ddl for DdlKind::Show</name>
  <files>src/parse.rs</files>
  <behavior>
    - SHOW SEMANTIC VIEWS (no clauses) -> "SELECT * FROM list_semantic_views()" (no regression)
    - SHOW SEMANTIC VIEWS LIKE '%pat%' -> "SELECT * FROM list_semantic_views() WHERE name ILIKE '%pat%'"
    - SHOW SEMANTIC VIEWS STARTS WITH 'pre' -> "SELECT * FROM list_semantic_views() WHERE name LIKE 'pre%'"
    - SHOW SEMANTIC VIEWS LIMIT 5 -> "SELECT * FROM list_semantic_views() LIMIT 5"
    - SHOW SEMANTIC VIEWS LIKE '%x%' STARTS WITH 'a' LIMIT 3 -> all three composed
    - SHOW SEMANTIC VIEWS IN should error (IN is not valid for SHOW VIEWS -- there is no scoping view)
    - SHOW SEMANTIC VIEWS FOR METRIC should error (FOR METRIC is only for SHOW DIMENSIONS)
    - Single-quote in pattern is SQL-escaped (existing behavior of extract_quoted_string)
  </behavior>
  <action>
Two changes in src/parse.rs:

1. **parse_show_filter_clauses** (line 315 entity match): Add `DdlKind::Show => "VIEWS"` to the entity match arm. Then in the IN clause section (line 332), add a guard: if `kind == DdlKind::Show`, return an error like "IN is not valid for SHOW SEMANTIC VIEWS (no scoping view)". The FOR METRIC section already rejects non-ShowDimensions kinds. The error messages in step 6 (unexpected tokens) should include the VIEWS usage string when kind is Show. The resulting ShowClauses will have in_view=None and for_metric=None for DdlKind::Show, which is correct.

2. **rewrite_ddl** (line 457): Replace the one-liner `DdlKind::Show => Ok(format!("SELECT * FROM {fn_name}()"))` with the same pattern used by ShowDimensions/ShowMetrics/ShowFacts (lines 459-496). Specifically:
   - Parse after_prefix: `let after_prefix = trimmed[plen..].trim();`
   - Call `parse_show_filter_clauses(after_prefix, kind)?`
   - The base query is always `format!("SELECT * FROM {fn_name}()")` (no IN variant for SHOW VIEWS)
   - Append `build_filter_suffix(clauses.like_pattern.as_deref(), clauses.starts_with.as_deref(), clauses.limit)`
   - Return the combined string

Move DdlKind::Show into the same match arm as ShowDimensions/ShowMetrics/ShowFacts to avoid code duplication. The only difference is that DdlKind::Show always uses `format!("SELECT * FROM {fn_name}()")` as base (no IN scoping, no _all variant). Inside the `if let Some(view_name) = clauses.in_view` block, DdlKind::Show will never enter (guarded by parse_show_filter_clauses rejecting IN for Show).

Add unit tests in the existing `mod tests` block near line 1987, following the same pattern:
- test_rewrite_show_views_like: `SHOW SEMANTIC VIEWS LIKE '%prod%'` -> `SELECT * FROM list_semantic_views() WHERE name ILIKE '%prod%'`
- test_rewrite_show_views_starts_with_limit: `SHOW SEMANTIC VIEWS STARTS WITH 'sales' LIMIT 5` -> expected SQL
- test_rewrite_show_views_all_clauses: `SHOW SEMANTIC VIEWS LIKE '%x%' STARTS WITH 'a' LIMIT 3` -> composed
- test_rewrite_show_views_in_error: `SHOW SEMANTIC VIEWS IN some_view` -> should be Err
- test_rewrite_show_views_for_metric_error: `SHOW SEMANTIC VIEWS FOR METRIC m` -> should be Err
- test_rewrite_show_views_no_clauses_regression: `SHOW SEMANTIC VIEWS` -> unchanged `SELECT * FROM list_semantic_views()`
  </action>
  <verify>
    <automated>cd /Users/paul/Documents/Dev/Personal/duckdb-semantic-views && cargo test -- test_rewrite_show 2>&1 | tail -20</automated>
  </verify>
  <done>All unit tests pass. SHOW SEMANTIC VIEWS rewrites with LIKE, STARTS WITH, LIMIT produce correct SQL. IN and FOR METRIC are rejected with clear errors. Bare SHOW SEMANTIC VIEWS still works.</done>
</task>

<task type="auto">
  <name>Task 2: Add sqllogictest cases for SHOW SEMANTIC VIEWS filtering</name>
  <files>test/sql/phase34_1_1_show_filtering.test</files>
  <action>
Append new test cases to the END of test/sql/phase34_1_1_show_filtering.test (after the existing ~220 lines). The existing setup (filter_sv and products_sv) is already sufficient -- two views exist so filtering is meaningful.

Add these sqllogictest cases:

**Test: SHOW SEMANTIC VIEWS LIKE '%filter%'** -- matches filter_sv only
```
query TT rowsort
SHOW SEMANTIC VIEWS LIKE '%filter%'
----
filter_sv	(result depends on base table -- use the actual base table name)
```
Note: list_semantic_views() returns (name VARCHAR, base_table VARCHAR). Check what base_table returns for these views by examining the VTab. The test setup uses `CREATE SEMANTIC VIEW filter_sv AS TABLES (c AS p3411_customers ...)` -- the first table alias is likely the base_table. Verify by running `SHOW SEMANTIC VIEWS` against the setup and observing the output columns. If unclear, use `query TT rowsort` and fill in expected output after a test run.

**Test: SHOW SEMANTIC VIEWS LIKE '%sv'** -- matches both filter_sv and products_sv (both end in _sv)

**Test: SHOW SEMANTIC VIEWS STARTS WITH 'filter'** -- matches filter_sv only (case-sensitive)

**Test: SHOW SEMANTIC VIEWS STARTS WITH 'Filter'** -- no matches (wrong case)

**Test: SHOW SEMANTIC VIEWS LIMIT 1** -- returns exactly 1 row

**Test: SHOW SEMANTIC VIEWS LIKE '%sv' LIMIT 1** -- both match but limited to 1

**Test: SHOW SEMANTIC VIEWS LIKE '%sv' STARTS WITH 'prod' LIMIT 10** -- only products_sv matches both conditions

**Error test: SHOW SEMANTIC VIEWS IN some_view** -- statement error, "IN is not valid"

**Error test: SHOW SEMANTIC VIEWS FOR METRIC m** -- statement error, "FOR METRIC is only valid"

For the expected output: Run the test once with `just build && just test-sql` to discover the actual base_table values, then update expected output to match. The base_table column for a multi-table semantic view might be empty or show the first table -- adjust assertions accordingly.
  </action>
  <verify>
    <automated>cd /Users/paul/Documents/Dev/Personal/duckdb-semantic-views && just build && just test-sql 2>&1 | tail -20</automated>
  </verify>
  <done>All sqllogictest cases pass including the new SHOW SEMANTIC VIEWS filter tests. Existing tests still pass (no regressions).</done>
</task>

</tasks>

<verification>
Run the full quality gate to ensure no regressions:

```bash
just test-all
```

This runs cargo test (unit + proptest), sqllogictest, and DuckLake CI tests.
</verification>

<success_criteria>
- `SHOW SEMANTIC VIEWS LIKE '%pattern%'` filters by name (case-insensitive)
- `SHOW SEMANTIC VIEWS STARTS WITH 'prefix'` filters by name prefix (case-sensitive)
- `SHOW SEMANTIC VIEWS LIMIT N` caps output to N rows
- All three clauses compose in standard Snowflake order
- `SHOW SEMANTIC VIEWS IN ...` produces a clear error (IN not valid for views)
- `SHOW SEMANTIC VIEWS FOR METRIC ...` produces a clear error
- Bare `SHOW SEMANTIC VIEWS` still works (regression test)
- `just test-all` passes
</success_criteria>

<output>
After completion, create `.planning/quick/260322-s2y-add-like-starts-with-limit-filtering-to-/260322-s2y-SUMMARY.md`
</output>
