-
Notifications
You must be signed in to change notification settings - Fork 125
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[v5.1.0] Refactor the rest of the repositories to use sqlalchemy core…
… 1.4 (#632) * Refactor the rest of the repositories to use sqlalchemy core 1.4 Co-authored-by: James Wilson <tsunyoku@users.noreply.github.com> * fix types & nullables * fmt * add & migrate to thin database adapter, ensure all queries are compatible with sqlalchemy 2.0 * bugfix startup process * Add `render_postcompile` flag to support `IN` clauses * log db queries in debug mode * remove default from logs.time (doesn't exist) * Fix bugs in favorites table repo * Bump minor version -- to 5.1.0 --------- Co-authored-by: James Wilson <tsunyoku@users.noreply.github.com> Co-authored-by: tsunyoku <tsunyoku@gmail.com>
- Loading branch information
1 parent
0cc409f
commit 26b8595
Showing
30 changed files
with
1,353 additions
and
1,656 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
from __future__ import annotations | ||
|
||
from typing import Any | ||
from typing import cast | ||
|
||
from databases import Database as _Database | ||
from databases.core import Transaction | ||
from sqlalchemy.dialects.mysql.mysqldb import MySQLDialect_mysqldb | ||
from sqlalchemy.sql.compiler import Compiled | ||
from sqlalchemy.sql.expression import ClauseElement | ||
|
||
from app import settings | ||
|
||
|
||
class MySQLDialect(MySQLDialect_mysqldb): | ||
default_paramstyle = "named" | ||
|
||
|
||
DIALECT = MySQLDialect() | ||
|
||
MySQLRow = dict[str, Any] | ||
MySQLParams = dict[str, Any] | None | ||
MySQLQuery = ClauseElement | str | ||
|
||
|
||
class Database: | ||
def __init__(self, url: str) -> None: | ||
self._database = _Database(url) | ||
|
||
async def connect(self) -> None: | ||
await self._database.connect() | ||
|
||
async def disconnect(self) -> None: | ||
await self._database.disconnect() | ||
|
||
def _compile(self, clause_element: ClauseElement) -> tuple[str, MySQLParams]: | ||
compiled: Compiled = clause_element.compile( | ||
dialect=DIALECT, | ||
compile_kwargs={"render_postcompile": True}, | ||
) | ||
if settings.DEBUG: | ||
print(str(compiled), compiled.params) | ||
return str(compiled), compiled.params | ||
|
||
async def fetch_one( | ||
self, | ||
query: MySQLQuery, | ||
params: MySQLParams = None, | ||
) -> MySQLRow | None: | ||
if isinstance(query, ClauseElement): | ||
query, params = self._compile(query) | ||
|
||
row = await self._database.fetch_one(query, params) | ||
return dict(row._mapping) if row is not None else None | ||
|
||
async def fetch_all( | ||
self, | ||
query: MySQLQuery, | ||
params: MySQLParams = None, | ||
) -> list[MySQLRow]: | ||
if isinstance(query, ClauseElement): | ||
query, params = self._compile(query) | ||
|
||
rows = await self._database.fetch_all(query, params) | ||
return [dict(row._mapping) for row in rows] | ||
|
||
async def fetch_val( | ||
self, | ||
query: MySQLQuery, | ||
params: MySQLParams = None, | ||
column: Any = 0, | ||
) -> Any: | ||
if isinstance(query, ClauseElement): | ||
query, params = self._compile(query) | ||
|
||
val = await self._database.fetch_val(query, params, column) | ||
return val | ||
|
||
async def execute(self, query: MySQLQuery, params: MySQLParams = None) -> int: | ||
if isinstance(query, ClauseElement): | ||
query, params = self._compile(query) | ||
|
||
rec_id = await self._database.execute(query, params) | ||
return cast(int, rec_id) | ||
|
||
# NOTE: this accepts str since current execute_many uses are not using alchemy. | ||
# alchemy does execute_many in a single query so this method will be unneeded once raw SQL is not in use. | ||
async def execute_many(self, query: str, params: list[MySQLParams]) -> None: | ||
if isinstance(query, ClauseElement): | ||
query, _ = self._compile(query) | ||
|
||
await self._database.execute_many(query, params) | ||
|
||
def transaction( | ||
self, | ||
*, | ||
force_rollback: bool = False, | ||
**kwargs: Any, | ||
) -> Transaction: | ||
return self._database.transaction(force_rollback=force_rollback, **kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.