Skip to content

Commit d74bca3

Browse files
committed
Switch from api.prepare() to reader.execute()
1 parent c1aff57 commit d74bca3

12 files changed

Lines changed: 392 additions & 324 deletions

File tree

CLAUDE.md

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -152,28 +152,28 @@ DRAW line MAPPING month AS x, total AS y
152152
### Quick Start
153153

154154
```rust
155-
use ggsql::{prepare, reader::DuckDBReader, writer::VegaLiteWriter};
155+
use ggsql::reader::{DuckDBReader, Reader};
156+
use ggsql::writer::VegaLiteWriter;
156157

157158
// Create a reader
158159
let reader = DuckDBReader::from_connection_string("duckdb://memory")?;
159160

160-
// Prepare the visualization
161-
let prepared = ggsql::prepare(
162-
"SELECT x, y FROM data VISUALISE x, y DRAW point",
163-
&reader
161+
// Execute the ggsql query
162+
let spec = reader.execute(
163+
"SELECT x, y FROM data VISUALISE x, y DRAW point"
164164
)?;
165165

166166
// Render to Vega-Lite JSON
167167
let writer = VegaLiteWriter::new();
168-
let json = prepared.render(&writer)?;
168+
let json = spec.render(&writer)?;
169169
```
170170

171171
### Core Functions
172172

173173
| Function | Purpose |
174174
| ------------------------ | ------------------------------------------------------ |
175-
| `prepare(query, reader)` | Main entry point: parse, execute SQL, resolve mappings |
176-
| `render(writer)` | Generate output (Vega-Lite JSON) from prepared data |
175+
| `reader.execute(query)` | Main entry point: parse, execute SQL, resolve mappings |
176+
| `spec.render(writer)` | Generate output (Vega-Lite JSON) from Spec |
177177
| `validate(query)` | Validate syntax + semantics, inspect query structure |
178178

179179
### Key Types
@@ -188,12 +188,12 @@ let json = prepared.render(&writer)?;
188188
- `errors()` - Validation errors
189189
- `warnings()` - Validation warnings
190190

191-
**`Prepared`** - Result of `prepare()`, ready for rendering:
191+
**`Spec`** - Result of `reader.execute()`, ready for rendering:
192192

193193
- `render(writer)` - Generate output (Vega-Lite JSON)
194194
- `plot()` - Resolved plot specification
195195
- `metadata()` - Rows, columns, layer count
196-
- `warnings()` - Validation warnings from preparation
196+
- `warnings()` - Validation warnings from execution
197197
- `data()` / `layer_data(i)` / `stat_data(i)` - Access DataFrames
198198
- `sql()` / `visual()` / `layer_sql(i)` / `stat_sql(i)` - Query introspection
199199

@@ -869,7 +869,7 @@ When running in Positron IDE, the extension provides enhanced functionality:
869869
**Features**:
870870

871871
- PyO3-based Rust bindings compiled to a native Python extension
872-
- Two-stage API mirroring the Rust API: `prepare()``render()`
872+
- Two-stage API mirroring the Rust API: `reader.execute()``render()`
873873
- DuckDB reader with DataFrame registration
874874
- Custom Python reader support: any object with `execute_sql(sql) -> DataFrame` method
875875
- Works with any narwhals-compatible DataFrame (polars, pandas, etc.)
@@ -897,20 +897,19 @@ reader = ggsql.DuckDBReader("duckdb://memory")
897897
df = pl.DataFrame({"x": [1, 2, 3], "y": [10, 20, 30]})
898898
reader.register("data", df)
899899

