reydb 1.1.52__py3-none-any.whl → 1.1.54__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,124 @@ 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
+ self.dbconn.close()
720
+
721
+ return result
722
+
723
+
724
+ __call__ = execute
725
+
726
+
727
+ def select(
811
728
  self,
812
729
  table: str,
730
+ fields: str | Iterable[str] | None = None,
813
731
  where: str | None = None,
732
+ group: str | None = None,
733
+ having: str | None = None,
734
+ order: str | None = None,
735
+ limit: int | str | tuple[int, int] | None = None,
814
736
  report: bool | None = None,
815
737
  **kwdata: Any
816
- ) -> bool:
738
+ ) -> Result:
817
739
  """
818
- Judge the exist of record.
740
+ Execute select SQL.
819
741
 
820
742
  Parameters
821
743
  ----------
822
744
  table : Table name.
823
- where : Match condition, `WHERE` clause content, join as `WHERE str`.
824
- - `None`: Match all.
825
- - `str`: Match condition.
745
+ fields : Select clause content.
746
+ - `None`: Is `SELECT *`.
747
+ - `str`: Join as `SELECT str`.
748
+ - `Iterable[str]`, Join as `SELECT ``str``: ...`.
749
+ `str and first character is ':'`: Use this syntax.
750
+ `str`: Use this field.
751
+ where : Clause `WHERE` content, join as `WHERE str`.
752
+ group : Clause `GROUP BY` content, join as `GROUP BY str`.
753
+ having : Clause `HAVING` content, join as `HAVING str`.
754
+ order : Clause `ORDER BY` content, join as `ORDER BY str`.
755
+ limit : Clause `LIMIT` content.
756
+ - `int | str`: Join as `LIMIT int/str`.
757
+ - `tuple[int, int]`: Join as `LIMIT int, int`.
826
758
  report : Whether report SQL execute information.
827
759
  - `None`, Use attribute `report_execute_info`: of object `ROption`.
828
760
  - `int`: Use this value.
@@ -830,7 +762,864 @@ class DatabaseExecute(DatabaseBase):
830
762
 
831
763
  Returns
832
764
  -------
833
- Judged result.
765
+ Result object.
766
+
767
+ Examples
768
+ --------
769
+ Parameter `fields`.
770
+ >>> fields = ['id', ':`id` + 1 AS `id_`']
771
+ >>> result = Database.execute.select('table', fields)
772
+ >>> print(result.to_table())
773
+ [{'id': 1, 'id_': 2}, ...]
774
+
775
+ Parameter `kwdata`.
776
+ >>> fields = '`id`, `id` + :value AS `id_`'
777
+ >>> result = Database.execute.select('table', fields, value=1)
778
+ >>> print(result.to_table())
779
+ [{'id': 1, 'id_': 2}, ...]
780
+ """
781
+
782
+ # Handle parameter.
783
+ sql = self.handle_select(table, fields, where, group, having, order, limit)
784
+
785
+ # Execute SQL.
786
+ result = self.execute(sql, report=report, **kwdata)
787
+
788
+ return result
789
+
790
+
791
+ def insert(
792
+ self,
793
+ table: str,
794
+ data: TableData,
795
+ duplicate: Literal['ignore', 'update'] | Container[str] | None = None,
796
+ report: bool | None = None,
797
+ **kwdata: Any
798
+ ) -> Result:
799
+ """
800
+ Execute insert SQL.
801
+
802
+ Parameters
803
+ ----------
804
+ table : Table name.
805
+ data : Insert data.
806
+ duplicate : Handle method when constraint error.
807
+ - `None`: Not handled.
808
+ - `ignore`: Use `UPDATE IGNORE INTO` clause.
809
+ - `update`: Use `ON DUPLICATE KEY UPDATE` clause and update all fields.
810
+ - `Container[str]`: Use `ON DUPLICATE KEY UPDATE` clause and update this fields.
811
+ report : Whether report SQL execute information.
812
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
813
+ - `int`: Use this value.
814
+ kwdata : Keyword parameters for filling.
815
+ - `str and first character is ':'`: Use this syntax.
816
+ - `Any`: Use this value.
817
+
818
+ Returns
819
+ -------
820
+ Result object.
821
+
822
+ Examples
823
+ --------
824
+ Parameter `data` and `kwdata`.
825
+ >>> data = [{'key': 'a'}, {'key': 'b'}]
826
+ >>> kwdata = {'value1': 1, 'value2': ':(SELECT 2)'}
827
+ >>> result = Database.execute.insert('table', data, **kwdata)
828
+ >>> print(result.rowcount)
829
+ 2
830
+ >>> result = Database.execute.select('table')
831
+ >>> print(result.to_table())
832
+ [{'key': 'a', 'value1': 1, 'value2': 2}, {'key': 'b', 'value1': 1, 'value2': 2}]
833
+ """
834
+
835
+ # Handle parameter.
836
+ sql, kwdata = self.handle_insert(table, data, duplicate, **kwdata)
837
+
838
+ # Execute SQL.
839
+ result = self.execute(sql, data, report, **kwdata)
840
+
841
+ return result
842
+
843
+
844
+ def update(
845
+ self,
846
+ table: str,
847
+ data: TableData,
848
+ where_fields: str | Iterable[str] | None = None,
849
+ report: bool | None = None,
850
+ **kwdata: Any
851
+ ) -> Result:
852
+ """
853
+ Execute update SQL.
854
+
855
+ Parameters
856
+ ----------
857
+ table : Table name.
858
+ data : Update data, clause `SET` and `WHERE` and `ORDER BY` and `LIMIT` content.
859
+ - `Key`: Table field.
860
+ `literal['order']`: Clause `ORDER BY` content, join as `ORDER BY str`.
861
+ `literal['limit']`: Clause `LIMIT` content, join as `LIMIT str`.
862
+ `Other`: Clause `SET` and `WHERE` content.
863
+ - `Value`: Table value.
864
+ `list | tuple`: Join as `field IN :str`.
865
+ `Any`: Join as `field = :str`.
866
+ where_fields : Clause `WHERE` content fields.
867
+ - `None`: The first key value pair of each item is judged.
868
+ - `str`: This key value pair of each item is judged.
869
+ - `Iterable[str]`: Multiple judged, `and`: relationship.
870
+ report : Whether report SQL execute information.
871
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
872
+ - `int`: Use this value.
873
+ kwdata : Keyword parameters for filling.
874
+ - `str and first character is ':'`: Use this syntax.
875
+ - `Any`: Use this value.
876
+
877
+ Returns
878
+ -------
879
+ Result object.
880
+
881
+ Examples
882
+ --------
883
+ Parameter `data` and `kwdata`.
884
+ >>> data = [{'key': 'a'}, {'key': 'b'}]
885
+ >>> kwdata = {'value': 1, 'name': ':`key`'}
886
+ >>> result = Database.execute.update('table', data, **kwdata)
887
+ >>> print(result.rowcount)
888
+ 2
889
+ >>> result = Database.execute.select('table')
890
+ >>> print(result.to_table())
891
+ [{'key': 'a', 'value': 1, 'name': 'a'}, {'key': 'b', 'value': 1, 'name': 'b'}]
892
+ """
893
+
894
+ # Handle parameter.
895
+ sql, data = self.handle_update(table, data, where_fields, **kwdata)
896
+
897
+ # Execute SQL.
898
+ result = self.execute(sql, data, report)
899
+
900
+ return result
901
+
902
+
903
+ def delete(
904
+ self,
905
+ table: str,
906
+ where: str | None = None,
907
+ order: str | None = None,
908
+ limit: int | str | None = None,
909
+ report: bool | None = None,
910
+ **kwdata: Any
911
+ ) -> Result:
912
+ """
913
+ Execute delete SQL.
914
+
915
+ Parameters
916
+ ----------
917
+ table : Table name.
918
+ where : Clause `WHERE` content, join as `WHERE str`.
919
+ order : Clause `ORDER BY` content, join as `ORDER BY str`.
920
+ limit : Clause `LIMIT` content, join as `LIMIT int/str`.
921
+ report : Whether report SQL execute information.
922
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
923
+ - `int`: Use this value.
924
+ kwdata : Keyword parameters for filling.
925
+
926
+ Returns
927
+ -------
928
+ Result object.
929
+
930
+ Examples
931
+ --------
932
+ Parameter `where` and `kwdata`.
933
+ >>> where = '`id` IN :ids'
934
+ >>> ids = (1, 2)
935
+ >>> result = Database.execute.delete('table', where, ids=ids)
936
+ >>> print(result.rowcount)
937
+ 2
938
+ """
939
+
940
+ # Handle parameter.
941
+ sql = self.handle_delete(table, where, order, limit)
942
+
943
+ # Execute SQL.
944
+ result = self.execute(sql, report=report, **kwdata)
945
+
946
+ return result
947
+
948
+
949
+ def copy(
950
+ self,
951
+ table: str,
952
+ where: str | None = None,
953
+ limit: int | str | tuple[int, int] | None = None,
954
+ report: bool | None = None,
955
+ **kwdata: Any
956
+ ) -> Result:
957
+ """
958
+ Execute inesrt SQL of copy records.
959
+
960
+ Parameters
961
+ ----------
962
+ table : Table name.
963
+ where : Clause `WHERE` content, join as `WHERE str`.
964
+ limit : Clause `LIMIT` content.
965
+ - `int | str`: Join as `LIMIT int/str`.
966
+ - `tuple[int, int]`: Join as `LIMIT int, int`.
967
+ report : Whether report SQL execute information.
968
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
969
+ - `int`: Use this value.
970
+ kwdata : Keyword parameters for filling.
971
+ - `In 'WHERE' syntax`: Fill 'WHERE' syntax.
972
+ - `Not in 'WHERE' syntax`: Fill 'INSERT' and 'SELECT' syntax.
973
+ `str and first character is ':'`: Use this syntax.
974
+ `Any`: Use this value.
975
+
976
+ Returns
977
+ -------
978
+ Result object.
979
+
980
+ Examples
981
+ --------
982
+ Parameter `where` and `kwdata`.
983
+ >>> where = '`id` IN :ids'
984
+ >>> ids = (1, 2, 3)
985
+ >>> result = Database.execute.copy('table', where, 2, ids=ids, id=None, time=':NOW()')
986
+ >>> print(result.rowcount)
987
+ 2
988
+ """
989
+
990
+ # Handle parameter.
991
+ sql = self.handle_copy(table, where, limit, **kwdata)
992
+
993
+ # Execute SQL.
994
+ result = self.execute(sql, report=report, **kwdata)
995
+
996
+ return result
997
+
998
+
999
+ def count(
1000
+ self,
1001
+ table: str,
1002
+ where: str | None = None,
1003
+ report: bool | None = None,
1004
+ **kwdata: Any
1005
+ ) -> int:
1006
+ """
1007
+ Execute inesrt SQL of count records.
1008
+
1009
+ Parameters
1010
+ ----------
1011
+ table : Table name.
1012
+ where : Match condition, `WHERE` clause content, join as `WHERE str`.
1013
+ - `None`: Match all.
1014
+ - `str`: Match condition.
1015
+ report : Whether report SQL execute information.
1016
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
1017
+ - `int`: Use this value.
1018
+ kwdata : Keyword parameters for filling.
1019
+
1020
+ Returns
1021
+ -------
1022
+ Record count.
1023
+
1024
+ Examples
1025
+ --------
1026
+ Parameter `where` and `kwdata`.
1027
+ >>> where = '`id` IN :ids'
1028
+ >>> ids = (1, 2)
1029
+ >>> result = Database.execute.count('table', where, ids=ids)
1030
+ >>> print(result)
1031
+ 2
1032
+ """
1033
+
1034
+ # Execute.
1035
+ result = self.select(table, '1', where=where, report=report, **kwdata)
1036
+ count = len(tuple(result))
1037
+
1038
+ return count
1039
+
1040
+
1041
+ def exist(
1042
+ self,
1043
+ table: str,
1044
+ where: str | None = None,
1045
+ report: bool | None = None,
1046
+ **kwdata: Any
1047
+ ) -> bool:
1048
+ """
1049
+ Execute inesrt SQL of Judge the exist of record.
1050
+
1051
+ Parameters
1052
+ ----------
1053
+ table : Table name.
1054
+ where : Match condition, `WHERE` clause content, join as `WHERE str`.
1055
+ - `None`: Match all.
1056
+ - `str`: Match condition.
1057
+ report : Whether report SQL execute information.
1058
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
1059
+ - `int`: Use this value.
1060
+ kwdata : Keyword parameters for filling.
1061
+
1062
+ Returns
1063
+ -------
1064
+ Judged result.
1065
+
1066
+ Examples
1067
+ --------
1068
+ Parameter `where` and `kwdata`.
1069
+ >>> data = [{'id': 1}]
1070
+ >>> Database.execute.insert('table', data)
1071
+ >>> where = '`id` = :id_'
1072
+ >>> id_ = 1
1073
+ >>> result = Database.execute.exist('table', where, id_=id_)
1074
+ >>> print(result)
1075
+ True
1076
+ """
1077
+
1078
+ # Execute.
1079
+ result = self.count(table, where, report, **kwdata)
1080
+
1081
+ # Judge.
1082
+ judge = result != 0
1083
+
1084
+ return judge
1085
+
1086
+
1087
+ def generator(
1088
+ self,
1089
+ sql: str | TextClause,
1090
+ data: TableData,
1091
+ report: bool | None = None,
1092
+ **kwdata: Any
1093
+ ) -> Generator[Result, Any, None]:
1094
+ """
1095
+ Return a generator that can execute SQL.
1096
+
1097
+ Parameters
1098
+ ----------
1099
+ sql : SQL in method `sqlalchemy.text` format, or `TextClause` object.
1100
+ data : Data set for filling.
1101
+ report : Whether report SQL execute information.
1102
+ - `None`: Use attribute `default_report`.
1103
+ - `bool`: Use this value.
1104
+ kwdata : Keyword parameters for filling.
1105
+
1106
+ Returns
1107
+ -------
1108
+ Generator.
1109
+ """
1110
+
1111
+ # Instance.
1112
+ func_generator = FunctionGenerator(
1113
+ self.execute,
1114
+ sql=sql,
1115
+ report=report,
1116
+ **kwdata
1117
+ )
1118
+
1119
+ # Add.
1120
+ for row in data:
1121
+ func_generator(**row)
1122
+
1123
+ # Create.
1124
+ generator = func_generator.generator()
1125
+
1126
+ return generator
1127
+
1128
+
1129
+ @overload
1130
+ def sleep(self, report: bool | None = None) -> int: ...
1131
+
1132
+ @overload
1133
+ def sleep(self, second: int, report: bool | None = None) -> int: ...
1134
+
1135
+ @overload
1136
+ def sleep(self, low: int = 0, high: int = 10, report: bool | None = None) -> int: ...
1137
+
1138
+ @overload
1139
+ def sleep(self, *thresholds: float, report: bool | None = None) -> float: ...
1140
+
1141
+ @overload
1142
+ def sleep(self, *thresholds: float, precision: Literal[0], report: bool | None = None) -> int: ...
1143
+
1144
+ @overload
1145
+ def sleep(self, *thresholds: float, precision: int, report: bool | None = None) -> float: ...
1146
+
1147
+ def sleep(self, *thresholds: float, precision: int | None = None, report: bool | None = None) -> float:
1148
+ """
1149
+ Let the database wait random seconds.
1150
+
1151
+ Parameters
1152
+ ----------
1153
+ thresholds : Low and high thresholds of random range, range contains thresholds.
1154
+ - When `length is 0`, then low and high thresholds is `0` and `10`.
1155
+ - When `length is 1`, then low and high thresholds is `0` and `thresholds[0]`.
1156
+ - When `length is 2`, then low and high thresholds is `thresholds[0]` and `thresholds[1]`.
1157
+ precision : Precision of random range, that is maximum decimal digits of return value.
1158
+ - `None`: Set to Maximum decimal digits of element of parameter `thresholds`.
1159
+ - `int`: Set to this value.
1160
+ report : Whether report SQL execute information.
1161
+ - `None`: Use attribute `default_report`.
1162
+ - `bool`: Use this value.
1163
+
1164
+ Returns
1165
+ -------
1166
+ Random seconds.
1167
+ - When parameters `precision` is `0`, then return int.
1168
+ - When parameters `precision` is `greater than 0`, then return float.
1169
+ """
1170
+
1171
+ # Handle parameter.
1172
+ if len(thresholds) == 1:
1173
+ second = thresholds[0]
1174
+ else:
1175
+ second = randn(*thresholds, precision=precision)
1176
+
1177
+ # Sleep.
1178
+ sql = f'SELECT SLEEP({second})'
1179
+ self.execute(sql, report=report)
1180
+
1181
+ return second
1182
+
1183
+
1184
+ class DatabaseExecuteAsync(DatabaseExecuteBase):
1185
+ """
1186
+ Asynchronous database execute type.
1187
+ """
1188
+
1189
+
1190
+ def __init__(self, dbconn: DatabaseConnectionAsync) -> None:
1191
+ """
1192
+ Build instance attributes.
1193
+
1194
+ Parameters
1195
+ ----------
1196
+ dbconn : `DatabaseConnectionAsync` instance.
1197
+ """
1198
+
1199
+ # Build.
1200
+ self.dbconn = dbconn
1201
+
1202
+
1203
+ async def execute(
1204
+ self,
1205
+ sql: str | TextClause,
1206
+ data: TableData | None = None,
1207
+ report: bool | None = None,
1208
+ **kwdata: Any
1209
+ ) -> Result:
1210
+ """
1211
+ Asynchronous execute SQL.
1212
+
1213
+ Parameters
1214
+ ----------
1215
+ sql : SQL in method `sqlalchemy.text` format, or `TextClause` object.
1216
+ data : Data set for filling.
1217
+ report : Whether report SQL execute information.
1218
+ - `None`: Use attribute `default_report`.
1219
+ - `bool`: Use this value.
1220
+ kwdata : Keyword parameters for filling.
1221
+
1222
+ Returns
1223
+ -------
1224
+ Result object.
1225
+ """
1226
+
1227
+ # Handle parameter.
1228
+ sql, data, report = self.handle_execute(sql, data, report, **kwdata)
1229
+
1230
+ # Transaction.
1231
+ await self.dbconn.get_begin()
1232
+
1233
+ # Execute.
1234
+
1235
+ ## Report.
1236
+ if report:
1237
+ tm = TimeMark()
1238
+ tm()
1239
+ result = await self.dbconn.aconn.execute(sql, data)
1240
+ tm()
1241
+
1242
+ ### Generate report.
1243
+ start_time = tm.records[0]['datetime']
1244
+ spend_time: Timedelta = tm.records[1]['timedelta']
1245
+ end_time = tm.records[1]['datetime']
1246
+ start_str = time_to(start_time, True)[:-3]
1247
+ spend_str = time_to(spend_time, True)[:-3]
1248
+ end_str = time_to(end_time, True)[:-3]
1249
+ report_runtime = 'Start: %s -> Spend: %ss -> End: %s' % (
1250
+ start_str,
1251
+ spend_str,
1252
+ end_str
1253
+ )
1254
+ report_info = (
1255
+ f'{report_runtime}\n'
1256
+ f'Row Count: {result.rowcount}'
1257
+ )
1258
+ sqls = [
1259
+ sql_part.strip()
1260
+ for sql_part in sql.text.split(';')
1261
+ if sql_part != ''
1262
+ ]
1263
+
1264
+ if data == []:
1265
+ echo(report_info, *sqls, title='SQL')
1266
+ else:
1267
+ echo(report_info, *sqls, data, title='SQL')
1268
+
1269
+ ## Not report.
1270
+ else:
1271
+ result = await self.dbconn.aconn.execute(sql, data)
1272
+
1273
+ # Automatic commit.
1274
+ if self.dbconn.autocommit:
1275
+ await self.dbconn.commit()
1276
+ await self.dbconn.close()
1277
+ await self.dbconn.db.dispose()
1278
+
1279
+ return result
1280
+
1281
+
1282
+ __call__ = execute
1283
+
1284
+
1285
+ async def select(
1286
+ self,
1287
+ table: str,
1288
+ fields: str | Iterable[str] | None = None,
1289
+ where: str | None = None,
1290
+ group: str | None = None,
1291
+ having: str | None = None,
1292
+ order: str | None = None,
1293
+ limit: int | str | tuple[int, int] | None = None,
1294
+ report: bool | None = None,
1295
+ **kwdata: Any
1296
+ ) -> Result:
1297
+ """
1298
+ Asynchronous execute select SQL.
1299
+
1300
+ Parameters
1301
+ ----------
1302
+ table : Table name.
1303
+ fields : Select clause content.
1304
+ - `None`: Is `SELECT *`.
1305
+ - `str`: Join as `SELECT str`.
1306
+ - `Iterable[str]`, Join as `SELECT ``str``: ...`.
1307
+ `str and first character is ':'`: Use this syntax.
1308
+ `str`: Use this field.
1309
+ where : Clause `WHERE` content, join as `WHERE str`.
1310
+ group : Clause `GROUP BY` content, join as `GROUP BY str`.
1311
+ having : Clause `HAVING` content, join as `HAVING str`.
1312
+ order : Clause `ORDER BY` content, join as `ORDER BY str`.
1313
+ limit : Clause `LIMIT` content.
1314
+ - `int | str`: Join as `LIMIT int/str`.
1315
+ - `tuple[int, int]`: Join as `LIMIT int, int`.
1316
+ report : Whether report SQL execute information.
1317
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
1318
+ - `int`: Use this value.
1319
+ kwdata : Keyword parameters for filling.
1320
+
1321
+ Returns
1322
+ -------
1323
+ Result object.
1324
+
1325
+ Examples
1326
+ --------
1327
+ Parameter `fields`.
1328
+ >>> fields = ['id', ':`id` + 1 AS `id_`']
1329
+ >>> result = Database.execute.select('table', fields)
1330
+ >>> print(result.to_table())
1331
+ [{'id': 1, 'id_': 2}, ...]
1332
+
1333
+ Parameter `kwdata`.
1334
+ >>> fields = '`id`, `id` + :value AS `id_`'
1335
+ >>> result = Database.execute.select('table', fields, value=1)
1336
+ >>> print(result.to_table())
1337
+ [{'id': 1, 'id_': 2}, ...]
1338
+ """
1339
+
1340
+ # Handle parameter.
1341
+ sql = self.handle_select(table, fields, where, group, having, order, limit)
1342
+
1343
+ # Execute SQL.
1344
+ result = await self.execute(sql, report=report, **kwdata)
1345
+
1346
+ return result
1347
+
1348
+
1349
+ async def insert(
1350
+ self,
1351
+ table: str,
1352
+ data: TableData,
1353
+ duplicate: Literal['ignore', 'update'] | Container[str] | None = None,
1354
+ report: bool | None = None,
1355
+ **kwdata: Any
1356
+ ) -> Result:
1357
+ """
1358
+ Asynchronous execute insert SQL.
1359
+
1360
+ Parameters
1361
+ ----------
1362
+ table : Table name.
1363
+ data : Insert data.
1364
+ duplicate : Handle method when constraint error.
1365
+ - `None`: Not handled.
1366
+ - `ignore`: Use `UPDATE IGNORE INTO` clause.
1367
+ - `update`: Use `ON DUPLICATE KEY UPDATE` clause and update all fields.
1368
+ - `Container[str]`: Use `ON DUPLICATE KEY UPDATE` clause and update this fields.
1369
+ report : Whether report SQL execute information.
1370
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
1371
+ - `int`: Use this value.
1372
+ kwdata : Keyword parameters for filling.
1373
+ - `str and first character is ':'`: Use this syntax.
1374
+ - `Any`: Use this value.
1375
+
1376
+ Returns
1377
+ -------
1378
+ Result object.
1379
+
1380
+ Examples
1381
+ --------
1382
+ Parameter `data` and `kwdata`.
1383
+ >>> data = [{'key': 'a'}, {'key': 'b'}]
1384
+ >>> kwdata = {'value1': 1, 'value2': ':(SELECT 2)'}
1385
+ >>> result = Database.execute.insert('table', data, **kwdata)
1386
+ >>> print(result.rowcount)
1387
+ 2
1388
+ >>> result = Database.execute.select('table')
1389
+ >>> print(result.to_table())
1390
+ [{'key': 'a', 'value1': 1, 'value2': 2}, {'key': 'b', 'value1': 1, 'value2': 2}]
1391
+ """
1392
+
1393
+ # Handle parameter.
1394
+ sql, kwdata = self.handle_insert(table, data, duplicate, **kwdata)
1395
+
1396
+ # Execute SQL.
1397
+ result = await self.execute(sql, data, report, **kwdata)
1398
+
1399
+ return result
1400
+
1401
+
1402
+ async def update(
1403
+ self,
1404
+ table: str,
1405
+ data: TableData,
1406
+ where_fields: str | Iterable[str] | None = None,
1407
+ report: bool | None = None,
1408
+ **kwdata: Any
1409
+ ) -> Result:
1410
+ """
1411
+ Asynchronous execute update SQL.
1412
+
1413
+ Parameters
1414
+ ----------
1415
+ table : Table name.
1416
+ data : Update data, clause `SET` and `WHERE` and `ORDER BY` and `LIMIT` content.
1417
+ - `Key`: Table field.
1418
+ `literal['order']`: Clause `ORDER BY` content, join as `ORDER BY str`.
1419
+ `literal['limit']`: Clause `LIMIT` content, join as `LIMIT str`.
1420
+ `Other`: Clause `SET` and `WHERE` content.
1421
+ - `Value`: Table value.
1422
+ `list | tuple`: Join as `field IN :str`.
1423
+ `Any`: Join as `field = :str`.
1424
+ where_fields : Clause `WHERE` content fields.
1425
+ - `None`: The first key value pair of each item is judged.
1426
+ - `str`: This key value pair of each item is judged.
1427
+ - `Iterable[str]`: Multiple judged, `and`: relationship.
1428
+ report : Whether report SQL execute information.
1429
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
1430
+ - `int`: Use this value.
1431
+ kwdata : Keyword parameters for filling.
1432
+ - `str and first character is ':'`: Use this syntax.
1433
+ - `Any`: Use this value.
1434
+
1435
+ Returns
1436
+ -------
1437
+ Result object.
1438
+
1439
+ Examples
1440
+ --------
1441
+ Parameter `data` and `kwdata`.
1442
+ >>> data = [{'key': 'a'}, {'key': 'b'}]
1443
+ >>> kwdata = {'value': 1, 'name': ':`key`'}
1444
+ >>> result = Database.execute.update('table', data, **kwdata)
1445
+ >>> print(result.rowcount)
1446
+ 2
1447
+ >>> result = Database.execute.select('table')
1448
+ >>> print(result.to_table())
1449
+ [{'key': 'a', 'value': 1, 'name': 'a'}, {'key': 'b', 'value': 1, 'name': 'b'}]
1450
+ """
1451
+
1452
+ # Handle parameter.
1453
+ sql, data = self.handle_update(table, data, where_fields, **kwdata)
1454
+
1455
+ # Execute SQL.
1456
+ result = await self.execute(sql, data, report)
1457
+
1458
+ return result
1459
+
1460
+
1461
+ async def delete(
1462
+ self,
1463
+ table: str,
1464
+ where: str | None = None,
1465
+ order: str | None = None,
1466
+ limit: int | str | None = None,
1467
+ report: bool | None = None,
1468
+ **kwdata: Any
1469
+ ) -> Result:
1470
+ """
1471
+ Asynchronous execute delete SQL.
1472
+
1473
+ Parameters
1474
+ ----------
1475
+ table : Table name.
1476
+ where : Clause `WHERE` content, join as `WHERE str`.
1477
+ order : Clause `ORDER BY` content, join as `ORDER BY str`.
1478
+ limit : Clause `LIMIT` content, join as `LIMIT int/str`.
1479
+ report : Whether report SQL execute information.
1480
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
1481
+ - `int`: Use this value.
1482
+ kwdata : Keyword parameters for filling.
1483
+
1484
+ Returns
1485
+ -------
1486
+ Result object.
1487
+
1488
+ Examples
1489
+ --------
1490
+ Parameter `where` and `kwdata`.
1491
+ >>> where = '`id` IN :ids'
1492
+ >>> ids = (1, 2)
1493
+ >>> result = Database.execute.delete('table', where, ids=ids)
1494
+ >>> print(result.rowcount)
1495
+ 2
1496
+ """
1497
+
1498
+ # Handle parameter.
1499
+ sql = self.handle_delete(table, where, order, limit)
1500
+
1501
+ # Execute SQL.
1502
+ result = await self.execute(sql, report=report, **kwdata)
1503
+
1504
+ return result
1505
+
1506
+
1507
+ async def copy(
1508
+ self,
1509
+ table: str,
1510
+ where: str | None = None,
1511
+ limit: int | str | tuple[int, int] | None = None,
1512
+ report: bool | None = None,
1513
+ **kwdata: Any
1514
+ ) -> Result:
1515
+ """
1516
+ Asynchronous execute inesrt SQL of copy records.
1517
+
1518
+ Parameters
1519
+ ----------
1520
+ table : Table name.
1521
+ where : Clause `WHERE` content, join as `WHERE str`.
1522
+ limit : Clause `LIMIT` content.
1523
+ - `int | str`: Join as `LIMIT int/str`.
1524
+ - `tuple[int, int]`: Join as `LIMIT int, int`.
1525
+ report : Whether report SQL execute information.
1526
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
1527
+ - `int`: Use this value.
1528
+ kwdata : Keyword parameters for filling.
1529
+ - `In 'WHERE' syntax`: Fill 'WHERE' syntax.
1530
+ - `Not in 'WHERE' syntax`: Fill 'INSERT' and 'SELECT' syntax.
1531
+ `str and first character is ':'`: Use this syntax.
1532
+ `Any`: Use this value.
1533
+
1534
+ Returns
1535
+ -------
1536
+ Result object.
1537
+
1538
+ Examples
1539
+ --------
1540
+ Parameter `where` and `kwdata`.
1541
+ >>> where = '`id` IN :ids'
1542
+ >>> ids = (1, 2, 3)
1543
+ >>> result = Database.execute.copy('table', where, 2, ids=ids, id=None, time=':NOW()')
1544
+ >>> print(result.rowcount)
1545
+ 2
1546
+ """
1547
+
1548
+ # Handle parameter.
1549
+ sql = self.handle_copy(table, where, limit, **kwdata)
1550
+
1551
+ # Execute SQL.
1552
+ result = await self.execute(sql, report=report, **kwdata)
1553
+
1554
+ return result
1555
+
1556
+
1557
+ async def count(
1558
+ self,
1559
+ table: str,
1560
+ where: str | None = None,
1561
+ report: bool | None = None,
1562
+ **kwdata: Any
1563
+ ) -> int:
1564
+ """
1565
+ Asynchronous execute inesrt SQL of count records.
1566
+
1567
+ Parameters
1568
+ ----------
1569
+ table : Table name.
1570
+ where : Match condition, `WHERE` clause content, join as `WHERE str`.
1571
+ - `None`: Match all.
1572
+ - `str`: Match condition.
1573
+ report : Whether report SQL execute information.
1574
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
1575
+ - `int`: Use this value.
1576
+ kwdata : Keyword parameters for filling.
1577
+
1578
+ Returns
1579
+ -------
1580
+ Record count.
1581
+
1582
+ Examples
1583
+ --------
1584
+ Parameter `where` and `kwdata`.
1585
+ >>> where = '`id` IN :ids'
1586
+ >>> ids = (1, 2)
1587
+ >>> result = Database.execute.count('table', where, ids=ids)
1588
+ >>> print(result)
1589
+ 2
1590
+ """
1591
+
1592
+ # Execute.
1593
+ result = await self.select(table, '1', where=where, report=report, **kwdata)
1594
+ count = len(tuple(result))
1595
+
1596
+ return count
1597
+
1598
+
1599
+ async def exist(
1600
+ self,
1601
+ table: str,
1602
+ where: str | None = None,
1603
+ report: bool | None = None,
1604
+ **kwdata: Any
1605
+ ) -> bool:
1606
+ """
1607
+ Asynchronous execute inesrt SQL of Judge the exist of record.
1608
+
1609
+ Parameters
1610
+ ----------
1611
+ table : Table name.
1612
+ where : Match condition, `WHERE` clause content, join as `WHERE str`.
1613
+ - `None`: Match all.
1614
+ - `str`: Match condition.
1615
+ report : Whether report SQL execute information.
1616
+ - `None`, Use attribute `report_execute_info`: of object `ROption`.
1617
+ - `int`: Use this value.
1618
+ kwdata : Keyword parameters for filling.
1619
+
1620
+ Returns
1621
+ -------
1622
+ Judged result.
834
1623
 
835
1624
  Examples
836
1625
  --------
@@ -845,7 +1634,7 @@ class DatabaseExecute(DatabaseBase):
845
1634
  """
