Skip to content

[Fabric] get_current_catalog() performs unnecessary DB round-trips in set_current_catalog() #5776

@fresioAS

Description

@fresioAS

Description

FabricEngineAdapter.set_current_catalog() calls get_current_catalog() twice per invocation — once to guard against a redundant switch, and once to verify the switch succeeded:

def set_current_catalog(self, catalog_name: str) -> None:
    current_catalog = self.get_current_catalog()   # DB round-trip #1

    if current_catalog and current_catalog == catalog_name:
        return

    ...
    self._target_catalog = catalog_name
    catalog_after_switch = self.get_current_catalog()  # DB round-trip #2

get_current_catalog() is inherited from GetCurrentCatalogFromFunctionMixin and executes SELECT db_name() against the database. Because Fabric sessions are stateless, each call opens a new connection and executes a query.


Root Cause

FabricEngineAdapter already maintains _target_catalog as a thread-local attribute that is the authoritative source of truth for what catalog the current thread's connection is pointed at:

@property
def _target_catalog(self) -> t.Optional[str]:
    return self._connection_pool.get_attribute("target_catalog")

New connections are always created using this value:

connection_factory_or_pool = lambda *args, **kwargs: original_connection_factory(
    target_catalog=self._target_catalog, *args, **kwargs
)

Since _target_catalog is always consistent with the catalog used for the next connection, querying the database to determine the current catalog is redundant.


Proposed Fix

Override get_current_catalog() in FabricEngineAdapter to read from _target_catalog directly, falling back to the configured database:

def get_current_catalog(self) -> t.Optional[str]:
    return self._target_catalog or self._extra_config.get("database")

This eliminates both DB round-trips in set_current_catalog() without any loss of correctness.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions