@@ -235,52 +235,78 @@ def test_read_sqlite_no_table_name(con, tmp_path):
235
235
scon .close ()
236
236
237
237
238
+ @pytest .fixture
239
+ def sqlite_path (tmp_path , data_dir ):
240
+ path = tmp_path / "test.db"
241
+ scon = sqlite3 .connect (str (path ))
242
+ try :
243
+ with scon :
244
+ scon .executescript ((data_dir .parent / "schema" / "sqlite.sql" ).read_text ())
245
+ yield path
246
+ finally :
247
+ scon .close ()
248
+
249
+
238
250
# Because we create a new connection and the test requires loading/installing a
239
251
# DuckDB extension, we need to xfail these on Nix.
240
252
@pytest .mark .xfail (
241
253
LINUX and SANDBOXED ,
242
254
reason = "nix on linux cannot download duckdb extensions or data due to sandboxing" ,
243
255
raises = duckdb .IOException ,
244
256
)
245
- def test_attach_sqlite (data_dir , tmp_path ):
246
- import sqlite3
247
-
257
+ def test_attach_sqlite (sqlite_path ):
248
258
# Create a new connection here because we already have the `ibis_testing`
249
259
# tables loaded in to the `con` fixture.
250
260
con = ibis .duckdb .connect ()
251
261
252
- test_db_path = tmp_path / "test.db"
253
- scon = sqlite3 .connect (test_db_path )
254
- try :
255
- with scon :
256
- scon .executescript ((data_dir .parent / "schema" / "sqlite.sql" ).read_text ())
257
-
258
- con .attach_sqlite (test_db_path )
259
- assert set (con .list_tables ()) >= {
262
+ catalogs_before = con .list_catalogs ()
263
+ assert con .list_tables () == []
264
+ for i in range (2 ):
265
+ name = con .attach_sqlite (sqlite_path , name = "foo" , skip_if_exists = True )
266
+ if i == 0 :
267
+ assert isinstance (name , str )
268
+ else :
269
+ assert name is None
270
+ assert con .list_tables () == []
271
+ assert set (con .list_catalogs ()) == {* catalogs_before , "foo" }
272
+ database = ("foo" , "main" )
273
+ assert set (con .list_tables (database = database )) >= {
260
274
"functional_alltypes" ,
261
275
"awards_players" ,
262
276
"batting" ,
263
277
"diamonds" ,
264
278
}
265
279
266
- fa = con .tables .functional_alltypes
267
- assert len (set (fa .schema ().types )) > 1
280
+ types = con .table ("functional_alltypes" , database = database ).schema ().types
281
+ assert any (not isinstance (t , dt .String ) for t in types )
282
+ assert any (isinstance (t , dt .String ) for t in types )
268
283
269
- # overwrite existing sqlite_db and force schema to all strings
270
- con .attach_sqlite (test_db_path , overwrite = True , all_varchar = True )
271
- assert set (con .list_tables ()) >= {
272
- "functional_alltypes" ,
273
- "awards_players" ,
274
- "batting" ,
275
- "diamonds" ,
276
- }
284
+ with pytest .raises (duckdb .BinderException ) as exc :
285
+ con .attach_sqlite (sqlite_path , name = "foo" )
286
+ assert "already" in str (exc .value )
277
287
278
- fa = con .tables .functional_alltypes
279
- types = fa .schema ().types
280
- assert len (set (types )) == 1
281
- assert dt .String (nullable = True ) in set (types )
282
- finally :
283
- scon .close ()
288
+ con .detach ("foo" )
289
+ assert con .list_catalogs () == catalogs_before
290
+
291
+ # Check for the name to be returned.
292
+ # Check all_varchar=True.
293
+ con = ibis .duckdb .connect ()
294
+ catalogs_before = con .list_catalogs ()
295
+ name = con .attach_sqlite (sqlite_path , all_varchar = True )
296
+ assert isinstance (name , str )
297
+ assert set (con .list_catalogs ()) == {* catalogs_before , name }
298
+ types = con .table ("functional_alltypes" , database = (name , "main" )).schema ().types
299
+ assert all (isinstance (t , dt .String ) for t in types )
300
+
301
+ # Explicitly NOT testing read_only=None in case duckdb's default changes
302
+ name = con .attach_sqlite (sqlite_path , name = "read_write" , read_only = False )
303
+ assert name == "read_write"
304
+ con .create_table ("t" , database = ("read_write" , "main" ), schema = {"a" : "int" })
305
+
306
+ name = con .attach_sqlite (sqlite_path , name = "read_only" , read_only = True )
307
+ assert name == "read_only"
308
+ with pytest .raises (duckdb .InvalidInputException ) as exc :
309
+ con .create_table ("t" , database = ("read_only" , "main" ), schema = {"a" : "int" })
284
310
285
311
286
312
def test_memtable_with_nullable_dtypes (con ):
0 commit comments