dapper-sqls 1.1.3__py3-none-any.whl → 1.2.1__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 +3 -1
- dapper_sqls/_types.py +25 -2
- dapper_sqls/async_dapper/async_executors.py +127 -52
- dapper_sqls/builders/model/model.py +418 -33
- dapper_sqls/builders/model/utils.py +334 -42
- dapper_sqls/builders/query.py +164 -43
- dapper_sqls/builders/stored.py +15 -5
- dapper_sqls/builders/stp.py +6 -2
- dapper_sqls/config.py +40 -31
- dapper_sqls/dapper/executors.py +130 -55
- dapper_sqls/http/__init__.py +4 -0
- dapper_sqls/http/aiohttp.py +155 -0
- dapper_sqls/http/decorators.py +123 -0
- dapper_sqls/http/models.py +58 -0
- dapper_sqls/http/request.py +140 -0
- dapper_sqls/models/__init__.py +3 -5
- dapper_sqls/models/base.py +246 -20
- dapper_sqls/models/connection.py +1 -1
- dapper_sqls/models/query_field.py +214 -0
- dapper_sqls/models/result.py +314 -44
- dapper_sqls/sqlite/__init__.py +1 -0
- dapper_sqls/sqlite/async_local_database.py +69 -5
- dapper_sqls/sqlite/decorators.py +69 -0
- dapper_sqls/sqlite/installer.py +8 -4
- dapper_sqls/sqlite/local_database.py +39 -5
- dapper_sqls/sqlite/models.py +25 -1
- dapper_sqls/sqlite/utils.py +2 -1
- dapper_sqls/utils.py +16 -4
- dapper_sqls-1.2.1.dist-info/METADATA +41 -0
- dapper_sqls-1.2.1.dist-info/RECORD +40 -0
- {dapper_sqls-1.1.3.dist-info → dapper_sqls-1.2.1.dist-info}/WHEEL +1 -1
- dapper_sqls-1.1.3.dist-info/METADATA +0 -10
- dapper_sqls-1.1.3.dist-info/RECORD +0 -33
- {dapper_sqls-1.1.3.dist-info → dapper_sqls-1.2.1.dist-info}/top_level.txt +0 -0
dapper_sqls/builders/stored.py
CHANGED
@@ -15,8 +15,15 @@ class StoredBuilder:
|
|
15
15
|
|
16
16
|
@classmethod
|
17
17
|
def update(cls, model: Type[BaseModel], where: Type[BaseModel]):
|
18
|
-
|
19
|
-
|
18
|
+
model._reset_defaults()
|
19
|
+
where._reset_defaults()
|
20
|
+
update_data = {k: int(v) if isinstance(v, bool) else v for k, v in model.model_dump(mode="json", exclude_none=True).items()}
|
21
|
+
where_data = {k: int(v) if isinstance(v, bool) else v for k, v in where.model_dump(mode="json", exclude_none=True).items()}
|
22
|
+
|
23
|
+
for key in where_data:
|
24
|
+
if key in update_data:
|
25
|
+
update_data.pop(key, None)
|
26
|
+
|
20
27
|
where_clause, where_params = cls._build_where_clause(**where_data)
|
21
28
|
|
22
29
|
set_clause = ", ".join([f"{key} = ?" for key in update_data.keys()])
|
@@ -26,7 +33,8 @@ class StoredBuilder:
|
|
26
33
|
|
27
34
|
@classmethod
|
28
35
|
def insert(cls, model : Type[BaseModel], name_column_id = 'Id'):
|
29
|
-
|
36
|
+
model._reset_defaults()
|
37
|
+
insert_data = {k: int(v) if isinstance(v, bool) else v for k, v in model.model_dump(mode="json", exclude_none=True).items()}
|
30
38
|
columns = ", ".join(insert_data.keys())
|
31
39
|
values = ", ".join(["?" for _ in insert_data.values()])
|
32
40
|
sql_query = f"""
|
@@ -38,8 +46,9 @@ class StoredBuilder:
|
|
38
46
|
|
39
47
|
@classmethod
|
40
48
|
def select(cls, model : Type[BaseModel], additional_sql : str = "" ,select_top : int= None):
|
49
|
+
model._reset_defaults()
|
41
50
|
top_clause = f"TOP ({select_top}) * " if select_top else "*"
|
42
|
-
select_data = {k: int(v) if isinstance(v, bool) else v for k, v in model.model_dump(exclude_none=True).items()}
|
51
|
+
select_data = {k: int(v) if isinstance(v, bool) else v for k, v in model.model_dump(mode="json", exclude_none=True).items()}
|
43
52
|
where_clause, parameters = cls._build_where_clause(**select_data)
|
44
53
|
|
45
54
|
sql_query = f"SELECT {top_clause} FROM {model.TABLE_NAME}"
|
@@ -50,7 +59,8 @@ class StoredBuilder:
|
|
50
59
|
|
51
60
|
@classmethod
|
52
61
|
def delete(cls, model : Type[BaseModel]):
|
53
|
-
|
62
|
+
model._reset_defaults()
|
63
|
+
delete_data = {k: int(v) if isinstance(v, bool) else v for k, v in model.model_dump(mode="json", exclude_none=True).items()}
|
54
64
|
where_clause, parameters = cls._build_where_clause(**delete_data)
|
55
65
|
if not where_clause:
|
56
66
|
raise ValueError("DELETE operation requires at least one condition.")
|
dapper_sqls/builders/stp.py
CHANGED
@@ -61,6 +61,7 @@ class StpBuilder(StpBaseBuilder):
|
|
61
61
|
with self.dapper.stored(args.attempts, args.wait_timeout) as db:
|
62
62
|
result = db.fetchone(self.query, self.params)
|
63
63
|
if args.model:
|
64
|
+
args.model._reset_defaults()
|
64
65
|
return self.dapper.load(args.model, result)
|
65
66
|
return result
|
66
67
|
|
@@ -78,7 +79,8 @@ class StpBuilder(StpBaseBuilder):
|
|
78
79
|
with self.dapper.stored(args.attempts, args.wait_timeout) as db:
|
79
80
|
result = db.fetchall(self.query, self.params)
|
80
81
|
if args.model:
|
81
|
-
|
82
|
+
args.model._reset_defaults()
|
83
|
+
return self.dapper.load(args.model, result)
|
82
84
|
return result
|
83
85
|
|
84
86
|
|
@@ -110,6 +112,7 @@ class AsyncStpBuilder(StpBaseBuilder):
|
|
110
112
|
async with await self.async_dapper.stored(args.attempts, args.wait_timeout) as db:
|
111
113
|
result = await db.fetchone(self.query, self.params)
|
112
114
|
if args.model:
|
115
|
+
args.model._reset_defaults()
|
113
116
|
return self.async_dapper.load(args.model, result)
|
114
117
|
return result
|
115
118
|
|
@@ -127,7 +130,8 @@ class AsyncStpBuilder(StpBaseBuilder):
|
|
127
130
|
async with await self.async_dapper.stored(args.attempts, args.wait_timeout) as db:
|
128
131
|
result = await db.fetchall(self.query, self.params)
|
129
132
|
if args.model:
|
130
|
-
|
133
|
+
args.model._reset_defaults()
|
134
|
+
return self.async_dapper.load(args.model, result)
|
131
135
|
return result
|
132
136
|
|
133
137
|
|
dapper_sqls/config.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
from .models import ConnectionStringData
|
3
3
|
import sys
|
4
|
+
import subprocess
|
4
5
|
|
5
6
|
class Config(object):
|
6
7
|
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):
|
@@ -72,41 +73,49 @@ class Config(object):
|
|
72
73
|
|
73
74
|
@staticmethod
|
74
75
|
def get_all_odbc_driver_versions():
|
75
|
-
driver_versions = []
|
76
76
|
|
77
|
+
driver_versions = []
|
77
78
|
# Verificar se o sistema é Windows e o módulo winreg está disponível
|
78
|
-
|
79
|
+
platform : str = sys.platform
|
80
|
+
if platform:
|
81
|
+
try:
|
82
|
+
import winreg # Importar o módulo winreg se estiver disponível
|
83
|
+
|
84
|
+
# Abrir a chave onde as informações sobre os drivers ODBC estão armazenadas
|
85
|
+
key_path = r"SOFTWARE\ODBC\ODBCINST.INI"
|
86
|
+
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path)
|
87
|
+
|
88
|
+
# Iterar sobre as subchaves para encontrar os drivers específicos
|
89
|
+
i = 0
|
90
|
+
while True:
|
91
|
+
try:
|
92
|
+
subkey_name = winreg.EnumKey(key, i)
|
93
|
+
subkey = winreg.OpenKey(key, subkey_name)
|
94
|
+
|
95
|
+
# Verificar se a subchave contém o valor 'Driver'
|
96
|
+
try:
|
97
|
+
driver_name, _ = winreg.QueryValueEx(subkey, "Driver")
|
98
|
+
if subkey_name.startswith('ODBC Driver'):
|
99
|
+
driver_versions.append(subkey_name)
|
100
|
+
|
101
|
+
except FileNotFoundError:
|
102
|
+
pass # A subchave não possui a entrada 'Driver'
|
103
|
+
|
104
|
+
i += 1
|
105
|
+
except OSError:
|
106
|
+
break
|
107
|
+
|
108
|
+
except Exception as e:
|
109
|
+
print(f"Erro ao acessar o registro: {e}")
|
110
|
+
else:
|
79
111
|
try:
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
# Iterar sobre as subchaves para encontrar os drivers específicos
|
87
|
-
i = 0
|
88
|
-
while True:
|
89
|
-
try:
|
90
|
-
subkey_name = winreg.EnumKey(key, i)
|
91
|
-
subkey = winreg.OpenKey(key, subkey_name)
|
92
|
-
|
93
|
-
# Verificar se a subchave contém o valor 'Driver'
|
94
|
-
try:
|
95
|
-
driver_name, _ = winreg.QueryValueEx(subkey, "Driver")
|
96
|
-
if subkey_name.startswith('ODBC Driver'):
|
97
|
-
driver_versions.append(subkey_name)
|
98
|
-
|
99
|
-
except FileNotFoundError:
|
100
|
-
pass # A subchave não possui a entrada 'Driver'
|
101
|
-
|
102
|
-
i += 1
|
103
|
-
except OSError:
|
104
|
-
break
|
105
|
-
|
112
|
+
result = subprocess.run(['odbcinst', '-q', '-d'], stdout=subprocess.PIPE, text=True)
|
113
|
+
for line in result.stdout.splitlines():
|
114
|
+
line = line.strip()
|
115
|
+
if line.startswith("[ODBC Driver") and "SQL Server" in line:
|
116
|
+
driver_versions.append(line.strip("[]"))
|
106
117
|
except Exception as e:
|
107
|
-
print(f"Erro ao
|
108
|
-
else:
|
109
|
-
print("A funcionalidade de obtenção de versões de drivers ODBC não é suportada neste sistema operacional.")
|
118
|
+
print(f"Erro ao detectar drivers ODBC no Linux: {e}")
|
110
119
|
|
111
120
|
return sorted(driver_versions, key=lambda x: int(x.split()[-4]), reverse=True) if driver_versions else []
|
112
121
|
|
dapper_sqls/dapper/executors.py
CHANGED
@@ -4,9 +4,8 @@ from time import sleep
|
|
4
4
|
from datetime import datetime
|
5
5
|
from typing import overload
|
6
6
|
from abc import ABC, abstractmethod
|
7
|
-
from ..models import ConnectionStringData, Result, UnavailableServiceException, BaseUpdate
|
7
|
+
from ..models import ConnectionStringData, Result, UnavailableServiceException, BaseUpdate, SearchTable, JoinSearchTable
|
8
8
|
from .._types import T, ExecType
|
9
|
-
from ..config import Config
|
10
9
|
from ..builders import QueryBuilder, StoredBuilder
|
11
10
|
from ..utils import Utils
|
12
11
|
|
@@ -14,6 +13,7 @@ class BaseExecutor(ABC, object):
|
|
14
13
|
def __init__(self, connectionStringData : ConnectionStringData, attempts : int, wait_timeout : int, sql_version : int | None, api_environment : bool):
|
15
14
|
self._connectionStringData = connectionStringData
|
16
15
|
self._cursor = None
|
16
|
+
self._connection_error : Exception = None
|
17
17
|
self._connection = None
|
18
18
|
self._wait_timeout = wait_timeout
|
19
19
|
self._attempts = attempts
|
@@ -25,19 +25,19 @@ class BaseExecutor(ABC, object):
|
|
25
25
|
for n in range(self._attempts):
|
26
26
|
odbc_version = f'ODBC Driver {self._sql_version} for SQL Server'
|
27
27
|
if not self._sql_version:
|
28
|
-
|
29
|
-
if
|
30
|
-
|
31
|
-
|
32
|
-
raise RuntimeError("Nenhuma vers�o do driver ODBC for SQL Server foi encontrada.")
|
28
|
+
drivers = [d for d in pyodbc.drivers() if 'SQL Server' in d]
|
29
|
+
if not drivers:
|
30
|
+
raise RuntimeError("Nenhum driver ODBC do SQL Server encontrado. Instale o ODBC Driver 17 ou 18.")
|
31
|
+
odbc_version = drivers[-1]
|
33
32
|
try:
|
34
33
|
connection_string = f'DRIVER={{{odbc_version}}};SERVER={cs_data.server};DATABASE={cs_data.database};UID={cs_data.username};PWD={cs_data.password}'
|
35
34
|
self._connection = pyodbc.connect(connection_string)
|
36
35
|
self._cursor = self._connection.cursor()
|
37
36
|
|
38
37
|
except Exception as e:
|
38
|
+
self._connection_error = e
|
39
39
|
print(e)
|
40
|
-
print(f'Erro na
|
40
|
+
print(f'Erro na conexção com a base de dados, nova tentativa em {self._wait_timeout}s')
|
41
41
|
sleep(self._wait_timeout)
|
42
42
|
|
43
43
|
return self
|
@@ -81,7 +81,7 @@ class BaseExecutor(ABC, object):
|
|
81
81
|
if isinstance(value, int):
|
82
82
|
self._attempts = value
|
83
83
|
else:
|
84
|
-
raise ValueError("O
|
84
|
+
raise ValueError("O número de tentativas deve ser um número inteiro.")
|
85
85
|
|
86
86
|
@property
|
87
87
|
def wait_timeout(self):
|
@@ -92,7 +92,7 @@ class BaseExecutor(ABC, object):
|
|
92
92
|
if isinstance(value, int):
|
93
93
|
self._wait_timeout = value
|
94
94
|
else:
|
95
|
-
raise ValueError("O tempo de espera deve ser um
|
95
|
+
raise ValueError("O tempo de espera deve ser um número inteiro.")
|
96
96
|
|
97
97
|
@abstractmethod
|
98
98
|
def _exec_(self, connection, operation_sql, exec_type):
|
@@ -120,41 +120,79 @@ class Query(BaseExecutor):
|
|
120
120
|
def __init__(self, connectionStringData : ConnectionStringData, attempts : int, wait_timeout : int, sql_version : int | None, api_environment : bool):
|
121
121
|
super().__init__(connectionStringData, attempts, wait_timeout, sql_version, api_environment)
|
122
122
|
|
123
|
+
@overload
|
124
|
+
def count(self, query : str) -> Result.Count:
|
125
|
+
pass
|
126
|
+
|
127
|
+
@overload
|
128
|
+
def count(self, model : T, additional_sql : str = "", select_top : int = None) -> Result.Count:
|
129
|
+
pass
|
130
|
+
|
131
|
+
def count(self, *args, **kwargs) -> T | Result.Count:
|
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
|
+
count_query = f"""
|
137
|
+
SELECT COUNT(*) AS Count FROM (
|
138
|
+
{args.query}
|
139
|
+
) AS count_subquery
|
140
|
+
"""
|
141
|
+
|
142
|
+
result : Result.Fetchone = self._exec_(self._connection, count_query, ExecType.fetchone)
|
143
|
+
if result.success:
|
144
|
+
return Result.Count(count_query, result.dict.get('Count', 0), result.status_code, result.error)
|
145
|
+
return Result.Count(count_query, 0, result.status_code, result.error)
|
146
|
+
|
123
147
|
@overload
|
124
148
|
def fetchone(self, query : str) -> Result.Fetchone:
|
125
149
|
pass
|
126
150
|
|
127
151
|
@overload
|
128
|
-
def fetchone(self, model : T, additional_sql : str = "") -> T:
|
152
|
+
def fetchone(self, model : T, additional_sql : str = "") -> Result.FetchoneModel[T]:
|
129
153
|
pass
|
130
154
|
|
131
|
-
def fetchone(self, *args, **kwargs) -> T | Result.Fetchone:
|
155
|
+
def fetchone(self, *args, **kwargs) -> Result.FetchoneModel[T] | Result.Fetchone:
|
132
156
|
args = Utils.args_query(*args, **kwargs)
|
133
157
|
if args.model:
|
134
158
|
args.query = QueryBuilder.select(args.model, args.additional_sql, args.select_top)
|
135
159
|
|
136
160
|
result = self._exec_(self._connection, args.query, ExecType.fetchone)
|
137
161
|
if args.model:
|
138
|
-
|
162
|
+
model_instance = args.model.__class__(**result.dict) if result.success else args.model.__class__()
|
163
|
+
return Result.FetchoneModel(model_instance, result)
|
139
164
|
return result
|
165
|
+
|
166
|
+
def fetchone_with_joins(self, main_search: SearchTable, joins: list[JoinSearchTable] = [], additional_sql: str = "", select_top: int = None) -> Result.Fetchone:
|
167
|
+
query = QueryBuilder.select_with_joins(main_search, joins, additional_sql, select_top)
|
168
|
+
result = self._exec_(self._connection, query, ExecType.fetchone)
|
169
|
+
result._organize_joined_tables(joins)
|
170
|
+
return result
|
140
171
|
|
141
172
|
@overload
|
142
173
|
def fetchall(self, query : str) -> Result.Fetchall:
|
143
174
|
pass
|
144
175
|
|
145
176
|
@overload
|
146
|
-
def fetchall(self, model : T, additional_sql : str = "", select_top : int = None) ->
|
177
|
+
def fetchall(self, model : T, additional_sql : str = "", select_top : int = None) -> Result.FetchallModel[T]:
|
147
178
|
pass
|
148
179
|
|
149
|
-
def fetchall(self, *args, **kwargs) ->
|
180
|
+
def fetchall(self, *args, **kwargs) -> Result.FetchallModel[T] | Result.Fetchall:
|
150
181
|
args = Utils.args_query(*args, **kwargs)
|
151
182
|
if args.model:
|
152
183
|
args.query = QueryBuilder.select(args.model, args.additional_sql, args.select_top)
|
153
184
|
|
154
185
|
result = self._exec_(self._connection, args.query, ExecType.fetchall)
|
155
186
|
if args.model:
|
156
|
-
|
187
|
+
models = [args.model.__class__(**r) for r in result.list_dict] if result.success else []
|
188
|
+
return Result.FetchallModel(models, result)
|
157
189
|
return result
|
190
|
+
|
191
|
+
def fetchall_with_joins(self, main_search: SearchTable, joins: list[JoinSearchTable] = [], additional_sql: str = "", select_top: int = None) -> Result.Fetchall:
|
192
|
+
query = QueryBuilder.select_with_joins(main_search, joins, additional_sql, select_top)
|
193
|
+
result = self._exec_(self._connection, query, ExecType.fetchall)
|
194
|
+
result._organize_joined_tables(joins)
|
195
|
+
return result
|
158
196
|
|
159
197
|
def execute(self, query : str) -> Result.Send:
|
160
198
|
return self._exec_(self._connection, query, ExecType.send)
|
@@ -174,21 +212,21 @@ class Query(BaseExecutor):
|
|
174
212
|
query = QueryBuilder.insert(model, name_column_id)
|
175
213
|
result : Result.Fetchone = self._exec_(self._connection, query, ExecType.fetchone)
|
176
214
|
if result.success:
|
177
|
-
return Result.Insert(result.dict.get('Id', 0), result.status_code, result.
|
178
|
-
return Result.Insert(0, result.status_code, result.
|
215
|
+
return Result.Insert(query, result.dict.get('Id', 0), result.status_code, result.error)
|
216
|
+
return Result.Insert(query, 0, result.status_code, result.error)
|
179
217
|
|
180
|
-
def _exec_(self, connection, query_sql : str, exec_type : ExecType)
|
218
|
+
def _exec_(self, connection, query_sql : str, exec_type : ExecType):
|
181
219
|
|
182
220
|
if not self._cursor:
|
183
221
|
if self._api_environment:
|
184
222
|
raise UnavailableServiceException()
|
185
223
|
|
186
224
|
if exec_type == ExecType.fetchone:
|
187
|
-
return Result.Fetchone(None, None,
|
225
|
+
return Result.Fetchone(query_sql, None, None, self._connection_error)
|
188
226
|
elif exec_type == ExecType.fetchall:
|
189
|
-
return Result.Fetchall(None, None,
|
227
|
+
return Result.Fetchall(query_sql, None, None, self._connection_error)
|
190
228
|
elif exec_type == ExecType.send:
|
191
|
-
return Result.Send(False,
|
229
|
+
return Result.Send(query_sql, False, self._connection_error)
|
192
230
|
|
193
231
|
try:
|
194
232
|
# executar
|
@@ -196,23 +234,23 @@ class Query(BaseExecutor):
|
|
196
234
|
|
197
235
|
# ober resultado se nessesario
|
198
236
|
if exec_type == ExecType.fetchone:
|
199
|
-
result = Result.Fetchone(self._cursor, response.fetchone())
|
237
|
+
result = Result.Fetchone(query_sql, self._cursor, response.fetchone())
|
200
238
|
elif exec_type == ExecType.fetchall:
|
201
|
-
result = Result.Fetchall(self._cursor, response.fetchall())
|
239
|
+
result = Result.Fetchall(query_sql, self._cursor, response.fetchall())
|
202
240
|
elif exec_type == ExecType.send:
|
203
|
-
result = Result.Send(True)
|
241
|
+
result = Result.Send(query_sql, True)
|
204
242
|
|
205
243
|
# fazer o commit
|
206
244
|
connection.commit()
|
207
245
|
|
208
246
|
except Exception as ex:
|
209
247
|
if exec_type == ExecType.fetchone:
|
210
|
-
return Result.Fetchone(
|
248
|
+
return Result.Fetchone(query_sql, None, None, ex)
|
211
249
|
elif exec_type == ExecType.fetchall:
|
212
|
-
return Result.Fetchall(
|
250
|
+
return Result.Fetchall(query_sql, None, None, ex)
|
213
251
|
elif exec_type == ExecType.send:
|
214
|
-
return Result.Send(
|
215
|
-
|
252
|
+
return Result.Send(query_sql, False, str(ex))
|
253
|
+
|
216
254
|
# retorna o resultado
|
217
255
|
return result
|
218
256
|
|
@@ -229,6 +267,30 @@ class Stored(BaseExecutor):
|
|
229
267
|
def __init__(self, connectionStringData : ConnectionStringData, attempts : int, wait_timeout : int,sql_version : int | None, api_environment : bool):
|
230
268
|
super().__init__(connectionStringData, attempts, wait_timeout, sql_version, api_environment)
|
231
269
|
|
270
|
+
@overload
|
271
|
+
def count(self, query : str) -> Result.Count:
|
272
|
+
pass
|
273
|
+
|
274
|
+
@overload
|
275
|
+
def count(self, model : T, additional_sql : str = "", select_top : int = None) -> Result.Count:
|
276
|
+
pass
|
277
|
+
|
278
|
+
def count(self, *args, **kwargs) -> T | Result.Count:
|
279
|
+
args = Utils.args_query(*args, **kwargs)
|
280
|
+
if args.model:
|
281
|
+
args.query = StoredBuilder.select(args.model, args.additional_sql, args.select_top)
|
282
|
+
|
283
|
+
count_query = f"""
|
284
|
+
SELECT COUNT(*) AS Count FROM (
|
285
|
+
{args.query}
|
286
|
+
) AS count_subquery
|
287
|
+
"""
|
288
|
+
|
289
|
+
result : Result.Fetchone = self._exec_(self._connection, count_query, ExecType.fetchone)
|
290
|
+
if result.success:
|
291
|
+
return Result.Count(count_query, result.dict.get('Count', 0), result.status_code, result.error)
|
292
|
+
return Result.Count(count_query, 0, result.status_code, result.error)
|
293
|
+
|
232
294
|
@overload
|
233
295
|
def fetchone(self, query : str, params : list | tuple) -> Result.Fetchone:
|
234
296
|
pass
|
@@ -238,17 +300,18 @@ class Stored(BaseExecutor):
|
|
238
300
|
pass
|
239
301
|
|
240
302
|
@overload
|
241
|
-
def fetchone(self, model : T, additional_sql : str = "") -> T:
|
303
|
+
def fetchone(self, model : T, additional_sql : str = "") -> Result.FetchoneModel[T]:
|
242
304
|
pass
|
243
305
|
|
244
|
-
def fetchone(self, *args, **kwargs) -> T | Result.Fetchone:
|
306
|
+
def fetchone(self, *args, **kwargs) -> Result.FetchoneModel[T] | Result.Fetchone:
|
245
307
|
args = Utils.args_stored(*args, **kwargs)
|
246
308
|
if args.model:
|
247
309
|
args.query, args.params = StoredBuilder.select(args.model, args.additional_sql, args.select_top)
|
248
310
|
|
249
311
|
result = self._exec_(self._connection, (args.query, *args.params), ExecType.fetchone)
|
250
312
|
if args.model:
|
251
|
-
|
313
|
+
model_instance = args.model.__class__(**result.dict) if result.success else args.model.__class__()
|
314
|
+
return Result.FetchoneModel(model_instance, result)
|
252
315
|
return result
|
253
316
|
|
254
317
|
@overload
|
@@ -260,17 +323,18 @@ class Stored(BaseExecutor):
|
|
260
323
|
pass
|
261
324
|
|
262
325
|
@overload
|
263
|
-
def fetchall(self, model : T, additional_sql : str = "", select_top : int = None) ->
|
326
|
+
def fetchall(self, model : T, additional_sql : str = "", select_top : int = None) -> Result.FetchallModel[T]:
|
264
327
|
pass
|
265
328
|
|
266
|
-
def fetchall(self, *args, **kwargs) ->
|
329
|
+
def fetchall(self, *args, **kwargs) -> Result.FetchallModel[T] | Result.Fetchall:
|
267
330
|
args = Utils.args_stored(*args, **kwargs)
|
268
331
|
if args.model:
|
269
332
|
args.query, args.params = StoredBuilder.select(args.model, args.additional_sql, args.select_top)
|
270
333
|
|
271
334
|
result = self._exec_(self._connection, (args.query, *args.params), ExecType.fetchall)
|
272
335
|
if args.model:
|
273
|
-
|
336
|
+
models = [args.model.__class__(**r) for r in result.list_dict] if result.success else []
|
337
|
+
return Result.FetchallModel(models, result)
|
274
338
|
return result
|
275
339
|
|
276
340
|
@overload
|
@@ -301,10 +365,11 @@ class Stored(BaseExecutor):
|
|
301
365
|
name_column_id = next(iter(insert_data.keys()))
|
302
366
|
|
303
367
|
query, params = StoredBuilder.insert(model, name_column_id)
|
304
|
-
|
368
|
+
stored_procedure = (query, *params)
|
369
|
+
result = self._exec_(self._connection, stored_procedure, ExecType.fetchone)
|
305
370
|
if result.success:
|
306
|
-
return Result.Insert(result.dict.get('Id', 0), result.status_code, result.
|
307
|
-
return Result.Insert(0, result.status_code, result.
|
371
|
+
return Result.Insert(stored_procedure, result.dict.get('Id', 0), result.status_code, result.error)
|
372
|
+
return Result.Insert(stored_procedure, 0, result.status_code, result.error)
|
308
373
|
|
309
374
|
def _exec_(self, connection , stored_procedure : tuple, exec_type : ExecType):
|
310
375
|
|
@@ -313,29 +378,39 @@ class Stored(BaseExecutor):
|
|
313
378
|
raise UnavailableServiceException()
|
314
379
|
|
315
380
|
if exec_type == ExecType.fetchone:
|
316
|
-
return Result.Fetchone(None, None,
|
381
|
+
return Result.Fetchone(stored_procedure, None, None, self._connection_error)
|
382
|
+
elif exec_type == ExecType.fetchall:
|
383
|
+
return Result.Fetchall(stored_procedure, None, None, self._connection_error)
|
384
|
+
elif exec_type == ExecType.send:
|
385
|
+
return Result.Send(stored_procedure, False, self._connection_error)
|
386
|
+
|
387
|
+
try:
|
388
|
+
# executar
|
389
|
+
response = self._cursor.execute(*stored_procedure)
|
390
|
+
|
391
|
+
# ober resultado se nessesario
|
392
|
+
if exec_type == ExecType.fetchone:
|
393
|
+
result = Result.Fetchone(stored_procedure, self._cursor, response.fetchone())
|
317
394
|
elif exec_type == ExecType.fetchall:
|
318
|
-
|
395
|
+
result = Result.Fetchall(stored_procedure, self._cursor, response.fetchall())
|
319
396
|
elif exec_type == ExecType.send:
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
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()
|
397
|
+
result = Result.Send(stored_procedure, True)
|
398
|
+
|
399
|
+
# fazer o commit
|
400
|
+
connection.commit()
|
335
401
|
|
402
|
+
except Exception as ex:
|
403
|
+
if exec_type == ExecType.fetchone:
|
404
|
+
return Result.Fetchone(stored_procedure, None, None, ex)
|
405
|
+
elif exec_type == ExecType.fetchall:
|
406
|
+
return Result.Fetchall(stored_procedure, None, None, ex)
|
407
|
+
elif exec_type == ExecType.send:
|
408
|
+
return Result.Send(stored_procedure, False, ex)
|
409
|
+
|
336
410
|
# retorna o resultado
|
337
411
|
return result
|
338
412
|
|
413
|
+
|
339
414
|
|
340
415
|
|
341
416
|
|