|
1 | | -//! High-level ggsql API. |
| 1 | +//! Query validation without SQL execution. |
2 | 2 | //! |
3 | | -//! Validation and query inspection without SQL execution. |
| 3 | +//! This module provides query syntax and semantic validation without executing |
| 4 | +//! any SQL. Use this for IDE integration, syntax checking, and query inspection. |
4 | 5 |
|
5 | 6 | use crate::parser; |
6 | 7 | use crate::Result; |
@@ -79,7 +80,7 @@ pub struct Location { |
79 | 80 | } |
80 | 81 |
|
81 | 82 | // ============================================================================ |
82 | | -// High-Level API Functions |
| 83 | +// Validation Function |
83 | 84 | // ============================================================================ |
84 | 85 |
|
85 | 86 | /// Validate query syntax and semantics without executing SQL. |
@@ -249,162 +250,6 @@ mod tests { |
249 | 250 | assert!(!validated.errors().is_empty()); |
250 | 251 | } |
251 | 252 |
|
252 | | - #[cfg(all(feature = "duckdb", feature = "vegalite"))] |
253 | | - #[test] |
254 | | - fn test_execute_and_render() { |
255 | | - use crate::reader::{DuckDBReader, Reader}; |
256 | | - use crate::writer::VegaLiteWriter; |
257 | | - |
258 | | - let reader = DuckDBReader::from_connection_string("duckdb://memory").unwrap(); |
259 | | - let spec = reader.execute("SELECT 1 as x, 2 as y VISUALISE x, y DRAW point").unwrap(); |
260 | | - |
261 | | - assert_eq!(spec.plot().layers.len(), 1); |
262 | | - assert_eq!(spec.metadata().layer_count, 1); |
263 | | - assert!(spec.data().is_some()); |
264 | | - |
265 | | - let writer = VegaLiteWriter::new(); |
266 | | - let result = spec.render(&writer).unwrap(); |
267 | | - assert!(result.contains("point")); |
268 | | - } |
269 | | - |
270 | | - #[cfg(all(feature = "duckdb", feature = "vegalite"))] |
271 | | - #[test] |
272 | | - fn test_execute_metadata() { |
273 | | - use crate::reader::{DuckDBReader, Reader}; |
274 | | - |
275 | | - let reader = DuckDBReader::from_connection_string("duckdb://memory").unwrap(); |
276 | | - let spec = reader.execute( |
277 | | - "SELECT * FROM (VALUES (1, 10), (2, 20), (3, 30)) AS t(x, y) VISUALISE x, y DRAW point", |
278 | | - ) |
279 | | - .unwrap(); |
280 | | - |
281 | | - let metadata = spec.metadata(); |
282 | | - assert_eq!(metadata.rows, 3); |
283 | | - assert_eq!(metadata.columns.len(), 2); |
284 | | - assert!(metadata.columns.contains(&"x".to_string())); |
285 | | - assert!(metadata.columns.contains(&"y".to_string())); |
286 | | - assert_eq!(metadata.layer_count, 1); |
287 | | - } |
288 | | - |
289 | | - #[cfg(all(feature = "duckdb", feature = "vegalite"))] |
290 | | - #[test] |
291 | | - fn test_execute_with_cte() { |
292 | | - use crate::reader::{DuckDBReader, Reader}; |
293 | | - |
294 | | - let reader = DuckDBReader::from_connection_string("duckdb://memory").unwrap(); |
295 | | - let query = r#" |
296 | | - WITH data AS ( |
297 | | - SELECT * FROM (VALUES (1, 10), (2, 20)) AS t(x, y) |
298 | | - ) |
299 | | - SELECT * FROM data |
300 | | - VISUALISE x, y DRAW point |
301 | | - "#; |
302 | | - |
303 | | - let spec = reader.execute(query).unwrap(); |
304 | | - |
305 | | - assert_eq!(spec.plot().layers.len(), 1); |
306 | | - assert!(spec.data().is_some()); |
307 | | - let df = spec.data().unwrap(); |
308 | | - assert_eq!(df.height(), 2); |
309 | | - } |
310 | | - |
311 | | - #[cfg(all(feature = "duckdb", feature = "vegalite"))] |
312 | | - #[test] |
313 | | - fn test_render_multi_layer() { |
314 | | - use crate::reader::{DuckDBReader, Reader}; |
315 | | - use crate::writer::VegaLiteWriter; |
316 | | - |
317 | | - let reader = DuckDBReader::from_connection_string("duckdb://memory").unwrap(); |
318 | | - let query = r#" |
319 | | - SELECT * FROM (VALUES (1, 10), (2, 20), (3, 30)) AS t(x, y) |
320 | | - VISUALISE |
321 | | - DRAW point MAPPING x AS x, y AS y |
322 | | - DRAW line MAPPING x AS x, y AS y |
323 | | - "#; |
324 | | - |
325 | | - let spec = reader.execute(query).unwrap(); |
326 | | - let writer = VegaLiteWriter::new(); |
327 | | - let result = spec.render(&writer).unwrap(); |
328 | | - |
329 | | - assert!(result.contains("layer")); |
330 | | - } |
331 | | - |
332 | | - #[cfg(all(feature = "duckdb", feature = "vegalite"))] |
333 | | - #[test] |
334 | | - fn test_register_and_query() { |
335 | | - use crate::reader::{DuckDBReader, Reader}; |
336 | | - use crate::writer::VegaLiteWriter; |
337 | | - use polars::prelude::*; |
338 | | - |
339 | | - let mut reader = DuckDBReader::from_connection_string("duckdb://memory").unwrap(); |
340 | | - |
341 | | - let df = df! { |
342 | | - "x" => [1i32, 2, 3], |
343 | | - "y" => [10i32, 20, 30], |
344 | | - } |
345 | | - .unwrap(); |
346 | | - |
347 | | - reader.register("my_data", df).unwrap(); |
348 | | - |
349 | | - let query = "SELECT * FROM my_data VISUALISE x, y DRAW point"; |
350 | | - let spec = reader.execute(query).unwrap(); |
351 | | - |
352 | | - assert_eq!(spec.metadata().rows, 3); |
353 | | - assert!(spec.metadata().columns.contains(&"x".to_string())); |
354 | | - |
355 | | - let writer = VegaLiteWriter::new(); |
356 | | - let result = spec.render(&writer).unwrap(); |
357 | | - assert!(result.contains("point")); |
358 | | - } |
359 | | - |
360 | | - #[cfg(all(feature = "duckdb", feature = "vegalite"))] |
361 | | - #[test] |
362 | | - fn test_register_and_join() { |
363 | | - use crate::reader::{DuckDBReader, Reader}; |
364 | | - use polars::prelude::*; |
365 | | - |
366 | | - let mut reader = DuckDBReader::from_connection_string("duckdb://memory").unwrap(); |
367 | | - |
368 | | - let sales = df! { |
369 | | - "id" => [1i32, 2, 3], |
370 | | - "amount" => [100i32, 200, 300], |
371 | | - "product_id" => [1i32, 1, 2], |
372 | | - } |
373 | | - .unwrap(); |
374 | | - |
375 | | - let products = df! { |
376 | | - "id" => [1i32, 2], |
377 | | - "name" => ["Widget", "Gadget"], |
378 | | - } |
379 | | - .unwrap(); |
380 | | - |
381 | | - reader.register("sales", sales).unwrap(); |
382 | | - reader.register("products", products).unwrap(); |
383 | | - |
384 | | - let query = r#" |
385 | | - SELECT s.id, s.amount, p.name |
386 | | - FROM sales s |
387 | | - JOIN products p ON s.product_id = p.id |
388 | | - VISUALISE id AS x, amount AS y |
389 | | - DRAW bar |
390 | | - "#; |
391 | | - |
392 | | - let spec = reader.execute(query).unwrap(); |
393 | | - assert_eq!(spec.metadata().rows, 3); |
394 | | - } |
395 | | - |
396 | | - #[cfg(feature = "duckdb")] |
397 | | - #[test] |
398 | | - fn test_execute_no_viz_fails() { |
399 | | - use crate::reader::{DuckDBReader, Reader}; |
400 | | - |
401 | | - let reader = DuckDBReader::from_connection_string("duckdb://memory").unwrap(); |
402 | | - let query = "SELECT 1 as x, 2 as y"; |
403 | | - |
404 | | - let result = reader.execute(query); |
405 | | - assert!(result.is_err()); |
406 | | - } |
407 | | - |
408 | 253 | #[test] |
409 | 254 | fn test_validate_sql_and_visual_content() { |
410 | 255 | let query = "SELECT 1 as x, 2 as y VISUALISE DRAW point MAPPING x AS x, y AS y DRAW line MAPPING x AS x, y AS y"; |
|
0 commit comments