---
phase: 40-show-command-alignment
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - src/ddl/list.rs
  - src/ddl/show_dims.rs
  - src/ddl/show_metrics.rs
  - src/ddl/show_facts.rs
  - test/sql/phase34_1_show_commands.test
autonomous: true
requirements: [SHOW-01, SHOW-02, SHOW-03, SHOW-04, SHOW-06, SHOW-07]

must_haves:
  truths:
    - "SHOW SEMANTIC VIEWS returns 5 columns: created_on, name, kind, database_name, schema_name"
    - "SHOW SEMANTIC DIMENSIONS returns 6 columns: database_name, schema_name, semantic_view_name, table_name, name, data_type"
    - "SHOW SEMANTIC METRICS returns 6 columns: database_name, schema_name, semantic_view_name, table_name, name, data_type"
    - "SHOW SEMANTIC FACTS returns 6 columns: database_name, schema_name, semantic_view_name, table_name, name, data_type"
    - "No SHOW command exposes an expr column"
    - "All SHOW commands use table_name not source_table"
  artifacts:
    - path: "src/ddl/list.rs"
      provides: "5-column SHOW VIEWS VTab"
      contains: "SEMANTIC_VIEW"
    - path: "src/ddl/show_dims.rs"
      provides: "6-column SHOW DIMS VTab"
      contains: "database_name"
    - path: "src/ddl/show_metrics.rs"
      provides: "6-column SHOW METRICS VTab"
      contains: "database_name"
    - path: "src/ddl/show_facts.rs"
      provides: "6-column SHOW FACTS VTab with data_type from Fact.output_type"
      contains: "database_name"
    - path: "test/sql/phase34_1_show_commands.test"
      provides: "Updated sqllogictest expectations for 6-column schemas"
      contains: "TTTTTT"
  key_links:
    - from: "src/ddl/list.rs"
      to: "crate::model::SemanticViewDefinition"
      via: "SemanticViewDefinition::from_json() for metadata extraction"
      pattern: "SemanticViewDefinition::from_json"
    - from: "src/ddl/show_facts.rs"
      to: "crate::model::Fact"
      via: "f.output_type.clone().unwrap_or_default() for data_type column"
      pattern: "output_type.*unwrap_or_default"
---

<objective>
Update 4 SHOW SEMANTIC VTab files (list.rs, show_dims.rs, show_metrics.rs, show_facts.rs) to Snowflake-aligned column schemas, and update the phase34_1_show_commands.test sqllogictest expectations.

Purpose: SHOW-01 through SHOW-04, SHOW-06, SHOW-07 require new column schemas with metadata columns and removal of expr/source_table.
Output: 4 updated VTab files + 1 updated test file. `cargo test` passes.
</objective>

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

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/40-show-command-alignment/40-RESEARCH.md
@.planning/phases/39-metadata-storage/39-01-SUMMARY.md

<interfaces>
<!-- Key types and contracts the executor needs. -->

From src/model.rs:
```rust
pub struct SemanticViewDefinition {
    pub base_table: String,
    pub tables: Vec<Table>,
    pub dimensions: Vec<Dimension>,
    pub metrics: Vec<Metric>,
    pub facts: Vec<Fact>,
    pub joins: Vec<Join>,
    // Phase 39 metadata fields:
    #[serde(default)]
    pub created_on: Option<String>,
    #[serde(default)]
    pub database_name: Option<String>,
    #[serde(default)]
    pub schema_name: Option<String>,
}

pub struct Dimension {
    pub name: String,
    pub expr: String,
    pub source_table: Option<String>,
    pub output_type: Option<String>,
}

pub struct Metric {
    pub name: String,
    pub expr: String,
    pub source_table: Option<String>,
    pub output_type: Option<String>,
    pub using_relationships: Vec<String>,
}

pub struct Fact {
    pub name: String,
    pub expr: String,
    pub source_table: Option<String>,
    pub output_type: Option<String>,  // Phase 39 addition
}

impl SemanticViewDefinition {
    pub fn from_json(name: &str, json: &str) -> Result<Self, serde_json::Error>;
}
```

From src/catalog.rs:
```rust
pub type CatalogState = Arc<RwLock<BTreeMap<String, String>>>;
// Keys: view names, Values: JSON strings
```
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Update list.rs and show_facts.rs VTab schemas</name>
  <read_first>
    - src/ddl/list.rs
    - src/ddl/show_facts.rs
    - src/model.rs (lines 190-210 for SVD metadata fields, lines 66-81 for Fact struct)
  </read_first>
  <files>src/ddl/list.rs, src/ddl/show_facts.rs</files>
  <action>
