reydb 1.1.52__py3-none-any.whl → 1.1.53__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 +90 -2
- reydb/rconfig.py +3 -3
- reydb/rconn.py +185 -15
- reydb/rdb.py +110 -24
- reydb/rexec.py +999 -293
- reydb/rfile.py +1 -1
- reydb/rorm.py +233 -36
- {reydb-1.1.52.dist-info → reydb-1.1.53.dist-info}/METADATA +1 -1
- reydb-1.1.53.dist-info/RECORD +17 -0
- reydb-1.1.52.dist-info/RECORD +0 -17
- {reydb-1.1.52.dist-info → reydb-1.1.53.dist-info}/WHEEL +0 -0
- {reydb-1.1.52.dist-info → reydb-1.1.53.dist-info}/licenses/LICENSE +0 -0
reydb/rexec.py
CHANGED
@@ -10,26 +10,27 @@
|
|
10
10
|
|
11
11
|
|
12
12
|
from typing import Any, Literal, overload
|
13
|
-
from collections.abc import Iterable, Generator, Container
|
14
|
-
from
|
15
|
-
from sqlalchemy import text as sqlalchemy_text
|
13
|
+
from collections.abc import Iterable, Generator, AsyncGenerator, Container
|
14
|
+
from datetime import timedelta as Timedelta
|
16
15
|
from sqlalchemy.sql.elements import TextClause
|
17
16
|
from reykit.rbase import throw, get_first_notnone
|
18
|
-
from reykit.rdata import FunctionGenerator
|
17
|
+
from reykit.rdata import FunctionGenerator
|
19
18
|
from reykit.rmonkey import monkey_sqlalchemy_result_more_fetch, monkey_sqlalchemy_row_index_field
|
20
19
|
from reykit.rrand import randn
|
21
20
|
from reykit.rre import findall
|
22
21
|
from reykit.rstdout import echo
|
23
22
|
from reykit.rtable import TableData, Table
|
23
|
+
from reykit.rtime import TimeMark, time_to
|
24
24
|
from reykit.rwrap import wrap_runtime
|
25
25
|
|
26
|
-
from .rbase import DatabaseBase
|
27
|
-
from .rconn import DatabaseConnection
|
26
|
+
from .rbase import DatabaseBase, handle_sql, handle_data
|
27
|
+
from .rconn import DatabaseConnection, DatabaseConnectionAsync
|
28
28
|
|
29
29
|
|
30
30
|
__all__ = (
|
31
31
|
'Result',
|
32
|
-
'DatabaseExecute'
|
32
|
+
'DatabaseExecute',
|
33
|
+
'DatabaseExecuteAsync'
|
33
34
|
)
|
34
35
|
|
35
36
|
|
@@ -39,9 +40,9 @@ Result = Result_
|
|
39
40
|
monkey_sqlalchemy_row_index_field()
|
40
41
|
|
41
42
|
|
42
|
-
class
|
43
|
+
class DatabaseExecuteBase(DatabaseBase):
|
43
44
|
"""
|
44
|
-
Database execute type.
|
45
|
+
Database execute base type.
|
45
46
|
"""
|
46
47
|
|
47
48
|
|
@@ -58,15 +59,15 @@ class DatabaseExecute(DatabaseBase):
|
|
58
59
|
self.dbconn = dbconn
|
59
60
|
|
60
61
|
|
61
|
-
def
|
62
|
+
def handle_execute(
|
62
63
|
self,
|
63
64
|
sql: str | TextClause,
|
64
65
|
data: TableData | None = None,
|
65
66
|
report: bool | None = None,
|
66
67
|
**kwdata: Any
|
67
|
-
) ->
|
68
|
+
) -> tuple[TextClause, list[dict], bool]:
|
68
69
|
"""
|
69
|
-
|
70
|
+
Handle parameters before execute SQL.
|
70
71
|
|
71
72
|
Parameters
|
72
73
|
----------
|
@@ -79,12 +80,12 @@ class DatabaseExecute(DatabaseBase):
|
|
79
80
|
|
80
81
|
Returns
|
81
82
|
-------
|
82
|
-
|
83
|
+
Parameters `sql` and `data` and `report`.
|
83
84
|
"""
|
84
85
|
|
85
86
|
# Handle parameter.
|
86
87
|
report = get_first_notnone(report, self.dbconn.db.default_report)
|
87
|
-
sql =
|
88
|
+
sql = handle_sql(sql)
|
88
89
|
if data is None:
|
89
90
|
if kwdata == {}:
|
90
91
|
data = []
|
@@ -95,43 +96,12 @@ class DatabaseExecute(DatabaseBase):
|
|
95
96
|
data = data_table.to_table()
|
96
97
|
for row in data:
|
97
98
|
row.update(kwdata)
|
98
|
-
data =
|
99
|
-
|
100
|
-
# Execute.
|
101
|
-
|
102
|
-
## Report.
|
103
|
-
if report:
|
104
|
-
execute = wrap_runtime(self.conn.execute, to_return=True)
|
105
|
-
result, report_runtime, *_ = execute(sql, data)
|
106
|
-
report_info = (
|
107
|
-
f'{report_runtime}\n'
|
108
|
-
f'Row Count: {result.rowcount}'
|
109
|
-
)
|
110
|
-
sqls = [
|
111
|
-
sql_part.strip()
|
112
|
-
for sql_part in sql.text.split(';')
|
113
|
-
if sql_part != ''
|
114
|
-
]
|
115
|
-
if data == []:
|
116
|
-
echo(report_info, *sqls, title='SQL')
|
117
|
-
else:
|
118
|
-
echo(report_info, *sqls, data, title='SQL')
|
119
|
-
|
120
|
-
## Not report.
|
121
|
-
else:
|
122
|
-
result = self.dbconn.conn.execute(sql, data)
|
123
|
-
|
124
|
-
# Automatic commit.
|
125
|
-
if self.dbconn.autocommit:
|
126
|
-
self.dbconn.conn.commit()
|
127
|
-
|
128
|
-
return result
|
129
|
-
|
99
|
+
data = handle_data(data, sql)
|
130
100
|
|
131
|
-
|
101
|
+
return sql, data, report
|
132
102
|
|
133
103
|
|
134
|
-
def
|
104
|
+
def handle_select(
|
135
105
|
self,
|
136
106
|
table: str,
|
137
107
|
fields: str | Iterable[str] | None = None,
|
@@ -139,12 +109,10 @@ class DatabaseExecute(DatabaseBase):
|
|
139
109
|
group: str | None = None,
|
140
110
|
having: str | None = None,
|
141
111
|
order: str | None = None,
|
142
|
-
limit: int | str | tuple[int, int] | None = None
|
143
|
-
|
144
|
-
**kwdata: Any
|
145
|
-
) -> Result:
|
112
|
+
limit: int | str | tuple[int, int] | None = None
|
113
|
+
) -> str:
|
146
114
|
"""
|
147
|
-
|
115
|
+
Handle parameters before execute select SQL.
|
148
116
|
|
149
117
|
Parameters
|
150
118
|
----------
|
@@ -162,28 +130,10 @@ class DatabaseExecute(DatabaseBase):
|
|
162
130
|
limit : Clause `LIMIT` content.
|
163
131
|
- `int | str`: Join as `LIMIT int/str`.
|
164
132
|
- `tuple[int, int]`: Join as `LIMIT int, int`.
|
165
|
-
report : Whether report SQL execute information.
|
166
|
-
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
167
|
-
- `int`: Use this value.
|
168
|
-
kwdata : Keyword parameters for filling.
|
169
133
|
|
170
134
|
Returns
|
171
135
|
-------
|
172
|
-
|
173
|
-
|
174
|
-
Examples
|
175
|
-
--------
|
176
|
-
Parameter `fields`.
|
177
|
-
>>> fields = ['id', ':`id` + 1 AS `id_`']
|
178
|
-
>>> result = Database.execute.select('table', fields)
|
179
|
-
>>> print(result.to_table())
|
180
|
-
[{'id': 1, 'id_': 2}, ...]
|
181
|
-
|
182
|
-
Parameter `kwdata`.
|
183
|
-
>>> fields = '`id`, `id` + :value AS `id_`'
|
184
|
-
>>> result = Database.execute.select('table', fields, value=1)
|
185
|
-
>>> print(result.to_table())
|
186
|
-
[{'id': 1, 'id_': 2}, ...]
|
136
|
+
Parameters `sql`.
|
187
137
|
"""
|
188
138
|
|
189
139
|
# Generate SQL.
|
@@ -245,22 +195,18 @@ class DatabaseExecute(DatabaseBase):
|
|
245
195
|
## Join sql part.
|
246
196
|
sql = '\n'.join(sql_list)
|
247
197
|
|
248
|
-
|
249
|
-
result = self.execute(sql, report=report, **kwdata)
|
250
|
-
|
251
|
-
return result
|
198
|
+
return sql
|
252
199
|
|
253
200
|
|
254
|
-
def
|
201
|
+
def handle_insert(
|
255
202
|
self,
|
256
203
|
table: str,
|
257
204
|
data: TableData,
|
258
205
|
duplicate: Literal['ignore', 'update'] | Container[str] | None = None,
|
259
|
-
report: bool | None = None,
|
260
206
|
**kwdata: Any
|
261
207
|
) -> Result:
|
262
208
|
"""
|
263
|
-
|
209
|
+
Handle parameters before execute insert SQL.
|
264
210
|
|
265
211
|
Parameters
|
266
212
|
----------
|
@@ -271,28 +217,13 @@ class DatabaseExecute(DatabaseBase):
|
|
271
217
|
- `ignore`: Use `UPDATE IGNORE INTO` clause.
|
272
218
|
- `update`: Use `ON DUPLICATE KEY UPDATE` clause and update all fields.
|
273
219
|
- `Container[str]`: Use `ON DUPLICATE KEY UPDATE` clause and update this fields.
|
274
|
-
report : Whether report SQL execute information.
|
275
|
-
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
276
|
-
- `int`: Use this value.
|
277
220
|
kwdata : Keyword parameters for filling.
|
278
221
|
- `str and first character is ':'`: Use this syntax.
|
279
222
|
- `Any`: Use this value.
|
280
223
|
|
281
224
|
Returns
|
282
225
|
-------
|
283
|
-
|
284
|
-
|
285
|
-
Examples
|
286
|
-
--------
|
287
|
-
Parameter `data` and `kwdata`.
|
288
|
-
>>> data = [{'key': 'a'}, {'key': 'b'}]
|
289
|
-
>>> kwdata = {'value1': 1, 'value2': ':(SELECT 2)'}
|
290
|
-
>>> result = Database.execute.insert('table', data, **kwdata)
|
291
|
-
>>> print(result.rowcount)
|
292
|
-
2
|
293
|
-
>>> result = Database.execute.select('table')
|
294
|
-
>>> print(result.to_table())
|
295
|
-
[{'key': 'a', 'value1': 1, 'value2': 2}, {'key': 'b', 'value1': 1, 'value2': 2}]
|
226
|
+
Parameters `sql` and `kwdata`.
|
296
227
|
"""
|
297
228
|
|
298
229
|
# Handle parameter.
|
@@ -395,22 +326,18 @@ class DatabaseExecute(DatabaseBase):
|
|
395
326
|
f' {update_content}'
|
396
327
|
)
|
397
328
|
|
398
|
-
|
399
|
-
result = self.execute(sql, data, report, **kwdata_replace)
|
400
|
-
|
401
|
-
return result
|
329
|
+
return sql, kwdata_replace
|
402
330
|
|
403
331
|
|
404
|
-
def
|
332
|
+
def handle_update(
|
405
333
|
self,
|
406
334
|
table: str,
|
407
335
|
data: TableData,
|
408
336
|
where_fields: str | Iterable[str] | None = None,
|
409
|
-
report: bool | None = None,
|
410
337
|
**kwdata: Any
|
411
338
|
) -> Result:
|
412
339
|
"""
|
413
|
-
|
340
|
+
Execute update SQL.
|
414
341
|
|
415
342
|
Parameters
|
416
343
|
----------
|
@@ -427,28 +354,13 @@ class DatabaseExecute(DatabaseBase):
|
|
427
354
|
- `None`: The first key value pair of each item is judged.
|
428
355
|
- `str`: This key value pair of each item is judged.
|
429
356
|
- `Iterable[str]`: Multiple judged, `and`: relationship.
|
430
|
-
report : Whether report SQL execute information.
|
431
|
-
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
432
|
-
- `int`: Use this value.
|
433
357
|
kwdata : Keyword parameters for filling.
|
434
358
|
- `str and first character is ':'`: Use this syntax.
|
435
359
|
- `Any`: Use this value.
|
436
360
|
|
437
361
|
Returns
|
438
362
|
-------
|
439
|
-
|
440
|
-
|
441
|
-
Examples
|
442
|
-
--------
|
443
|
-
Parameter `data` and `kwdata`.
|
444
|
-
>>> data = [{'key': 'a'}, {'key': 'b'}]
|
445
|
-
>>> kwdata = {'value': 1, 'name': ':`key`'}
|
446
|
-
>>> result = Database.execute.update('table', data, **kwdata)
|
447
|
-
>>> print(result.rowcount)
|
448
|
-
2
|
449
|
-
>>> result = Database.execute.select('table')
|
450
|
-
>>> print(result.to_table())
|
451
|
-
[{'key': 'a', 'value': 1, 'name': 'a'}, {'key': 'b', 'value': 1, 'name': 'b'}]
|
363
|
+
Parameters `sql` and `data`.
|
452
364
|
"""
|
453
365
|
|
454
366
|
# Handle parameter.
|
@@ -554,23 +466,18 @@ class DatabaseExecute(DatabaseBase):
|
|
554
466
|
## Join sqls.
|
555
467
|
sqls = ';\n'.join(sqls_list)
|
556
468
|
|
557
|
-
|
558
|
-
result = self.execute(sqls, data_flatten, report)
|
559
|
-
|
560
|
-
return result
|
469
|
+
return sqls, data_flatten
|
561
470
|
|
562
471
|
|
563
|
-
def
|
472
|
+
def handle_delete(
|
564
473
|
self,
|
565
474
|
table: str,
|
566
475
|
where: str | None = None,
|
567
476
|
order: str | None = None,
|
568
|
-
limit: int | str | None = None
|
569
|
-
report: bool | None = None,
|
570
|
-
**kwdata: Any
|
477
|
+
limit: int | str | None = None
|
571
478
|
) -> Result:
|
572
479
|
"""
|
573
|
-
|
480
|
+
Execute delete SQL.
|
574
481
|
|
575
482
|
Parameters
|
576
483
|
----------
|
@@ -578,23 +485,10 @@ class DatabaseExecute(DatabaseBase):
|
|
578
485
|
where : Clause `WHERE` content, join as `WHERE str`.
|
579
486
|
order : Clause `ORDER BY` content, join as `ORDER BY str`.
|
580
487
|
limit : Clause `LIMIT` content, join as `LIMIT int/str`.
|
581
|
-
report : Whether report SQL execute information.
|
582
|
-
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
583
|
-
- `int`: Use this value.
|
584
|
-
kwdata : Keyword parameters for filling.
|
585
488
|
|
586
489
|
Returns
|
587
490
|
-------
|
588
|
-
|
589
|
-
|
590
|
-
Examples
|
591
|
-
--------
|
592
|
-
Parameter `where` and `kwdata`.
|
593
|
-
>>> where = '`id` IN :ids'
|
594
|
-
>>> ids = (1, 2)
|
595
|
-
>>> result = Database.execute.delete('table', where, ids=ids)
|
596
|
-
>>> print(result.rowcount)
|
597
|
-
2
|
491
|
+
Parameter `sql`.
|
598
492
|
"""
|
599
493
|
|
600
494
|
# Generate SQL.
|
@@ -622,22 +516,18 @@ class DatabaseExecute(DatabaseBase):
|
|
622
516
|
## Join sqls.
|
623
517
|
sqls = '\n'.join(sqls)
|
624
518
|
|
625
|
-
|
626
|
-
result = self.execute(sqls, report=report, **kwdata)
|
627
|
-
|
628
|
-
return result
|
519
|
+
return sqls
|
629
520
|
|
630
521
|
|
631
|
-
def
|
522
|
+
def handle_copy(
|
632
523
|
self,
|
633
524
|
table: str,
|
634
525
|
where: str | None = None,
|
635
526
|
limit: int | str | tuple[int, int] | None = None,
|
636
|
-
report: bool | None = None,
|
637
527
|
**kwdata: Any
|
638
528
|
) -> Result:
|
639
529
|
"""
|
640
|
-
|
530
|
+
Execute inesrt SQL of copy records.
|
641
531
|
|
642
532
|
Parameters
|
643
533
|
----------
|
@@ -646,9 +536,6 @@ class DatabaseExecute(DatabaseBase):
|
|
646
536
|
limit : Clause `LIMIT` content.
|
647
537
|
- `int | str`: Join as `LIMIT int/str`.
|
648
538
|
- `tuple[int, int]`: Join as `LIMIT int, int`.
|
649
|
-
report : Whether report SQL execute information.
|
650
|
-
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
651
|
-
- `int`: Use this value.
|
652
539
|
kwdata : Keyword parameters for filling.
|
653
540
|
- `In 'WHERE' syntax`: Fill 'WHERE' syntax.
|
654
541
|
- `Not in 'WHERE' syntax`: Fill 'INSERT' and 'SELECT' syntax.
|
@@ -657,16 +544,7 @@ class DatabaseExecute(DatabaseBase):
|
|
657
544
|
|
658
545
|
Returns
|
659
546
|
-------
|
660
|
-
|
661
|
-
|
662
|
-
Examples
|
663
|
-
--------
|
664
|
-
Parameter `where` and `kwdata`.
|
665
|
-
>>> where = '`id` IN :ids'
|
666
|
-
>>> ids = (1, 2, 3)
|
667
|
-
>>> result = Database.execute.copy('table', where, 2, ids=ids, id=None, time=':NOW()')
|
668
|
-
>>> print(result.rowcount)
|
669
|
-
2
|
547
|
+
Parameters `sql`.
|
670
548
|
"""
|
671
549
|
|
672
550
|
# Handle parameter.
|
@@ -759,70 +637,123 @@ class DatabaseExecute(DatabaseBase):
|
|
759
637
|
## Join.
|
760
638
|
sql = '\n'.join(sqls)
|
761
639
|
|
762
|
-
|
763
|
-
result = self.execute(sql, report=report, **kwdata)
|
640
|
+
return sql
|
764
641
|
|
765
|
-
|
642
|
+
|
643
|
+
class DatabaseExecute(DatabaseExecuteBase):
|
644
|
+
"""
|
645
|
+
Database execute type.
|
646
|
+
"""
|
766
647
|
|
767
648
|
|
768
|
-
def
|
649
|
+
def __init__(self, dbconn: DatabaseConnection) -> None:
|
650
|
+
"""
|
651
|
+
Build instance attributes.
|
652
|
+
|
653
|
+
Parameters
|
654
|
+
----------
|
655
|
+
dbconn : `DatabaseConnection` instance.
|
656
|
+
"""
|
657
|
+
|
658
|
+
# Build.
|
659
|
+
self.dbconn = dbconn
|
660
|
+
|
661
|
+
|
662
|
+
def execute(
|
769
663
|
self,
|
770
|
-
|
771
|
-
|
664
|
+
sql: str | TextClause,
|
665
|
+
data: TableData | None = None,
|
772
666
|
report: bool | None = None,
|
773
667
|
**kwdata: Any
|
774
|
-
) ->
|
668
|
+
) -> Result:
|
775
669
|
"""
|
776
|
-
|
670
|
+
Execute SQL.
|
777
671
|
|
778
672
|
Parameters
|
779
673
|
----------
|
780
|
-
|
781
|
-
|
782
|
-
- `None`: Match all.
|
783
|
-
- `str`: Match condition.
|
674
|
+
sql : SQL in method `sqlalchemy.text` format, or `TextClause` object.
|
675
|
+
data : Data set for filling.
|
784
676
|
report : Whether report SQL execute information.
|
785
|
-
- `None
|
786
|
-
- `
|
677
|
+
- `None`: Use attribute `default_report`.
|
678
|
+
- `bool`: Use this value.
|
787
679
|
kwdata : Keyword parameters for filling.
|
788
680
|
|
789
681
|
Returns
|
790
682
|
-------
|
791
|
-
|
792
|
-
|
793
|
-
Examples
|
794
|
-
--------
|
795
|
-
Parameter `where` and `kwdata`.
|
796
|
-
>>> where = '`id` IN :ids'
|
797
|
-
>>> ids = (1, 2)
|
798
|
-
>>> result = Database.execute.count('table', where, ids=ids)
|
799
|
-
>>> print(result)
|
800
|
-
2
|
683
|
+
Result object.
|
801
684
|
"""
|
802
685
|
|
686
|
+
# Handle parameter.
|
687
|
+
sql, data, report = self.handle_execute(sql, data, report, **kwdata)
|
688
|
+
|
689
|
+
# Transaction.
|
690
|
+
self.dbconn.get_begin()
|
691
|
+
|
803
692
|
# Execute.
|
804
|
-
result = self.select(table, '1', where=where, report=report, **kwdata)
|
805
|
-
count = len(tuple(result))
|
806
693
|
|
807
|
-
|
694
|
+
## Report.
|
695
|
+
if report:
|
696
|
+
execute = wrap_runtime(self.dbconn.execute, to_return=True)
|
697
|
+
result, report_runtime, *_ = execute(sql, data)
|
698
|
+
report_info = (
|
699
|
+
f'{report_runtime}\n'
|
700
|
+
f'Row Count: {result.rowcount}'
|
701
|
+
)
|
702
|
+
sqls = [
|
703
|
+
sql_part.strip()
|
704
|
+
for sql_part in sql.text.split(';')
|
705
|
+
if sql_part != ''
|
706
|
+
]
|
707
|
+
if data == []:
|
708
|
+
echo(report_info, *sqls, title='SQL')
|
709
|
+
else:
|
710
|
+
echo(report_info, *sqls, data, title='SQL')
|
808
711
|
|
712
|
+
## Not report.
|
713
|
+
else:
|
714
|
+
result = self.dbconn.conn.execute(sql, data)
|
809
715
|
|
810
|
-
|
716
|
+
# Automatic commit.
|
717
|
+
if self.dbconn.autocommit:
|
718
|
+
self.dbconn.commit()
|
719
|
+
|
720
|
+
return result
|
721
|
+
|
722
|
+
|
723
|
+
__call__ = execute
|
724
|
+
|
725
|
+
|
726
|
+
def select(
|
811
727
|
self,
|
812
728
|
table: str,
|
729
|
+
fields: str | Iterable[str] | None = None,
|
813
730
|
where: str | None = None,
|
731
|
+
group: str | None = None,
|
732
|
+
having: str | None = None,
|
733
|
+
order: str | None = None,
|
734
|
+
limit: int | str | tuple[int, int] | None = None,
|
814
735
|
report: bool | None = None,
|
815
736
|
**kwdata: Any
|
816
|
-
) ->
|
737
|
+
) -> Result:
|
817
738
|
"""
|
818
|
-
|
739
|
+
Execute select SQL.
|
819
740
|
|
820
741
|
Parameters
|
821
742
|
----------
|
822
743
|
table : Table name.
|
823
|
-
|
824
|
-
- `None`:
|
825
|
-
- `str`:
|
744
|
+
fields : Select clause content.
|
745
|
+
- `None`: Is `SELECT *`.
|
746
|
+
- `str`: Join as `SELECT str`.
|
747
|
+
- `Iterable[str]`, Join as `SELECT ``str``: ...`.
|
748
|
+
`str and first character is ':'`: Use this syntax.
|
749
|
+
`str`: Use this field.
|
750
|
+
where : Clause `WHERE` content, join as `WHERE str`.
|
751
|
+
group : Clause `GROUP BY` content, join as `GROUP BY str`.
|
752
|
+
having : Clause `HAVING` content, join as `HAVING str`.
|
753
|
+
order : Clause `ORDER BY` content, join as `ORDER BY str`.
|
754
|
+
limit : Clause `LIMIT` content.
|
755
|
+
- `int | str`: Join as `LIMIT int/str`.
|
756
|
+
- `tuple[int, int]`: Join as `LIMIT int, int`.
|
826
757
|
report : Whether report SQL execute information.
|
827
758
|
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
828
759
|
- `int`: Use this value.
|
@@ -830,7 +761,862 @@ class DatabaseExecute(DatabaseBase):
|
|
830
761
|
|
831
762
|
Returns
|
832
763
|
-------
|
833
|
-
|
764
|
+
Result object.
|
765
|
+
|
766
|
+
Examples
|
767
|
+
--------
|
768
|
+
Parameter `fields`.
|
769
|
+
>>> fields = ['id', ':`id` + 1 AS `id_`']
|
770
|
+
>>> result = Database.execute.select('table', fields)
|
771
|
+
>>> print(result.to_table())
|
772
|
+
[{'id': 1, 'id_': 2}, ...]
|
773
|
+
|
774
|
+
Parameter `kwdata`.
|
775
|
+
>>> fields = '`id`, `id` + :value AS `id_`'
|
776
|
+
>>> result = Database.execute.select('table', fields, value=1)
|
777
|
+
>>> print(result.to_table())
|
778
|
+
[{'id': 1, 'id_': 2}, ...]
|
779
|
+
"""
|
780
|
+
|
781
|
+
# Handle parameter.
|
782
|
+
sql = self.handle_select(table, fields, where, group, having, order, limit)
|
783
|
+
|
784
|
+
# Execute SQL.
|
785
|
+
result = self.execute(sql, report=report, **kwdata)
|
786
|
+
|
787
|
+
return result
|
788
|
+
|
789
|
+
|
790
|
+
def insert(
|
791
|
+
self,
|
792
|
+
table: str,
|
793
|
+
data: TableData,
|
794
|
+
duplicate: Literal['ignore', 'update'] | Container[str] | None = None,
|
795
|
+
report: bool | None = None,
|
796
|
+
**kwdata: Any
|
797
|
+
) -> Result:
|
798
|
+
"""
|
799
|
+
Execute insert SQL.
|
800
|
+
|
801
|
+
Parameters
|
802
|
+
----------
|
803
|
+
table : Table name.
|
804
|
+
data : Insert data.
|
805
|
+
duplicate : Handle method when constraint error.
|
806
|
+
- `None`: Not handled.
|
807
|
+
- `ignore`: Use `UPDATE IGNORE INTO` clause.
|
808
|
+
- `update`: Use `ON DUPLICATE KEY UPDATE` clause and update all fields.
|
809
|
+
- `Container[str]`: Use `ON DUPLICATE KEY UPDATE` clause and update this fields.
|
810
|
+
report : Whether report SQL execute information.
|
811
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
812
|
+
- `int`: Use this value.
|
813
|
+
kwdata : Keyword parameters for filling.
|
814
|
+
- `str and first character is ':'`: Use this syntax.
|
815
|
+
- `Any`: Use this value.
|
816
|
+
|
817
|
+
Returns
|
818
|
+
-------
|
819
|
+
Result object.
|
820
|
+
|
821
|
+
Examples
|
822
|
+
--------
|
823
|
+
Parameter `data` and `kwdata`.
|
824
|
+
>>> data = [{'key': 'a'}, {'key': 'b'}]
|
825
|
+
>>> kwdata = {'value1': 1, 'value2': ':(SELECT 2)'}
|
826
|
+
>>> result = Database.execute.insert('table', data, **kwdata)
|
827
|
+
>>> print(result.rowcount)
|
828
|
+
2
|
829
|
+
>>> result = Database.execute.select('table')
|
830
|
+
>>> print(result.to_table())
|
831
|
+
[{'key': 'a', 'value1': 1, 'value2': 2}, {'key': 'b', 'value1': 1, 'value2': 2}]
|
832
|
+
"""
|
833
|
+
|
834
|
+
# Handle parameter.
|
835
|
+
sql, kwdata = self.handle_insert(table, data, duplicate, **kwdata)
|
836
|
+
|
837
|
+
# Execute SQL.
|
838
|
+
result = self.execute(sql, data, report, **kwdata)
|
839
|
+
|
840
|
+
return result
|
841
|
+
|
842
|
+
|
843
|
+
def update(
|
844
|
+
self,
|
845
|
+
table: str,
|
846
|
+
data: TableData,
|
847
|
+
where_fields: str | Iterable[str] | None = None,
|
848
|
+
report: bool | None = None,
|
849
|
+
**kwdata: Any
|
850
|
+
) -> Result:
|
851
|
+
"""
|
852
|
+
Execute update SQL.
|
853
|
+
|
854
|
+
Parameters
|
855
|
+
----------
|
856
|
+
table : Table name.
|
857
|
+
data : Update data, clause `SET` and `WHERE` and `ORDER BY` and `LIMIT` content.
|
858
|
+
- `Key`: Table field.
|
859
|
+
`literal['order']`: Clause `ORDER BY` content, join as `ORDER BY str`.
|
860
|
+
`literal['limit']`: Clause `LIMIT` content, join as `LIMIT str`.
|
861
|
+
`Other`: Clause `SET` and `WHERE` content.
|
862
|
+
- `Value`: Table value.
|
863
|
+
`list | tuple`: Join as `field IN :str`.
|
864
|
+
`Any`: Join as `field = :str`.
|
865
|
+
where_fields : Clause `WHERE` content fields.
|
866
|
+
- `None`: The first key value pair of each item is judged.
|
867
|
+
- `str`: This key value pair of each item is judged.
|
868
|
+
- `Iterable[str]`: Multiple judged, `and`: relationship.
|
869
|
+
report : Whether report SQL execute information.
|
870
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
871
|
+
- `int`: Use this value.
|
872
|
+
kwdata : Keyword parameters for filling.
|
873
|
+
- `str and first character is ':'`: Use this syntax.
|
874
|
+
- `Any`: Use this value.
|
875
|
+
|
876
|
+
Returns
|
877
|
+
-------
|
878
|
+
Result object.
|
879
|
+
|
880
|
+
Examples
|
881
|
+
--------
|
882
|
+
Parameter `data` and `kwdata`.
|
883
|
+
>>> data = [{'key': 'a'}, {'key': 'b'}]
|
884
|
+
>>> kwdata = {'value': 1, 'name': ':`key`'}
|
885
|
+
>>> result = Database.execute.update('table', data, **kwdata)
|
886
|
+
>>> print(result.rowcount)
|
887
|
+
2
|
888
|
+
>>> result = Database.execute.select('table')
|
889
|
+
>>> print(result.to_table())
|
890
|
+
[{'key': 'a', 'value': 1, 'name': 'a'}, {'key': 'b', 'value': 1, 'name': 'b'}]
|
891
|
+
"""
|
892
|
+
|
893
|
+
# Handle parameter.
|
894
|
+
sql, data = self.handle_update(table, data, where_fields, **kwdata)
|
895
|
+
|
896
|
+
# Execute SQL.
|
897
|
+
result = self.execute(sql, data, report)
|
898
|
+
|
899
|
+
return result
|
900
|
+
|
901
|
+
|
902
|
+
def delete(
|
903
|
+
self,
|
904
|
+
table: str,
|
905
|
+
where: str | None = None,
|
906
|
+
order: str | None = None,
|
907
|
+
limit: int | str | None = None,
|
908
|
+
report: bool | None = None,
|
909
|
+
**kwdata: Any
|
910
|
+
) -> Result:
|
911
|
+
"""
|
912
|
+
Execute delete SQL.
|
913
|
+
|
914
|
+
Parameters
|
915
|
+
----------
|
916
|
+
table : Table name.
|
917
|
+
where : Clause `WHERE` content, join as `WHERE str`.
|
918
|
+
order : Clause `ORDER BY` content, join as `ORDER BY str`.
|
919
|
+
limit : Clause `LIMIT` content, join as `LIMIT int/str`.
|
920
|
+
report : Whether report SQL execute information.
|
921
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
922
|
+
- `int`: Use this value.
|
923
|
+
kwdata : Keyword parameters for filling.
|
924
|
+
|
925
|
+
Returns
|
926
|
+
-------
|
927
|
+
Result object.
|
928
|
+
|
929
|
+
Examples
|
930
|
+
--------
|
931
|
+
Parameter `where` and `kwdata`.
|
932
|
+
>>> where = '`id` IN :ids'
|
933
|
+
>>> ids = (1, 2)
|
934
|
+
>>> result = Database.execute.delete('table', where, ids=ids)
|
935
|
+
>>> print(result.rowcount)
|
936
|
+
2
|
937
|
+
"""
|
938
|
+
|
939
|
+
# Handle parameter.
|
940
|
+
sql = self.handle_delete(table, where, order, limit)
|
941
|
+
|
942
|
+
# Execute SQL.
|
943
|
+
result = self.execute(sql, report=report, **kwdata)
|
944
|
+
|
945
|
+
return result
|
946
|
+
|
947
|
+
|
948
|
+
def copy(
|
949
|
+
self,
|
950
|
+
table: str,
|
951
|
+
where: str | None = None,
|
952
|
+
limit: int | str | tuple[int, int] | None = None,
|
953
|
+
report: bool | None = None,
|
954
|
+
**kwdata: Any
|
955
|
+
) -> Result:
|
956
|
+
"""
|
957
|
+
Execute inesrt SQL of copy records.
|
958
|
+
|
959
|
+
Parameters
|
960
|
+
----------
|
961
|
+
table : Table name.
|
962
|
+
where : Clause `WHERE` content, join as `WHERE str`.
|
963
|
+
limit : Clause `LIMIT` content.
|
964
|
+
- `int | str`: Join as `LIMIT int/str`.
|
965
|
+
- `tuple[int, int]`: Join as `LIMIT int, int`.
|
966
|
+
report : Whether report SQL execute information.
|
967
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
968
|
+
- `int`: Use this value.
|
969
|
+
kwdata : Keyword parameters for filling.
|
970
|
+
- `In 'WHERE' syntax`: Fill 'WHERE' syntax.
|
971
|
+
- `Not in 'WHERE' syntax`: Fill 'INSERT' and 'SELECT' syntax.
|
972
|
+
`str and first character is ':'`: Use this syntax.
|
973
|
+
`Any`: Use this value.
|
974
|
+
|
975
|
+
Returns
|
976
|
+
-------
|
977
|
+
Result object.
|
978
|
+
|
979
|
+
Examples
|
980
|
+
--------
|
981
|
+
Parameter `where` and `kwdata`.
|
982
|
+
>>> where = '`id` IN :ids'
|
983
|
+
>>> ids = (1, 2, 3)
|
984
|
+
>>> result = Database.execute.copy('table', where, 2, ids=ids, id=None, time=':NOW()')
|
985
|
+
>>> print(result.rowcount)
|
986
|
+
2
|
987
|
+
"""
|
988
|
+
|
989
|
+
# Handle parameter.
|
990
|
+
sql = self.handle_copy(table, where, limit, **kwdata)
|
991
|
+
|
992
|
+
# Execute SQL.
|
993
|
+
result = self.execute(sql, report=report, **kwdata)
|
994
|
+
|
995
|
+
return result
|
996
|
+
|
997
|
+
|
998
|
+
def count(
|
999
|
+
self,
|
1000
|
+
table: str,
|
1001
|
+
where: str | None = None,
|
1002
|
+
report: bool | None = None,
|
1003
|
+
**kwdata: Any
|
1004
|
+
) -> int:
|
1005
|
+
"""
|
1006
|
+
Execute inesrt SQL of count records.
|
1007
|
+
|
1008
|
+
Parameters
|
1009
|
+
----------
|
1010
|
+
table : Table name.
|
1011
|
+
where : Match condition, `WHERE` clause content, join as `WHERE str`.
|
1012
|
+
- `None`: Match all.
|
1013
|
+
- `str`: Match condition.
|
1014
|
+
report : Whether report SQL execute information.
|
1015
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
1016
|
+
- `int`: Use this value.
|
1017
|
+
kwdata : Keyword parameters for filling.
|
1018
|
+
|
1019
|
+
Returns
|
1020
|
+
-------
|
1021
|
+
Record count.
|
1022
|
+
|
1023
|
+
Examples
|
1024
|
+
--------
|
1025
|
+
Parameter `where` and `kwdata`.
|
1026
|
+
>>> where = '`id` IN :ids'
|
1027
|
+
>>> ids = (1, 2)
|
1028
|
+
>>> result = Database.execute.count('table', where, ids=ids)
|
1029
|
+
>>> print(result)
|
1030
|
+
2
|
1031
|
+
"""
|
1032
|
+
|
1033
|
+
# Execute.
|
1034
|
+
result = self.select(table, '1', where=where, report=report, **kwdata)
|
1035
|
+
count = len(tuple(result))
|
1036
|
+
|
1037
|
+
return count
|
1038
|
+
|
1039
|
+
|
1040
|
+
def exist(
|
1041
|
+
self,
|
1042
|
+
table: str,
|
1043
|
+
where: str | None = None,
|
1044
|
+
report: bool | None = None,
|
1045
|
+
**kwdata: Any
|
1046
|
+
) -> bool:
|
1047
|
+
"""
|
1048
|
+
Execute inesrt SQL of Judge the exist of record.
|
1049
|
+
|
1050
|
+
Parameters
|
1051
|
+
----------
|
1052
|
+
table : Table name.
|
1053
|
+
where : Match condition, `WHERE` clause content, join as `WHERE str`.
|
1054
|
+
- `None`: Match all.
|
1055
|
+
- `str`: Match condition.
|
1056
|
+
report : Whether report SQL execute information.
|
1057
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
1058
|
+
- `int`: Use this value.
|
1059
|
+
kwdata : Keyword parameters for filling.
|
1060
|
+
|
1061
|
+
Returns
|
1062
|
+
-------
|
1063
|
+
Judged result.
|
1064
|
+
|
1065
|
+
Examples
|
1066
|
+
--------
|
1067
|
+
Parameter `where` and `kwdata`.
|
1068
|
+
>>> data = [{'id': 1}]
|
1069
|
+
>>> Database.execute.insert('table', data)
|
1070
|
+
>>> where = '`id` = :id_'
|
1071
|
+
>>> id_ = 1
|
1072
|
+
>>> result = Database.execute.exist('table', where, id_=id_)
|
1073
|
+
>>> print(result)
|
1074
|
+
True
|
1075
|
+
"""
|
1076
|
+
|
1077
|
+
# Execute.
|
1078
|
+
result = self.count(table, where, report, **kwdata)
|
1079
|
+
|
1080
|
+
# Judge.
|
1081
|
+
judge = result != 0
|
1082
|
+
|
1083
|
+
return judge
|
1084
|
+
|
1085
|
+
|
1086
|
+
def generator(
|
1087
|
+
self,
|
1088
|
+
sql: str | TextClause,
|
1089
|
+
data: TableData,
|
1090
|
+
report: bool | None = None,
|
1091
|
+
**kwdata: Any
|
1092
|
+
) -> Generator[Result, Any, None]:
|
1093
|
+
"""
|
1094
|
+
Return a generator that can execute SQL.
|
1095
|
+
|
1096
|
+
Parameters
|
1097
|
+
----------
|
1098
|
+
sql : SQL in method `sqlalchemy.text` format, or `TextClause` object.
|
1099
|
+
data : Data set for filling.
|
1100
|
+
report : Whether report SQL execute information.
|
1101
|
+
- `None`: Use attribute `default_report`.
|
1102
|
+
- `bool`: Use this value.
|
1103
|
+
kwdata : Keyword parameters for filling.
|
1104
|
+
|
1105
|
+
Returns
|
1106
|
+
-------
|
1107
|
+
Generator.
|
1108
|
+
"""
|
1109
|
+
|
1110
|
+
# Instance.
|
1111
|
+
func_generator = FunctionGenerator(
|
1112
|
+
self.execute,
|
1113
|
+
sql=sql,
|
1114
|
+
report=report,
|
1115
|
+
**kwdata
|
1116
|
+
)
|
1117
|
+
|
1118
|
+
# Add.
|
1119
|
+
for row in data:
|
1120
|
+
func_generator(**row)
|
1121
|
+
|
1122
|
+
# Create.
|
1123
|
+
generator = func_generator.generator()
|
1124
|
+
|
1125
|
+
return generator
|
1126
|
+
|
1127
|
+
|
1128
|
+
@overload
|
1129
|
+
def sleep(self, report: bool | None = None) -> int: ...
|
1130
|
+
|
1131
|
+
@overload
|
1132
|
+
def sleep(self, second: int, report: bool | None = None) -> int: ...
|
1133
|
+
|
1134
|
+
@overload
|
1135
|
+
def sleep(self, low: int = 0, high: int = 10, report: bool | None = None) -> int: ...
|
1136
|
+
|
1137
|
+
@overload
|
1138
|
+
def sleep(self, *thresholds: float, report: bool | None = None) -> float: ...
|
1139
|
+
|
1140
|
+
@overload
|
1141
|
+
def sleep(self, *thresholds: float, precision: Literal[0], report: bool | None = None) -> int: ...
|
1142
|
+
|
1143
|
+
@overload
|
1144
|
+
def sleep(self, *thresholds: float, precision: int, report: bool | None = None) -> float: ...
|
1145
|
+
|
1146
|
+
def sleep(self, *thresholds: float, precision: int | None = None, report: bool | None = None) -> float:
|
1147
|
+
"""
|
1148
|
+
Let the database wait random seconds.
|
1149
|
+
|
1150
|
+
Parameters
|
1151
|
+
----------
|
1152
|
+
thresholds : Low and high thresholds of random range, range contains thresholds.
|
1153
|
+
- When `length is 0`, then low and high thresholds is `0` and `10`.
|
1154
|
+
- When `length is 1`, then low and high thresholds is `0` and `thresholds[0]`.
|
1155
|
+
- When `length is 2`, then low and high thresholds is `thresholds[0]` and `thresholds[1]`.
|
1156
|
+
precision : Precision of random range, that is maximum decimal digits of return value.
|
1157
|
+
- `None`: Set to Maximum decimal digits of element of parameter `thresholds`.
|
1158
|
+
- `int`: Set to this value.
|
1159
|
+
report : Whether report SQL execute information.
|
1160
|
+
- `None`: Use attribute `default_report`.
|
1161
|
+
- `bool`: Use this value.
|
1162
|
+
|
1163
|
+
Returns
|
1164
|
+
-------
|
1165
|
+
Random seconds.
|
1166
|
+
- When parameters `precision` is `0`, then return int.
|
1167
|
+
- When parameters `precision` is `greater than 0`, then return float.
|
1168
|
+
"""
|
1169
|
+
|
1170
|
+
# Handle parameter.
|
1171
|
+
if len(thresholds) == 1:
|
1172
|
+
second = thresholds[0]
|
1173
|
+
else:
|
1174
|
+
second = randn(*thresholds, precision=precision)
|
1175
|
+
|
1176
|
+
# Sleep.
|
1177
|
+
sql = f'SELECT SLEEP({second})'
|
1178
|
+
self.execute(sql, report=report)
|
1179
|
+
|
1180
|
+
return second
|
1181
|
+
|
1182
|
+
|
1183
|
+
class DatabaseExecuteAsync(DatabaseExecuteBase):
|
1184
|
+
"""
|
1185
|
+
Asynchronous database execute type.
|
1186
|
+
"""
|
1187
|
+
|
1188
|
+
|
1189
|
+
def __init__(self, dbconn: DatabaseConnectionAsync) -> None:
|
1190
|
+
"""
|
1191
|
+
Build instance attributes.
|
1192
|
+
|
1193
|
+
Parameters
|
1194
|
+
----------
|
1195
|
+
dbconn : `DatabaseConnectionAsync` instance.
|
1196
|
+
"""
|
1197
|
+
|
1198
|
+
# Build.
|
1199
|
+
self.dbconn = dbconn
|
1200
|
+
|
1201
|
+
|
1202
|
+
async def execute(
|
1203
|
+
self,
|
1204
|
+
sql: str | TextClause,
|
1205
|
+
data: TableData | None = None,
|
1206
|
+
report: bool | None = None,
|
1207
|
+
**kwdata: Any
|
1208
|
+
) -> Result:
|
1209
|
+
"""
|
1210
|
+
Asynchronous execute SQL.
|
1211
|
+
|
1212
|
+
Parameters
|
1213
|
+
----------
|
1214
|
+
sql : SQL in method `sqlalchemy.text` format, or `TextClause` object.
|
1215
|
+
data : Data set for filling.
|
1216
|
+
report : Whether report SQL execute information.
|
1217
|
+
- `None`: Use attribute `default_report`.
|
1218
|
+
- `bool`: Use this value.
|
1219
|
+
kwdata : Keyword parameters for filling.
|
1220
|
+
|
1221
|
+
Returns
|
1222
|
+
-------
|
1223
|
+
Result object.
|
1224
|
+
"""
|
1225
|
+
|
1226
|
+
# Handle parameter.
|
1227
|
+
sql, data, report = self.handle_execute(sql, data, report, **kwdata)
|
1228
|
+
|
1229
|
+
# Transaction.
|
1230
|
+
await self.dbconn.get_begin()
|
1231
|
+
|
1232
|
+
# Execute.
|
1233
|
+
|
1234
|
+
## Report.
|
1235
|
+
if report:
|
1236
|
+
tm = TimeMark()
|
1237
|
+
tm()
|
1238
|
+
result = await self.dbconn.conn.execute(sql, data)
|
1239
|
+
tm()
|
1240
|
+
|
1241
|
+
### Generate report.
|
1242
|
+
start_time = tm.records[0]['datetime']
|
1243
|
+
spend_time: Timedelta = tm.records[1]['timedelta']
|
1244
|
+
end_time = tm.records[1]['datetime']
|
1245
|
+
start_str = time_to(start_time, True)[:-3]
|
1246
|
+
spend_str = time_to(spend_time, True)[:-3]
|
1247
|
+
end_str = time_to(end_time, True)[:-3]
|
1248
|
+
report_runtime = 'Start: %s -> Spend: %ss -> End: %s' % (
|
1249
|
+
start_str,
|
1250
|
+
spend_str,
|
1251
|
+
end_str
|
1252
|
+
)
|
1253
|
+
report_info = (
|
1254
|
+
f'{report_runtime}\n'
|
1255
|
+
f'Row Count: {result.rowcount}'
|
1256
|
+
)
|
1257
|
+
sqls = [
|
1258
|
+
sql_part.strip()
|
1259
|
+
for sql_part in sql.text.split(';')
|
1260
|
+
if sql_part != ''
|
1261
|
+
]
|
1262
|
+
|
1263
|
+
if data == []:
|
1264
|
+
echo(report_info, *sqls, title='SQL')
|
1265
|
+
else:
|
1266
|
+
echo(report_info, *sqls, data, title='SQL')
|
1267
|
+
|
1268
|
+
## Not report.
|
1269
|
+
else:
|
1270
|
+
result = await self.dbconn.conn.execute(sql, data)
|
1271
|
+
|
1272
|
+
# Automatic commit.
|
1273
|
+
if self.dbconn.autocommit:
|
1274
|
+
await self.dbconn.commit()
|
1275
|
+
|
1276
|
+
return result
|
1277
|
+
|
1278
|
+
|
1279
|
+
__call__ = execute
|
1280
|
+
|
1281
|
+
|
1282
|
+
async def select(
|
1283
|
+
self,
|
1284
|
+
table: str,
|
1285
|
+
fields: str | Iterable[str] | None = None,
|
1286
|
+
where: str | None = None,
|
1287
|
+
group: str | None = None,
|
1288
|
+
having: str | None = None,
|
1289
|
+
order: str | None = None,
|
1290
|
+
limit: int | str | tuple[int, int] | None = None,
|
1291
|
+
report: bool | None = None,
|
1292
|
+
**kwdata: Any
|
1293
|
+
) -> Result:
|
1294
|
+
"""
|
1295
|
+
Asynchronous execute select SQL.
|
1296
|
+
|
1297
|
+
Parameters
|
1298
|
+
----------
|
1299
|
+
table : Table name.
|
1300
|
+
fields : Select clause content.
|
1301
|
+
- `None`: Is `SELECT *`.
|
1302
|
+
- `str`: Join as `SELECT str`.
|
1303
|
+
- `Iterable[str]`, Join as `SELECT ``str``: ...`.
|
1304
|
+
`str and first character is ':'`: Use this syntax.
|
1305
|
+
`str`: Use this field.
|
1306
|
+
where : Clause `WHERE` content, join as `WHERE str`.
|
1307
|
+
group : Clause `GROUP BY` content, join as `GROUP BY str`.
|
1308
|
+
having : Clause `HAVING` content, join as `HAVING str`.
|
1309
|
+
order : Clause `ORDER BY` content, join as `ORDER BY str`.
|
1310
|
+
limit : Clause `LIMIT` content.
|
1311
|
+
- `int | str`: Join as `LIMIT int/str`.
|
1312
|
+
- `tuple[int, int]`: Join as `LIMIT int, int`.
|
1313
|
+
report : Whether report SQL execute information.
|
1314
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
1315
|
+
- `int`: Use this value.
|
1316
|
+
kwdata : Keyword parameters for filling.
|
1317
|
+
|
1318
|
+
Returns
|
1319
|
+
-------
|
1320
|
+
Result object.
|
1321
|
+
|
1322
|
+
Examples
|
1323
|
+
--------
|
1324
|
+
Parameter `fields`.
|
1325
|
+
>>> fields = ['id', ':`id` + 1 AS `id_`']
|
1326
|
+
>>> result = Database.execute.select('table', fields)
|
1327
|
+
>>> print(result.to_table())
|
1328
|
+
[{'id': 1, 'id_': 2}, ...]
|
1329
|
+
|
1330
|
+
Parameter `kwdata`.
|
1331
|
+
>>> fields = '`id`, `id` + :value AS `id_`'
|
1332
|
+
>>> result = Database.execute.select('table', fields, value=1)
|
1333
|
+
>>> print(result.to_table())
|
1334
|
+
[{'id': 1, 'id_': 2}, ...]
|
1335
|
+
"""
|
1336
|
+
|
1337
|
+
# Handle parameter.
|
1338
|
+
sql = self.handle_select(table, fields, where, group, having, order, limit)
|
1339
|
+
|
1340
|
+
# Execute SQL.
|
1341
|
+
result = await self.execute(sql, report=report, **kwdata)
|
1342
|
+
|
1343
|
+
return result
|
1344
|
+
|
1345
|
+
|
1346
|
+
async def insert(
|
1347
|
+
self,
|
1348
|
+
table: str,
|
1349
|
+
data: TableData,
|
1350
|
+
duplicate: Literal['ignore', 'update'] | Container[str] | None = None,
|
1351
|
+
report: bool | None = None,
|
1352
|
+
**kwdata: Any
|
1353
|
+
) -> Result:
|
1354
|
+
"""
|
1355
|
+
Asynchronous execute insert SQL.
|
1356
|
+
|
1357
|
+
Parameters
|
1358
|
+
----------
|
1359
|
+
table : Table name.
|
1360
|
+
data : Insert data.
|
1361
|
+
duplicate : Handle method when constraint error.
|
1362
|
+
- `None`: Not handled.
|
1363
|
+
- `ignore`: Use `UPDATE IGNORE INTO` clause.
|
1364
|
+
- `update`: Use `ON DUPLICATE KEY UPDATE` clause and update all fields.
|
1365
|
+
- `Container[str]`: Use `ON DUPLICATE KEY UPDATE` clause and update this fields.
|
1366
|
+
report : Whether report SQL execute information.
|
1367
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
1368
|
+
- `int`: Use this value.
|
1369
|
+
kwdata : Keyword parameters for filling.
|
1370
|
+
- `str and first character is ':'`: Use this syntax.
|
1371
|
+
- `Any`: Use this value.
|
1372
|
+
|
1373
|
+
Returns
|
1374
|
+
-------
|
1375
|
+
Result object.
|
1376
|
+
|
1377
|
+
Examples
|
1378
|
+
--------
|
1379
|
+
Parameter `data` and `kwdata`.
|
1380
|
+
>>> data = [{'key': 'a'}, {'key': 'b'}]
|
1381
|
+
>>> kwdata = {'value1': 1, 'value2': ':(SELECT 2)'}
|
1382
|
+
>>> result = Database.execute.insert('table', data, **kwdata)
|
1383
|
+
>>> print(result.rowcount)
|
1384
|
+
2
|
1385
|
+
>>> result = Database.execute.select('table')
|
1386
|
+
>>> print(result.to_table())
|
1387
|
+
[{'key': 'a', 'value1': 1, 'value2': 2}, {'key': 'b', 'value1': 1, 'value2': 2}]
|
1388
|
+
"""
|
1389
|
+
|
1390
|
+
# Handle parameter.
|
1391
|
+
sql, kwdata = self.handle_insert(table, data, duplicate, **kwdata)
|
1392
|
+
|
1393
|
+
# Execute SQL.
|
1394
|
+
result = await self.execute(sql, data, report, **kwdata)
|
1395
|
+
|
1396
|
+
return result
|
1397
|
+
|
1398
|
+
|
1399
|
+
async def update(
|
1400
|
+
self,
|
1401
|
+
table: str,
|
1402
|
+
data: TableData,
|
1403
|
+
where_fields: str | Iterable[str] | None = None,
|
1404
|
+
report: bool | None = None,
|
1405
|
+
**kwdata: Any
|
1406
|
+
) -> Result:
|
1407
|
+
"""
|
1408
|
+
Asynchronous execute update SQL.
|
1409
|
+
|
1410
|
+
Parameters
|
1411
|
+
----------
|
1412
|
+
table : Table name.
|
1413
|
+
data : Update data, clause `SET` and `WHERE` and `ORDER BY` and `LIMIT` content.
|
1414
|
+
- `Key`: Table field.
|
1415
|
+
`literal['order']`: Clause `ORDER BY` content, join as `ORDER BY str`.
|
1416
|
+
`literal['limit']`: Clause `LIMIT` content, join as `LIMIT str`.
|
1417
|
+
`Other`: Clause `SET` and `WHERE` content.
|
1418
|
+
- `Value`: Table value.
|
1419
|
+
`list | tuple`: Join as `field IN :str`.
|
1420
|
+
`Any`: Join as `field = :str`.
|
1421
|
+
where_fields : Clause `WHERE` content fields.
|
1422
|
+
- `None`: The first key value pair of each item is judged.
|
1423
|
+
- `str`: This key value pair of each item is judged.
|
1424
|
+
- `Iterable[str]`: Multiple judged, `and`: relationship.
|
1425
|
+
report : Whether report SQL execute information.
|
1426
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
1427
|
+
- `int`: Use this value.
|
1428
|
+
kwdata : Keyword parameters for filling.
|
1429
|
+
- `str and first character is ':'`: Use this syntax.
|
1430
|
+
- `Any`: Use this value.
|
1431
|
+
|
1432
|
+
Returns
|
1433
|
+
-------
|
1434
|
+
Result object.
|
1435
|
+
|
1436
|
+
Examples
|
1437
|
+
--------
|
1438
|
+
Parameter `data` and `kwdata`.
|
1439
|
+
>>> data = [{'key': 'a'}, {'key': 'b'}]
|
1440
|
+
>>> kwdata = {'value': 1, 'name': ':`key`'}
|
1441
|
+
>>> result = Database.execute.update('table', data, **kwdata)
|
1442
|
+
>>> print(result.rowcount)
|
1443
|
+
2
|
1444
|
+
>>> result = Database.execute.select('table')
|
1445
|
+
>>> print(result.to_table())
|
1446
|
+
[{'key': 'a', 'value': 1, 'name': 'a'}, {'key': 'b', 'value': 1, 'name': 'b'}]
|
1447
|
+
"""
|
1448
|
+
|
1449
|
+
# Handle parameter.
|
1450
|
+
sql, data = self.handle_update(table, data, where_fields, **kwdata)
|
1451
|
+
|
1452
|
+
# Execute SQL.
|
1453
|
+
result = await self.execute(sql, data, report)
|
1454
|
+
|
1455
|
+
return result
|
1456
|
+
|
1457
|
+
|
1458
|
+
async def delete(
|
1459
|
+
self,
|
1460
|
+
table: str,
|
1461
|
+
where: str | None = None,
|
1462
|
+
order: str | None = None,
|
1463
|
+
limit: int | str | None = None,
|
1464
|
+
report: bool | None = None,
|
1465
|
+
**kwdata: Any
|
1466
|
+
) -> Result:
|
1467
|
+
"""
|
1468
|
+
Asynchronous execute delete SQL.
|
1469
|
+
|
1470
|
+
Parameters
|
1471
|
+
----------
|
1472
|
+
table : Table name.
|
1473
|
+
where : Clause `WHERE` content, join as `WHERE str`.
|
1474
|
+
order : Clause `ORDER BY` content, join as `ORDER BY str`.
|
1475
|
+
limit : Clause `LIMIT` content, join as `LIMIT int/str`.
|
1476
|
+
report : Whether report SQL execute information.
|
1477
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
1478
|
+
- `int`: Use this value.
|
1479
|
+
kwdata : Keyword parameters for filling.
|
1480
|
+
|
1481
|
+
Returns
|
1482
|
+
-------
|
1483
|
+
Result object.
|
1484
|
+
|
1485
|
+
Examples
|
1486
|
+
--------
|
1487
|
+
Parameter `where` and `kwdata`.
|
1488
|
+
>>> where = '`id` IN :ids'
|
1489
|
+
>>> ids = (1, 2)
|
1490
|
+
>>> result = Database.execute.delete('table', where, ids=ids)
|
1491
|
+
>>> print(result.rowcount)
|
1492
|
+
2
|
1493
|
+
"""
|
1494
|
+
|
1495
|
+
# Handle parameter.
|
1496
|
+
sql = self.handle_delete(table, where, order, limit)
|
1497
|
+
|
1498
|
+
# Execute SQL.
|
1499
|
+
result = await self.execute(sql, report=report, **kwdata)
|
1500
|
+
|
1501
|
+
return result
|
1502
|
+
|
1503
|
+
|
1504
|
+
async def copy(
|
1505
|
+
self,
|
1506
|
+
table: str,
|
1507
|
+
where: str | None = None,
|
1508
|
+
limit: int | str | tuple[int, int] | None = None,
|
1509
|
+
report: bool | None = None,
|
1510
|
+
**kwdata: Any
|
1511
|
+
) -> Result:
|
1512
|
+
"""
|
1513
|
+
Asynchronous execute inesrt SQL of copy records.
|
1514
|
+
|
1515
|
+
Parameters
|
1516
|
+
----------
|
1517
|
+
table : Table name.
|
1518
|
+
where : Clause `WHERE` content, join as `WHERE str`.
|
1519
|
+
limit : Clause `LIMIT` content.
|
1520
|
+
- `int | str`: Join as `LIMIT int/str`.
|
1521
|
+
- `tuple[int, int]`: Join as `LIMIT int, int`.
|
1522
|
+
report : Whether report SQL execute information.
|
1523
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
1524
|
+
- `int`: Use this value.
|
1525
|
+
kwdata : Keyword parameters for filling.
|
1526
|
+
- `In 'WHERE' syntax`: Fill 'WHERE' syntax.
|
1527
|
+
- `Not in 'WHERE' syntax`: Fill 'INSERT' and 'SELECT' syntax.
|
1528
|
+
`str and first character is ':'`: Use this syntax.
|
1529
|
+
`Any`: Use this value.
|
1530
|
+
|
1531
|
+
Returns
|
1532
|
+
-------
|
1533
|
+
Result object.
|
1534
|
+
|
1535
|
+
Examples
|
1536
|
+
--------
|
1537
|
+
Parameter `where` and `kwdata`.
|
1538
|
+
>>> where = '`id` IN :ids'
|
1539
|
+
>>> ids = (1, 2, 3)
|
1540
|
+
>>> result = Database.execute.copy('table', where, 2, ids=ids, id=None, time=':NOW()')
|
1541
|
+
>>> print(result.rowcount)
|
1542
|
+
2
|
1543
|
+
"""
|
1544
|
+
|
1545
|
+
# Handle parameter.
|
1546
|
+
sql = self.handle_copy(table, where, limit, **kwdata)
|
1547
|
+
|
1548
|
+
# Execute SQL.
|
1549
|
+
result = await self.execute(sql, report=report, **kwdata)
|
1550
|
+
|
1551
|
+
return result
|
1552
|
+
|
1553
|
+
|
1554
|
+
async def count(
|
1555
|
+
self,
|
1556
|
+
table: str,
|
1557
|
+
where: str | None = None,
|
1558
|
+
report: bool | None = None,
|
1559
|
+
**kwdata: Any
|
1560
|
+
) -> int:
|
1561
|
+
"""
|
1562
|
+
Asynchronous execute inesrt SQL of count records.
|
1563
|
+
|
1564
|
+
Parameters
|
1565
|
+
----------
|
1566
|
+
table : Table name.
|
1567
|
+
where : Match condition, `WHERE` clause content, join as `WHERE str`.
|
1568
|
+
- `None`: Match all.
|
1569
|
+
- `str`: Match condition.
|
1570
|
+
report : Whether report SQL execute information.
|
1571
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
1572
|
+
- `int`: Use this value.
|
1573
|
+
kwdata : Keyword parameters for filling.
|
1574
|
+
|
1575
|
+
Returns
|
1576
|
+
-------
|
1577
|
+
Record count.
|
1578
|
+
|
1579
|
+
Examples
|
1580
|
+
--------
|
1581
|
+
Parameter `where` and `kwdata`.
|
1582
|
+
>>> where = '`id` IN :ids'
|
1583
|
+
>>> ids = (1, 2)
|
1584
|
+
>>> result = Database.execute.count('table', where, ids=ids)
|
1585
|
+
>>> print(result)
|
1586
|
+
2
|
1587
|
+
"""
|
1588
|
+
|
1589
|
+
# Execute.
|
1590
|
+
result = await self.select(table, '1', where=where, report=report, **kwdata)
|
1591
|
+
count = len(tuple(result))
|
1592
|
+
|
1593
|
+
return count
|
1594
|
+
|
1595
|
+
|
1596
|
+
async def exist(
|
1597
|
+
self,
|
1598
|
+
table: str,
|
1599
|
+
where: str | None = None,
|
1600
|
+
report: bool | None = None,
|
1601
|
+
**kwdata: Any
|
1602
|
+
) -> bool:
|
1603
|
+
"""
|
1604
|
+
Asynchronous execute inesrt SQL of Judge the exist of record.
|
1605
|
+
|
1606
|
+
Parameters
|
1607
|
+
----------
|
1608
|
+
table : Table name.
|
1609
|
+
where : Match condition, `WHERE` clause content, join as `WHERE str`.
|
1610
|
+
- `None`: Match all.
|
1611
|
+
- `str`: Match condition.
|
1612
|
+
report : Whether report SQL execute information.
|
1613
|
+
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
1614
|
+
- `int`: Use this value.
|
1615
|
+
kwdata : Keyword parameters for filling.
|
1616
|
+
|
1617
|
+
Returns
|
1618
|
+
-------
|
1619
|
+
Judged result.
|
834
1620
|
|
835
1621
|
Examples
|
836
1622
|
--------
|
@@ -845,7 +1631,7 @@ class DatabaseExecute(DatabaseBase):
|
|
845
1631
|
"""
|
846
1632
|
|
847
1633
|
# Execute.
|
848
|
-
result = self.count(table, where, report, **kwdata)
|
1634
|
+
result = await self.count(table, where, report, **kwdata)
|
849
1635
|
|
850
1636
|
# Judge.
|
851
1637
|
judge = result != 0
|
@@ -853,15 +1639,15 @@ class DatabaseExecute(DatabaseBase):
|
|
853
1639
|
return judge
|
854
1640
|
|
855
1641
|
|
856
|
-
def generator(
|
1642
|
+
async def generator(
|
857
1643
|
self,
|
858
1644
|
sql: str | TextClause,
|
859
1645
|
data: TableData,
|
860
1646
|
report: bool | None = None,
|
861
1647
|
**kwdata: Any
|
862
|
-
) ->
|
1648
|
+
) -> AsyncGenerator[Result, Any]:
|
863
1649
|
"""
|
864
|
-
|
1650
|
+
Asynchronous return a generator that can execute SQL.
|
865
1651
|
|
866
1652
|
Parameters
|
867
1653
|
----------
|
@@ -874,7 +1660,7 @@ class DatabaseExecute(DatabaseBase):
|
|
874
1660
|
|
875
1661
|
Returns
|
876
1662
|
-------
|
877
|
-
|
1663
|
+
AsyncGenerator.
|
878
1664
|
"""
|
879
1665
|
|
880
1666
|
# Instance.
|
@@ -889,30 +1675,33 @@ class DatabaseExecute(DatabaseBase):
|
|
889
1675
|
for row in data:
|
890
1676
|
func_generator(**row)
|
891
1677
|
|
892
|
-
|
1678
|
+
# Create.
|
1679
|
+
agenerator = func_generator.agenerator()
|
1680
|
+
|
1681
|
+
return agenerator
|
893
1682
|
|
894
1683
|
|
895
1684
|
@overload
|
896
|
-
def sleep(self, report: bool | None = None) -> int: ...
|
1685
|
+
async def sleep(self, report: bool | None = None) -> int: ...
|
897
1686
|
|
898
1687
|
@overload
|
899
|
-
def sleep(self, second: int, report: bool | None = None) -> int: ...
|
1688
|
+
async def sleep(self, second: int, report: bool | None = None) -> int: ...
|
900
1689
|
|
901
1690
|
@overload
|
902
|
-
def sleep(self, low: int = 0, high: int = 10, report: bool | None = None) -> int: ...
|
1691
|
+
async def sleep(self, low: int = 0, high: int = 10, report: bool | None = None) -> int: ...
|
903
1692
|
|
904
1693
|
@overload
|
905
|
-
def sleep(self, *thresholds: float, report: bool | None = None) -> float: ...
|
1694
|
+
async def sleep(self, *thresholds: float, report: bool | None = None) -> float: ...
|
906
1695
|
|
907
1696
|
@overload
|
908
|
-
def sleep(self, *thresholds: float, precision: Literal[0], report: bool | None = None) -> int: ...
|
1697
|
+
async def sleep(self, *thresholds: float, precision: Literal[0], report: bool | None = None) -> int: ...
|
909
1698
|
|
910
1699
|
@overload
|
911
|
-
def sleep(self, *thresholds: float, precision: int, report: bool | None = None) -> float: ...
|
1700
|
+
async def sleep(self, *thresholds: float, precision: int, report: bool | None = None) -> float: ...
|
912
1701
|
|
913
|
-
def sleep(self, *thresholds: float, precision: int | None = None, report: bool | None = None) -> float:
|
1702
|
+
async def sleep(self, *thresholds: float, precision: int | None = None, report: bool | None = None) -> float:
|
914
1703
|
"""
|
915
|
-
|
1704
|
+
Asynchronous let the database wait random seconds.
|
916
1705
|
|
917
1706
|
Parameters
|
918
1707
|
----------
|
@@ -942,89 +1731,6 @@ class DatabaseExecute(DatabaseBase):
|
|
942
1731
|
|
943
1732
|
# Sleep.
|
944
1733
|
sql = f'SELECT SLEEP({second})'
|
945
|
-
self.execute(sql, report=report)
|
1734
|
+
await self.execute(sql, report=report)
|
946
1735
|
|
947
1736
|
return second
|
948
|
-
|
949
|
-
|
950
|
-
def handle_sql(self, sql: str | TextClause) -> TextClause:
|
951
|
-
"""
|
952
|
-
Handle SQL.
|
953
|
-
|
954
|
-
Parameters
|
955
|
-
----------
|
956
|
-
sql : SQL in method `sqlalchemy.text` format, or TextClause object.
|
957
|
-
|
958
|
-
Returns
|
959
|
-
-------
|
960
|
-
TextClause instance.
|
961
|
-
"""
|
962
|
-
|
963
|
-
# Handle parameter.
|
964
|
-
if type(sql) == TextClause:
|
965
|
-
sql = sql.text
|
966
|
-
|
967
|
-
# Handle.
|
968
|
-
sql = sql.strip()
|
969
|
-
if sql[-1] != ';':
|
970
|
-
sql += ';'
|
971
|
-
sql = sqlalchemy_text(sql)
|
972
|
-
|
973
|
-
return sql
|
974
|
-
|
975
|
-
|
976
|
-
def handle_data(
|
977
|
-
self,
|
978
|
-
data: list[dict],
|
979
|
-
sql: str | TextClause,
|
980
|
-
) -> list[dict]:
|
981
|
-
"""
|
982
|
-
Handle data based on the content of SQL.
|
983
|
-
|
984
|
-
Parameters
|
985
|
-
----------
|
986
|
-
data : Data set for filling.
|
987
|
-
sql : SQL in method `sqlalchemy.text` format, or TextClause object.
|
988
|
-
|
989
|
-
Returns
|
990
|
-
-------
|
991
|
-
Filled data.
|
992
|
-
"""
|
993
|
-
|
994
|
-
# Handle parameter.
|
995
|
-
if type(sql) == TextClause:
|
996
|
-
sql = sql.text
|
997
|
-
|
998
|
-
# Extract keys.
|
999
|
-
pattern = '(?<!\\\\):(\\w+)'
|
1000
|
-
sql_keys = findall(pattern, sql)
|
1001
|
-
|
1002
|
-
# Extract keys of syntax "in".
|
1003
|
-
pattern = '[iI][nN]\\s+(?<!\\\\):(\\w+)'
|
1004
|
-
sql_keys_in = findall(pattern, sql)
|
1005
|
-
|
1006
|
-
# Loop.
|
1007
|
-
for row in data:
|
1008
|
-
if row == {}:
|
1009
|
-
continue
|
1010
|
-
for key in sql_keys:
|
1011
|
-
value = row.get(key)
|
1012
|
-
|
1013
|
-
# Empty string.
|
1014
|
-
if value == '':
|
1015
|
-
value = None
|
1016
|
-
|
1017
|
-
# Convert.
|
1018
|
-
elif (
|
1019
|
-
type(value) in (list, dict)
|
1020
|
-
and key not in sql_keys_in
|
1021
|
-
):
|
1022
|
-
value = to_json(value)
|
1023
|
-
|
1024
|
-
# Enum.
|
1025
|
-
elif isinstance(type(value), EnumType):
|
1026
|
-
value = value.value
|
1027
|
-
|
1028
|
-
row[key] = value
|
1029
|
-
|
1030
|
-
return data
|