File tree Expand file tree Collapse file tree 3 files changed +45
-3
lines changed
tests/unit_tests/commands/databases Expand file tree Collapse file tree 3 files changed +45
-3
lines changed Original file line number Diff line number Diff line change @@ -80,9 +80,19 @@ def run(self) -> Model:
80
80
# existing personal tokens.
81
81
self ._handle_oauth2 ()
82
82
83
- # build new DB
83
+ # Some DBs require running a query to get the default catalog.
84
+ # In these cases, if the current connection is broken then
85
+ # `get_default_catalog` would raise an exception. We need to
86
+ # gracefully handle that so that the connection can be fixed.
84
87
original_database_name = self ._model .database_name
85
- original_catalog = self ._model .get_default_catalog ()
88
+ force_update : bool = False
89
+ try :
90
+ original_catalog = self ._model .get_default_catalog ()
91
+ except Exception :
92
+ original_catalog = None
93
+ force_update = True
94
+
95
+ # build new DB
86
96
database = DatabaseDAO .update (self ._model , self ._properties )
87
97
database .set_sqlalchemy_uri (database .sqlalchemy_uri )
88
98
ssh_tunnel = self ._handle_ssh_tunnel (database )
@@ -92,7 +102,8 @@ def run(self) -> Model:
92
102
# configured with multi-catalog support; if it was enabled or is enabled in the
93
103
# update we don't update the assets
94
104
if (
95
- new_catalog != original_catalog
105
+ force_update
106
+ or new_catalog != original_catalog
96
107
and not self ._model .allow_multi_catalog
97
108
and not database .allow_multi_catalog
98
109
):
Original file line number Diff line number Diff line change @@ -440,6 +440,8 @@ def get_default_catalog(cls, database: Database) -> str:
440
440
"""
441
441
Return the default catalog.
442
442
443
+ It's optionally specified in `connect_args.catalog`. If not:
444
+
443
445
The default behavior for Databricks is confusing. When Unity Catalog is not
444
446
enabled we have (the DB engine spec hasn't been tested with it enabled):
445
447
@@ -451,6 +453,10 @@ def get_default_catalog(cls, database: Database) -> str:
451
453
To handle permissions correctly we use the result of `SHOW CATALOGS` when a
452
454
single catalog is returned.
453
455
"""
456
+ connect_args = cls .get_extra_params (database )["engine_params" ]["connect_args" ]
457
+ if default_catalog := connect_args .get ("catalog" ):
458
+ return default_catalog
459
+
454
460
with database .get_sqla_engine () as engine :
455
461
catalogs = {catalog for (catalog ,) in engine .execute ("SHOW CATALOGS" )}
456
462
if len (catalogs ) == 1 :
Original file line number Diff line number Diff line change @@ -642,3 +642,28 @@ def test_update_without_catalog_change(mocker: MockerFixture) -> None:
642
642
UpdateDatabaseCommand (1 , {}).run ()
643
643
644
644
update_catalog_attribute .assert_not_called ()
645
+
646
+
647
+ def test_update_broken_connection (mocker : MockerFixture ) -> None :
648
+ """
649
+ Test that updating a database with a broken connection works
650
+ even if it has to run a query to get the default catalog.
651
+ """
652
+ database = mocker .MagicMock ()
653
+ database .get_default_catalog .side_effect = Exception ("Broken connection" )
654
+ database .id = 1
655
+ new_db = mocker .MagicMock ()
656
+ new_db .get_default_catalog .return_value = "main"
657
+
658
+ database_dao = mocker .patch ("superset.commands.database.update.DatabaseDAO" )
659
+ database_dao .find_by_id .return_value = database
660
+ database_dao .update .return_value = new_db
661
+ mocker .patch ("superset.commands.database.update.SyncPermissionsCommand" )
662
+
663
+ update_catalog_attribute = mocker .patch .object (
664
+ UpdateDatabaseCommand ,
665
+ "_update_catalog_attribute" ,
666
+ )
667
+ UpdateDatabaseCommand (1 , {}).run ()
668
+
669
+ update_catalog_attribute .assert_called_once_with (1 , "main" )
You can’t perform that action at this time.
0 commit comments