900-
# Prepare visualization
901-
prepared = ggsql.prepare(
902-
"SELECT * FROM data VISUALISE x, y DRAW point",
903-
reader
900+
# Execute visualization
901+
spec = reader.execute(
902+
"SELECT * FROM data VISUALISE x, y DRAW point"
904903
)
905904

906905
# Inspect metadata
907-
print(f"Rows: {prepared.metadata()['rows']}")
908-
print(f"Columns: {prepared.metadata()['columns']}")
909-
print(f"SQL: {prepared.sql()}")
906+
print(f"Rows: {spec.metadata()['rows']}")
907+
print(f"Columns: {spec.metadata()['columns']}")
908+
print(f"SQL: {spec.sql()}")
910909

911910
# Render to Vega-Lite JSON
912911
writer = ggsql.VegaLiteWriter()
913-
json_output = prepared.render(writer)
912+
json_output = spec.render(writer)
914913
```
915914

916915
**Convenience Function** (`render_altair`):
@@ -943,22 +942,23 @@ print(f"Errors: {validated.errors()}")
943942

944943
**Classes**:
945944

946-
| Class | Description |
947-
| -------------------------- | -------------------------------------------- |
948-
| `DuckDBReader(connection)` | Database reader with DataFrame registration |
949-
| `VegaLiteWriter()` | Vega-Lite JSON output writer |
950-
| `Validated` | Result of `validate()` with query inspection |
951-
| `Prepared` | Result of `prepare()`, ready for rendering |
945+
| Class | Description |
946+
| -------------------------- | ------------------------------------------------ |
947+
| `DuckDBReader(connection)` | Database reader with DataFrame registration |
948+
| `VegaLiteWriter()` | Vega-Lite JSON output writer |
949+
| `Validated` | Result of `validate()` with query inspection |
950+
| `Spec` | Result of `reader.execute()`, ready for rendering |
952951

953952
**Functions**:
954953

955-
| Function | Description |
956-
| ------------------------ | ------------------------------------------------- |
957-
| `validate(query)` | Syntax/semantic validation with query inspection |
958-
| `prepare(query, reader)` | Full preparation (reader can be native or custom) |
959-
| `render_altair(df, viz)` | Convenience: render DataFrame to Altair chart |
954+
| Function | Description |
955+
| -------------------------- | ------------------------------------------------- |
956+
| `validate(query)` | Syntax/semantic validation with query inspection |
957+
| `reader.execute(query)` | Execute ggsql query, return Spec |
958+
| `execute(query, reader)` | Execute with custom reader (bridge path) |
959+
| `render_altair(df, viz)` | Convenience: render DataFrame to Altair chart |
960960

961-
**Prepared Object Methods**:
961+
**Spec Methods**:
962962

963963
| Method | Description |
964964
| ---------------- | -------------------------------------------- |
@@ -988,9 +988,9 @@ class MyReader:
988988
def execute_sql(self, sql: str) -> pl.DataFrame:
989989
return pl.DataFrame({"x": [1, 2, 3], "y": [10, 20, 30]})
990990

991-
# Use custom reader with prepare()
991+
# Use custom reader with ggsql.execute()
992992
reader = MyReader()
993-
prepared = ggsql.prepare(
993+
spec = ggsql.execute(
994994
"SELECT * FROM data VISUALISE x, y DRAW point",
995995
reader
996996
)

ggsql-jupyter/src/executor.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
66
use anyhow::Result;
77
use ggsql::{
8-
prepare,
98
reader::{DuckDBReader, Reader},
109
validate,
1110
writer::VegaLiteWriter,
@@ -69,17 +68,17 @@ impl QueryExecutor {
6968
return Ok(ExecutionResult::DataFrame(df));
7069
}
7170

72-
// 3. Prepare data using the new API
73-
let prepared = prepare(code, &self.reader)?;
71+
// 3. Execute ggsql query using reader
72+
let spec = self.reader.execute(code)?;
7473

7574
tracing::info!(
76-
"Data prepared: {} rows, {} layers",
77-
prepared.metadata().rows,
78-
prepared.metadata().layer_count
75+
"Query executed: {} rows, {} layers",
76+
spec.metadata().rows,
77+
spec.metadata().layer_count
7978
);
8079

8180
// 4. Render to Vega-Lite
82-
let vega_json = prepared.render(&self.writer)?;
81+
let vega_json = spec.render(&self.writer)?;
8382

8483
tracing::debug!("Generated Vega-Lite spec: {} chars", vega_json.len());
8584

ggsql-python/README.md

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -84,30 +84,29 @@ df = pl.DataFrame({
8484
})
8585
reader.register("sales", df)
8686

87-
# 3. Prepare the visualization
88-
prepared = ggsql.prepare(
87+
# 3. Execute the ggsql query
88+
spec = reader.execute(
8989
"""
9090
SELECT * FROM sales
9191
VISUALISE date AS x, revenue AS y, region AS color
9292
DRAW line
9393
LABEL title => 'Sales by Region'
94-
""",
95-
reader
94+
"""
9695
)
9796

9897
# 4. Inspect metadata
99-
print(f"Rows: {prepared.metadata()['rows']}")
100-
print(f"Columns: {prepared.metadata()['columns']}")
101-
print(f"Layers: {prepared.layer_count()}")
98+
print(f"Rows: {spec.metadata()['rows']}")
99+
print(f"Columns: {spec.metadata()['columns']}")
100+
print(f"Layers: {spec.layer_count()}")
102101

103102
# 5. Inspect SQL/VISUALISE portions and data
104-
print(f"SQL: {prepared.sql()}")
105-
print(f"Visual: {prepared.visual()}")
106-
print(prepared.data()) # Returns polars DataFrame
103+
print(f"SQL: {spec.sql()}")
104+
print(f"Visual: {spec.visual()}")
105+
print(spec.data()) # Returns polars DataFrame
107106

108107
# 6. Render to Vega-Lite JSON
109108
writer = ggsql.VegaLiteWriter()
110-
vegalite_json = prepared.render(writer)
109+
vegalite_json = spec.render(writer)
111110
print(vegalite_json)
112111
```
113112

@@ -136,7 +135,7 @@ Writer that generates Vega-Lite v6 JSON specifications.
136135

137136
```python
138137
writer = ggsql.VegaLiteWriter()
139-
json_output = prepared.render(writer)
138+
json_output = spec.render(writer)
140139
```
141140

142141
#### `Validated`
@@ -152,9 +151,9 @@ Result of `validate()` containing query analysis without SQL execution.
152151
- `errors() -> list[dict]` - Validation errors with messages and locations
153152
- `warnings() -> list[dict]` - Validation warnings
154153

155-
#### `Prepared`
154+
#### `Spec`
156155

157-
Result of `prepare()`, containing resolved visualization ready for rendering.
156+
Result of `reader.execute()`, containing resolved visualization ready for rendering.
158157

159158
**Methods:**
160159

@@ -168,7 +167,7 @@ Result of `prepare()`, containing resolved visualization ready for rendering.
168167
- `stat_data(index: int) -> polars.DataFrame | None` - Statistical transform data
169168
- `layer_sql(index: int) -> str | None` - Layer filter SQL
170169
- `stat_sql(index: int) -> str | None` - Stat transform SQL
171-
- `warnings() -> list[dict]` - Validation warnings from preparation
170+
- `warnings() -> list[dict]` - Validation warnings from execution
172171

173172
### Functions
174173

@@ -185,13 +184,13 @@ else:
185184
print(f"Error: {error['message']}")
186185
```
187186

188-
#### `prepare(query: str, reader: DuckDBReader) -> Prepared`
187+
#### `reader.execute(query: str) -> Spec`
189188

190-
Parse, validate, and execute a ggsql query.
189+
Execute a ggsql query and return the visualization specification.
191190

192191
```python
193192
reader = ggsql.DuckDBReader("duckdb://memory")
194-
prepared = ggsql.prepare("SELECT 1 AS x, 2 AS y VISUALISE x, y DRAW point", reader)
193+
spec = reader.execute("SELECT 1 AS x, 2 AS y VISUALISE x, y DRAW point")
195194
```
196195

197196
#### `render_altair(df, viz: str, **kwargs) -> altair.Chart`
@@ -253,14 +252,14 @@ class CSVReader:
253252
# A real implementation would parse SQL to determine which file to load
254253
return pl.read_csv(f"{self.data_dir}/data.csv")
255254

256-
# Use custom reader with prepare()
255+
# Use custom reader with ggsql.execute()
257256
reader = CSVReader("/path/to/data")
258-
prepared = ggsql.prepare(
257+
spec = ggsql.execute(
259258
"SELECT * FROM data VISUALISE x, y DRAW point",
260259
reader
261260
)
262261
writer = ggsql.VegaLiteWriter()
263-
json_output = prepared.render(writer)
262+
json_output = spec.render(writer)
264263
```
265264

266265
**Optional methods** for custom readers:

ggsql-python/python/ggsql/__init__.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@
1111
DuckDBReader,
1212
VegaLiteWriter,
1313
Validated,
14-
Prepared,
14+
Spec,
1515
validate,
16-
prepare,
16+
execute,
1717
)
1818

1919
__all__ = [
2020
# Classes
2121
"DuckDBReader",
2222
"VegaLiteWriter",
2323
"Validated",
24-
"Prepared",
24+
"Spec",
2525
# Functions
2626
"validate",
27-
"prepare",
27+
"execute",
2828
"render_altair",
2929
]
3030
__version__ = "0.1.0"
@@ -81,10 +81,10 @@ def render_altair(
8181
# Build full query: SELECT * FROM __data__ + VISUALISE clause
8282
query = f"SELECT * FROM __data__ {viz}"
8383

84-
# Prepare and render
85-
prepared = prepare(query, reader)
84+
# Execute and render
85+
spec = reader.execute(query)
8686
writer = VegaLiteWriter()
87-
vegalite_json = prepared.render(writer)
87+
vegalite_json = spec.render(writer)
8888

8989
# Parse to determine the correct Altair class
9090
spec = json.loads(vegalite_json)

0 commit comments

Comments
 (0)