reydb 1.1.48__py3-none-any.whl → 1.1.49__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.
- reydb/rbase.py +101 -2
- reydb/rbuild.py +17 -21
- reydb/rconfig.py +9 -14
- reydb/rconn.py +23 -44
- reydb/rdb.py +60 -1422
- reydb/rerror.py +1 -6
- reydb/rexec.py +820 -183
- reydb/rfile.py +3 -8
- reydb/rinfo.py +37 -95
- {reydb-1.1.48.dist-info → reydb-1.1.49.dist-info}/METADATA +1 -1
- reydb-1.1.49.dist-info/RECORD +16 -0
- reydb-1.1.48.dist-info/RECORD +0 -16
- {reydb-1.1.48.dist-info → reydb-1.1.49.dist-info}/WHEEL +0 -0
- {reydb-1.1.48.dist-info → reydb-1.1.49.dist-info}/licenses/LICENSE +0 -0
reydb/rbase.py
CHANGED
@@ -9,9 +9,10 @@
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
|
12
|
-
from typing import Any, TypedDict, Literal
|
12
|
+
from typing import Any, TypedDict, Literal, overload
|
13
13
|
from sqlalchemy.engine.base import Engine, Connection
|
14
14
|
from sqlalchemy.engine.url import URL
|
15
|
+
from sqlalchemy.sql.elements import TextClause
|
15
16
|
from reykit.rbase import Base, throw
|
16
17
|
from reykit.rre import search
|
17
18
|
|
@@ -19,7 +20,8 @@ from reykit.rre import search
|
|
19
20
|
__all__ = (
|
20
21
|
'DatabaseBase',
|
21
22
|
'extract_url',
|
22
|
-
'extract_engine'
|
23
|
+
'extract_engine',
|
24
|
+
'extract_path'
|
23
25
|
)
|
24
26
|
|
25
27
|
|
@@ -187,3 +189,100 @@ def extract_engine(engine: Engine | Connection) -> dict[
|
|
187
189
|
}
|
188
190
|
|
189
191
|
return params
|
192
|
+
|
193
|
+
|
194
|
+
def extract_path(
|
195
|
+
path: str | tuple[str] | tuple[str, str] | tuple[str, str, str]
|
196
|
+
) -> tuple[str, str | None, str | None]:
|
197
|
+
"""
|
198
|
+
Extract table name and database name and column name from path.
|
199
|
+
|
200
|
+
Parameters
|
201
|
+
----------
|
202
|
+
path : Path.
|
203
|
+
- `str` and not contain '.' or contain '`': Database name.
|
204
|
+
- `str` and contain '.': Database name and table name, column name is optional. Format is 'database.table[.column]'.
|
205
|
+
- `tuple`: Format is `(database[, table, column])`.
|
206
|
+
|
207
|
+
Returns
|
208
|
+
-------
|
209
|
+
Names.
|
210
|
+
"""
|
211
|
+
|
212
|
+
# Type str.
|
213
|
+
if type(path) == str:
|
214
|
+
|
215
|
+
## Single.
|
216
|
+
if (
|
217
|
+
'.' not in path
|
218
|
+
or '`' in path
|
219
|
+
):
|
220
|
+
name = path.replace('`', '')
|
221
|
+
names = (name, None, None)
|
222
|
+
|
223
|
+
## Multiple.
|
224
|
+
else:
|
225
|
+
names = path.split('.', 2)
|
226
|
+
if len(names) == 2:
|
227
|
+
names.append(None)
|
228
|
+
names = tuple(names)
|
229
|
+
|
230
|
+
# Type tuple.
|
231
|
+
else:
|
232
|
+
if len(path) == 1:
|
233
|
+
path += (None, None)
|
234
|
+
if len(path) == 2:
|
235
|
+
path += (None,)
|
236
|
+
names = path
|
237
|
+
|
238
|
+
return names
|
239
|
+
|
240
|
+
|
241
|
+
def get_syntax(self, sql: str | TextClause) -> list[str]:
|
242
|
+
"""
|
243
|
+
Extract SQL syntax type for each segment form SQL.
|
244
|
+
|
245
|
+
Parameters
|
246
|
+
----------
|
247
|
+
sql : SQL text or TextClause object.
|
248
|
+
|
249
|
+
Returns
|
250
|
+
-------
|
251
|
+
SQL syntax type for each segment.
|
252
|
+
"""
|
253
|
+
|
254
|
+
# Handle parameter.
|
255
|
+
if type(sql) == TextClause:
|
256
|
+
sql = sql.text
|
257
|
+
|
258
|
+
# Extract.
|
259
|
+
syntax = [
|
260
|
+
search('[a-zA-Z]+', sql_part).upper()
|
261
|
+
for sql_part in sql.split(';')
|
262
|
+
if sql_part != ''
|
263
|
+
]
|
264
|
+
|
265
|
+
return syntax
|
266
|
+
|
267
|
+
|
268
|
+
def is_multi_sql(self, sql: str | TextClause) -> bool:
|
269
|
+
"""
|
270
|
+
Judge whether it is multi segment SQL.
|
271
|
+
|
272
|
+
Parameters
|
273
|
+
----------
|
274
|
+
sql : SQL text or TextClause object.
|
275
|
+
|
276
|
+
Returns
|
277
|
+
-------
|
278
|
+
Judgment result.
|
279
|
+
"""
|
280
|
+
|
281
|
+
# Handle parameter.
|
282
|
+
if type(sql) == TextClause:
|
283
|
+
sql = sql.text
|
284
|
+
|
285
|
+
# Judge.
|
286
|
+
if ';' in sql.rstrip()[:-1]:
|
287
|
+
return True
|
288
|
+
return False
|
reydb/rbuild.py
CHANGED
@@ -14,7 +14,7 @@ from copy import deepcopy
|
|
14
14
|
from reykit.rbase import throw
|
15
15
|
from reykit.rstdout import ask
|
16
16
|
|
17
|
-
from .rbase import DatabaseBase
|
17
|
+
from .rbase import DatabaseBase, extract_path
|
18
18
|
from .rconn import DatabaseConnection
|
19
19
|
from .rdb import Database
|
20
20
|
|
@@ -61,11 +61,6 @@ class DatabaseBuild(DatabaseBase):
|
|
61
61
|
database : Database or DatabaseConnection instance.
|
62
62
|
"""
|
63
63
|
|
64
|
-
# SQLite.
|
65
|
-
if database.backend == 'sqlite':
|
66
|
-
text = 'not suitable for SQLite databases'
|
67
|
-
throw(AssertionError, text=text)
|
68
|
-
|
69
64
|
# Set attribute.
|
70
65
|
self.database = database
|
71
66
|
self._schema: dict[str, dict[str, list[str]]] | None = None
|
@@ -285,7 +280,8 @@ class DatabaseBuild(DatabaseBase):
|
|
285
280
|
"""
|
286
281
|
|
287
282
|
# Handle parameter.
|
288
|
-
|
283
|
+
if type(path) == str:
|
284
|
+
database, table, _ = extract_path(path)
|
289
285
|
if fields.__class__ == dict:
|
290
286
|
fields = [fields]
|
291
287
|
if primary.__class__ == str:
|
@@ -375,7 +371,7 @@ class DatabaseBuild(DatabaseBase):
|
|
375
371
|
"""
|
376
372
|
|
377
373
|
# Handle parameter.
|
378
|
-
database, view, _ =
|
374
|
+
database, view, _ = extract_path(path)
|
379
375
|
|
380
376
|
# Generate SQL.
|
381
377
|
select = select.replace('\n', '\n ')
|
@@ -502,7 +498,7 @@ class DatabaseBuild(DatabaseBase):
|
|
502
498
|
"""
|
503
499
|
|
504
500
|
# Handle parameter.
|
505
|
-
database, table, _ =
|
501
|
+
database, table, _ = extract_path(path)
|
506
502
|
|
507
503
|
# Generate.
|
508
504
|
sql = f'DROP TABLE `{database}`.`{table}`'
|
@@ -535,7 +531,7 @@ class DatabaseBuild(DatabaseBase):
|
|
535
531
|
"""
|
536
532
|
|
537
533
|
# Handle parameter.
|
538
|
-
database, view, _ =
|
534
|
+
database, view, _ = extract_path(path)
|
539
535
|
|
540
536
|
# Generate SQL.
|
541
537
|
sql = 'DROP VIEW `%s`.`%s`' % (database, view)
|
@@ -649,7 +645,7 @@ class DatabaseBuild(DatabaseBase):
|
|
649
645
|
"""
|
650
646
|
|
651
647
|
# Handle parameter.
|
652
|
-
database, table, _ =
|
648
|
+
database, table, _ = extract_path(path)
|
653
649
|
if fields.__class__ == dict:
|
654
650
|
fields = [fields]
|
655
651
|
if primary.__class__ == str:
|
@@ -739,7 +735,7 @@ class DatabaseBuild(DatabaseBase):
|
|
739
735
|
"""
|
740
736
|
|
741
737
|
# Handle parameter.
|
742
|
-
database, table, _ =
|
738
|
+
database, table, _ = extract_path(path)
|
743
739
|
if fields.__class__ == str:
|
744
740
|
fields = [fields]
|
745
741
|
if indexes.__class__ == str:
|
@@ -829,7 +825,7 @@ class DatabaseBuild(DatabaseBase):
|
|
829
825
|
"""
|
830
826
|
|
831
827
|
# Handle parameter.
|
832
|
-
database, table, _ =
|
828
|
+
database, table, _ = extract_path(path)
|
833
829
|
if fields.__class__ == dict:
|
834
830
|
fields = [fields]
|
835
831
|
|
@@ -925,7 +921,7 @@ class DatabaseBuild(DatabaseBase):
|
|
925
921
|
"""
|
926
922
|
|
927
923
|
# Handle parameter.
|
928
|
-
database, view, _ =
|
924
|
+
database, view, _ = extract_path(path)
|
929
925
|
|
930
926
|
# Generate SQL.
|
931
927
|
sql = 'ALTER VIEW `%s`.`%s` AS\n%s' % (database, view, select)
|
@@ -958,7 +954,7 @@ class DatabaseBuild(DatabaseBase):
|
|
958
954
|
"""
|
959
955
|
|
960
956
|
# Handle parameter.
|
961
|
-
database, table, _ =
|
957
|
+
database, table, _ = extract_path(path)
|
962
958
|
|
963
959
|
# Generate.
|
964
960
|
sql = f'TRUNCATE TABLE `{database}`.`{table}`'
|
@@ -972,7 +968,7 @@ class DatabaseBuild(DatabaseBase):
|
|
972
968
|
|
973
969
|
def exist(
|
974
970
|
self,
|
975
|
-
path: str | tuple[str, str |
|
971
|
+
path: str | tuple[str] | tuple[str, str] | tuple[str, str, str]
|
976
972
|
) -> bool:
|
977
973
|
"""
|
978
974
|
Judge database or table or column exists.
|
@@ -981,7 +977,7 @@ class DatabaseBuild(DatabaseBase):
|
|
981
977
|
----------
|
982
978
|
path : Database name and table name and column name.
|
983
979
|
- `str`: Automatic extract.
|
984
|
-
- `tuple
|
980
|
+
- `tuple`: Format is `(database[, table, column]).`
|
985
981
|
|
986
982
|
Returns
|
987
983
|
-------
|
@@ -989,7 +985,7 @@ class DatabaseBuild(DatabaseBase):
|
|
989
985
|
"""
|
990
986
|
|
991
987
|
# Handle parameter.
|
992
|
-
database, table, column =
|
988
|
+
database, table, column = extract_path(path)
|
993
989
|
if self._schema is None:
|
994
990
|
self._schema = self.database.schema(False)
|
995
991
|
|
@@ -1101,7 +1097,7 @@ class DatabaseBuild(DatabaseBase):
|
|
1101
1097
|
# Table.
|
1102
1098
|
for params in tables:
|
1103
1099
|
path = params['path']
|
1104
|
-
database, table, _ =
|
1100
|
+
database, table, _ = extract_path(path)
|
1105
1101
|
|
1106
1102
|
## Exist.
|
1107
1103
|
exist = self.database.build.exist((database, table, None))
|
@@ -1124,7 +1120,7 @@ class DatabaseBuild(DatabaseBase):
|
|
1124
1120
|
# View.
|
1125
1121
|
for params in views:
|
1126
1122
|
path = params['path']
|
1127
|
-
database, view, _ =
|
1123
|
+
database, view, _ = extract_path(path)
|
1128
1124
|
|
1129
1125
|
## Exist.
|
1130
1126
|
exist = self.database.build.exist((database, view, None))
|
@@ -1147,7 +1143,7 @@ class DatabaseBuild(DatabaseBase):
|
|
1147
1143
|
# View stats.
|
1148
1144
|
for params in views_stats:
|
1149
1145
|
path = params['path']
|
1150
|
-
database, view, _ =
|
1146
|
+
database, view, _ = extract_path(path)
|
1151
1147
|
|
1152
1148
|
## Exist.
|
1153
1149
|
exist = self.database.build.exist((database, view, None))
|
reydb/rconfig.py
CHANGED
@@ -54,11 +54,6 @@ class DatabaseConfig(object):
|
|
54
54
|
Build instance attributes.
|
55
55
|
"""
|
56
56
|
|
57
|
-
# SQLite.
|
58
|
-
if database.backend == 'sqlite':
|
59
|
-
text = 'not suitable for SQLite databases'
|
60
|
-
throw(AssertionError, text=text)
|
61
|
-
|
62
57
|
# Build.
|
63
58
|
self.database = database
|
64
59
|
|
@@ -199,7 +194,7 @@ class DatabaseConfig(object):
|
|
199
194
|
"""
|
200
195
|
|
201
196
|
# Get.
|
202
|
-
result = self.database.
|
197
|
+
result = self.database.execute.select(
|
203
198
|
(self.db_names['base'], self.db_names['base.config']),
|
204
199
|
['key', 'value', 'type', 'note'],
|
205
200
|
order='IFNULL(`update_time`, `create_time`) DESC'
|
@@ -235,7 +230,7 @@ class DatabaseConfig(object):
|
|
235
230
|
|
236
231
|
# Get.
|
237
232
|
where = '`key` = :key'
|
238
|
-
result = self.database.
|
233
|
+
result = self.database.execute.select(
|
239
234
|
(self.db_names['base'], self.db_names['base.config']),
|
240
235
|
'`value`',
|
241
236
|
where,
|
@@ -281,7 +276,7 @@ class DatabaseConfig(object):
|
|
281
276
|
'type': type(default).__name__,
|
282
277
|
'note': default_note
|
283
278
|
}
|
284
|
-
result = self.database.
|
279
|
+
result = self.database.execute.insert(
|
285
280
|
(self.db_names['base'], self.db_names['base.config']),
|
286
281
|
data,
|
287
282
|
'ignore'
|
@@ -322,7 +317,7 @@ class DatabaseConfig(object):
|
|
322
317
|
row['type'] = type(row['value']).__name__
|
323
318
|
|
324
319
|
# Update.
|
325
|
-
self.database.
|
320
|
+
self.database.execute.insert(
|
326
321
|
(self.db_names['base'], self.db_names['base.config']),
|
327
322
|
data,
|
328
323
|
'update'
|
@@ -345,7 +340,7 @@ class DatabaseConfig(object):
|
|
345
340
|
else:
|
346
341
|
where = '`key` in :key'
|
347
342
|
limit = None
|
348
|
-
result = self.database.
|
343
|
+
result = self.database.execute.delete(
|
349
344
|
(self.db_names['base'], self.db_names['base.config']),
|
350
345
|
where,
|
351
346
|
limit=limit,
|
@@ -367,7 +362,7 @@ class DatabaseConfig(object):
|
|
367
362
|
"""
|
368
363
|
|
369
364
|
# Get.
|
370
|
-
result = self.database.
|
365
|
+
result = self.database.execute.select(
|
371
366
|
(self.db_names['base'], self.db_names['base.config']),
|
372
367
|
['key', 'value']
|
373
368
|
)
|
@@ -393,7 +388,7 @@ class DatabaseConfig(object):
|
|
393
388
|
"""
|
394
389
|
|
395
390
|
# Get.
|
396
|
-
result = self.database.
|
391
|
+
result = self.database.execute.select(
|
397
392
|
(self.db_names['base'], self.db_names['base.config']),
|
398
393
|
'`key`'
|
399
394
|
)
|
@@ -418,7 +413,7 @@ class DatabaseConfig(object):
|
|
418
413
|
"""
|
419
414
|
|
420
415
|
# Get.
|
421
|
-
result = self.database.
|
416
|
+
result = self.database.execute.select(
|
422
417
|
(self.db_names['base'], self.db_names['base.config']),
|
423
418
|
'`value`'
|
424
419
|
)
|
@@ -480,7 +475,7 @@ class DatabaseConfig(object):
|
|
480
475
|
'type': type(value).__name__,
|
481
476
|
'note': note
|
482
477
|
}
|
483
|
-
self.database.
|
478
|
+
self.database.execute.insert(
|
484
479
|
(self.db_names['base'], self.db_names['base.config']),
|
485
480
|
data,
|
486
481
|
'update'
|
reydb/rconn.py
CHANGED
@@ -10,10 +10,9 @@
|
|
10
10
|
|
11
11
|
|
12
12
|
from typing import Self
|
13
|
-
from sqlalchemy.engine.base import Connection
|
14
|
-
from sqlalchemy.sql.elements import TextClause
|
15
13
|
|
16
|
-
from .
|
14
|
+
from .rbase import DatabaseBase
|
15
|
+
from .rdb import Database
|
17
16
|
|
18
17
|
|
19
18
|
__all__ = (
|
@@ -21,7 +20,7 @@ __all__ = (
|
|
21
20
|
)
|
22
21
|
|
23
22
|
|
24
|
-
class DatabaseConnection(
|
23
|
+
class DatabaseConnection(DatabaseBase):
|
25
24
|
"""
|
26
25
|
Database connection type.
|
27
26
|
"""
|
@@ -29,66 +28,46 @@ class DatabaseConnection(Database):
|
|
29
28
|
|
30
29
|
def __init__(
|
31
30
|
self,
|
32
|
-
|
33
|
-
|
31
|
+
db: Database,
|
32
|
+
autocommit: bool
|
34
33
|
) -> None:
|
35
34
|
"""
|
36
35
|
Build instance attributes.
|
37
36
|
|
38
37
|
Parameters
|
39
38
|
----------
|
40
|
-
|
41
|
-
|
39
|
+
db : Database instance.
|
40
|
+
autocommit: Whether automatic commit connection.
|
42
41
|
"""
|
43
42
|
|
44
|
-
#
|
45
|
-
self.
|
46
|
-
self.
|
43
|
+
# Build.
|
44
|
+
self.db = db
|
45
|
+
self.autocommit = autocommit
|
46
|
+
self.conn = db.engine.connect()
|
47
47
|
self.begin = None
|
48
|
-
self.username = rdatabase.username
|
49
|
-
self.password = rdatabase.password
|
50
|
-
self.host = rdatabase.host
|
51
|
-
self.port = rdatabase.port
|
52
|
-
self.database = rdatabase.database
|
53
|
-
self.query = rdatabase.query
|
54
|
-
self.pool_recycle = rdatabase.pool_recycle
|
55
48
|
|
56
49
|
|
57
|
-
|
58
|
-
|
59
|
-
sql: TextClause,
|
60
|
-
data: list[dict],
|
61
|
-
report: bool
|
62
|
-
) -> Result:
|
50
|
+
@property
|
51
|
+
def execute(self):
|
63
52
|
"""
|
64
|
-
|
65
|
-
|
66
|
-
Parameters
|
67
|
-
----------
|
68
|
-
sql : TextClause object.
|
69
|
-
data : Data set for filling.
|
70
|
-
report : Whether report SQL execute information.
|
53
|
+
Build `database execute` instance.
|
71
54
|
|
72
55
|
Returns
|
73
56
|
-------
|
74
|
-
|
57
|
+
Instance.
|
75
58
|
"""
|
76
59
|
|
60
|
+
# Import.
|
61
|
+
from .rexec import DatabaseExecute
|
62
|
+
|
77
63
|
# Create transaction.
|
78
64
|
if self.begin is None:
|
79
|
-
self.begin = self.
|
80
|
-
|
81
|
-
# Execute.
|
65
|
+
self.begin = self.conn.begin()
|
82
66
|
|
83
|
-
|
84
|
-
|
85
|
-
result = self.executor_report(self.connection, sql, data)
|
86
|
-
|
87
|
-
## Not report.
|
88
|
-
else:
|
89
|
-
result = self.connection.execute(sql, data)
|
67
|
+
# Build.
|
68
|
+
exec = DatabaseExecute(self)
|
90
69
|
|
91
|
-
return
|
70
|
+
return exec
|
92
71
|
|
93
72
|
|
94
73
|
def commit(self) -> None:
|
@@ -119,7 +98,7 @@ class DatabaseConnection(Database):
|
|
119
98
|
"""
|
120
99
|
|
121
100
|
# Close.
|
122
|
-
self.
|
101
|
+
self.conn.close()
|
123
102
|
|
124
103
|
|
125
104
|
def __enter__(self) -> Self:
|