ormlambda 3.35.2__py3-none-any.whl → 4.0.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 +79 -51
- ormlambda/caster/caster.py +6 -1
- ormlambda/common/abstract_classes/__init__.py +0 -2
- ormlambda/common/enums/__init__.py +1 -0
- ormlambda/common/enums/order_type.py +9 -0
- ormlambda/common/errors/__init__.py +13 -3
- ormlambda/common/global_checker.py +86 -8
- ormlambda/common/interfaces/IQueryCommand.py +2 -2
- ormlambda/common/interfaces/__init__.py +0 -2
- ormlambda/dialects/__init__.py +75 -3
- ormlambda/dialects/default/base.py +1 -1
- ormlambda/dialects/mysql/__init__.py +35 -78
- ormlambda/dialects/mysql/base.py +226 -40
- ormlambda/dialects/mysql/clauses/ST_AsText.py +26 -0
- ormlambda/dialects/mysql/clauses/ST_Contains.py +30 -0
- ormlambda/dialects/mysql/clauses/__init__.py +1 -0
- ormlambda/dialects/mysql/repository/__init__.py +1 -0
- ormlambda/{databases/my_sql → dialects/mysql/repository}/repository.py +0 -5
- ormlambda/dialects/mysql/types.py +6 -0
- ormlambda/engine/base.py +26 -4
- ormlambda/errors.py +9 -0
- ormlambda/model/base_model.py +3 -10
- ormlambda/repository/base_repository.py +1 -1
- ormlambda/repository/interfaces/IRepositoryBase.py +0 -7
- ormlambda/repository/response.py +12 -7
- ormlambda/sql/__init__.py +12 -3
- ormlambda/sql/clause_info/__init__.py +0 -2
- ormlambda/sql/clause_info/clause_info.py +94 -76
- ormlambda/sql/clause_info/interface/IAggregate.py +14 -4
- ormlambda/sql/clause_info/interface/IClauseInfo.py +6 -11
- ormlambda/sql/clauses/alias.py +6 -37
- ormlambda/sql/clauses/count.py +21 -36
- ormlambda/sql/clauses/group_by.py +13 -19
- ormlambda/sql/clauses/having.py +2 -6
- ormlambda/sql/clauses/insert.py +3 -3
- ormlambda/sql/clauses/interfaces/__init__.py +0 -1
- ormlambda/sql/clauses/join/join_context.py +5 -12
- ormlambda/sql/clauses/joins.py +34 -52
- ormlambda/sql/clauses/limit.py +1 -2
- ormlambda/sql/clauses/offset.py +1 -2
- ormlambda/sql/clauses/order.py +17 -21
- ormlambda/sql/clauses/select.py +56 -28
- ormlambda/sql/clauses/update.py +13 -10
- ormlambda/sql/clauses/where.py +20 -39
- ormlambda/sql/column/__init__.py +1 -0
- ormlambda/sql/column/column.py +19 -12
- ormlambda/sql/column/column_proxy.py +117 -0
- ormlambda/sql/column_table_proxy.py +23 -0
- ormlambda/sql/comparer.py +31 -65
- ormlambda/sql/compiler.py +248 -58
- ormlambda/sql/context/__init__.py +304 -0
- ormlambda/sql/ddl.py +19 -5
- ormlambda/sql/elements.py +3 -0
- ormlambda/sql/foreign_key.py +42 -64
- ormlambda/sql/functions/__init__.py +0 -1
- ormlambda/sql/functions/concat.py +35 -38
- ormlambda/sql/functions/max.py +12 -36
- ormlambda/sql/functions/min.py +13 -28
- ormlambda/sql/functions/sum.py +17 -33
- ormlambda/sql/sqltypes.py +2 -0
- ormlambda/sql/table/__init__.py +1 -0
- ormlambda/sql/table/table.py +32 -49
- ormlambda/sql/table/table_proxy.py +88 -0
- ormlambda/sql/type_api.py +4 -1
- ormlambda/sql/types.py +15 -12
- ormlambda/statements/__init__.py +0 -2
- ormlambda/statements/base_statement.py +51 -84
- ormlambda/statements/interfaces/IStatements.py +77 -123
- ormlambda/statements/interfaces/__init__.py +1 -1
- ormlambda/statements/query_builder.py +296 -128
- ormlambda/statements/statements.py +120 -110
- ormlambda/statements/types.py +5 -25
- ormlambda/util/__init__.py +7 -86
- ormlambda/util/langhelpers.py +102 -0
- ormlambda/util/module_tree/dynamic_module.py +1 -1
- ormlambda/util/preloaded.py +80 -0
- ormlambda/util/typing.py +12 -3
- {ormlambda-3.35.2.dist-info → ormlambda-4.0.0.dist-info}/METADATA +29 -31
- ormlambda-4.0.0.dist-info/RECORD +139 -0
- ormlambda/common/abstract_classes/clause_info_converter.py +0 -65
- ormlambda/common/abstract_classes/decomposition_query.py +0 -141
- ormlambda/common/abstract_classes/query_base.py +0 -15
- ormlambda/common/interfaces/ICustomAlias.py +0 -7
- ormlambda/common/interfaces/IDecompositionQuery.py +0 -33
- ormlambda/databases/__init__.py +0 -4
- ormlambda/databases/my_sql/__init__.py +0 -3
- ormlambda/databases/my_sql/clauses/ST_AsText.py +0 -37
- ormlambda/databases/my_sql/clauses/ST_Contains.py +0 -36
- ormlambda/databases/my_sql/clauses/__init__.py +0 -14
- ormlambda/databases/my_sql/clauses/count.py +0 -33
- ormlambda/databases/my_sql/clauses/delete.py +0 -9
- ormlambda/databases/my_sql/clauses/drop_table.py +0 -26
- ormlambda/databases/my_sql/clauses/group_by.py +0 -17
- ormlambda/databases/my_sql/clauses/having.py +0 -12
- ormlambda/databases/my_sql/clauses/insert.py +0 -9
- ormlambda/databases/my_sql/clauses/joins.py +0 -14
- ormlambda/databases/my_sql/clauses/limit.py +0 -6
- ormlambda/databases/my_sql/clauses/offset.py +0 -6
- ormlambda/databases/my_sql/clauses/order.py +0 -8
- ormlambda/databases/my_sql/clauses/update.py +0 -8
- ormlambda/databases/my_sql/clauses/upsert.py +0 -9
- ormlambda/databases/my_sql/clauses/where.py +0 -7
- ormlambda/dialects/interface/__init__.py +0 -1
- ormlambda/dialects/interface/dialect.py +0 -78
- ormlambda/sql/clause_info/aggregate_function_base.py +0 -96
- ormlambda/sql/clause_info/clause_info_context.py +0 -87
- ormlambda/sql/clauses/interfaces/ISelect.py +0 -17
- ormlambda/sql/clauses/new_join.py +0 -119
- ormlambda/util/load_module.py +0 -21
- ormlambda/util/plugin_loader.py +0 -32
- ormlambda-3.35.2.dist-info/RECORD +0 -159
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/__init__.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/caster.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/__init__.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/boolean.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/bytes.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/date.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/datetime.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/decimal.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/float.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/int.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/iterable.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/json.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/none.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/point.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/types/string.py +0 -0
- /ormlambda/{databases/my_sql → dialects/mysql/repository}/pool_types.py +0 -0
- {ormlambda-3.35.2.dist-info → ormlambda-4.0.0.dist-info}/AUTHORS +0 -0
- {ormlambda-3.35.2.dist-info → ormlambda-4.0.0.dist-info}/LICENSE +0 -0
- {ormlambda-3.35.2.dist-info → ormlambda-4.0.0.dist-info}/WHEEL +0 -0
ormlambda/__init__.py
CHANGED
@@ -1,59 +1,87 @@
|
|
1
|
-
|
1
|
+
# COMMENT: Necesary to load all variables inside ormalambda.env
|
2
|
+
import ormlambda.env # noqa: F401
|
2
3
|
|
3
4
|
# region enums
|
4
|
-
from .common.enums import
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
from .common.enums import JoinType as JoinType
|
6
|
+
from .common.enums import ConditionType as ConditionType
|
7
|
+
from .common.enums import OrderType as OrderType
|
8
|
+
|
9
|
+
|
8
10
|
# endregion
|
9
11
|
|
10
12
|
# region sql
|
11
|
-
from .sql import
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
from .sql import Column as Column
|
14
|
+
from .sql import ColumnProxy as ColumnProxy
|
15
|
+
from .sql import Table as Table
|
16
|
+
from .sql import ForeignKey as ForeignKey
|
17
|
+
from .sql import TableProxy as TableProxy
|
18
|
+
|
19
|
+
|
16
20
|
# endregion
|
17
21
|
|
18
22
|
from .repository import BaseRepository as BaseRepository
|
19
|
-
|
20
|
-
from .
|
21
|
-
from .model.base_model import
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
from .engine import
|
27
|
-
|
28
|
-
from .sql.sqltypes import
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
23
|
+
|
24
|
+
from .model.base_model import BaseModel as BaseModel
|
25
|
+
from .model.base_model import ORM as ORM
|
26
|
+
# COMMENT: to avoid relative import we need to import BaseModel after import Table,Column, ForeignKey, IRepositoryBase and Disassembler
|
27
|
+
|
28
|
+
from .engine import create_engine as create_engine
|
29
|
+
from .engine import URL as URL
|
30
|
+
from .engine import make_url as make_url
|
31
|
+
|
32
|
+
from .sql.sqltypes import JSON as JSON
|
33
|
+
from .sql.sqltypes import UUID as UUID
|
34
|
+
from .sql.sqltypes import NullType as NullType
|
35
|
+
from .sql.sqltypes import INTEGER as INTEGER
|
36
|
+
from .sql.sqltypes import INT as INT
|
37
|
+
from .sql.sqltypes import SMALLINTEGER as SMALLINTEGER
|
38
|
+
from .sql.sqltypes import BIGINTEGER as BIGINTEGER
|
39
|
+
from .sql.sqltypes import NUMERIC as NUMERIC
|
40
|
+
from .sql.sqltypes import FLOAT as FLOAT
|
41
|
+
from .sql.sqltypes import REAL as REAL
|
42
|
+
from .sql.sqltypes import DOUBLE as DOUBLE
|
43
|
+
from .sql.sqltypes import DECIMAL as DECIMAL
|
44
|
+
from .sql.sqltypes import STRING as STRING
|
45
|
+
from .sql.sqltypes import TEXT as TEXT
|
46
|
+
from .sql.sqltypes import UNICODE as UNICODE
|
47
|
+
from .sql.sqltypes import UNICODETEXT as UNICODETEXT
|
48
|
+
from .sql.sqltypes import CHAR as CHAR
|
49
|
+
from .sql.sqltypes import NCHAR as NCHAR
|
50
|
+
from .sql.sqltypes import BLOB as BLOB
|
51
|
+
from .sql.sqltypes import VARCHAR as VARCHAR
|
52
|
+
from .sql.sqltypes import NVARCHAR as NVARCHAR
|
53
|
+
from .sql.sqltypes import DATE as DATE
|
54
|
+
from .sql.sqltypes import TIME as TIME
|
55
|
+
from .sql.sqltypes import DATETIME as DATETIME
|
56
|
+
from .sql.sqltypes import TIMESTAMP as TIMESTAMP
|
57
|
+
from .sql.sqltypes import BOOLEAN as BOOLEAN
|
58
|
+
from .sql.sqltypes import LARGEBINARY as LARGEBINARY
|
59
|
+
from .sql.sqltypes import VARBINARY as VARBINARY
|
60
|
+
from .sql.sqltypes import ENUM as ENUM
|
61
|
+
from .sql.sqltypes import POINT as POINT
|
62
|
+
|
63
|
+
|
64
|
+
from .sql.clauses import Alias as Alias
|
65
|
+
from .sql.clauses import Count as Count
|
66
|
+
from .sql.clauses import Delete as Delete
|
67
|
+
from .sql.clauses import GroupBy as GroupBy
|
68
|
+
from .sql.clauses import Insert as Insert
|
69
|
+
from .sql.clauses import JoinSelector as JoinSelector
|
70
|
+
from .sql.clauses import Limit as Limit
|
71
|
+
from .sql.clauses import Offset as Offset
|
72
|
+
from .sql.clauses import Order as Order
|
73
|
+
from .sql.clauses import Select as Select
|
74
|
+
from .sql.clauses import Where as Where
|
75
|
+
from .sql.clauses import Having as Having
|
76
|
+
from .sql.clauses import Update as Update
|
77
|
+
from .sql.clauses import Upsert as Upsert
|
78
|
+
|
79
|
+
from .sql.functions import Max as Max
|
80
|
+
from .sql.functions import Min as Min
|
81
|
+
from .sql.functions import Concat as Concat
|
82
|
+
from .sql.functions import Sum as Sum
|
83
|
+
|
84
|
+
|
85
|
+
from . import util as _util
|
86
|
+
|
87
|
+
_util.import_prefix("ormlambda")
|
ormlambda/caster/caster.py
CHANGED
@@ -62,4 +62,9 @@ class Caster(ICaster):
|
|
62
62
|
column_type = type(value)
|
63
63
|
else:
|
64
64
|
column_type = type_value
|
65
|
-
|
65
|
+
|
66
|
+
caster_class = cls.CASTER_SELECTOR().get(column_type, None)
|
67
|
+
if not caster_class:
|
68
|
+
raise ValueError(f"'{column_type}' type has not a Caster class created.")
|
69
|
+
|
70
|
+
return caster_class(value, column_type)
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
2
2
|
import inspect
|
3
3
|
import typing as tp
|
4
4
|
|
5
|
+
from ormlambda import util
|
5
6
|
|
6
7
|
if tp.TYPE_CHECKING:
|
7
8
|
from ormlambda.sql.clause_info import ClauseInfo
|
@@ -35,16 +36,25 @@ class AggregateFunctionError[T](Exception):
|
|
35
36
|
agg_methods = self.__get_all_aggregate_method(self.clause)
|
36
37
|
return f"You cannot use aggregation method like '{agg_methods}' to return model objects. Try specifying 'flavour' attribute as 'dict'."
|
37
38
|
|
39
|
+
@util.preload_module("ormlambda.sql.clause_info")
|
38
40
|
def __get_all_aggregate_method(self, clauses: list[ClauseInfo]) -> str:
|
39
41
|
"""
|
40
|
-
Get the class name of those classes that inherit from '
|
42
|
+
Get the class name of those classes that inherit from 'IAggregate' class in order to create a better error message.
|
41
43
|
"""
|
42
|
-
from ormlambda.sql.clause_info import AggregateFunctionBase
|
43
44
|
|
45
|
+
IAggregate = util.preloaded.sql_clause_info.IAggregate
|
44
46
|
res: set[str] = set()
|
45
47
|
if not isinstance(clauses, tp.Iterable):
|
46
48
|
return clauses.__class__.__name__
|
47
49
|
for clause in clauses:
|
48
|
-
if isinstance(clause,
|
50
|
+
if isinstance(clause, IAggregate):
|
49
51
|
res.add(clause.__class__.__name__)
|
50
52
|
return ", ".join(res)
|
53
|
+
|
54
|
+
|
55
|
+
class NotCallableError(ValueError):
|
56
|
+
def __init__(self, *args):
|
57
|
+
super().__init__(*args)
|
58
|
+
|
59
|
+
def __str__(self)->str:
|
60
|
+
return f"You must provide a function or callable to proceed with the query creation. Passed '{self.args[0].__class__.__name__}' "
|
@@ -1,28 +1,106 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
import re
|
3
|
-
from typing import Any, TYPE_CHECKING
|
3
|
+
from typing import Any, TYPE_CHECKING, Iterable, Callable
|
4
4
|
|
5
5
|
from ormlambda.common.errors import UnmatchedLambdaParameterError
|
6
|
+
from ormlambda.common.errors import NotCallableError
|
7
|
+
from ormlambda import util
|
6
8
|
|
7
9
|
if TYPE_CHECKING:
|
8
|
-
from ormlambda.sql import
|
10
|
+
from ormlambda.sql.types import SelectCol # FIXME [ ]: enhance the name
|
11
|
+
from ormlambda import TableProxy
|
12
|
+
from ormlambda.sql.column import ColumnProxy
|
9
13
|
|
10
14
|
|
11
|
-
|
15
|
+
# type LambdaResponse[T] = TableProxy[T] | ColumnProxy[T] | Comparer
|
16
|
+
class GlobalChecker[T: TableProxy]:
|
17
|
+
FIRST_QUOTE = "`"
|
18
|
+
END_QUOTE = "`"
|
19
|
+
|
12
20
|
@staticmethod
|
13
21
|
def is_lambda_function(obj: Any) -> bool:
|
14
22
|
return callable(obj) and not isinstance(obj, type)
|
15
23
|
|
24
|
+
@util.preload_module("ormlambda.sql")
|
16
25
|
@classmethod
|
17
|
-
def resolved_callback_object(cls,
|
18
|
-
|
19
|
-
return obj
|
26
|
+
def resolved_callback_object(cls, table: T, lambda_func: Callable[[T], Any]) -> tuple[SelectCol, ...]:
|
27
|
+
TableProxy = util.preloaded.sql_table.TableProxy
|
20
28
|
|
21
29
|
try:
|
22
|
-
|
30
|
+
table_proxy = TableProxy(table)
|
31
|
+
|
32
|
+
if not callable(lambda_func):
|
33
|
+
raise NotCallableError(lambda_func)
|
34
|
+
|
35
|
+
if isinstance(lambda_func, Iterable):
|
36
|
+
# We hit that condition when trying to pass column or function dynamically into select clause.
|
37
|
+
|
38
|
+
# max_fn = Max(lambda x: x.Col1)
|
39
|
+
# min_fn = Min(lambda x: x.Col1)
|
40
|
+
# sum_fn = Sum(lambda x: x.Col1)
|
41
|
+
# result = self.model.select(
|
42
|
+
# (
|
43
|
+
# max_fn,
|
44
|
+
# min_fn,
|
45
|
+
# sum_fn,
|
46
|
+
# ),
|
47
|
+
# flavour=dict,
|
48
|
+
# )
|
49
|
+
|
50
|
+
response = []
|
51
|
+
|
52
|
+
for item in lambda_func:
|
53
|
+
response.append(item)
|
54
|
+
return response
|
55
|
+
|
56
|
+
response = lambda_func(table_proxy)
|
57
|
+
result = []
|
58
|
+
|
59
|
+
if isinstance(response, str) or not isinstance(response, Iterable):
|
60
|
+
response = [response]
|
61
|
+
|
62
|
+
for item in response:
|
63
|
+
column = cls.parser_object(item, table)
|
64
|
+
|
65
|
+
result.extend(column)
|
66
|
+
|
67
|
+
return result
|
68
|
+
|
23
69
|
except TypeError as err:
|
24
70
|
cond1 = r"takes \d+ positional argument but \d+ were given"
|
25
71
|
cond2 = r"missing \d+ required positional arguments:"
|
26
72
|
if re.search(r"(" + f"{cond1}|{cond2}" + r")", err.args[0]):
|
27
|
-
raise UnmatchedLambdaParameterError(len(
|
73
|
+
raise UnmatchedLambdaParameterError(len(table), lambda_func)
|
28
74
|
raise err
|
75
|
+
|
76
|
+
@util.preload_module(
|
77
|
+
"ormlambda.sql.column",
|
78
|
+
"ormlambda.sql.table",
|
79
|
+
"ormlambda.sql.comparer",
|
80
|
+
"ormlambda.sql.column_table_proxy",
|
81
|
+
)
|
82
|
+
@staticmethod
|
83
|
+
def parser_object(item: Any, table: T) -> tuple[ColumnProxy, ...]:
|
84
|
+
ColumnProxy = util.preloaded.sql_column.ColumnProxy
|
85
|
+
Column = util.preloaded.sql_column.Column
|
86
|
+
|
87
|
+
TableProxy = util.preloaded.sql_table.TableProxy
|
88
|
+
Comparer = util.preloaded.sql_comparer.Comparer
|
89
|
+
FKChain = util.preloaded.sql_column_table_proxy.FKChain
|
90
|
+
|
91
|
+
if isinstance(item, TableProxy):
|
92
|
+
return item.get_columns()
|
93
|
+
|
94
|
+
if isinstance(item, str):
|
95
|
+
# If we got a string, probably means that it'll be an alias,
|
96
|
+
# so we'll want to avoid add string alias table to alias like `address`.count
|
97
|
+
new_col = Column(dtype=str, column_name=item)
|
98
|
+
new_col.table = table
|
99
|
+
return [ColumnProxy(new_col, path=FKChain(table, None))]
|
100
|
+
if isinstance(item, Comparer):
|
101
|
+
return [item]
|
102
|
+
|
103
|
+
if isinstance(item, ColumnProxy):
|
104
|
+
return [item]
|
105
|
+
|
106
|
+
return [item]
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
-
from abc import
|
2
|
+
from abc import ABC
|
3
3
|
from typing import TYPE_CHECKING
|
4
4
|
|
5
5
|
if TYPE_CHECKING:
|
@@ -9,7 +9,7 @@ if TYPE_CHECKING:
|
|
9
9
|
class IQuery(ABC):
|
10
10
|
"""Interface to queries that retrieve any element such as select, limit, offset, where, group by, etc..."""
|
11
11
|
|
12
|
-
@abstractmethod
|
12
|
+
# @abstractmethod
|
13
13
|
def query(self, dialect: Dialect, **kwargs) -> str: ...
|
14
14
|
|
15
15
|
def __repr__(self) -> str:
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from .ICustomAlias import ICustomAlias as ICustomAlias
|
2
|
-
from .IDecompositionQuery import IDecompositionQuery as IDecompositionQuery
|
3
1
|
from .IJoinSelector import IJoinSelector as IJoinSelector
|
4
2
|
from .INonQueryCommand import INonQueryCommand as INonQueryCommand
|
5
3
|
from .IQueryCommand import IQuery as IQuery
|
ormlambda/dialects/__init__.py
CHANGED
@@ -1,13 +1,83 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
-
from typing import Callable, Optional, Type, TYPE_CHECKING
|
2
|
+
from typing import Callable, Optional, Type, TYPE_CHECKING, ClassVar
|
3
|
+
import abc
|
3
4
|
from ormlambda import util
|
4
5
|
import importlib
|
5
6
|
|
7
|
+
|
6
8
|
if TYPE_CHECKING:
|
7
|
-
from .
|
9
|
+
from ormlambda.caster.caster import Caster
|
10
|
+
from ormlambda.repository.interfaces.IRepositoryBase import DBAPIConnection
|
11
|
+
from ormlambda.sql.types import DDLCompiler, SQLCompiler, TypeCompiler
|
12
|
+
from ormlambda import BaseRepository
|
8
13
|
|
9
14
|
|
10
|
-
|
15
|
+
class Dialect(abc.ABC):
|
16
|
+
"""
|
17
|
+
Abstract base class for all database dialects.
|
18
|
+
"""
|
19
|
+
|
20
|
+
dbapi: Optional[DBAPIConnection]
|
21
|
+
"""A reference to the DBAPI module object itself.
|
22
|
+
|
23
|
+
Ormlambda dialects import DBAPI modules using the classmethod
|
24
|
+
:meth:`.Dialect.import_dbapi`. The rationale is so that any dialect
|
25
|
+
module can be imported and used to generate SQL statements without the
|
26
|
+
need for the actual DBAPI driver to be installed. Only when an
|
27
|
+
:class:`.Engine` is constructed using :func:`.create_engine` does the
|
28
|
+
DBAPI get imported; at that point, the creation process will assign
|
29
|
+
the DBAPI module to this attribute.
|
30
|
+
|
31
|
+
Dialects should therefore implement :meth:`.Dialect.import_dbapi`
|
32
|
+
which will import the necessary module and return it, and then refer
|
33
|
+
to ``self.dbapi`` in dialect code in order to refer to the DBAPI module
|
34
|
+
contents.
|
35
|
+
|
36
|
+
.. versionchanged:: The :attr:`.Dialect.dbapi` attribute is exclusively
|
37
|
+
used as the per-:class:`.Dialect`-instance reference to the DBAPI
|
38
|
+
module. The previous not-fully-documented ``.Dialect.dbapi()``
|
39
|
+
classmethod is deprecated and replaced by :meth:`.Dialect.import_dbapi`.
|
40
|
+
|
41
|
+
"""
|
42
|
+
|
43
|
+
name: ClassVar[str]
|
44
|
+
"""The name of the dialect, e.g. 'sqlite', 'postgresql', etc."""
|
45
|
+
driver: ClassVar[str]
|
46
|
+
"""The driver used by the dialect, e.g. 'sqlite3', 'psycopg2', etc."""
|
47
|
+
|
48
|
+
ddl_compiler: ClassVar[Type[DDLCompiler]]
|
49
|
+
"""The DDL compiler class used by the dialect."""
|
50
|
+
|
51
|
+
statement_compiler: ClassVar[Type[SQLCompiler]]
|
52
|
+
"""The statement compiler class used by the dialect."""
|
53
|
+
|
54
|
+
type_compiler_cls: ClassVar[Type[TypeCompiler]]
|
55
|
+
"""The type compiler class used by the dialect."""
|
56
|
+
|
57
|
+
type_compiler_instance: ClassVar[TypeCompiler]
|
58
|
+
"""The instance of the type compiler class used by the dialect."""
|
59
|
+
|
60
|
+
repository_cls: ClassVar[Type[BaseRepository]]
|
61
|
+
"""The repository class used by the dialect."""
|
62
|
+
|
63
|
+
caster: ClassVar[Type[Caster]]
|
64
|
+
|
65
|
+
@classmethod
|
66
|
+
def get_dialect_cls(cls) -> Type[Dialect]:
|
67
|
+
return cls
|
68
|
+
|
69
|
+
@classmethod
|
70
|
+
@abc.abstractmethod
|
71
|
+
def import_dbapi(cls) -> DBAPIConnection:
|
72
|
+
"""
|
73
|
+
Import the DB API module for the dialect.
|
74
|
+
This method should be implemented by subclasses to import the
|
75
|
+
appropriate DB API module for the dialect.
|
76
|
+
"""
|
77
|
+
...
|
78
|
+
|
79
|
+
def __repr__(self):
|
80
|
+
return f"{Dialect.__name__}: {type(self).__name__}"
|
11
81
|
|
12
82
|
|
13
83
|
def _auto_fn(name: str) -> Optional[Callable[[], Type[Dialect]]]:
|
@@ -37,3 +107,5 @@ def _auto_fn(name: str) -> Optional[Callable[[], Type[Dialect]]]:
|
|
37
107
|
|
38
108
|
|
39
109
|
registry = util.PluginLoader("ormlambda.dialects", auto_fn=_auto_fn)
|
110
|
+
|
111
|
+
__all__ = ("mysql", "sqlite")
|
@@ -1,84 +1,41 @@
|
|
1
|
-
from . import base
|
2
|
-
from . import mysqlconnector
|
1
|
+
from . import base as base
|
2
|
+
from . import mysqlconnector as mysqlconnector
|
3
3
|
|
4
|
-
from .base import BIGINT
|
5
|
-
from .base import
|
6
|
-
from .base import
|
7
|
-
from .base import
|
8
|
-
from .base import
|
9
|
-
from .base import
|
10
|
-
from .base import
|
11
|
-
from .base import
|
12
|
-
from .base import
|
13
|
-
from .base import
|
14
|
-
from .base import
|
15
|
-
from .base import
|
16
|
-
from .base import
|
17
|
-
from .base import
|
18
|
-
from .base import
|
19
|
-
from .base import
|
20
|
-
from .base import
|
21
|
-
from .base import
|
22
|
-
from .base import
|
23
|
-
from .base import
|
24
|
-
from .base import
|
25
|
-
from .base import
|
26
|
-
from .base import
|
27
|
-
from .base import
|
28
|
-
from .base import
|
29
|
-
from .base import
|
30
|
-
from .base import
|
31
|
-
from .base import
|
32
|
-
from .base import
|
33
|
-
from .base import
|
34
|
-
from .
|
4
|
+
from .base import BIGINT as BIGINT
|
5
|
+
from .base import BIT as BIT
|
6
|
+
from .base import BLOB as BLOB
|
7
|
+
from .base import BOOLEAN as BOOLEAN
|
8
|
+
from .base import CHAR as CHAR
|
9
|
+
from .base import DATE as DATE
|
10
|
+
from .base import DATETIME as DATETIME
|
11
|
+
from .base import DECIMAL as DECIMAL
|
12
|
+
from .base import DOUBLE as DOUBLE
|
13
|
+
from .base import FLOAT as FLOAT
|
14
|
+
from .base import INTEGER as INTEGER
|
15
|
+
from .base import LONGBLOB as LONGBLOB
|
16
|
+
from .base import LONGTEXT as LONGTEXT
|
17
|
+
from .base import MEDIUMBLOB as MEDIUMBLOB
|
18
|
+
from .base import MEDIUMINT as MEDIUMINT
|
19
|
+
from .base import MEDIUMTEXT as MEDIUMTEXT
|
20
|
+
from .base import NCHAR as NCHAR
|
21
|
+
from .base import NUMERIC as NUMERIC
|
22
|
+
from .base import NVARCHAR as NVARCHAR
|
23
|
+
from .base import REAL as REAL
|
24
|
+
from .base import SMALLINT as SMALLINT
|
25
|
+
from .base import TEXT as TEXT
|
26
|
+
from .base import TIME as TIME
|
27
|
+
from .base import TIMESTAMP as TIMESTAMP
|
28
|
+
from .base import TINYBLOB as TINYBLOB
|
29
|
+
from .base import TINYINT as TINYINT
|
30
|
+
from .base import TINYTEXT as TINYTEXT
|
31
|
+
from .base import VARBINARY as VARBINARY
|
32
|
+
from .base import VARCHAR as VARCHAR
|
33
|
+
from .base import YEAR as YEAR
|
34
|
+
from .types import POINT as POINT
|
35
35
|
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
"BIGINT",
|
40
|
-
"BINARY",
|
41
|
-
"BIT",
|
42
|
-
"BLOB",
|
43
|
-
"BOOLEAN",
|
44
|
-
"CHAR",
|
45
|
-
"DATE",
|
46
|
-
"DATETIME",
|
47
|
-
"DECIMAL",
|
48
|
-
"DOUBLE",
|
49
|
-
"ENUM",
|
50
|
-
"FLOAT",
|
51
|
-
"INET4",
|
52
|
-
"INET6",
|
53
|
-
"INTEGER",
|
54
|
-
"INTEGER",
|
55
|
-
"JSON",
|
56
|
-
"LONGBLOB",
|
57
|
-
"LONGTEXT",
|
58
|
-
"MEDIUMBLOB",
|
59
|
-
"MEDIUMINT",
|
60
|
-
"MEDIUMTEXT",
|
61
|
-
"NCHAR",
|
62
|
-
"NVARCHAR",
|
63
|
-
"NUMERIC",
|
64
|
-
"SET",
|
65
|
-
"SMALLINT",
|
66
|
-
"REAL",
|
67
|
-
"TEXT",
|
68
|
-
"TIME",
|
69
|
-
"TIMESTAMP",
|
70
|
-
"TINYBLOB",
|
71
|
-
"TINYINT",
|
72
|
-
"TINYTEXT",
|
73
|
-
"VARBINARY",
|
74
|
-
"VARCHAR",
|
75
|
-
"YEAR",
|
76
|
-
"dialect",
|
77
|
-
"insert",
|
78
|
-
"Insert",
|
79
|
-
"match",
|
80
|
-
)
|
81
|
-
|
37
|
+
from .repository import MySQLRepository as MySQLRepository # noqa: F401
|
38
|
+
from .caster import MySQLCaster as MySQLCaster # noqa: F401
|
82
39
|
|
83
40
|
# default dialect
|
84
41
|
base.dialect = dialect = mysqlconnector.dialect
|