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/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 enum import EnumType
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, to_json
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 DatabaseExecute(DatabaseBase):
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 execute(
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
- ) -> Result:
68
+ ) -> tuple[TextClause, list[dict], bool]:
67
69
  """
68
- Execute SQL.
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
- Result object.
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 = self.handle_sql(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 = self.handle_data(data, sql)
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
- __call__ = execute
101
+ return sql, data, report
131
102
 
132
103
 
133
- def select(
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
- report: bool | None = None,
143
- **kwdata: Any
144
- ) -> Result:
112
+ limit: int | str | tuple[int, int] | None = None
113
+ ) -> str:
145
114
  """
146
- Execute select SQL.
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
- Result object.
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
- # Execute SQL.
248
- result = self.execute(sql, report=report, **kwdata)
249
-
250
- return result
198
+ return sql
251
199
 
252
200
 
253
- def insert(
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
- Insert the data of table in the datebase.
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
- Result object.
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
- # Execute SQL.
398
- result = self.execute(sql, data, report, **kwdata_replace)
399
-
400
- return result
329
+ return sql, kwdata_replace
401
330
 
402
331
 
403
- def update(
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
- Update the data of table in the datebase.
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
- Result object.
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
- # Execute SQL.
557
- result = self.execute(sqls, data_flatten, report)
558
-
559
- return result
469
+ return sqls, data_flatten
560
470
 
561
471
 
562
- def delete(
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
- Delete the data of table in the datebase.
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
- Result object.
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
- # Execute SQL.
625
- result = self.execute(sqls, report=report, **kwdata)
626
-
627
- return result
519
+ return sqls
628
520
 
629
521
 
630
- def copy(
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
- Copy record of table in the datebase.
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
- Result object.
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
- # Execute SQL.
762
- result = self.execute(sql, report=report, **kwdata)
640
+ return sql
763
641
 
764
- return result
642
+
643
+ class DatabaseExecute(DatabaseExecuteBase):
644
+ """
645
+ Database execute type.
646
+ """
765
647
 
766
648
 
767
- def count(
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
- table: str,
770
- where: str | None = None,
664
+ sql: str | TextClause,
665
+ data: TableData | None = None,
771
666
  report: bool | None = None,
772
667
  **kwdata: Any
773
- ) -> int:
668
+ ) -> Result:
774
669
  """
775
- Count records.
670
+ Execute SQL.
776
671
 
777
672
  Parameters
778
673
  ----------
779
- table : Table name.
780
- where : Match condition, `WHERE` clause content, join as `WHERE str`.
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`, Use attribute `report_execute_info`: of object `ROption`.
785
- - `int`: Use this value.
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
- Record count.
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
- return count
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
- def exist(
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
- ) -> bool:
737
+ ) -> Result:
816
738
  """
817
- Judge the exist of record.
739
+ Execute select SQL.
818
740
 
819
741
  Parameters
820
742
  ----------
821
743
  table : Table name.
822
- where : Match condition, `WHERE` clause content, join as `WHERE str`.
823
- - `None`: Match all.
824
- - `str`: Match condition.
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
- Judged result.
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
- ) -> Generator[Result, Any, None]:
1648
+ ) -> AsyncGenerator[Result, Any]:
862
1649
  """
863
- Return a generator that can execute SQL.
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
- Generator.
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
- return func_generator.generator
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
- Parameters
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
- Returns
903
- -------
904
- TextClause instance.
905
- """
1687
+ @overload
1688
+ async def sleep(self, second: int, report: bool | None = None) -> int: ...
906
1689
 
907
- # Handle parameter.
908
- if type(sql) == TextClause:
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
- # Handle.
912
- sql = sql.strip()
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
- return sql
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 handle_data(
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
- Handle data based on the content of SQL.
1704
+ Asynchronous let the database wait random seconds.
927
1705
 
928
1706
  Parameters
929
1707
  ----------
930
- data : Data set for filling.
931
- sql : SQL in method `sqlalchemy.text` format, or TextClause object.
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
- Filled data.
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 type(sql) == TextClause:
940
- sql = sql.text
941
-
942
- # Extract keys.
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
- row[key] = value
1732
+ # Sleep.
1733
+ sql = f'SELECT SLEEP({second})'
1734
+ await self.execute(sql, report=report)
973
1735
 
974
- return data
1736
+ return second