reydb 1.1.51__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 +186 -16
- reydb/rdb.py +111 -25
- reydb/rexec.py +1026 -264
- reydb/rfile.py +1 -1
- reydb/rinfo.py +10 -11
- reydb/rorm.py +450 -35
- {reydb-1.1.51.dist-info → reydb-1.1.53.dist-info}/METADATA +1 -1
- reydb-1.1.53.dist-info/RECORD +17 -0
- reydb-1.1.51.dist-info/RECORD +0 -17
- {reydb-1.1.51.dist-info → reydb-1.1.53.dist-info}/WHEEL +0 -0
- {reydb-1.1.51.dist-info → reydb-1.1.53.dist-info}/licenses/LICENSE +0 -0
reydb/rexec.py
CHANGED
@@ -9,26 +9,28 @@
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
|
12
|
-
from typing import Any, Literal
|
13
|
-
from collections.abc import Iterable, Generator, Container
|
14
|
-
from
|
15
|
-
from sqlalchemy import text as sqlalchemy_text
|
12
|
+
from typing import Any, Literal, overload
|
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
|
19
|
+
from reykit.rrand import randn
|
20
20
|
from reykit.rre import findall
|
21
21
|
from reykit.rstdout import echo
|
22
22
|
from reykit.rtable import TableData, Table
|
23
|
+
from reykit.rtime import TimeMark, time_to
|
23
24
|
from reykit.rwrap import wrap_runtime
|
24
25
|
|
25
|
-
from .rbase import DatabaseBase
|
26
|
-
from .rconn import DatabaseConnection
|
26
|
+
from .rbase import DatabaseBase, handle_sql, handle_data
|
27
|
+
from .rconn import DatabaseConnection, DatabaseConnectionAsync
|
27
28
|
|
28
29
|
|
29
30
|
__all__ = (
|
30
31
|
'Result',
|
31
|
-
'DatabaseExecute'
|
32
|
+
'DatabaseExecute',
|
33
|
+
'DatabaseExecuteAsync'
|
32
34
|
)
|
33
35
|
|
34
36
|
|
@@ -38,9 +40,9 @@ Result = Result_
|
|
38
40
|
monkey_sqlalchemy_row_index_field()
|
39
41
|
|
40
42
|
|
41
|
-
class
|
43
|
+
class DatabaseExecuteBase(DatabaseBase):
|
42
44
|
"""
|
43
|
-
Database execute type.
|
45
|
+
Database execute base type.
|
44
46
|
"""
|
45
47
|
|
46
48
|
|
@@ -57,15 +59,15 @@ class DatabaseExecute(DatabaseBase):
|
|
57
59
|
self.dbconn = dbconn
|
58
60
|
|
59
61
|
|
60
|
-
def
|
62
|
+
def handle_execute(
|
61
63
|
self,
|
62
64
|
sql: str | TextClause,
|
63
65
|
data: TableData | None = None,
|
64
66
|
report: bool | None = None,
|
65
67
|
**kwdata: Any
|
66
|
-
) ->
|
68
|
+
) -> tuple[TextClause, list[dict], bool]:
|
67
69
|
"""
|
68
|
-
|
70
|
+
Handle parameters before execute SQL.
|
69
71
|
|
70
72
|
Parameters
|
71
73
|
----------
|
@@ -78,12 +80,12 @@ class DatabaseExecute(DatabaseBase):
|
|
78
80
|
|
79
81
|
Returns
|
80
82
|
-------
|
81
|
-
|
83
|
+
Parameters `sql` and `data` and `report`.
|
82
84
|
"""
|
83
85
|
|
84
86
|
# Handle parameter.
|
85
87
|
report = get_first_notnone(report, self.dbconn.db.default_report)
|
86
|
-
sql =
|
88
|
+
sql = handle_sql(sql)
|
87
89
|
if data is None:
|
88
90
|
if kwdata == {}:
|
89
91
|
data = []
|
@@ -94,43 +96,12 @@ class DatabaseExecute(DatabaseBase):
|
|
94
96
|
data = data_table.to_table()
|
95
97
|
for row in data:
|
96
98
|
row.update(kwdata)
|
97
|
-
data =
|
98
|
-
|
99
|
-
# Execute.
|
100
|
-
|
101
|
-
## Report.
|
102
|
-
if report:
|
103
|
-
execute = wrap_runtime(self.conn.execute, to_return=True)
|
104
|
-
result, report_runtime, *_ = execute(sql, data)
|
105
|
-
report_info = (
|
106
|
-
f'{report_runtime}\n'
|
107
|
-
f'Row Count: {result.rowcount}'
|
108
|
-
)
|
109
|
-
sqls = [
|
110
|
-
sql_part.strip()
|
111
|
-
for sql_part in sql.text.split(';')
|
112
|
-
if sql_part != ''
|
113
|
-
]
|
114
|
-
if data == []:
|
115
|
-
echo(report_info, *sqls, title='SQL')
|
116
|
-
else:
|
117
|
-
echo(report_info, *sqls, data, title='SQL')
|
118
|
-
|
119
|
-
## Not report.
|
120
|
-
else:
|
121
|
-
result = self.dbconn.conn.execute(sql, data)
|
122
|
-
|
123
|
-
# Automatic commit.
|
124
|
-
if self.dbconn.autocommit:
|
125
|
-
self.dbconn.conn.commit()
|
126
|
-
|
127
|
-
return result
|
128
|
-
|
99
|
+
data = handle_data(data, sql)
|
129
100
|
|
130
|
-
|
101
|
+
return sql, data, report
|
131
102
|
|
132
103
|
|
133
|
-
def
|
104
|
+
def handle_select(
|
134
105
|
self,
|
135
106
|
table: str,
|
136
107
|
fields: str | Iterable[str] | None = None,
|
@@ -138,12 +109,10 @@ class DatabaseExecute(DatabaseBase):
|
|
138
109
|
group: str | None = None,
|
139
110
|
having: str | None = None,
|
140
111
|
order: str | None = None,
|
141
|
-
limit: int | str | tuple[int, int] | None = None
|
142
|
-
|
143
|
-
**kwdata: Any
|
144
|
-
) -> Result:
|
112
|
+
limit: int | str | tuple[int, int] | None = None
|
113
|
+
) -> str:
|
145
114
|
"""
|
146
|
-
|
115
|
+
Handle parameters before execute select SQL.
|
147
116
|
|
148
117
|
Parameters
|
149
118
|
----------
|
@@ -161,28 +130,10 @@ class DatabaseExecute(DatabaseBase):
|
|
161
130
|
limit : Clause `LIMIT` content.
|
162
131
|
- `int | str`: Join as `LIMIT int/str`.
|
163
132
|
- `tuple[int, int]`: Join as `LIMIT int, int`.
|
164
|
-
report : Whether report SQL execute information.
|
165
|
-
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
166
|
-
- `int`: Use this value.
|
167
|
-
kwdata : Keyword parameters for filling.
|
168
133
|
|
169
134
|
Returns
|
170
135
|
-------
|
171
|
-
|
172
|
-
|
173
|
-
Examples
|
174
|
-
--------
|
175
|
-
Parameter `fields`.
|
176
|
-
>>> fields = ['id', ':`id` + 1 AS `id_`']
|
177
|
-
>>> result = Database.execute.select('table', fields)
|
178
|
-
>>> print(result.to_table())
|
179
|
-
[{'id': 1, 'id_': 2}, ...]
|
180
|
-
|
181
|
-
Parameter `kwdata`.
|
182
|
-
>>> fields = '`id`, `id` + :value AS `id_`'
|
183
|
-
>>> result = Database.execute.select('table', fields, value=1)
|
184
|
-
>>> print(result.to_table())
|
185
|
-
[{'id': 1, 'id_': 2}, ...]
|
136
|
+
Parameters `sql`.
|
186
137
|
"""
|
187
138
|
|
188
139
|
# Generate SQL.
|
@@ -244,22 +195,18 @@ class DatabaseExecute(DatabaseBase):
|
|
244
195
|
## Join sql part.
|
245
196
|
sql = '\n'.join(sql_list)
|
246
197
|
|
247
|
-
|
248
|
-
result = self.execute(sql, report=report, **kwdata)
|
249
|
-
|
250
|
-
return result
|
198
|
+
return sql
|
251
199
|
|
252
200
|
|
253
|
-
def
|
201
|
+
def handle_insert(
|
254
202
|
self,
|
255
203
|
table: str,
|
256
204
|
data: TableData,
|
257
205
|
duplicate: Literal['ignore', 'update'] | Container[str] | None = None,
|
258
|
-
report: bool | None = None,
|
259
206
|
**kwdata: Any
|
260
207
|
) -> Result:
|
261
208
|
"""
|
262
|
-
|
209
|
+
Handle parameters before execute insert SQL.
|
263
210
|
|
264
211
|
Parameters
|
265
212
|
----------
|
@@ -270,28 +217,13 @@ class DatabaseExecute(DatabaseBase):
|
|
270
217
|
- `ignore`: Use `UPDATE IGNORE INTO` clause.
|
271
218
|
- `update`: Use `ON DUPLICATE KEY UPDATE` clause and update all fields.
|
272
219
|
- `Container[str]`: Use `ON DUPLICATE KEY UPDATE` clause and update this fields.
|
273
|
-
report : Whether report SQL execute information.
|
274
|
-
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
275
|
-
- `int`: Use this value.
|
276
220
|
kwdata : Keyword parameters for filling.
|
277
221
|
- `str and first character is ':'`: Use this syntax.
|
278
222
|
- `Any`: Use this value.
|
279
223
|
|
280
224
|
Returns
|
281
225
|
-------
|
282
|
-
|
283
|
-
|
284
|
-
Examples
|
285
|
-
--------
|
286
|
-
Parameter `data` and `kwdata`.
|
287
|
-
>>> data = [{'key': 'a'}, {'key': 'b'}]
|
288
|
-
>>> kwdata = {'value1': 1, 'value2': ':(SELECT 2)'}
|
289
|
-
>>> result = Database.execute.insert('table', data, **kwdata)
|
290
|
-
>>> print(result.rowcount)
|
291
|
-
2
|
292
|
-
>>> result = Database.execute.select('table')
|
293
|
-
>>> print(result.to_table())
|
294
|
-
[{'key': 'a', 'value1': 1, 'value2': 2}, {'key': 'b', 'value1': 1, 'value2': 2}]
|
226
|
+
Parameters `sql` and `kwdata`.
|
295
227
|
"""
|
296
228
|
|
297
229
|
# Handle parameter.
|
@@ -394,22 +326,18 @@ class DatabaseExecute(DatabaseBase):
|
|
394
326
|
f' {update_content}'
|
395
327
|
)
|
396
328
|
|
397
|
-
|
398
|
-
result = self.execute(sql, data, report, **kwdata_replace)
|
399
|
-
|
400
|
-
return result
|
329
|
+
return sql, kwdata_replace
|
401
330
|
|
402
331
|
|
403
|
-
def
|
332
|
+
def handle_update(
|
404
333
|
self,
|
405
334
|
table: str,
|
406
335
|
data: TableData,
|
407
336
|
where_fields: str | Iterable[str] | None = None,
|
408
|
-
report: bool | None = None,
|
409
337
|
**kwdata: Any
|
410
338
|
) -> Result:
|
411
339
|
"""
|
412
|
-
|
340
|
+
Execute update SQL.
|
413
341
|
|
414
342
|
Parameters
|
415
343
|
----------
|
@@ -426,28 +354,13 @@ class DatabaseExecute(DatabaseBase):
|
|
426
354
|
- `None`: The first key value pair of each item is judged.
|
427
355
|
- `str`: This key value pair of each item is judged.
|
428
356
|
- `Iterable[str]`: Multiple judged, `and`: relationship.
|
429
|
-
report : Whether report SQL execute information.
|
430
|
-
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
431
|
-
- `int`: Use this value.
|
432
357
|
kwdata : Keyword parameters for filling.
|
433
358
|
- `str and first character is ':'`: Use this syntax.
|
434
359
|
- `Any`: Use this value.
|
435
360
|
|
436
361
|
Returns
|
437
362
|
-------
|
438
|
-
|
439
|
-
|
440
|
-
Examples
|
441
|
-
--------
|
442
|
-
Parameter `data` and `kwdata`.
|
443
|
-
>>> data = [{'key': 'a'}, {'key': 'b'}]
|
444
|
-
>>> kwdata = {'value': 1, 'name': ':`key`'}
|
445
|
-
>>> result = Database.execute.update('table', data, **kwdata)
|
446
|
-
>>> print(result.rowcount)
|
447
|
-
2
|
448
|
-
>>> result = Database.execute.select('table')
|
449
|
-
>>> print(result.to_table())
|
450
|
-
[{'key': 'a', 'value': 1, 'name': 'a'}, {'key': 'b', 'value': 1, 'name': 'b'}]
|
363
|
+
Parameters `sql` and `data`.
|
451
364
|
"""
|
452
365
|
|
453
366
|
# Handle parameter.
|
@@ -553,23 +466,18 @@ class DatabaseExecute(DatabaseBase):
|
|
553
466
|
## Join sqls.
|
554
467
|
sqls = ';\n'.join(sqls_list)
|
555
468
|
|
556
|
-
|
557
|
-
result = self.execute(sqls, data_flatten, report)
|
558
|
-
|
559
|
-
return result
|
469
|
+
return sqls, data_flatten
|
560
470
|
|
561
471
|
|
562
|
-
def
|
472
|
+
def handle_delete(
|
563
473
|
self,
|
564
474
|
table: str,
|
565
475
|
where: str | None = None,
|
566
476
|
order: str | None = None,
|
567
|
-
limit: int | str | None = None
|
568
|
-
report: bool | None = None,
|
569
|
-
**kwdata: Any
|
477
|
+
limit: int | str | None = None
|
570
478
|
) -> Result:
|
571
479
|
"""
|
572
|
-
|
480
|
+
Execute delete SQL.
|
573
481
|
|
574
482
|
Parameters
|
575
483
|
----------
|
@@ -577,23 +485,10 @@ class DatabaseExecute(DatabaseBase):
|
|
577
485
|
where : Clause `WHERE` content, join as `WHERE str`.
|
578
486
|
order : Clause `ORDER BY` content, join as `ORDER BY str`.
|
579
487
|
limit : Clause `LIMIT` content, join as `LIMIT int/str`.
|
580
|
-
report : Whether report SQL execute information.
|
581
|
-
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
582
|
-
- `int`: Use this value.
|
583
|
-
kwdata : Keyword parameters for filling.
|
584
488
|
|
585
489
|
Returns
|
586
490
|
-------
|
587
|
-
|
588
|
-
|
589
|
-
Examples
|
590
|
-
--------
|
591
|
-
Parameter `where` and `kwdata`.
|
592
|
-
>>> where = '`id` IN :ids'
|
593
|
-
>>> ids = (1, 2)
|
594
|
-
>>> result = Database.execute.delete('table', where, ids=ids)
|
595
|
-
>>> print(result.rowcount)
|
596
|
-
2
|
491
|
+
Parameter `sql`.
|
597
492
|
"""
|
598
493
|
|
599
494
|
# Generate SQL.
|
@@ -621,22 +516,18 @@ class DatabaseExecute(DatabaseBase):
|
|
621
516
|
## Join sqls.
|
622
517
|
sqls = '\n'.join(sqls)
|
623
518
|
|
624
|
-
|
625
|
-
result = self.execute(sqls, report=report, **kwdata)
|
626
|
-
|
627
|
-
return result
|
519
|
+
return sqls
|
628
520
|
|
629
521
|
|
630
|
-
def
|
522
|
+
def handle_copy(
|
631
523
|
self,
|
632
524
|
table: str,
|
633
525
|
where: str | None = None,
|
634
526
|
limit: int | str | tuple[int, int] | None = None,
|
635
|
-
report: bool | None = None,
|
636
527
|
**kwdata: Any
|
637
528
|
) -> Result:
|
638
529
|
"""
|
639
|
-
|
530
|
+
Execute inesrt SQL of copy records.
|
640
531
|
|
641
532
|
Parameters
|
642
533
|
----------
|
@@ -645,9 +536,6 @@ class DatabaseExecute(DatabaseBase):
|
|
645
536
|
limit : Clause `LIMIT` content.
|
646
537
|
- `int | str`: Join as `LIMIT int/str`.
|
647
538
|
- `tuple[int, int]`: Join as `LIMIT int, int`.
|
648
|
-
report : Whether report SQL execute information.
|
649
|
-
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
650
|
-
- `int`: Use this value.
|
651
539
|
kwdata : Keyword parameters for filling.
|
652
540
|
- `In 'WHERE' syntax`: Fill 'WHERE' syntax.
|
653
541
|
- `Not in 'WHERE' syntax`: Fill 'INSERT' and 'SELECT' syntax.
|
@@ -656,16 +544,7 @@ class DatabaseExecute(DatabaseBase):
|
|
656
544
|
|
657
545
|
Returns
|
658
546
|
-------
|
659
|
-
|
660
|
-
|
661
|
-
Examples
|
662
|
-
--------
|
663
|
-
Parameter `where` and `kwdata`.
|
664
|
-
>>> where = '`id` IN :ids'
|
665
|
-
>>> ids = (1, 2, 3)
|
666
|
-
>>> result = Database.execute.copy('table', where, 2, ids=ids, id=None, time=':NOW()')
|
667
|
-
>>> print(result.rowcount)
|
668
|
-
2
|
547
|
+
Parameters `sql`.
|
669
548
|
"""
|
670
549
|
|
671
550
|
# Handle parameter.
|
@@ -758,70 +637,123 @@ class DatabaseExecute(DatabaseBase):
|
|
758
637
|
## Join.
|
759
638
|
sql = '\n'.join(sqls)
|
760
639
|
|
761
|
-
|
762
|
-
result = self.execute(sql, report=report, **kwdata)
|
640
|
+
return sql
|
763
641
|
|
764
|
-
|
642
|
+
|
643
|
+
class DatabaseExecute(DatabaseExecuteBase):
|
644
|
+
"""
|
645
|
+
Database execute type.
|
646
|
+
"""
|
765
647
|
|
766
648
|
|
767
|
-
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(
|
768
663
|
self,
|
769
|
-
|
770
|
-
|
664
|
+
sql: str | TextClause,
|
665
|
+
data: TableData | None = None,
|
771
666
|
report: bool | None = None,
|
772
667
|
**kwdata: Any
|
773
|
-
) ->
|
668
|
+
) -> Result:
|
774
669
|
"""
|
775
|
-
|
670
|
+
Execute SQL.
|
776
671
|
|
777
672
|
Parameters
|
778
673
|
----------
|
779
|
-
|
780
|
-
|
781
|
-
- `None`: Match all.
|
782
|
-
- `str`: Match condition.
|
674
|
+
sql : SQL in method `sqlalchemy.text` format, or `TextClause` object.
|
675
|
+
data : Data set for filling.
|
783
676
|
report : Whether report SQL execute information.
|
784
|
-
- `None
|
785
|
-
- `
|
677
|
+
- `None`: Use attribute `default_report`.
|
678
|
+
- `bool`: Use this value.
|
786
679
|
kwdata : Keyword parameters for filling.
|
787
680
|
|
788
681
|
Returns
|
789
682
|
-------
|
790
|
-
|
791
|
-
|
792
|
-
Examples
|
793
|
-
--------
|
794
|
-
Parameter `where` and `kwdata`.
|
795
|
-
>>> where = '`id` IN :ids'
|
796
|
-
>>> ids = (1, 2)
|
797
|
-
>>> result = Database.execute.count('table', where, ids=ids)
|
798
|
-
>>> print(result)
|
799
|
-
2
|
683
|
+
Result object.
|
800
684
|
"""
|
801
685
|
|
686
|
+
# Handle parameter.
|
687
|
+
sql, data, report = self.handle_execute(sql, data, report, **kwdata)
|
688
|
+
|
689
|
+
# Transaction.
|
690
|
+
self.dbconn.get_begin()
|
691
|
+
|
802
692
|
# Execute.
|
803
|
-
result = self.select(table, '1', where=where, report=report, **kwdata)
|
804
|
-
count = len(tuple(result))
|
805
693
|
|
806
|
-
|
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')
|
807
711
|
|
712
|
+
## Not report.
|
713
|
+
else:
|
714
|
+
result = self.dbconn.conn.execute(sql, data)
|
808
715
|
|
809
|
-
|
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(
|
810
727
|
self,
|
811
728
|
table: str,
|
729
|
+
fields: str | Iterable[str] | None = None,
|
812
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,
|
813
735
|
report: bool | None = None,
|
814
736
|
**kwdata: Any
|
815
|
-
) ->
|
737
|
+
) -> Result:
|
816
738
|
"""
|
817
|
-
|
739
|
+
Execute select SQL.
|
818
740
|
|
819
741
|
Parameters
|
820
742
|
----------
|
821
743
|
table : Table name.
|
822
|
-
|
823
|
-
- `None`:
|
824
|
-
- `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`.
|
825
757
|
report : Whether report SQL execute information.
|
826
758
|
- `None`, Use attribute `report_execute_info`: of object `ROption`.
|
827
759
|
- `int`: Use this value.
|
@@ -829,7 +761,862 @@ class DatabaseExecute(DatabaseBase):
|
|
829
761
|
|
830
762
|
Returns
|
831
763
|
-------
|
832
|
-
|
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.
|
833
1620
|
|
834
1621
|
Examples
|
835
1622
|
--------
|
@@ -844,7 +1631,7 @@ class DatabaseExecute(DatabaseBase):
|
|
844
1631
|
"""
|
845
1632
|
|
846
1633
|
# Execute.
|
847
|
-
result = self.count(table, where, report, **kwdata)
|
1634
|
+
result = await self.count(table, where, report, **kwdata)
|
848
1635
|
|
849
1636
|
# Judge.
|
850
1637
|
judge = result != 0
|
@@ -852,15 +1639,15 @@ class DatabaseExecute(DatabaseBase):
|
|
852
1639
|
return judge
|
853
1640
|
|
854
1641
|
|
855
|
-
def generator(
|
1642
|
+
async def generator(
|
856
1643
|
self,
|
857
1644
|
sql: str | TextClause,
|
858
1645
|
data: TableData,
|
859
1646
|
report: bool | None = None,
|
860
1647
|
**kwdata: Any
|
861
|
-
) ->
|
1648
|
+
) -> AsyncGenerator[Result, Any]:
|
862
1649
|
"""
|
863
|
-
|
1650
|
+
Asynchronous return a generator that can execute SQL.
|
864
1651
|
|
865
1652
|
Parameters
|
866
1653
|
----------
|
@@ -873,7 +1660,7 @@ class DatabaseExecute(DatabaseBase):
|
|
873
1660
|
|
874
1661
|
Returns
|
875
1662
|
-------
|
876
|
-
|
1663
|
+
AsyncGenerator.
|
877
1664
|
"""
|
878
1665
|
|
879
1666
|
# Instance.
|
@@ -888,87 +1675,62 @@ class DatabaseExecute(DatabaseBase):
|
|
888
1675
|
for row in data:
|
889
1676
|
func_generator(**row)
|
890
1677
|
|
891
|
-
|
1678
|
+
# Create.
|
1679
|
+
agenerator = func_generator.agenerator()
|
892
1680
|
|
1681
|
+
return agenerator
|
893
1682
|
|
894
|
-
def handle_sql(self, sql: str | TextClause) -> TextClause:
|
895
|
-
"""
|
896
|
-
Handle SQL.
|
897
1683
|
|
898
|
-
|
899
|
-
|
900
|
-
sql : SQL in method `sqlalchemy.text` format, or TextClause object.
|
1684
|
+
@overload
|
1685
|
+
async def sleep(self, report: bool | None = None) -> int: ...
|
901
1686
|
|
902
|
-
|
903
|
-
|
904
|
-
TextClause instance.
|
905
|
-
"""
|
1687
|
+
@overload
|
1688
|
+
async def sleep(self, second: int, report: bool | None = None) -> int: ...
|
906
1689
|
|
907
|
-
|
908
|
-
|
909
|
-
sql = sql.text
|
1690
|
+
@overload
|
1691
|
+
async def sleep(self, low: int = 0, high: int = 10, report: bool | None = None) -> int: ...
|
910
1692
|
|
911
|
-
|
912
|
-
|
913
|
-
if sql[-1] != ';':
|
914
|
-
sql += ';'
|
915
|
-
sql = sqlalchemy_text(sql)
|
1693
|
+
@overload
|
1694
|
+
async def sleep(self, *thresholds: float, report: bool | None = None) -> float: ...
|
916
1695
|
|
917
|
-
|
1696
|
+
@overload
|
1697
|
+
async def sleep(self, *thresholds: float, precision: Literal[0], report: bool | None = None) -> int: ...
|
918
1698
|
|
1699
|
+
@overload
|
1700
|
+
async def sleep(self, *thresholds: float, precision: int, report: bool | None = None) -> float: ...
|
919
1701
|
|
920
|
-
def
|
921
|
-
self,
|
922
|
-
data: list[dict],
|
923
|
-
sql: str | TextClause,
|
924
|
-
) -> list[dict]:
|
1702
|
+
async def sleep(self, *thresholds: float, precision: int | None = None, report: bool | None = None) -> float:
|
925
1703
|
"""
|
926
|
-
|
1704
|
+
Asynchronous let the database wait random seconds.
|
927
1705
|
|
928
1706
|
Parameters
|
929
1707
|
----------
|
930
|
-
|
931
|
-
|
1708
|
+
thresholds : Low and high thresholds of random range, range contains thresholds.
|
1709
|
+
- When `length is 0`, then low and high thresholds is `0` and `10`.
|
1710
|
+
- When `length is 1`, then low and high thresholds is `0` and `thresholds[0]`.
|
1711
|
+
- When `length is 2`, then low and high thresholds is `thresholds[0]` and `thresholds[1]`.
|
1712
|
+
precision : Precision of random range, that is maximum decimal digits of return value.
|
1713
|
+
- `None`: Set to Maximum decimal digits of element of parameter `thresholds`.
|
1714
|
+
- `int`: Set to this value.
|
1715
|
+
report : Whether report SQL execute information.
|
1716
|
+
- `None`: Use attribute `default_report`.
|
1717
|
+
- `bool`: Use this value.
|
932
1718
|
|
933
1719
|
Returns
|
934
1720
|
-------
|
935
|
-
|
1721
|
+
Random seconds.
|
1722
|
+
- When parameters `precision` is `0`, then return int.
|
1723
|
+
- When parameters `precision` is `greater than 0`, then return float.
|
936
1724
|
"""
|
937
1725
|
|
938
1726
|
# Handle parameter.
|
939
|
-
if
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
pattern = '(?<!\\\\):(\\w+)'
|
944
|
-
sql_keys = findall(pattern, sql)
|
945
|
-
|
946
|
-
# Extract keys of syntax "in".
|
947
|
-
pattern = '[iI][nN]\\s+(?<!\\\\):(\\w+)'
|
948
|
-
sql_keys_in = findall(pattern, sql)
|
949
|
-
|
950
|
-
# Loop.
|
951
|
-
for row in data:
|
952
|
-
if row == {}:
|
953
|
-
continue
|
954
|
-
for key in sql_keys:
|
955
|
-
value = row.get(key)
|
956
|
-
|
957
|
-
# Empty string.
|
958
|
-
if value == '':
|
959
|
-
value = None
|
960
|
-
|
961
|
-
# Convert.
|
962
|
-
elif (
|
963
|
-
type(value) in (list, dict)
|
964
|
-
and key not in sql_keys_in
|
965
|
-
):
|
966
|
-
value = to_json(value)
|
967
|
-
|
968
|
-
# Enum.
|
969
|
-
elif isinstance(type(value), EnumType):
|
970
|
-
value = value.value
|
1727
|
+
if len(thresholds) == 1:
|
1728
|
+
second = thresholds[0]
|
1729
|
+
else:
|
1730
|
+
second = randn(*thresholds, precision=precision)
|
971
1731
|
|
972
|
-
|
1732
|
+
# Sleep.
|
1733
|
+
sql = f'SELECT SLEEP({second})'
|
1734
|
+
await self.execute(sql, report=report)
|
973
1735
|
|
974
|
-
return
|
1736
|
+
return second
|