@@ -13,6 +13,66 @@ use std::cell::RefCell;
1313use std:: collections:: HashSet ;
1414use std:: sync:: Arc ;
1515
16+ // =============================================================================
17+ // DuckDB builtin data registration
18+ // =============================================================================
19+
20+ /// Register any builtin datasets referenced in the SQL with a DuckDB connection.
21+ ///
22+ /// Finds `ggsql:X` patterns in the SQL, writes the embedded parquet data to
23+ /// a temp file, and creates a table named `__ggsql_data_X__` in DuckDB.
24+ #[ cfg( feature = "builtin-data" ) ]
25+ fn register_builtin_datasets_duckdb (
26+ sql : & str ,
27+ conn : & Connection ,
28+ ) -> Result < ( ) > {
29+ use std:: { env, fs} ;
30+
31+ let dataset_names = super :: data:: extract_builtin_dataset_names ( sql) ?;
32+
33+ // Load spatial extension before registering datasets that contain
34+ // geometry columns, so DuckDB reads them as GEOMETRY rather than BLOB.
35+ if dataset_names. iter ( ) . any ( |n| n == "world" ) {
36+ let _ = conn. execute ( "LOAD spatial" , params ! [ ] ) ;
37+ }
38+
39+ for name in dataset_names {
40+ let Some ( parquet_bytes) = super :: data:: builtin_parquet_bytes ( & name) else {
41+ continue ;
42+ } ;
43+
44+ let table_name = naming:: builtin_data_table ( & name) ;
45+
46+ // Write parquet to temp file for DuckDB's read_parquet
47+ let mut tmp_path = env:: temp_dir ( ) ;
48+ tmp_path. push ( format ! ( "{}.parquet" , name) ) ;
49+ if !tmp_path. exists ( ) {
50+ fs:: write ( & tmp_path, parquet_bytes) . map_err ( |e| {
51+ GgsqlError :: ReaderError ( format ! (
52+ "Failed to write builtin dataset '{}' to {}: {}" ,
53+ name,
54+ tmp_path. display( ) ,
55+ e
56+ ) )
57+ } ) ?;
58+ }
59+
60+ let create_sql = format ! (
61+ "CREATE TABLE IF NOT EXISTS {} AS SELECT * FROM read_parquet('{}')" ,
62+ naming:: quote_ident( & table_name) ,
63+ tmp_path. display( )
64+ ) ;
65+
66+ conn. execute ( & create_sql, params ! [ ] ) . map_err ( |e| {
67+ GgsqlError :: ReaderError ( format ! (
68+ "Failed to register builtin dataset '{}': {}" ,
69+ name, e
70+ ) )
71+ } ) ?;
72+ }
73+ Ok ( ( ) )
74+ }
75+
1676/// DuckDB SQL dialect with native function support.
1777///
1878/// Overrides SQL generation methods to use DuckDB-native functions
@@ -214,7 +274,7 @@ impl Reader for DuckDBReader {
214274 fn execute_sql ( & self , sql : & str ) -> Result < DataFrame > {
215275 // Register builtin datasets if referenced
216276 #[ cfg( feature = "builtin-data" ) ]
217- super :: data :: register_builtin_datasets_duckdb ( sql, & self . conn ) ?;
277+ register_builtin_datasets_duckdb ( sql, & self . conn ) ?;
218278
219279 // Rewrite ggsql:name → __ggsql_data_name__ in SQL
220280 let sql = super :: data:: rewrite_namespaced_sql ( sql) ?;
0 commit comments