846
1635
 
847
1636
  # Execute.
848
- result = self.count(table, where, report, **kwdata)
1637
+ result = await self.count(table, where, report, **kwdata)
849
1638
 
850
1639
  # Judge.
851
1640
  judge = result != 0
@@ -853,15 +1642,15 @@ class DatabaseExecute(DatabaseBase):
853
1642
  return judge
854
1643
 
855
1644
 
856
- def generator(
1645
+ async def generator(
857
1646
  self,
858
1647
  sql: str | TextClause,
859
1648
  data: TableData,
860
1649
  report: bool | None = None,
861
1650
  **kwdata: Any
862
- ) -> Generator[Result, Any, None]:
1651
+ ) -> AsyncGenerator[Result, Any]:
863
1652
  """
864
- Return a generator that can execute SQL.
1653
+ Asynchronous return a generator that can execute SQL.
865
1654
 
866
1655
  Parameters
867
1656
  ----------
@@ -874,7 +1663,7 @@ class DatabaseExecute(DatabaseBase):
874
1663
 
875
1664
  Returns
876
1665
  -------
877
- Generator.
1666
+ AsyncGenerator.
878
1667
  """
879
1668
 
880
1669
  # Instance.
@@ -889,30 +1678,33 @@ class DatabaseExecute(DatabaseBase):
889
1678
  for row in data:
