"""Database client abstraction with lazy SQLAlchemy import."""from__future__importannotationsfromtypingimportAnyfromsteplib.core.exceptionsimportMissingDependencyError
[docs]classDatabaseClient:"""Database client backed by SQLAlchemy (requires the ``[db]`` extra). Attributes: engine: The SQLAlchemy engine instance. connection: The active SQLAlchemy connection. """def__init__(self,connection_string:str)->None:"""Initialize the SQLAlchemy engine, importing lazily. Args: connection_string: A SQLAlchemy-compatible connection string. Raises: MissingDependencyError: If SQLAlchemy is not installed. """try:fromsqlalchemyimportcreate_engine,textexceptImportErrorasexc:raiseMissingDependencyError("db","sqlalchemy")fromexcself._text=textself.engine=create_engine(connection_string)self.connection=self.engine.connect()
[docs]defexecute(self,query:str,params:dict[str,Any]|None=None)->list[dict[str,Any]]:"""Execute a SQL query and return rows as a list of dicts. Args: query: The SQL query string. params: Optional bind parameters. Returns: A list of dictionaries, one per row, keyed by column name. """result=self.connection.execute(self._text(query),paramsor{})columns=list(result.keys())return[dict(zip(columns,row,strict=False))forrowinresult.fetchall()]
[docs]defexecute_scalar(self,query:str,params:dict[str,Any]|None=None)->Any:"""Execute a SQL query and return a single scalar value. Args: query: The SQL query string. params: Optional bind parameters. Returns: The first column of the first row. """result=self.connection.execute(self._text(query),paramsor{})returnresult.scalar()
[docs]defbegin(self)->Any:"""Begin a transaction on the underlying connection. Returns: The transaction object from SQLAlchemy. """returnself.connection.begin()
[docs]defclose(self)->None:"""Close the connection and dispose the engine."""self.connection.close()self.engine.dispose()
[docs]defget_client(connection_string:str)->DatabaseClient:"""Return a database client for the given connection string. Args: connection_string: A SQLAlchemy-compatible connection string. Returns: A ``DatabaseClient`` instance. Raises: MissingDependencyError: If SQLAlchemy is not installed. """returnDatabaseClient(connection_string)