dapper-sqls 0.9.2__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.
- dapper_sqls/__init__.py +7 -0
- dapper_sqls/_types.py +15 -0
- dapper_sqls/async_dapper/__init__.py +5 -0
- dapper_sqls/async_dapper/async_dapper.py +67 -0
- dapper_sqls/async_dapper/async_executors.py +343 -0
- dapper_sqls/builders/__init__.py +7 -0
- dapper_sqls/builders/model/__init__.py +5 -0
- dapper_sqls/builders/model/model.py +375 -0
- dapper_sqls/builders/model/utils.py +420 -0
- dapper_sqls/builders/query.py +80 -0
- dapper_sqls/builders/stored.py +66 -0
- dapper_sqls/builders/stp.py +133 -0
- dapper_sqls/config.py +109 -0
- dapper_sqls/dapper/__init__.py +6 -0
- dapper_sqls/dapper/dapper.py +66 -0
- dapper_sqls/dapper/executors.py +342 -0
- dapper_sqls/decorators.py +63 -0
- dapper_sqls/models/__init__.py +8 -0
- dapper_sqls/models/base.py +35 -0
- dapper_sqls/models/connection.py +60 -0
- dapper_sqls/models/http.py +10 -0
- dapper_sqls/models/result.py +123 -0
- dapper_sqls/sqlite/__init__.py +4 -0
- dapper_sqls/sqlite/local_database.py +268 -0
- dapper_sqls/sqlite/models.py +30 -0
- dapper_sqls/utils.py +89 -0
- dapper_sqls-0.9.2.dist-info/METADATA +11 -0
- dapper_sqls-0.9.2.dist-info/RECORD +30 -0
- dapper_sqls-0.9.2.dist-info/WHEEL +5 -0
- dapper_sqls-0.9.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,133 @@
|
|
1
|
+
from ..utils import get_dict_args, Utils
|
2
|
+
from .._types import T
|
3
|
+
from ..models import Result
|
4
|
+
from typing import overload, Union
|
5
|
+
from abc import ABC
|
6
|
+
|
7
|
+
class StpBaseBuilder(ABC):
|
8
|
+
|
9
|
+
@staticmethod
|
10
|
+
def build_data(stp_name : str, **kwargs : dict[str, Union[int, str, any]]):
|
11
|
+
query = f"EXEC {stp_name} "
|
12
|
+
i = 0
|
13
|
+
for chave, valor in kwargs.items():
|
14
|
+
i += 1
|
15
|
+
query += f"@{chave} = ?"
|
16
|
+
if i < len(kwargs):
|
17
|
+
query += ", "
|
18
|
+
|
19
|
+
return query, tuple(kwargs.values())
|
20
|
+
|
21
|
+
|
22
|
+
def __init__(self, stp_name : str, _locals : Union[object ,dict[str, Union[int, str, any]]]):
|
23
|
+
_locals = _locals if isinstance(_locals, dict) else _locals()
|
24
|
+
query , params = self.build_data(stp_name, **get_dict_args(_locals, ignore_values_none=False))
|
25
|
+
self._query = query
|
26
|
+
self._params = params
|
27
|
+
|
28
|
+
@property
|
29
|
+
def query(self):
|
30
|
+
return self._query
|
31
|
+
|
32
|
+
@property
|
33
|
+
def params(self):
|
34
|
+
return self._params
|
35
|
+
|
36
|
+
class StpBuilder(StpBaseBuilder):
|
37
|
+
|
38
|
+
def __init__(self, dapper, stp_name : str, _locals : Union[object ,dict[str, Union[int, str, any]]]):
|
39
|
+
self._dapper = dapper
|
40
|
+
super().__init__(stp_name, _locals)
|
41
|
+
|
42
|
+
@property
|
43
|
+
def dapper(self):
|
44
|
+
return self._dapper
|
45
|
+
|
46
|
+
def execute(self, attempts : int = None, wait_timeout : int = None) -> Result.Send:
|
47
|
+
with self.dapper.stored(attempts, wait_timeout) as db:
|
48
|
+
return db.execute(self.query, self.params)
|
49
|
+
|
50
|
+
@overload
|
51
|
+
def fetchone(self, attempts : int = None, wait_timeout : int = None) -> Result.Fetchone:
|
52
|
+
pass
|
53
|
+
|
54
|
+
@overload
|
55
|
+
def fetchone(self, model : T , attempts : int = None, wait_timeout : int = None) -> T:
|
56
|
+
pass
|
57
|
+
|
58
|
+
def fetchone(self, *args, **kwargs) -> T | Result.Fetchone:
|
59
|
+
args = Utils.args_stp(*args, **kwargs)
|
60
|
+
|
61
|
+
with self.dapper.stored(args.attempts, args.wait_timeout) as db:
|
62
|
+
result = db.fetchone(self.query, self.params)
|
63
|
+
if args.model:
|
64
|
+
return self.dapper.load(args.model, result)
|
65
|
+
return result
|
66
|
+
|
67
|
+
@overload
|
68
|
+
def fetchall(self, attempts : int = None, wait_timeout : int = None) -> Result.Fetchall:
|
69
|
+
pass
|
70
|
+
|
71
|
+
@overload
|
72
|
+
def fetchall(self, model : T, attempts : int = None, wait_timeout : int = None) -> list[T]:
|
73
|
+
pass
|
74
|
+
|
75
|
+
def fetchall(self, *args, **kwargs) -> list[T] | Result.Fetchall:
|
76
|
+
args = Utils.args_stp(*args, **kwargs)
|
77
|
+
|
78
|
+
with self.dapper.stored(args.attempts, args.wait_timeout) as db:
|
79
|
+
result = db.fetchall(self.query, self.params)
|
80
|
+
if args.model:
|
81
|
+
return self.dapper.load(args.model, result)
|
82
|
+
return result
|
83
|
+
|
84
|
+
|
85
|
+
class AsyncStpBuilder(StpBaseBuilder):
|
86
|
+
|
87
|
+
def __init__(self, async_dapper, stp_name : str, _locals : Union[object ,dict[str, Union[int, str, any]]]):
|
88
|
+
self._async_dapper = async_dapper
|
89
|
+
super().__init__(stp_name, _locals)
|
90
|
+
|
91
|
+
@property
|
92
|
+
def async_dapper(self):
|
93
|
+
return self._async_dapper
|
94
|
+
|
95
|
+
async def execute(self, attempts : int = None, wait_timeout : int = None) -> Result.Send:
|
96
|
+
async with await self.async_dapper.stored(attempts, wait_timeout) as db:
|
97
|
+
return await db.execute(self.query, self.params)
|
98
|
+
|
99
|
+
@overload
|
100
|
+
async def fetchone(self, attempts : int = None, wait_timeout : int = None) -> Result.Fetchone:
|
101
|
+
pass
|
102
|
+
|
103
|
+
@overload
|
104
|
+
async def fetchone(self, model : T , attempts : int = None, wait_timeout : int = None) -> T:
|
105
|
+
pass
|
106
|
+
|
107
|
+
async def fetchone(self, *args, **kwargs) -> T | Result.Fetchone:
|
108
|
+
args = Utils.args_stp(*args, **kwargs)
|
109
|
+
|
110
|
+
async with await self.async_dapper.stored(args.attempts, args.wait_timeout) as db:
|
111
|
+
result = await db.fetchone(self.query, self.params)
|
112
|
+
if args.model:
|
113
|
+
return self.async_dapper.load(args.model, result)
|
114
|
+
return result
|
115
|
+
|
116
|
+
@overload
|
117
|
+
async def fetchall(self, attempts : int = None, wait_timeout : int = None) -> Result.Fetchall:
|
118
|
+
pass
|
119
|
+
|
120
|
+
@overload
|
121
|
+
async def fetchall(self, model : T , attempts : int = None, wait_timeout : int = None) -> list[T]:
|
122
|
+
pass
|
123
|
+
|
124
|
+
async def fetchall(self, *args, **kwargs) -> list[T] | Result.Fetchall:
|
125
|
+
args = Utils.args_stp(*args, **kwargs)
|
126
|
+
|
127
|
+
async with await self.async_dapper.stored(args.attempts, args.wait_timeout) as db:
|
128
|
+
result = await db.fetchall(self.query, self.params)
|
129
|
+
if args.model:
|
130
|
+
return self.async_dapper.load(args.model, result)
|
131
|
+
return result
|
132
|
+
|
133
|
+
|
dapper_sqls/config.py
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# -*- coding: latin -*-
|
2
|
+
from .models import ConnectionStringData
|
3
|
+
import winreg
|
4
|
+
|
5
|
+
class Config(object):
|
6
|
+
def __init__(self, server: str, database: str, username: str, password: str, sql_version: int = None, api_environment=False, default_attempts=1, default_wait_timeout=2):
|
7
|
+
self._api_environment = api_environment
|
8
|
+
self._default_attempts = default_attempts
|
9
|
+
self._default_wait_timeout = default_wait_timeout
|
10
|
+
self._connectionStringDataQuery = ConnectionStringData(server, database, username, password)
|
11
|
+
self._connectionStringDataStored = ConnectionStringData(server, database, username, password)
|
12
|
+
self._sql_version = sql_version
|
13
|
+
|
14
|
+
@property
|
15
|
+
def api_environment(self):
|
16
|
+
return self._api_environment
|
17
|
+
|
18
|
+
@api_environment.setter
|
19
|
+
def api_environment(self, value):
|
20
|
+
if not isinstance(value, bool):
|
21
|
+
raise ValueError("O valor atribu�do a api_environment deve ser do tipo booleano")
|
22
|
+
self._api_environment = value
|
23
|
+
|
24
|
+
@property
|
25
|
+
def default_attempts(self):
|
26
|
+
return self._default_attempts
|
27
|
+
|
28
|
+
@default_attempts.setter
|
29
|
+
def default_attempts(self, value):
|
30
|
+
if not isinstance(value, int):
|
31
|
+
raise ValueError("O valor atribu�do a default_attempts deve ser do tipo inteiro")
|
32
|
+
self._default_attempts = value
|
33
|
+
|
34
|
+
@property
|
35
|
+
def default_wait_timeout(self):
|
36
|
+
return self._default_wait_timeout
|
37
|
+
|
38
|
+
@default_wait_timeout.setter
|
39
|
+
def default_wait_timeout(self, value):
|
40
|
+
if not isinstance(value, int):
|
41
|
+
raise ValueError("O valor atribu�do a default_wait_timeout deve ser do tipo inteiro")
|
42
|
+
self._default_wait_timeout = value
|
43
|
+
|
44
|
+
@property
|
45
|
+
def connectionStringDataQuery(self):
|
46
|
+
return self._connectionStringDataQuery
|
47
|
+
|
48
|
+
@connectionStringDataQuery.setter
|
49
|
+
def connectionStringDataQuery(self, value):
|
50
|
+
if not isinstance(value, ConnectionStringData):
|
51
|
+
raise ValueError("O valor atribu�do a connectionStringDataQuery deve ser do tipo ConnectionStringData")
|
52
|
+
self._connectionStringDataQuery = value
|
53
|
+
|
54
|
+
@property
|
55
|
+
def connectionStringDataStored(self):
|
56
|
+
return self._connectionStringDataStored
|
57
|
+
|
58
|
+
@connectionStringDataStored.setter
|
59
|
+
def connectionStringDataStored(self, value):
|
60
|
+
if not isinstance(value, ConnectionStringData):
|
61
|
+
raise ValueError("O valor atribu�do a connectionStringDataStored deve ser do tipo ConnectionStringData")
|
62
|
+
self._connectionStringDataStored = value
|
63
|
+
|
64
|
+
@property
|
65
|
+
def sql_version(self):
|
66
|
+
return self._sql_version
|
67
|
+
|
68
|
+
@sql_version.setter
|
69
|
+
def sql_version(self, value):
|
70
|
+
if not isinstance(value, int) and value is not None:
|
71
|
+
raise ValueError("O valor atribu�do a sql_version deve ser do tipo inteiro ou None")
|
72
|
+
self._sql_version = value
|
73
|
+
|
74
|
+
@staticmethod
|
75
|
+
def get_all_odbc_driver_versions():
|
76
|
+
driver_versions = []
|
77
|
+
try:
|
78
|
+
# Abrir a chave onde as informa��es sobre os drivers ODBC est�o armazenadas
|
79
|
+
key_path = r"SOFTWARE\ODBC\ODBCINST.INI"
|
80
|
+
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path)
|
81
|
+
|
82
|
+
# Iterar sobre as subchaves para encontrar os drivers espec�ficos
|
83
|
+
i = 0
|
84
|
+
while True:
|
85
|
+
try:
|
86
|
+
subkey_name = winreg.EnumKey(key, i)
|
87
|
+
subkey = winreg.OpenKey(key, subkey_name)
|
88
|
+
|
89
|
+
# Verificar se a subchave cont�m o valor 'Driver'
|
90
|
+
try:
|
91
|
+
driver_name, _ = winreg.QueryValueEx(subkey, "Driver")
|
92
|
+
if subkey_name.startswith('ODBC Driver'):
|
93
|
+
driver_versions.append(subkey_name)
|
94
|
+
|
95
|
+
except FileNotFoundError:
|
96
|
+
pass # A subchave n�o possui a entrada 'Driver'
|
97
|
+
|
98
|
+
i += 1
|
99
|
+
except OSError:
|
100
|
+
break
|
101
|
+
|
102
|
+
except Exception as e:
|
103
|
+
print(f"Erro ao acessar o registro: {e}")
|
104
|
+
|
105
|
+
return sorted(driver_versions, key=lambda x: int(x.split()[-4]), reverse=True)
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# -*- coding: latin -*-
|
2
|
+
from .._types import T
|
3
|
+
from ..config import Config
|
4
|
+
from ..models import Result
|
5
|
+
from typing import Type, overload
|
6
|
+
from .executors import Query, Stored
|
7
|
+
|
8
|
+
class Dapper(object):
|
9
|
+
|
10
|
+
def __init__(self, server: str , database : str , username : str, password : str, sql_version : int = None, api_environment = False, default_attempts = 1, default_wait_timeout = 2):
|
11
|
+
self._config = Config(server, database, username, password, sql_version, api_environment, default_attempts, default_wait_timeout)
|
12
|
+
|
13
|
+
def query(self, attempts : int = None, wait_timeout : int = None):
|
14
|
+
attempts = attempts if attempts else self.config.default_attempts
|
15
|
+
wait_timeout = wait_timeout if wait_timeout else self.config.default_wait_timeout
|
16
|
+
return Query(self.config.connectionStringDataQuery.get(), attempts, wait_timeout, self._config.sql_version, self._config.api_environment)
|
17
|
+
|
18
|
+
def stored(self, attempts : int = None, wait_timeout : int = None):
|
19
|
+
attempts = attempts if attempts else self.config.default_attempts
|
20
|
+
wait_timeout = wait_timeout if wait_timeout else self.config.default_wait_timeout
|
21
|
+
return Stored(self.config.connectionStringDataStored.get() , attempts, wait_timeout, self._config.sql_version, self._config.api_environment)
|
22
|
+
|
23
|
+
@property
|
24
|
+
def config(self):
|
25
|
+
return self._config
|
26
|
+
|
27
|
+
@overload
|
28
|
+
@staticmethod
|
29
|
+
def load(model : Type[T], dict_data : dict) -> T:
|
30
|
+
pass
|
31
|
+
|
32
|
+
@overload
|
33
|
+
@staticmethod
|
34
|
+
def load(model : Type[T], list_dict_data : list[dict]) -> list[T]:
|
35
|
+
pass
|
36
|
+
|
37
|
+
@overload
|
38
|
+
@staticmethod
|
39
|
+
def load(model : Type[T], fetchone : Result.Fetchone) -> T:
|
40
|
+
pass
|
41
|
+
|
42
|
+
@overload
|
43
|
+
@staticmethod
|
44
|
+
def load(model : Type[T], fetchall : Result.Fetchall) -> list[T]:
|
45
|
+
pass
|
46
|
+
|
47
|
+
@staticmethod
|
48
|
+
def load(*args) -> object | list[object]:
|
49
|
+
model = args[0]
|
50
|
+
data = args[1]
|
51
|
+
if isinstance(args[1], dict) or isinstance(args[1], Result.Fetchone):
|
52
|
+
if isinstance(args[1], Result.Fetchone):
|
53
|
+
data = data.dict
|
54
|
+
if all(value is None for value in data.values()):
|
55
|
+
return model()
|
56
|
+
|
57
|
+
return model(**data)
|
58
|
+
|
59
|
+
if isinstance(args[1], Result.Fetchall):
|
60
|
+
data = data.list_dict
|
61
|
+
|
62
|
+
return [model(**d) for d in data]
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
|
@@ -0,0 +1,342 @@
|
|
1
|
+
# -*- coding: latin -*-
|
2
|
+
import pyodbc
|
3
|
+
from time import sleep
|
4
|
+
from datetime import datetime
|
5
|
+
from typing import overload
|
6
|
+
from abc import ABC, abstractmethod
|
7
|
+
from ..models import ConnectionStringData, Result, UnavailableServiceException, BaseUpdate
|
8
|
+
from .._types import T, ExecType
|
9
|
+
from ..config import Config
|
10
|
+
from ..builders import QueryBuilder, StoredBuilder
|
11
|
+
from ..utils import Utils
|
12
|
+
|
13
|
+
class BaseExecutor(ABC, object):
|
14
|
+
def __init__(self, connectionStringData : ConnectionStringData, attempts : int, wait_timeout : int, sql_version : int | None, api_environment : bool):
|
15
|
+
self._connectionStringData = connectionStringData
|
16
|
+
self._cursor = None
|
17
|
+
self._connection = None
|
18
|
+
self._wait_timeout = wait_timeout
|
19
|
+
self._attempts = attempts
|
20
|
+
self._sql_version = sql_version
|
21
|
+
self._api_environment = api_environment
|
22
|
+
|
23
|
+
def __enter__(self):
|
24
|
+
cs_data = self._connectionStringData
|
25
|
+
for n in range(self._attempts):
|
26
|
+
odbc_version = f'ODBC Driver {self._sql_version} for SQL Server'
|
27
|
+
if not self._sql_version:
|
28
|
+
all_driver_versions = Config.get_all_odbc_driver_versions()
|
29
|
+
if all_driver_versions:
|
30
|
+
odbc_version = all_driver_versions[0]
|
31
|
+
else:
|
32
|
+
raise RuntimeError("Nenhuma vers�o do driver ODBC for SQL Server foi encontrada.")
|
33
|
+
try:
|
34
|
+
connection_string = f'DRIVER={{{odbc_version}}};SERVER={cs_data.server};DATABASE={cs_data.database};UID={cs_data.username};PWD={cs_data.password}'
|
35
|
+
self._connection = pyodbc.connect(connection_string)
|
36
|
+
self._cursor = self._connection.cursor()
|
37
|
+
|
38
|
+
except Exception as e:
|
39
|
+
print(e)
|
40
|
+
print(f'Erro na conex�o com a base de dados, nova tentativa em {self._wait_timeout}s')
|
41
|
+
sleep(self._wait_timeout)
|
42
|
+
|
43
|
+
return self
|
44
|
+
|
45
|
+
def __exit__(self, *args):
|
46
|
+
if self._cursor:
|
47
|
+
self._cursor.close()
|
48
|
+
if self._connection:
|
49
|
+
self._connection.close()
|
50
|
+
|
51
|
+
@property
|
52
|
+
def connectionStringData(self):
|
53
|
+
return self._connectionStringData
|
54
|
+
|
55
|
+
@property
|
56
|
+
def api_environment(self):
|
57
|
+
return self._api_environment
|
58
|
+
|
59
|
+
@property
|
60
|
+
def sql_version(self):
|
61
|
+
return self._sql_version
|
62
|
+
|
63
|
+
@property
|
64
|
+
def cursor(self):
|
65
|
+
if not self._cursor:
|
66
|
+
if self._connection:
|
67
|
+
self._cursor = self._connection.cursor()
|
68
|
+
return self._cursor
|
69
|
+
|
70
|
+
@property
|
71
|
+
def connection(self):
|
72
|
+
if self._connection:
|
73
|
+
return self._connection
|
74
|
+
|
75
|
+
@property
|
76
|
+
def attempts(self):
|
77
|
+
return self._attempts
|
78
|
+
|
79
|
+
@attempts.setter
|
80
|
+
def attempts(self, value):
|
81
|
+
if isinstance(value, int):
|
82
|
+
self._attempts = value
|
83
|
+
else:
|
84
|
+
raise ValueError("O n�mero de tentativas deve ser um n�mero inteiro.")
|
85
|
+
|
86
|
+
@property
|
87
|
+
def wait_timeout(self):
|
88
|
+
return self._wait_timeout
|
89
|
+
|
90
|
+
@wait_timeout.setter
|
91
|
+
def wait_timeout(self, value):
|
92
|
+
if isinstance(value, int):
|
93
|
+
self._wait_timeout = value
|
94
|
+
else:
|
95
|
+
raise ValueError("O tempo de espera deve ser um n�mero inteiro.")
|
96
|
+
|
97
|
+
@abstractmethod
|
98
|
+
def _exec_(self, connection, operation_sql, exec_type):
|
99
|
+
pass
|
100
|
+
|
101
|
+
class QueryUpdate(BaseUpdate):
|
102
|
+
def __init__(self, executor : BaseExecutor, model : T):
|
103
|
+
super().__init__(executor, model)
|
104
|
+
|
105
|
+
@overload
|
106
|
+
def where(self, model : T) -> Result.Send:
|
107
|
+
pass
|
108
|
+
|
109
|
+
@overload
|
110
|
+
def where(self, query : str) -> Result.Send:
|
111
|
+
pass
|
112
|
+
|
113
|
+
def where(self, *args) -> Result.Send:
|
114
|
+
query = QueryBuilder.update(self._set_data, *args)
|
115
|
+
return self.executor._exec_(self.executor.connection , query, ExecType.send)
|
116
|
+
|
117
|
+
|
118
|
+
class Query(BaseExecutor):
|
119
|
+
|
120
|
+
def __init__(self, connectionStringData : ConnectionStringData, attempts : int, wait_timeout : int, sql_version : int | None, api_environment : bool):
|
121
|
+
super().__init__(connectionStringData, attempts, wait_timeout, sql_version, api_environment)
|
122
|
+
|
123
|
+
@overload
|
124
|
+
def fetchone(self, query : str) -> Result.Fetchone:
|
125
|
+
pass
|
126
|
+
|
127
|
+
@overload
|
128
|
+
def fetchone(self, model : T, additional_sql : str = "") -> T:
|
129
|
+
pass
|
130
|
+
|
131
|
+
def fetchone(self, *args, **kwargs) -> T | Result.Fetchone:
|
132
|
+
args = Utils.args_query(*args, **kwargs)
|
133
|
+
if args.model:
|
134
|
+
args.query = QueryBuilder.select(args.model, args.additional_sql, args.select_top)
|
135
|
+
|
136
|
+
result = self._exec_(self._connection, args.query, ExecType.fetchone)
|
137
|
+
if args.model:
|
138
|
+
return args.model.__class__(**result.dict) if result.success else args.model.__class__()
|
139
|
+
return result
|
140
|
+
|
141
|
+
@overload
|
142
|
+
def fetchall(self, query : str) -> Result.Fetchall:
|
143
|
+
pass
|
144
|
+
|
145
|
+
@overload
|
146
|
+
def fetchall(self, model : T, additional_sql : str = "", select_top : int = None) -> list[T]:
|
147
|
+
pass
|
148
|
+
|
149
|
+
def fetchall(self, *args, **kwargs) -> list[T] | Result.Fetchall:
|
150
|
+
args = Utils.args_query(*args, **kwargs)
|
151
|
+
if args.model:
|
152
|
+
args.query = QueryBuilder.select(args.model, args.additional_sql, args.select_top)
|
153
|
+
|
154
|
+
result = self._exec_(self._connection, args.query, ExecType.fetchall)
|
155
|
+
if args.model:
|
156
|
+
return [args.model.__class__(**r) for r in result.list_dict] if result.success else []
|
157
|
+
return result
|
158
|
+
|
159
|
+
def execute(self, query : str) -> Result.Send:
|
160
|
+
return self._exec_(self._connection, query, ExecType.send)
|
161
|
+
|
162
|
+
def delete(self, model: T) -> Result.Send:
|
163
|
+
query = QueryBuilder.delete(model)
|
164
|
+
return self._exec_(self._connection, query, ExecType.send)
|
165
|
+
|
166
|
+
def update(self, model: T):
|
167
|
+
return QueryUpdate(self, model)
|
168
|
+
|
169
|
+
def insert(self, model: T, name_column_id = 'Id') -> Result.Insert:
|
170
|
+
insert_data = model.model_dump()
|
171
|
+
if name_column_id not in insert_data:
|
172
|
+
name_column_id = next(iter(insert_data.keys()))
|
173
|
+
|
174
|
+
query = QueryBuilder.insert(model, name_column_id)
|
175
|
+
result : Result.Fetchone = self._exec_(self._connection, query, ExecType.fetchone)
|
176
|
+
if result.success:
|
177
|
+
return Result.Insert(result.dict.get('Id', 0), result.status_code, result.message)
|
178
|
+
return Result.Insert(0, result.status_code, result.message)
|
179
|
+
|
180
|
+
def _exec_(self, connection, query_sql : str, exec_type : ExecType) -> Result.Send:
|
181
|
+
|
182
|
+
if not self._cursor:
|
183
|
+
if self._api_environment:
|
184
|
+
raise UnavailableServiceException()
|
185
|
+
|
186
|
+
if exec_type == ExecType.fetchone:
|
187
|
+
return Result.Fetchone(None, None, 503)
|
188
|
+
elif exec_type == ExecType.fetchall:
|
189
|
+
return Result.Fetchall(None, None, 503)
|
190
|
+
elif exec_type == ExecType.send:
|
191
|
+
return Result.Send(False, 503)
|
192
|
+
|
193
|
+
try:
|
194
|
+
# executar
|
195
|
+
response = self._cursor.execute(query_sql)
|
196
|
+
|
197
|
+
# ober resultado se nessesario
|
198
|
+
if exec_type == ExecType.fetchone:
|
199
|
+
result = Result.Fetchone(self._cursor, response.fetchone())
|
200
|
+
elif exec_type == ExecType.fetchall:
|
201
|
+
result = Result.Fetchall(self._cursor, response.fetchall())
|
202
|
+
elif exec_type == ExecType.send:
|
203
|
+
result = Result.Send(True)
|
204
|
+
|
205
|
+
# fazer o commit
|
206
|
+
connection.commit()
|
207
|
+
|
208
|
+
except Exception as ex:
|
209
|
+
if exec_type == ExecType.fetchone:
|
210
|
+
return Result.Fetchone(None, None, 503, str(ex))
|
211
|
+
elif exec_type == ExecType.fetchall:
|
212
|
+
return Result.Fetchall(None, None, 503, str(ex))
|
213
|
+
elif exec_type == ExecType.send:
|
214
|
+
return Result.Send(False, 503, str(ex))
|
215
|
+
|
216
|
+
# retorna o resultado
|
217
|
+
return result
|
218
|
+
|
219
|
+
class StoredUpdate(BaseUpdate):
|
220
|
+
def __init__(self, executor : BaseExecutor, model : T):
|
221
|
+
super().__init__(executor, model)
|
222
|
+
|
223
|
+
def where(self, data : T) -> Result.Send:
|
224
|
+
query, params = StoredBuilder.update(self._set_data, data)
|
225
|
+
return self.executor._exec_(self.executor.connection, (query, *params), ExecType.send)
|
226
|
+
|
227
|
+
class Stored(BaseExecutor):
|
228
|
+
|
229
|
+
def __init__(self, connectionStringData : ConnectionStringData, attempts : int, wait_timeout : int,sql_version : int | None, api_environment : bool):
|
230
|
+
super().__init__(connectionStringData, attempts, wait_timeout, sql_version, api_environment)
|
231
|
+
|
232
|
+
@overload
|
233
|
+
def fetchone(self, query : str, params : list | tuple) -> Result.Fetchone:
|
234
|
+
pass
|
235
|
+
|
236
|
+
@overload
|
237
|
+
def fetchone(self, query : str, *params : int | str | datetime) -> Result.Fetchone:
|
238
|
+
pass
|
239
|
+
|
240
|
+
@overload
|
241
|
+
def fetchone(self, model : T, additional_sql : str = "") -> T:
|
242
|
+
pass
|
243
|
+
|
244
|
+
def fetchone(self, *args, **kwargs) -> T | Result.Fetchone:
|
245
|
+
args = Utils.args_stored(*args, **kwargs)
|
246
|
+
if args.model:
|
247
|
+
args.query, args.params = StoredBuilder.select(args.model, args.additional_sql, args.select_top)
|
248
|
+
|
249
|
+
result = self._exec_(self._connection, (args.query, *args.params), ExecType.fetchone)
|
250
|
+
if args.model:
|
251
|
+
return args.model.__class__(**result.dict) if result.success else args.model.__class__()
|
252
|
+
return result
|
253
|
+
|
254
|
+
@overload
|
255
|
+
def fetchall(self, query : str, params : list | tuple) -> Result.Fetchall:
|
256
|
+
pass
|
257
|
+
|
258
|
+
@overload
|
259
|
+
def fetchall(self, query : str, *params : int | str | datetime) -> Result.Fetchall:
|
260
|
+
pass
|
261
|
+
|
262
|
+
@overload
|
263
|
+
def fetchall(self, model : T, additional_sql : str = "", select_top : int = None) -> list[T]:
|
264
|
+
pass
|
265
|
+
|
266
|
+
def fetchall(self, *args, **kwargs) -> list[T] | Result.Fetchall:
|
267
|
+
args = Utils.args_stored(*args, **kwargs)
|
268
|
+
if args.model:
|
269
|
+
args.query, args.params = StoredBuilder.select(args.model, args.additional_sql, args.select_top)
|
270
|
+
|
271
|
+
result = self._exec_(self._connection, (args.query, *args.params), ExecType.fetchall)
|
272
|
+
if args.model:
|
273
|
+
return [args.model.__class__(**r) for r in result.list_dict] if result.success else []
|
274
|
+
return result
|
275
|
+
|
276
|
+
@overload
|
277
|
+
def execute(self, query : str, *params : str | int) -> Result.Send:
|
278
|
+
pass
|
279
|
+
|
280
|
+
@overload
|
281
|
+
def execute(self, query : str, params : list | tuple) -> Result.Send:
|
282
|
+
pass
|
283
|
+
|
284
|
+
def execute(self, *args) -> Result.Send:
|
285
|
+
query = args[0]
|
286
|
+
params = args[1:]
|
287
|
+
if len(params) == 1 and isinstance(params[0], (list, tuple)):
|
288
|
+
params = params[0]
|
289
|
+
return self._exec_(self._connection, (query, *params), ExecType.send)
|
290
|
+
|
291
|
+
def delete(self, model: T) -> Result.Send:
|
292
|
+
query, params = StoredBuilder.delete(model)
|
293
|
+
return self._exec_(self._connection, (query, *params), ExecType.send)
|
294
|
+
|
295
|
+
def update(self, model: T):
|
296
|
+
return StoredUpdate(self, model)
|
297
|
+
|
298
|
+
def insert(self, model: T, name_column_id = 'Id') -> Result.Insert:
|
299
|
+
insert_data = model.model_dump()
|
300
|
+
if name_column_id not in insert_data:
|
301
|
+
name_column_id = next(iter(insert_data.keys()))
|
302
|
+
|
303
|
+
query, params = StoredBuilder.insert(model, name_column_id)
|
304
|
+
result = self._exec_(self._connection, (query, *params), ExecType.fetchone)
|
305
|
+
if result.success:
|
306
|
+
return Result.Insert(result.dict.get('Id', 0), result.status_code, result.message)
|
307
|
+
return Result.Insert(0, result.status_code, result.message)
|
308
|
+
|
309
|
+
def _exec_(self, connection , stored_procedure : tuple, exec_type : ExecType):
|
310
|
+
|
311
|
+
if not self._cursor:
|
312
|
+
if self._api_environment:
|
313
|
+
raise UnavailableServiceException()
|
314
|
+
|
315
|
+
if exec_type == ExecType.fetchone:
|
316
|
+
return Result.Fetchone(None, None, 503)
|
317
|
+
elif exec_type == ExecType.fetchall:
|
318
|
+
return Result.Fetchall(None, None, 503)
|
319
|
+
elif exec_type == ExecType.send:
|
320
|
+
return Result.Send(False, 503)
|
321
|
+
|
322
|
+
# executar
|
323
|
+
response = self._cursor.execute(*stored_procedure)
|
324
|
+
|
325
|
+
# ober resultado se nessesario
|
326
|
+
if exec_type == ExecType.fetchone:
|
327
|
+
result = Result.Fetchone(self._cursor, response.fetchone())
|
328
|
+
elif exec_type == ExecType.fetchall:
|
329
|
+
result = Result.Fetchall(self._cursor, response.fetchall())
|
330
|
+
elif exec_type == ExecType.send:
|
331
|
+
result = Result.Send(True)
|
332
|
+
|
333
|
+
# fazer o commit
|
334
|
+
connection.commit()
|
335
|
+
|
336
|
+
# retorna o resultado
|
337
|
+
return result
|
338
|
+
|
339
|
+
|
340
|
+
|
341
|
+
|
342
|
+
|