890
1679
  func_generator(**row)
891
1680
 
892
- return func_generator.generator
1681
+ # Create.
1682
+ agenerator = func_generator.agenerator()
1683
+
1684
+ return agenerator
893
1685
 
894
1686
 
895
1687
  @overload
896
- def sleep(self, report: bool | None = None) -> int: ...
1688
+ async def sleep(self, report: bool | None = None) -> int: ...
897
1689
 
898
1690
  @overload
899
- def sleep(self, second: int, report: bool | None = None) -> int: ...
1691
+ async def sleep(self, second: int, report: bool | None = None) -> int: ...
900
1692
 
901
1693
  @overload
902
- def sleep(self, low: int = 0, high: int = 10, report: bool | None = None) -> int: ...
1694
+ async def sleep(self, low: int = 0, high: int = 10, report: bool | None = None) -> int: ...
903
1695
 
904
1696
  @overload
905
- def sleep(self, *thresholds: float, report: bool | None = None) -> float: ...
1697
+ async def sleep(self, *thresholds: float, report: bool | None = None) -> float: ...
906
1698
 
907
1699
  @overload
908
- def sleep(self, *thresholds: float, precision: Literal[0], report: bool | None = None) -> int: ...
1700
+ async def sleep(self, *thresholds: float, precision: Literal[0], report: bool | None = None) -> int: ...
909
1701
 
910
1702
  @overload
911
- def sleep(self, *thresholds: float, precision: int, report: bool | None = None) -> float: ...
1703
+ async def sleep(self, *thresholds: float, precision: int, report: bool | None = None) -> float: ...
912
1704
 
913
- def sleep(self, *thresholds: float, precision: int | None = None, report: bool | None = None) -> float:
1705
+ async def sleep(self, *thresholds: float, precision: int | None = None, report: bool | None = None) -> float:
914
1706
  """
915
- Let the database wait random seconds.
1707
+ Asynchronous let the database wait random seconds.
916
1708
 
917
1709
  Parameters
918
1710
  ----------
@@ -942,89 +1734,6 @@ class DatabaseExecute(DatabaseBase):
942
1734
 
943
1735
  # Sleep.
944
1736
  sql = f'SELECT SLEEP({second})'
945
- self.execute(sql, report=report)
1737
+ await self.execute(sql, report=report)
946
1738
 
947
1739
  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