@@ -41,6 +41,16 @@ def __new__(cls, *args, **kwargs):
4141 cls ._instance ._initialize (* args , ** kwargs ) # Initialize only once
4242 return cls ._instance
4343
44+ def _safe_attach (self , alias : str , url : str , type_clause : str = "" ):
45+ try :
46+ self .conn .execute (f"DETACH DATABASE { alias } " )
47+ except (duckdb .BinderException , duckdb .CatalogException ):
48+ pass
49+ if type_clause :
50+ self .conn .execute (f"ATTACH '{ url } ' AS { alias } { type_clause } " )
51+ else :
52+ self .conn .execute (f"ATTACH '{ url } ' AS { alias } " )
53+
4454 def _initialize (self , db_url , omop_db_url = None ):
4555 # by default, duckdb uses in memory database
4656 self .conn = duckdb .connect (db_url )
@@ -52,18 +62,9 @@ def _initialize(self, db_url, omop_db_url=None):
5262 if omop_db_url .startswith ("postgresql://" ):
5363 # omop db is postgreSQL
5464 self .load_postgres_extension ()
55- self .conn .execute (f"""
56- ATTACH '{ self .omop_cdm_db_url } ' as { self .omop_alias } (TYPE postgres)
57- """ )
65+ self ._safe_attach (self .omop_alias , self .omop_cdm_db_url , "(TYPE postgres)" )
5866 elif omop_db_url .endswith (".duckdb" ):
59- try :
60- self .conn .execute (f"DETACH DATABASE { self .omop_alias } " )
61- except (duckdb .BinderException , duckdb .CatalogException ):
62- # ignore if not attached yet
63- pass
64- self .conn .execute (f"""
65- ATTACH '{ self .omop_cdm_db_url } ' as { self .omop_alias }
66- """ )
67+ self ._safe_attach (self .omop_alias , self .omop_cdm_db_url )
6768 else :
6869 raise ValueError ("Unsupported OMOP database backend" )
6970
0 commit comments