reydb 1.1.52__py3-none-any.whl → 1.1.53__py3-none-any.whl

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