**list.rs (SHOW SEMANTIC VIEWS) -- 2 cols to 5 cols (SHOW-01):**

1. Add `use crate::model::SemanticViewDefinition;` import.
2. Replace `rows: Vec<(String, String)>` with a named struct:
```rust
struct ListRow {
    created_on: String,
    name: String,
    kind: String,
    database_name: String,
    schema_name: String,
}
```
3. Update `ListBindData` to use `rows: Vec<ListRow>`.
4. Update SAFETY comment for `ListBindData` accordingly.
5. In `bind()`, replace the 2 `add_result_column` calls with 5:
   - `"created_on"` (Varchar)
   - `"name"` (Varchar)
   - `"kind"` (Varchar)
   - `"database_name"` (Varchar)
   - `"schema_name"` (Varchar)
6. In `bind()`, replace the manual `serde_json::Value` extraction with `SemanticViewDefinition::from_json()`:
```rust
for (name, json) in guard.iter() {
    let def = SemanticViewDefinition::from_json(name, json).ok();
    let (created_on, database_name, schema_name) = match &def {
        Some(d) => (
            d.created_on.clone().unwrap_or_default(),
            d.database_name.clone().unwrap_or_default(),
            d.schema_name.clone().unwrap_or_default(),
        ),
        None => (String::new(), String::new(), String::new()),
    };
    rows.push(ListRow {
        created_on,
        name: name.clone(),
        kind: "SEMANTIC_VIEW".to_string(),
        database_name,
        schema_name,
    });
}
rows.sort_by(|a, b| a.name.cmp(&b.name));
```
7. In `func()`, update vector emission to 5 columns (indices 0-4):
   - `flat_vector(0)` -> `created_on`
   - `flat_vector(1)` -> `name`
   - `flat_vector(2)` -> `kind`
   - `flat_vector(3)` -> `database_name`
   - `flat_vector(4)` -> `schema_name`
8. Remove the `serde_json` import (it was used for raw JSON parsing; no longer needed).
9. Update doc comments to reflect 5-column schema.

**show_facts.rs (SHOW SEMANTIC FACTS) -- 4 cols to 6 cols (SHOW-04, SHOW-06, SHOW-07):**

1. Update `ShowFactRow` struct: remove `expr`, rename `source_table` to `table_name`, add `database_name`, `schema_name`, `data_type`:
```rust
struct ShowFactRow {
    database_name: String,
    schema_name: String,
    semantic_view_name: String,
    table_name: String,
    name: String,
    data_type: String,
}
```
2. Update `bind_output_columns` to declare 6 columns in order:
   - `"database_name"`, `"schema_name"`, `"semantic_view_name"`, `"table_name"`, `"name"`, `"data_type"` (all Varchar)
3. Update `collect_facts` to propagate `database_name`/`schema_name` from the definition and `data_type` from `f.output_type`:
```rust
fn collect_facts(view_name: &str, json: &str) -> Vec<ShowFactRow> {
    let Ok(def) = SemanticViewDefinition::from_json(view_name, json) else {
        return Vec::new();
    };
    let db_name = def.database_name.clone().unwrap_or_default();
    let sch_name = def.schema_name.clone().unwrap_or_default();
    def.facts
        .iter()
        .map(|f| ShowFactRow {
            database_name: db_name.clone(),
            schema_name: sch_name.clone(),
            semantic_view_name: view_name.to_string(),
            table_name: f.source_table.clone().unwrap_or_default(),
            name: f.name.clone(),
            data_type: f.output_type.clone().unwrap_or_default(),
        })
        .collect()
}
```
4. Update `emit_rows` to emit 6 columns (indices 0-5):
   - `flat_vector(0)` -> `database_name`
   - `flat_vector(1)` -> `schema_name`
   - `flat_vector(2)` -> `semantic_view_name`
   - `flat_vector(3)` -> `table_name`
   - `flat_vector(4)` -> `name`
   - `flat_vector(5)` -> `data_type`
5. Update doc comments to reflect 6-column schema.
  </action>
  <verify>
    <automated>cd /Users/paul/Documents/Dev/Personal/duckdb-semantic-views && cargo check 2>&1 | tail -5</automated>
  </verify>
  <acceptance_criteria>
    - `list.rs` contains `"created_on"` column declaration
    - `list.rs` contains `"kind"` column declaration
    - `list.rs` contains `"SEMANTIC_VIEW"` string literal
    - `list.rs` contains `SemanticViewDefinition::from_json`
    - `list.rs` does NOT contain `"base_table"` column name
    - `list.rs` does NOT contain `serde_json::Value`
    - `show_facts.rs` contains `"database_name"` column declaration
    - `show_facts.rs` contains `"data_type"` column declaration
    - `show_facts.rs` does NOT contain `"expr"` column declaration
    - `show_facts.rs` does NOT contain `"source_table"` column name (uses `"table_name"`)
    - `show_facts.rs` contains `output_type.clone().unwrap_or_default()`
    - `cargo check` succeeds
  </acceptance_criteria>
  <done>list.rs emits 5 Snowflake-aligned columns with metadata from SVD; show_facts.rs emits 6 columns with data_type from Fact.output_type; both compile cleanly</done>
