ormlambda 3.11.2__py3-none-any.whl → 3.34.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ormlambda/__init__.py +3 -1
- ormlambda/caster/__init__.py +1 -1
- ormlambda/caster/caster.py +29 -12
- ormlambda/common/abstract_classes/clause_info_converter.py +65 -0
- ormlambda/common/abstract_classes/decomposition_query.py +27 -68
- ormlambda/common/abstract_classes/non_query_base.py +10 -8
- ormlambda/common/abstract_classes/query_base.py +3 -1
- ormlambda/common/errors/__init__.py +29 -0
- ormlambda/common/interfaces/ICustomAlias.py +1 -1
- ormlambda/common/interfaces/IQueryCommand.py +6 -2
- ormlambda/dialects/__init__.py +39 -0
- ormlambda/dialects/default/__init__.py +1 -0
- ormlambda/dialects/default/base.py +39 -0
- ormlambda/dialects/interface/__init__.py +1 -0
- ormlambda/dialects/interface/dialect.py +78 -0
- ormlambda/dialects/mysql/__init__.py +38 -0
- ormlambda/dialects/mysql/base.py +388 -0
- ormlambda/dialects/mysql/caster/caster.py +39 -0
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/__init__.py +1 -0
- ormlambda/dialects/mysql/caster/types/boolean.py +35 -0
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/bytes.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/datetime.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/float.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/int.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/iterable.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/none.py +8 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/point.py +4 -4
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/string.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/clauses/ST_AsText.py +8 -7
- ormlambda/{databases/my_sql → dialects/mysql}/clauses/ST_Contains.py +10 -5
- ormlambda/dialects/mysql/clauses/__init__.py +13 -0
- ormlambda/dialects/mysql/clauses/count.py +33 -0
- ormlambda/dialects/mysql/clauses/delete.py +9 -0
- ormlambda/dialects/mysql/clauses/group_by.py +17 -0
- ormlambda/dialects/mysql/clauses/having.py +12 -0
- ormlambda/dialects/mysql/clauses/insert.py +9 -0
- ormlambda/dialects/mysql/clauses/joins.py +14 -0
- ormlambda/dialects/mysql/clauses/limit.py +6 -0
- ormlambda/dialects/mysql/clauses/offset.py +6 -0
- ormlambda/dialects/mysql/clauses/order.py +8 -0
- ormlambda/dialects/mysql/clauses/update.py +8 -0
- ormlambda/dialects/mysql/clauses/upsert.py +9 -0
- ormlambda/dialects/mysql/clauses/where.py +7 -0
- ormlambda/dialects/mysql/mysqlconnector.py +46 -0
- ormlambda/dialects/mysql/repository/__init__.py +1 -0
- ormlambda/dialects/mysql/repository/repository.py +212 -0
- ormlambda/dialects/mysql/types.py +732 -0
- ormlambda/dialects/sqlite/__init__.py +5 -0
- ormlambda/dialects/sqlite/base.py +47 -0
- ormlambda/dialects/sqlite/pysqlite.py +32 -0
- ormlambda/engine/__init__.py +1 -0
- ormlambda/engine/base.py +77 -0
- ormlambda/engine/create.py +9 -23
- ormlambda/engine/url.py +34 -19
- ormlambda/env.py +30 -0
- ormlambda/errors.py +17 -0
- ormlambda/model/base_model.py +7 -9
- ormlambda/repository/base_repository.py +36 -5
- ormlambda/repository/interfaces/IRepositoryBase.py +119 -12
- ormlambda/repository/response.py +134 -0
- ormlambda/sql/clause_info/__init__.py +2 -1
- ormlambda/sql/clause_info/aggregate_function_base.py +96 -0
- ormlambda/sql/clause_info/clause_info.py +35 -115
- ormlambda/sql/clause_info/interface/IClauseInfo.py +37 -0
- ormlambda/sql/clause_info/interface/__init__.py +1 -0
- ormlambda/sql/clauses/__init__.py +14 -0
- ormlambda/{databases/my_sql → sql}/clauses/alias.py +23 -6
- ormlambda/{databases/my_sql → sql}/clauses/count.py +15 -1
- ormlambda/{databases/my_sql → sql}/clauses/delete.py +22 -7
- ormlambda/sql/clauses/group_by.py +30 -0
- ormlambda/{databases/my_sql → sql}/clauses/having.py +7 -2
- ormlambda/{databases/my_sql → sql}/clauses/insert.py +16 -9
- ormlambda/sql/clauses/interfaces/__init__.py +5 -0
- ormlambda/sql/clauses/join/__init__.py +1 -0
- ormlambda/{databases/my_sql → sql/clauses/join}/join_context.py +15 -7
- ormlambda/{databases/my_sql → sql}/clauses/joins.py +29 -19
- ormlambda/sql/clauses/limit.py +15 -0
- ormlambda/sql/clauses/offset.py +15 -0
- ormlambda/{databases/my_sql → sql}/clauses/order.py +14 -24
- ormlambda/{databases/my_sql → sql}/clauses/select.py +14 -13
- ormlambda/{databases/my_sql → sql}/clauses/update.py +24 -11
- ormlambda/{databases/my_sql → sql}/clauses/upsert.py +19 -10
- ormlambda/{databases/my_sql → sql}/clauses/where.py +28 -8
- ormlambda/sql/column/__init__.py +1 -0
- ormlambda/sql/{column.py → column/column.py} +85 -22
- ormlambda/sql/comparer.py +51 -37
- ormlambda/sql/compiler.py +668 -0
- ormlambda/sql/ddl.py +82 -0
- ormlambda/sql/elements.py +36 -0
- ormlambda/sql/foreign_key.py +61 -39
- ormlambda/{databases/my_sql → sql}/functions/concat.py +13 -5
- ormlambda/{databases/my_sql → sql}/functions/max.py +9 -4
- ormlambda/{databases/my_sql → sql}/functions/min.py +9 -13
- ormlambda/{databases/my_sql → sql}/functions/sum.py +8 -10
- ormlambda/sql/sqltypes.py +647 -0
- ormlambda/sql/table/__init__.py +1 -1
- ormlambda/sql/table/table.py +175 -0
- ormlambda/sql/table/table_constructor.py +1 -208
- ormlambda/sql/type_api.py +35 -0
- ormlambda/sql/types.py +3 -1
- ormlambda/sql/visitors.py +74 -0
- ormlambda/statements/__init__.py +1 -0
- ormlambda/statements/base_statement.py +34 -40
- ormlambda/statements/interfaces/IStatements.py +28 -21
- ormlambda/statements/query_builder.py +163 -0
- ormlambda/{databases/my_sql → statements}/statements.py +68 -210
- ormlambda/statements/types.py +2 -2
- ormlambda/types/__init__.py +24 -0
- ormlambda/types/metadata.py +42 -0
- ormlambda/util/__init__.py +87 -0
- ormlambda/{utils → util}/module_tree/dynamic_module.py +4 -3
- ormlambda/util/plugin_loader.py +32 -0
- ormlambda/util/typing.py +6 -0
- ormlambda-3.34.0.dist-info/AUTHORS +32 -0
- {ormlambda-3.11.2.dist-info → ormlambda-3.34.0.dist-info}/METADATA +56 -10
- ormlambda-3.34.0.dist-info/RECORD +152 -0
- ormlambda/components/__init__.py +0 -4
- ormlambda/components/delete/__init__.py +0 -2
- ormlambda/components/delete/abstract_delete.py +0 -17
- ormlambda/components/insert/__init__.py +0 -2
- ormlambda/components/insert/abstract_insert.py +0 -25
- ormlambda/components/select/__init__.py +0 -1
- ormlambda/components/update/__init__.py +0 -2
- ormlambda/components/update/abstract_update.py +0 -29
- ormlambda/components/upsert/__init__.py +0 -2
- ormlambda/components/upsert/abstract_upsert.py +0 -25
- ormlambda/databases/__init__.py +0 -5
- ormlambda/databases/my_sql/__init__.py +0 -4
- ormlambda/databases/my_sql/caster/caster.py +0 -39
- ormlambda/databases/my_sql/clauses/__init__.py +0 -20
- ormlambda/databases/my_sql/clauses/create_database.py +0 -35
- ormlambda/databases/my_sql/clauses/drop_database.py +0 -17
- ormlambda/databases/my_sql/clauses/drop_table.py +0 -23
- ormlambda/databases/my_sql/clauses/group_by.py +0 -31
- ormlambda/databases/my_sql/clauses/limit.py +0 -17
- ormlambda/databases/my_sql/clauses/offset.py +0 -17
- ormlambda/databases/my_sql/repository/__init__.py +0 -1
- ormlambda/databases/my_sql/repository/repository.py +0 -351
- ormlambda/engine/template.py +0 -47
- ormlambda/sql/dtypes.py +0 -94
- ormlambda/utils/__init__.py +0 -1
- ormlambda-3.11.2.dist-info/RECORD +0 -120
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/__init__.py +0 -0
- /ormlambda/{databases/my_sql/types.py → dialects/mysql/repository/pool_types.py} +0 -0
- /ormlambda/{components/delete → sql/clauses/interfaces}/IDelete.py +0 -0
- /ormlambda/{components/insert → sql/clauses/interfaces}/IInsert.py +0 -0
- /ormlambda/{components/select → sql/clauses/interfaces}/ISelect.py +0 -0
- /ormlambda/{components/update → sql/clauses/interfaces}/IUpdate.py +0 -0
- /ormlambda/{components/upsert → sql/clauses/interfaces}/IUpsert.py +0 -0
- /ormlambda/{databases/my_sql → sql}/functions/__init__.py +0 -0
- /ormlambda/{utils → util}/module_tree/__init__.py +0 -0
- /ormlambda/{utils → util}/module_tree/dfs_traversal.py +0 -0
- {ormlambda-3.11.2.dist-info → ormlambda-3.34.0.dist-info}/LICENSE +0 -0
- {ormlambda-3.11.2.dist-info → ormlambda-3.34.0.dist-info}/WHEEL +0 -0
@@ -1,7 +1,12 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import TYPE_CHECKING
|
1
3
|
from ormlambda.sql.clause_info import AggregateFunctionBase
|
2
4
|
from ormlambda.sql.types import ColumnType, AliasType
|
3
5
|
from ormlambda.sql.clause_info.clause_info_context import ClauseContextType
|
4
6
|
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from ormlambda.dialects import Dialect
|
9
|
+
|
5
10
|
|
6
11
|
class ST_AsText[T, TProp](AggregateFunctionBase[None]):
|
7
12
|
"""
|
@@ -20,16 +25,12 @@ class ST_AsText[T, TProp](AggregateFunctionBase[None]):
|
|
20
25
|
alias_table: AliasType[ColumnType[TProp]] = None,
|
21
26
|
alias_clause: AliasType[ColumnType[TProp]] = None,
|
22
27
|
context: ClauseContextType = None,
|
28
|
+
*,
|
29
|
+
dialect: Dialect,
|
23
30
|
) -> None:
|
24
31
|
default_alias_clause = self.create_alias_from(point) if not alias_clause else alias_clause
|
25
32
|
|
26
|
-
super().__init__(
|
27
|
-
table=point.table,
|
28
|
-
column=point,
|
29
|
-
alias_table=alias_table,
|
30
|
-
alias_clause=default_alias_clause,
|
31
|
-
context=context,
|
32
|
-
)
|
33
|
+
super().__init__(table=point.table, column=point, alias_table=alias_table, alias_clause=default_alias_clause, context=context, dialect=dialect)
|
33
34
|
|
34
35
|
@staticmethod
|
35
36
|
def create_alias_from(element: ColumnType[TProp]) -> str:
|
@@ -1,3 +1,4 @@
|
|
1
|
+
from __future__ import annotations
|
1
2
|
import typing as tp
|
2
3
|
|
3
4
|
from shapely import Point
|
@@ -6,6 +7,9 @@ from ormlambda import Column
|
|
6
7
|
from ormlambda.sql.types import ColumnType, AliasType
|
7
8
|
from ormlambda.sql.clause_info import ClauseInfo, IAggregate
|
8
9
|
|
10
|
+
if tp.TYPE_CHECKING:
|
11
|
+
from ormlambda.dialects import Dialect
|
12
|
+
|
9
13
|
|
10
14
|
class ST_Contains(IAggregate):
|
11
15
|
FUNCTION_NAME: str = "ST_Contains"
|
@@ -16,15 +20,16 @@ class ST_Contains(IAggregate):
|
|
16
20
|
point: Point,
|
17
21
|
alias_table: tp.Optional[AliasType[ColumnType[TProp]]] = None,
|
18
22
|
alias_clause: tp.Optional[AliasType[ColumnType[TProp]]] = None,
|
23
|
+
*,
|
24
|
+
dialect: Dialect,
|
19
25
|
):
|
20
|
-
self.attr1: ClauseInfo[Point] = ClauseInfo(column.table, column, alias_table)
|
21
|
-
self.attr2: ClauseInfo[Point] = ClauseInfo[Point](None, point)
|
26
|
+
self.attr1: ClauseInfo[Point] = ClauseInfo(column.table, column, alias_table, dialect=dialect)
|
27
|
+
self.attr2: ClauseInfo[Point] = ClauseInfo[Point](None, point, dialect=dialect)
|
22
28
|
|
23
29
|
self._alias_clause: AliasType[ColumnType[TProp]] = alias_clause
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
return f"{self.FUNCTION_NAME}({self.attr1.query}, {self.attr2.query})"
|
31
|
+
def query(self, dialect: Dialect, **kwargs) -> str:
|
32
|
+
return f"{self.FUNCTION_NAME}({self.attr1.query(dialect,**kwargs)}, {self.attr2.query(dialect,**kwargs)})"
|
28
33
|
|
29
34
|
@property
|
30
35
|
def alias_clause(self) -> tp.Optional[str]:
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from .delete import DeleteQuery as Delete
|
2
|
+
from .insert import InsertQuery as Insert
|
3
|
+
from .joins import JoinSelector as JoinSelector
|
4
|
+
from .limit import Limit as Limit
|
5
|
+
from .offset import Offset as Offset
|
6
|
+
from .order import Order as Order
|
7
|
+
from .update import Update as Update
|
8
|
+
from .upsert import UpsertQuery as Upsert
|
9
|
+
from .where import Where as Where
|
10
|
+
from .having import Having as Having
|
11
|
+
from .count import Count as Count
|
12
|
+
from .group_by import GroupBy as GroupBy
|
13
|
+
from .ST_AsText import ST_AsText as ST_AsText
|
@@ -0,0 +1,33 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from ormlambda.sql.clauses import Count
|
3
|
+
from ormlambda.sql.clause_info.clause_info_context import ClauseContextType
|
4
|
+
|
5
|
+
from ormlambda.sql.types import AliasType, ColumnType
|
6
|
+
|
7
|
+
from ormlambda import Table
|
8
|
+
|
9
|
+
from typing import TYPE_CHECKING
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from ormlambda import Table
|
13
|
+
from ormlambda.sql.types import ColumnType, AliasType, TableType
|
14
|
+
|
15
|
+
|
16
|
+
class Count[T: Table](Count[T]):
|
17
|
+
def __init__[TProp: Table](
|
18
|
+
self,
|
19
|
+
element: ColumnType[T] | TableType[TProp],
|
20
|
+
alias_table: AliasType[ColumnType[TProp]] = None,
|
21
|
+
alias_clause: AliasType[ColumnType[TProp]] = "count",
|
22
|
+
context: ClauseContextType = None,
|
23
|
+
keep_asterisk: bool = True,
|
24
|
+
preserve_context: bool = True,
|
25
|
+
) -> None:
|
26
|
+
super().__init__(
|
27
|
+
element=element,
|
28
|
+
alias_table=alias_table,
|
29
|
+
alias_clause=alias_clause,
|
30
|
+
context=context,
|
31
|
+
keep_asterisk=keep_asterisk,
|
32
|
+
preserve_context=preserve_context,
|
33
|
+
)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
from ormlambda import Table
|
2
|
+
from ormlambda.repository import IRepositoryBase
|
3
|
+
from ormlambda.sql.clauses import Delete
|
4
|
+
from mysql.connector import MySQLConnection
|
5
|
+
|
6
|
+
|
7
|
+
class DeleteQuery[T: Table](Delete[T, MySQLConnection]):
|
8
|
+
def __init__(self, model: T, repository: IRepositoryBase) -> None:
|
9
|
+
super().__init__(model, repository)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
from ormlambda.sql.clause_info import ClauseInfoContext
|
2
|
+
from ormlambda.sql.clauses import GroupBy
|
3
|
+
from ormlambda.sql.types import ColumnType
|
4
|
+
|
5
|
+
|
6
|
+
class GroupBy(GroupBy):
|
7
|
+
def __init__(
|
8
|
+
self,
|
9
|
+
column: ColumnType,
|
10
|
+
context: ClauseInfoContext,
|
11
|
+
**kwargs,
|
12
|
+
):
|
13
|
+
super().__init__(
|
14
|
+
column=column,
|
15
|
+
context=context,
|
16
|
+
**kwargs,
|
17
|
+
)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from ormlambda.sql.clauses import Having
|
4
|
+
|
5
|
+
|
6
|
+
class Having(Having):
|
7
|
+
"""
|
8
|
+
The purpose of this class is to create 'WHERE' condition queries properly.
|
9
|
+
"""
|
10
|
+
|
11
|
+
def __init__(self, *comparer, restrictive=True, context=None):
|
12
|
+
super().__init__(*comparer, restrictive=restrictive, context=context)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from ormlambda import Table
|
3
|
+
from ormlambda.sql.clauses import Insert
|
4
|
+
from mysql.connector import MySQLConnection
|
5
|
+
|
6
|
+
|
7
|
+
class InsertQuery[T: Table](Insert[T, MySQLConnection]):
|
8
|
+
def __init__(self, model, repository):
|
9
|
+
super().__init__(model, repository)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
|
5
|
+
from ormlambda.sql.clauses import JoinSelector
|
6
|
+
|
7
|
+
# TODOL [x]: Try to import Table module without circular import Error
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
from ormlambda import Table
|
10
|
+
|
11
|
+
|
12
|
+
class JoinSelector[TLeft: Table, TRight: Table](JoinSelector[TLeft, TRight]):
|
13
|
+
def __init__(self, where, by, alias="{table}", context=None, **kw):
|
14
|
+
super().__init__(where, by, alias, context, **kw)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# dialects/mysql/mysqlconnector.py
|
2
|
+
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
3
|
+
# <see AUTHORS file>
|
4
|
+
#
|
5
|
+
# This module is part of SQLAlchemy and is released under
|
6
|
+
# the MIT License: https://www.opensource.org/licenses/mit-license.php
|
7
|
+
# mypy: ignore-errors
|
8
|
+
|
9
|
+
r"""
|
10
|
+
.. dialect:: mysql+mysqlconnector
|
11
|
+
:name: MySQL Connector/Python
|
12
|
+
:dbapi: myconnpy
|
13
|
+
:connectstring: mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
|
14
|
+
:url: https://pypi.org/project/mysql-connector-python/
|
15
|
+
|
16
|
+
.. note::
|
17
|
+
|
18
|
+
The MySQL Connector/Python DBAPI has had many issues since its release,
|
19
|
+
some of which may remain unresolved, and the mysqlconnector dialect is
|
20
|
+
The recommended MySQL dialects are mysqlclient and PyMySQL.
|
21
|
+
|
22
|
+
""" # noqa
|
23
|
+
|
24
|
+
from __future__ import annotations
|
25
|
+
from types import ModuleType
|
26
|
+
from .base import MySQLCompiler
|
27
|
+
from .base import MySQLDialect
|
28
|
+
|
29
|
+
|
30
|
+
class MySQLCompiler_mysqlconnector(MySQLCompiler):
|
31
|
+
def visit_mod_binary(self, binary, operator, **kw):
|
32
|
+
return self.process(binary.left, **kw) + " % " + self.process(binary.right, **kw)
|
33
|
+
|
34
|
+
|
35
|
+
class MySQLDialect_mysqlconnector(MySQLDialect):
|
36
|
+
driver = "mysqlconnector"
|
37
|
+
statement_compiler = MySQLCompiler_mysqlconnector
|
38
|
+
|
39
|
+
@classmethod
|
40
|
+
def import_dbapi(cls) -> ModuleType:
|
41
|
+
from mysql import connector
|
42
|
+
|
43
|
+
return connector
|
44
|
+
|
45
|
+
|
46
|
+
dialect = MySQLDialect_mysqlconnector
|
@@ -0,0 +1 @@
|
|
1
|
+
from .repository import MySQLRepository
|
@@ -0,0 +1,212 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
import contextlib
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Generator, Iterable, Optional, Type, override, TYPE_CHECKING, Unpack
|
5
|
+
import uuid
|
6
|
+
|
7
|
+
# from mysql.connector.pooling import MySQLConnectionPool
|
8
|
+
from mysql.connector import MySQLConnection # noqa: F401
|
9
|
+
from mysql.connector.pooling import MySQLConnectionPool # noqa: F401
|
10
|
+
from ormlambda.repository import BaseRepository
|
11
|
+
|
12
|
+
# Custom libraries
|
13
|
+
from ormlambda.repository.response import Response
|
14
|
+
from ormlambda.caster import Caster
|
15
|
+
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from ormlambda import URL as _URL
|
18
|
+
from ormlambda.sql.clauses import Select
|
19
|
+
from .pool_types import MySQLArgs
|
20
|
+
|
21
|
+
|
22
|
+
class MySQLRepository(BaseRepository[MySQLConnectionPool]):
|
23
|
+
# def get_connection[**P, TReturn](func: Callable[Concatenate[MySQLRepository, MySQLConnection, P], TReturn]) -> Callable[P, TReturn]:
|
24
|
+
# def wrapper(self: MySQLRepository, *args: P.args, **kwargs: P.kwargs):
|
25
|
+
# with self.get_connection() as cnx:
|
26
|
+
# try:
|
27
|
+
# return func(self, cnx._cnx, *args, **kwargs)
|
28
|
+
# except Exception as e:
|
29
|
+
# cnx._cnx.rollback()
|
30
|
+
# raise e
|
31
|
+
|
32
|
+
# return wrapper
|
33
|
+
|
34
|
+
#
|
35
|
+
|
36
|
+
def __init__(
|
37
|
+
self,
|
38
|
+
/,
|
39
|
+
url: Optional[_URL] = None,
|
40
|
+
*,
|
41
|
+
user: Optional[str] = None,
|
42
|
+
password: Optional[str] = None,
|
43
|
+
host: Optional[str] = None,
|
44
|
+
database: Optional[str] = None,
|
45
|
+
**kwargs: Unpack[MySQLArgs],
|
46
|
+
):
|
47
|
+
timeout = self.__add_connection_timeout(kwargs)
|
48
|
+
name = self.__add_pool_name(kwargs)
|
49
|
+
size = self.__add_pool_size(kwargs)
|
50
|
+
attr = kwargs.copy()
|
51
|
+
attr["connection_timeout"] = timeout
|
52
|
+
attr["pool_name"] = name
|
53
|
+
attr["pool_size"] = size
|
54
|
+
|
55
|
+
super().__init__(
|
56
|
+
user=user if not url else url.username,
|
57
|
+
password=password if not url else url.password,
|
58
|
+
host=host if not url else url.host,
|
59
|
+
database=database if not url else url.database,
|
60
|
+
pool=MySQLConnectionPool,
|
61
|
+
**attr,
|
62
|
+
)
|
63
|
+
|
64
|
+
@staticmethod
|
65
|
+
def __add_connection_timeout(kwargs: MySQLArgs) -> int:
|
66
|
+
if "connection_timeout" not in kwargs.keys():
|
67
|
+
return 60
|
68
|
+
return int(kwargs.pop("connection_timeout"))
|
69
|
+
|
70
|
+
@staticmethod
|
71
|
+
def __add_pool_name(kwargs: MySQLArgs) -> str:
|
72
|
+
if "pool_name" not in kwargs.keys():
|
73
|
+
return str(uuid.uuid4())
|
74
|
+
|
75
|
+
return kwargs.pop("pool_name")
|
76
|
+
|
77
|
+
@staticmethod
|
78
|
+
def __add_pool_size(kwargs: MySQLArgs) -> int:
|
79
|
+
if "pool_size" not in kwargs.keys():
|
80
|
+
return 5
|
81
|
+
return int(kwargs.pop("pool_size"))
|
82
|
+
|
83
|
+
@contextlib.contextmanager
|
84
|
+
def get_connection(self) -> Generator[MySQLConnection, None, None]:
|
85
|
+
with self._pool.get_connection() as cnx:
|
86
|
+
try:
|
87
|
+
yield cnx._cnx
|
88
|
+
cnx._cnx.commit()
|
89
|
+
except Exception as exc:
|
90
|
+
cnx._cnx.rollback()
|
91
|
+
raise exc
|
92
|
+
|
93
|
+
@override
|
94
|
+
def read_sql[TFlavour: Iterable](
|
95
|
+
self,
|
96
|
+
query: str,
|
97
|
+
flavour: tuple | Type[TFlavour] = tuple,
|
98
|
+
**kwargs,
|
99
|
+
) -> tuple[TFlavour]:
|
100
|
+
"""
|
101
|
+
Return tuple of tuples by default.
|
102
|
+
|
103
|
+
ATTRIBUTE
|
104
|
+
-
|
105
|
+
- query:str: string of request to the server
|
106
|
+
- flavour: Type[TFlavour]: Useful to return tuple of any Iterable type as dict,set,list...
|
107
|
+
"""
|
108
|
+
|
109
|
+
select: Select = kwargs.pop("select", None)
|
110
|
+
|
111
|
+
with self.get_connection() as cnx:
|
112
|
+
with cnx.cursor(buffered=True) as cursor:
|
113
|
+
cursor.execute(query)
|
114
|
+
values: list[tuple] = cursor.fetchall()
|
115
|
+
columns: tuple[str] = cursor.column_names
|
116
|
+
return Response(
|
117
|
+
dialect=self._dialect,
|
118
|
+
response_values=values,
|
119
|
+
columns=columns,
|
120
|
+
flavour=flavour,
|
121
|
+
select=select,
|
122
|
+
).response(**kwargs)
|
123
|
+
|
124
|
+
# FIXME [ ]: this method does not comply with the implemented interface
|
125
|
+
def create_tables_code_first(self, path: str | Path) -> None:
|
126
|
+
return
|
127
|
+
from ormlambda.utils.module_tree.dynamic_module import ModuleTree
|
128
|
+
|
129
|
+
if not isinstance(path, Path | str):
|
130
|
+
raise ValueError
|
131
|
+
|
132
|
+
if isinstance(path, str):
|
133
|
+
path = Path(path).resolve()
|
134
|
+
|
135
|
+
if not path.exists():
|
136
|
+
raise FileNotFoundError
|
137
|
+
|
138
|
+
module_tree: ModuleTree = ModuleTree(path)
|
139
|
+
|
140
|
+
queries_list: list[str] = module_tree.get_queries()
|
141
|
+
|
142
|
+
for query in queries_list:
|
143
|
+
with self.get_connection() as cnx:
|
144
|
+
with cnx.cursor(buffered=True) as cursor:
|
145
|
+
cursor.execute(query)
|
146
|
+
return None
|
147
|
+
|
148
|
+
@override
|
149
|
+
def executemany_with_values(self, query: str, values) -> None:
|
150
|
+
with self.get_connection() as cnx:
|
151
|
+
with cnx.cursor(buffered=True) as cursor:
|
152
|
+
cursor.executemany(query, values)
|
153
|
+
return None
|
154
|
+
|
155
|
+
@override
|
156
|
+
def execute_with_values(self, query: str, values) -> None:
|
157
|
+
with self.get_connection() as cnx:
|
158
|
+
with cnx.cursor(buffered=True) as cursor:
|
159
|
+
cursor.execute(query, values)
|
160
|
+
return None
|
161
|
+
|
162
|
+
@override
|
163
|
+
def execute(self, query: str) -> None:
|
164
|
+
with self.get_connection() as cnx:
|
165
|
+
with cnx.cursor(buffered=True) as cursor:
|
166
|
+
cursor.execute(query)
|
167
|
+
return None
|
168
|
+
|
169
|
+
@override
|
170
|
+
def database_exists(self, name: str) -> bool:
|
171
|
+
temp_config = self._pool._cnx_config
|
172
|
+
|
173
|
+
config_without_db = temp_config.copy()
|
174
|
+
|
175
|
+
if "database" in config_without_db:
|
176
|
+
config_without_db.pop("database")
|
177
|
+
self._pool.set_config(**config_without_db)
|
178
|
+
|
179
|
+
with self.get_connection() as cnx:
|
180
|
+
with cnx.cursor(buffered=True) as cursor:
|
181
|
+
cursor.execute(f"SHOW DATABASES LIKE {Caster.PLACEHOLDER};", (name,))
|
182
|
+
res = cursor.fetchmany(1)
|
183
|
+
|
184
|
+
self._pool.set_config(**temp_config)
|
185
|
+
return len(res) > 0
|
186
|
+
|
187
|
+
@override
|
188
|
+
def table_exists(self, name: str) -> bool:
|
189
|
+
with self.get_connection() as cnx:
|
190
|
+
if not cnx.database:
|
191
|
+
raise Exception("No database selected")
|
192
|
+
with cnx.cursor(buffered=True) as cursor:
|
193
|
+
cursor.execute(f"SHOW TABLES LIKE {Caster.PLACEHOLDER};", (name,))
|
194
|
+
res = cursor.fetchmany(1)
|
195
|
+
return len(res) > 0
|
196
|
+
|
197
|
+
@property
|
198
|
+
def database(self) -> Optional[str]:
|
199
|
+
return self._pool._cnx_config.get("database", None)
|
200
|
+
|
201
|
+
@database.setter
|
202
|
+
def database(self, value: str) -> None:
|
203
|
+
"""Change the current database using USE statement"""
|
204
|
+
|
205
|
+
if not self.database_exists(value):
|
206
|
+
raise ValueError(f"You cannot set the non-existent '{value}' database.")
|
207
|
+
|
208
|
+
old_config: MySQLArgs = self._pool._cnx_config.copy()
|
209
|
+
old_config["database"] = value
|
210
|
+
|
211
|
+
self._pool._remove_connections()
|
212
|
+
self._pool = type(self)(**old_config)._pool
|