</task>

<task type="auto">
  <name>Task 2: Update show_dims.rs, show_metrics.rs, and phase34_1_show_commands.test</name>
  <read_first>
    - src/ddl/show_dims.rs
    - src/ddl/show_metrics.rs
    - test/sql/phase34_1_show_commands.test
  </read_first>
  <files>src/ddl/show_dims.rs, src/ddl/show_metrics.rs, test/sql/phase34_1_show_commands.test</files>
  <action>
**show_dims.rs (SHOW SEMANTIC DIMENSIONS) -- 5 cols to 6 cols (SHOW-02, SHOW-06, SHOW-07):**

1. Update `ShowDimRow` struct: remove `expr`, rename `source_table` to `table_name`, add `database_name` and `schema_name`:
```rust
struct ShowDimRow {
    database_name: String,
    schema_name: String,
    semantic_view_name: String,
    table_name: String,
    name: String,
    data_type: String,
}
```
2. Update `bind_output_columns` to declare 6 columns:
   - `"database_name"`, `"schema_name"`, `"semantic_view_name"`, `"table_name"`, `"name"`, `"data_type"` (all Varchar)
3. Update `collect_dims` to propagate `database_name`/`schema_name` from the definition:
```rust
fn collect_dims(view_name: &str, json: &str) -> Vec<ShowDimRow> {
    let Ok(def) = SemanticViewDefinition::from_json(view_name, json) else {
        return Vec::new();
    };
    let db_name = def.database_name.clone().unwrap_or_default();
    let sch_name = def.schema_name.clone().unwrap_or_default();
    def.dimensions
        .iter()
        .map(|d| ShowDimRow {
            database_name: db_name.clone(),
            schema_name: sch_name.clone(),
            semantic_view_name: view_name.to_string(),
            table_name: d.source_table.clone().unwrap_or_default(),
            name: d.name.clone(),
            data_type: d.output_type.clone().unwrap_or_default(),
        })
        .collect()
}
```
4. Update `emit_rows` to emit 6 columns (indices 0-5):
   - `flat_vector(0)` -> `database_name`
   - `flat_vector(1)` -> `schema_name`
   - `flat_vector(2)` -> `semantic_view_name`
   - `flat_vector(3)` -> `table_name`
   - `flat_vector(4)` -> `name`
   - `flat_vector(5)` -> `data_type`
5. Update doc comments.

**show_metrics.rs (SHOW SEMANTIC METRICS) -- identical pattern to show_dims.rs (SHOW-03, SHOW-06, SHOW-07):**

Apply the exact same transformation as show_dims.rs but for metrics:
1. Update `ShowMetricRow`: remove `expr`, rename `source_table` to `table_name`, add `database_name`, `schema_name`.
2. Update `bind_output_columns`: 6 columns same as dims.
3. Update `collect_metrics`: propagate `database_name`/`schema_name`, use `m.source_table` -> `table_name`, `m.output_type` -> `data_type`.
4. Update `emit_rows`: 6 flat_vectors (indices 0-5).
5. Update doc comments.

**phase34_1_show_commands.test -- update expected output for new schemas:**

1. **SHOW SEMANTIC DIMENSIONS tests (Tests 1, 2, 8):** Change `query TTTTT` to `query TTTTTT`. Update expected rows to 6-column format. The new row format is:
   `memory	main	{view_name}	{table_alias}	{dim_name}	(empty)`
   where `database_name=memory`, `schema_name=main` (standard sqllogictest in-memory values), `expr` column is removed, `source_table` is now `table_name` (same value, just renamed column).

   Example for Test 1 (SHOW SEMANTIC DIMENSIONS IN orders_sv):
   ```
   query TTTTTT rowsort
   SHOW SEMANTIC DIMENSIONS IN orders_sv
   ----
   memory	main	orders_sv	c	customer_name	(empty)
   memory	main	orders_sv	c	region	(empty)
   memory	main	orders_sv	o	order_date	(empty)
   ```
   Note: rowsort sorts lexicographically across all columns. The previous sort was by `semantic_view_name` first (col 0), now `database_name` is col 0 so all rows have `memory` as col 0 and `main` as col 1 -- the effective sort is still by `semantic_view_name` (col 2) then by remaining cols.

2. **SHOW SEMANTIC METRICS tests (Tests 3, 4):** Change `query TTTTT` to `query TTTTTT`. Same pattern:
   `memory	main	{view_name}	{table_alias}	{metric_name}	(empty)`

   Example for Test 3:
   ```
   query TTTTTT rowsort
   SHOW SEMANTIC METRICS IN orders_sv
   ----
   memory	main	orders_sv	o	order_count	(empty)
   memory	main	orders_sv	o	total_amount	(empty)
   ```

3. **SHOW SEMANTIC FACTS tests (Tests 5, 6):** Change `query TTTT` to `query TTTTTT`. New format:
   `memory	main	{view_name}	{table_alias}	{fact_name}	(empty)`
   The last `(empty)` is `data_type` -- will show the inferred fact type. Since the test creates tables with `DECIMAL(10,2)` for `amount`, the fact `o.raw_amount AS o.amount` should have `output_type` inferred. However, the Phase 39 type inference uses `typeof()` which returns the DuckDB type name. For `DECIMAL(10,2)`, DuckDB `typeof()` returns `DECIMAL(10,2)`. So expect `DECIMAL(10,2)` for `raw_amount`.

   IMPORTANT: Verify by checking what Phase 39's type inference produces. If uncertain, use `(empty)` and adjust after running tests.

   Example for Test 5:
   ```
   query TTTTTT rowsort
   SHOW SEMANTIC FACTS IN orders_sv
   ----
   memory	main	orders_sv	o	raw_amount	DECIMAL(10,2)
   ```

4. Update sort expectations: With `rowsort`, the full row string is sorted lexicographically. Since `database_name` and `schema_name` are now the first two columns and are identical across all rows (both `memory` and `main`), the effective sort is by `semantic_view_name` then remaining columns -- same as before.
  </action>
  <verify>
    <automated>cd /Users/paul/Documents/Dev/Personal/duckdb-semantic-views && cargo check 2>&1 | tail -5</automated>
  </verify>
  <acceptance_criteria>
    - `show_dims.rs` contains `"database_name"` column declaration
    - `show_dims.rs` does NOT contain `"expr"` column declaration
    - `show_dims.rs` does NOT contain `"source_table"` column name
    - `show_dims.rs` contains `flat_vector(5)` (6th column, 0-indexed)
    - `show_metrics.rs` contains `"database_name"` column declaration
    - `show_metrics.rs` does NOT contain `"expr"` column declaration
    - `show_metrics.rs` does NOT contain `"source_table"` column name
    - `phase34_1_show_commands.test` contains `query TTTTTT` (6 T's for dims/metrics/facts)
    - `phase34_1_show_commands.test` does NOT contain `query TTTTT ` (5 T's followed by space, old dims/metrics format)
    - `phase34_1_show_commands.test` does NOT contain `query TTTT ` (4 T's followed by space, old facts format)
    - `phase34_1_show_commands.test` contains `memory` (database_name in expected output)
    - `cargo check` succeeds
  </acceptance_criteria>
  <done>show_dims.rs and show_metrics.rs emit 6-column Snowflake-aligned schemas; phase34_1_show_commands.test expectations match new schemas; all code compiles</done>
</task>

</tasks>

<verification>
After both tasks complete:
1. `cargo check` passes (compile-time validation)
2. `cargo test` passes (unit tests -- the VTab schema changes don't affect unit tests since VTab tests run through sqllogictest)
3. Note: `just test-sql` will NOT fully pass yet because `phase34_1_1_show_filtering.test` and `phase34_1_show_dims_for_metric.test` still reference old schemas -- those are updated in Plan 02.
</verification>

<success_criteria>
- list.rs outputs 5 columns: created_on, name, kind, database_name, schema_name (SHOW-01)
- show_dims.rs outputs 6 columns: database_name, schema_name, semantic_view_name, table_name, name, data_type (SHOW-02)
- show_metrics.rs outputs 6 columns: database_name, schema_name, semantic_view_name, table_name, name, data_type (SHOW-03)
- show_facts.rs outputs 6 columns: database_name, schema_name, semantic_view_name, table_name, name, data_type (SHOW-04)
- No VTab file contains an "expr" column declaration (SHOW-06)
- No VTab file contains a "source_table" column name (SHOW-07)
- phase34_1_show_commands.test expectations match new column schemas
- `cargo check` passes
</success_criteria>

<output>
After completion, create `.planning/phases/40-show-command-alignment/40-01-SUMMARY.md`
</output>
