reydb 1.1.59__py3-none-any.whl → 1.1.61__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/rbuild.py CHANGED
@@ -9,17 +9,20 @@
9
9
  """
10
10
 
11
11
 
12
- from typing import TypedDict, NotRequired, Literal
12
+ from typing import TypedDict, NotRequired, Literal, Type, TypeVar, Generic
13
13
  from copy import deepcopy
14
- from reykit.rbase import throw
14
+ from reykit.rbase import throw, is_instance
15
15
  from reykit.rstdout import ask
16
16
 
17
17
  from . import rdb
18
18
  from .rbase import DatabaseBase, extract_path
19
+ from .rorm import DatabaseORMModel
19
20
 
20
21
 
21
22
  __all__ = (
23
+ 'DatabaseBuildSuper',
22
24
  'DatabaseBuild',
25
+ 'DatabaseBuildAsync'
23
26
  )
24
27
 
25
28
 
@@ -43,15 +46,16 @@ IndexSet = TypedDict(
43
46
  'comment': NotRequired[str | None]
44
47
  }
45
48
  )
49
+ DatabaseT = TypeVar('DatabaseT', 'rdb.Database', 'rdb.DatabaseAsync')
46
50
 
47
51
 
48
- class DatabaseBuild(DatabaseBase):
52
+ class DatabaseBuildSuper(DatabaseBase, Generic[DatabaseT]):
49
53
  """
50
- Database build type.
54
+ Database build super type.
51
55
  """
52
56
 
53
57
 
54
- def __init__(self, db: 'rdb.Database') -> None:
58
+ def __init__(self, db: DatabaseT) -> None:
55
59
  """
56
60
  Build instance attributes.
57
61
 
@@ -65,15 +69,14 @@ class DatabaseBuild(DatabaseBase):
65
69
  self._schema: dict[str, dict[str, list[str]]] | None = None
66
70
 
67
71
 
68
- def create_database(
72
+ def get_sql_create_database(
69
73
  self,
70
74
  name: str,
71
- character: str = 'utf8mb3',
72
- collate: str = 'utf8mb3_general_ci',
73
- execute: bool = True
75
+ character: str = 'utf8mb4',
76
+ collate: str = 'utf8mb4_0900_ai_ci'
74
77
  ) -> str:
75
78
  """
76
- Create database.
79
+ Get SQL of create database.
77
80
 
78
81
  Parameters
79
82
  ----------
@@ -84,16 +87,12 @@ class DatabaseBuild(DatabaseBase):
84
87
 
85
88
  Returns
86
89
  -------
87
- Execute SQL.
90
+ SQL.
88
91
  """
89
92
 
90
93
  # Generate.
91
94
  sql = f'CREATE DATABASE `{name}` CHARACTER SET {character} COLLATE {collate}'
92
95
 
93
- # Execute.
94
- if execute:
95
- self.db.execute(sql)
96
-
97
96
  return sql
98
97
 
99
98
 
@@ -216,7 +215,7 @@ class DatabaseBuild(DatabaseBase):
216
215
  return sql
217
216
 
218
217
 
219
- def create_table(
218
+ def get_sql_create_table(
220
219
  self,
221
220
  path: str | tuple[str, str],
222
221
  fields: FieldSet | list[FieldSet],
@@ -224,13 +223,12 @@ class DatabaseBuild(DatabaseBase):
224
223
  indexes: IndexSet | list[IndexSet] | None = None,
225
224
  engine: str = 'InnoDB',
226
225
  increment: int = 1,
227
- charset: str = 'utf8mb3',
228
- collate: str = 'utf8mb3_general_ci',
229
- comment: str | None = None,
230
- execute: bool = True
226
+ charset: str = 'utf8mb4',
227
+ collate: str = 'utf8mb4_0900_ai_ci',
228
+ comment: str | None = None
231
229
  ) -> str:
232
230
  """
233
- Create table.
231
+ Get SQL of create table.
234
232
 
235
233
  Parameters
236
234
  ----------
@@ -275,7 +273,7 @@ class DatabaseBuild(DatabaseBase):
275
273
 
276
274
  Returns
277
275
  -------
278
- Execute SQL.
276
+ SQL.
279
277
  """
280
278
 
281
279
  # Handle parameter.
@@ -340,21 +338,16 @@ class DatabaseBuild(DatabaseBase):
340
338
  f') ENGINE={engine} AUTO_INCREMENT={increment} CHARSET={charset} COLLATE={collate}{sql_comment}'
341
339
  )
342
340
 
343
- # Execute.
344
- if execute:
345
- self.db.execute(sql)
346
-
347
341
  return sql
348
342
 
349
343
 
350
- def create_view(
344
+ def get_sql_create_view(
351
345
  self,
352
346
  path: str | tuple[str, str],
353
- select: str,
354
- execute: bool = True
347
+ select: str
355
348
  ) -> str:
356
349
  """
357
- Create view.
350
+ Get SQL of create view.
358
351
 
359
352
  Parameters
360
353
  ----------
@@ -366,7 +359,7 @@ class DatabaseBuild(DatabaseBase):
366
359
 
367
360
  Returns
368
361
  -------
369
- Execute SQL.
362
+ SQL.
370
363
  """
371
364
 
372
365
  # Handle parameter.
@@ -376,21 +369,16 @@ class DatabaseBuild(DatabaseBase):
376
369
  select = select.replace('\n', '\n ')
377
370
  sql = 'CREATE VIEW `%s`.`%s` AS (\n %s\n)' % (database, view, select)
378
371
 
379
- # Execute.
380
- if execute:
381
- self.db.execute(sql)
382
-
383
372
  return sql
384
373
 
385
374
 
386
- def create_view_stats(
375
+ def get_sql_create_view_stats(
387
376
  self,
388
377
  path: str | tuple[str, str],
389
- items: list[dict],
390
- execute: bool = True
378
+ items: list[dict]
391
379
  ) -> str:
392
380
  """
393
- Create stats view.
381
+ Get SQL of create stats view.
394
382
 
395
383
  Parameters
396
384
  ----------
@@ -405,7 +393,7 @@ class DatabaseBuild(DatabaseBase):
405
393
 
406
394
  Returns
407
395
  -------
408
- Execute SQL.
396
+ SQL.
409
397
  """
410
398
 
411
399
  # Check.
@@ -439,22 +427,17 @@ class DatabaseBuild(DatabaseBase):
439
427
  select = '\nUNION\n'.join(selects)
440
428
 
441
429
  # Create.
442
- sql = self.create_view(
443
- path,
444
- select,
445
- execute
446
- )
430
+ sql = self.get_sql_create_view(path, select)
447
431
 
448
432
  return sql
449
433
 
450
434
 
451
- def drop_database(
435
+ def get_sql_drop_database(
452
436
  self,
453
- database: str,
454
- execute: bool = True
437
+ database: str
455
438
  ) -> str:
456
439
  """
457
- Drop database.
440
+ Get SQL of drop database.
458
441
 
459
442
  Parameters
460
443
  ----------
@@ -463,26 +446,21 @@ class DatabaseBuild(DatabaseBase):
463
446
 
464
447
  Returns
465
448
  -------
466
- Execute SQL.
449
+ SQL.
467
450
  """
468
451
 
469
452
  # Generate.
470
453
  sql = f'DROP DATABASE `{database}`'
471
454
 
472
- # Execute.
473
- if execute:
474
- self.db.execute(sql)
475
-
476
455
  return sql
477
456
 
478
457
 
479
- def drop_table(
458
+ def get_sql_drop_table(
480
459
  self,
481
- path: str | tuple[str, str],
482
- execute: bool = True
460
+ path: str | tuple[str, str]
483
461
  ) -> str:
484
462
  """
485
- Drop table.
463
+ Get SQL of drop table.
486
464
 
487
465
  Parameters
488
466
  ----------
@@ -493,7 +471,7 @@ class DatabaseBuild(DatabaseBase):
493
471
 
494
472
  Returns
495
473
  -------
496
- Execute SQL.
474
+ SQL.
497
475
  """
498
476
 
499
477
  # Handle parameter.
@@ -502,20 +480,15 @@ class DatabaseBuild(DatabaseBase):
502
480
  # Generate.
503
481
  sql = f'DROP TABLE `{database}`.`{table}`'
504
482
 
505
- # Execute.
506
- if execute:
507
- self.db.execute(sql)
508
-
509
483
  return sql
510
484
 
511
485
 
512
- def drop_view(
486
+ def get_sql_drop_view(
513
487
  self,
514
- path: str | tuple[str, str],
515
- execute: bool = True
488
+ path: str | tuple[str, str]
516
489
  ) -> str:
517
490
  """
518
- Drop view.
491
+ Get SQL of drop view.
519
492
 
520
493
  Parameters
521
494
  ----------
@@ -526,7 +499,7 @@ class DatabaseBuild(DatabaseBase):
526
499
 
527
500
  Returns
528
501
  -------
529
- Execute SQL.
502
+ SQL.
530
503
  """
531
504
 
532
505
  # Handle parameter.
@@ -535,22 +508,17 @@ class DatabaseBuild(DatabaseBase):
535
508
  # Generate SQL.
536
509
  sql = 'DROP VIEW `%s`.`%s`' % (database, view)
537
510
 
538
- # Execute.
539
- if execute:
540
- self.db.execute(sql)
541
-
542
511
  return sql
543
512
 
544
513
 
545
- def alter_database(
514
+ def get_sql_alter_database(
546
515
  self,
547
516
  database: str,
548
517
  character: str | None = None,
549
- collate: str | None = None,
550
- execute: bool = True
518
+ collate: str | None = None
551
519
  ) -> str:
552
520
  """
553
- Alter database.
521
+ Get SQL of alter database.
554
522
 
555
523
  Parameters
556
524
  ----------
@@ -565,7 +533,7 @@ class DatabaseBuild(DatabaseBase):
565
533
 
566
534
  Returns
567
535
  -------
568
- Execute SQL.
536
+ SQL.
569
537
  """
570
538
 
571
539
  # Generate.
@@ -585,23 +553,18 @@ class DatabaseBuild(DatabaseBase):
585
553
  ## Join.
586
554
  sql = f'ALTER DATABASE `{database}`{sql_character}{sql_collate}'
587
555
 
588
- # Execute.
589
- if execute:
590
- self.db.execute(sql)
591
-
592
556
  return sql
593
557
 
594
558
 
595
- def alter_table_add(
559
+ def get_sql_alter_table_add(
596
560
  self,
597
561
  path: str | tuple[str, str],
598
562
  fields: FieldSet | list[FieldSet] | None = None,
599
563
  primary: str | list[str] | None = None,
600
- indexes: IndexSet | list[IndexSet] | None = None,
601
- execute: bool = True
564
+ indexes: IndexSet | list[IndexSet] | None = None
602
565
  ) -> str:
603
566
  """
604
- Alter table add filed.
567
+ Get SQL of alter table add filed.
605
568
 
606
569
  Parameters
607
570
  ----------
@@ -640,7 +603,7 @@ class DatabaseBuild(DatabaseBase):
640
603
 
641
604
  Returns
642
605
  -------
643
- Execute SQL.
606
+ SQL.
644
607
  """
645
608
 
646
609
  # Handle parameter.
@@ -700,23 +663,18 @@ class DatabaseBuild(DatabaseBase):
700
663
  f' ADD {sql_content}'
701
664
  )
702
665
 
703
- # Execute.
704
- if execute:
705
- self.db.execute(sql)
706
-
707
666
  return sql
708
667
 
709
668
 
710
- def alter_table_drop(
669
+ def get_sql_alter_table_drop(
711
670
  self,
712
671
  path: str | tuple[str, str],
713
672
  fields: str | list[str] | None = None,
714
673
  primary: bool = False,
715
- indexes: str | list[str] | None = None,
716
- execute: bool = True
674
+ indexes: str | list[str] | None = None
717
675
  ) -> str:
718
676
  """
719
- Alter table drop field.
677
+ Get SQL of alter table drop field.
720
678
 
721
679
  Parameters
722
680
  ----------
@@ -730,7 +688,7 @@ class DatabaseBuild(DatabaseBase):
730
688
 
731
689
  Returns
732
690
  -------
733
- Execute SQL.
691
+ SQL.
734
692
  """
735
693
 
736
694
  # Handle parameter.
@@ -771,14 +729,10 @@ class DatabaseBuild(DatabaseBase):
771
729
  f' DROP {sql_content}'
772
730
  )
773
731
 
774
- # Execute.
775
- if execute:
776
- self.db.execute(sql)
777
-
778
732
  return sql
779
733
 
780
734
 
781
- def alter_table_change(
735
+ def get_sql_alter_table_change(
782
736
  self,
783
737
  path: str | tuple[str, str],
784
738
  fields: FieldSet | list[FieldSet] | None = None,
@@ -786,11 +740,10 @@ class DatabaseBuild(DatabaseBase):
786
740
  engine: str | None = None,
787
741
  increment: int | None = None,
788
742
  charset: str | None = None,
789
- collate: str | None = None,
790
- execute: bool = True
743
+ collate: str | None = None
791
744
  ) -> str:
792
745
  """
793
- Alter database.
746
+ Get SQL of alter database.
794
747
 
795
748
  Parameters
796
749
  ----------
@@ -820,7 +773,7 @@ class DatabaseBuild(DatabaseBase):
820
773
 
821
774
  Returns
822
775
  -------
823
- Execute SQL.
776
+ SQL.
824
777
  """
825
778
 
826
779
  # Handle parameter.
@@ -890,21 +843,16 @@ class DatabaseBuild(DatabaseBase):
890
843
  f' {sql_content}'
891
844
  )
892
845
 
893
- # Execute.
894
- if execute:
895
- self.db.execute(sql)
896
-
897
846
  return sql
898
847
 
899
848
 
900
- def alter_view(
849
+ def get_sql_alter_view(
901
850
  self,
902
851
  path: str | tuple[str, str],
903
- select: str,
904
- execute: bool = True
852
+ select: str
905
853
  ) -> str:
906
854
  """
907
- Alter view.
855
+ Get SQL of alter view.
908
856
 
909
857
  Parameters
910
858
  ----------
@@ -916,7 +864,7 @@ class DatabaseBuild(DatabaseBase):
916
864
 
917
865
  Returns
918
866
  -------
919
- Execute SQL.
867
+ SQL.
920
868
  """
921
869
 
922
870
  # Handle parameter.
@@ -925,20 +873,15 @@ class DatabaseBuild(DatabaseBase):
925
873
  # Generate SQL.
926
874
  sql = 'ALTER VIEW `%s`.`%s` AS\n%s' % (database, view, select)
927
875
 
928
- # Execute.
929
- if execute:
930
- self.db.execute(sql)
931
-
932
876
  return sql
933
877
 
934
878
 
935
- def truncate_table(
879
+ def get_sql_truncate_table(
936
880
  self,
937
- path: str | tuple[str, str],
938
- execute: bool = True
881
+ path: str | tuple[str, str]
939
882
  ) -> str:
940
883
  """
941
- Truncate table.
884
+ Get SQL of truncate table.
942
885
 
943
886
  Parameters
944
887
  ----------
@@ -949,7 +892,7 @@ class DatabaseBuild(DatabaseBase):
949
892
 
950
893
  Returns
951
894
  -------
952
- Execute SQL.
895
+ SQL.
953
896
  """
954
897
 
955
898
  # Handle parameter.
@@ -958,11 +901,285 @@ class DatabaseBuild(DatabaseBase):
958
901
  # Generate.
959
902
  sql = f'TRUNCATE TABLE `{database}`.`{table}`'
960
903
 
961
- # Execute.
962
- if execute:
904
+ return sql
905
+
906
+
907
+ def input_confirm_build(
908
+ self,
909
+ sql: str
910
+ ) -> None:
911
+ """
912
+ Print tip text, and confirm execute SQL. If reject, throw exception.
913
+
914
+ Parameters
915
+ ----------
916
+ sql : SQL.
917
+ """
918
+
919
+ # Confirm.
920
+ text = 'Do you want to execute SQL to build the database? Otherwise stop program. (y/n) '
921
+ command = ask(
922
+ sql,
923
+ text,
924
+ title='SQL',
925
+ frame='top'
926
+ )
927
+
928
+ # Check.
929
+ while True:
930
+ command = command.lower()
931
+ match command:
932
+
933
+ ## Confirm.
934
+ case 'y':
935
+ break
936
+
937
+ ## Stop.
938
+ case 'n':
939
+ raise AssertionError('program stop')
940
+
941
+ ## Reenter.
942
+ case _:
943
+ text = 'Incorrect input, reenter. (y/n) '
944
+ command = input(text)
945
+
946
+
947
+ def get_orm_table_text(self, model: DatabaseORMModel) -> str:
948
+ """
949
+ Get table text from ORM model.
950
+
951
+ Parameters
952
+ ----------
953
+ model : ORM model instances.
954
+
955
+ Returns
956
+ -------
957
+ Table text.
958
+ """
959
+
960
+ # Get.
961
+ table = model.table()
962
+ text = f'TABLE `{self.db.database}`.`{table}`'
963
+ if 'mysql_charset' in table.kwargs:
964
+ text += f" | CHARSET '{table.kwargs['mysql_charset']}'"
965
+ if table.comment:
966
+ text += f" | COMMENT '{table.comment}'"
967
+
968
+ ## Field.
969
+ text += '\n' + '\n'.join(
970
+ [
971
+ f' FIELD `{column.name}` : {column.type}' + (
972
+ ' | NOT NULL'
973
+ if (
974
+ not column.nullable
975
+ or column.primary_key
976
+ )
977
+ else ' | NULL'
978
+ ) + (
979
+ ''
980
+ if not column.primary_key
981
+ else ' | KEY AUTO'
982
+ if column.autoincrement
983
+ else ' | KEY'
984
+ ) + (
985
+ f" | DEFAULT '{column.server_default.arg}'"
986
+ if column.server_default
987
+ else ''
988
+ ) + (
989
+ f" | COMMMENT '{column.comment}'"
990
+ if column.comment
991
+ else ''
992
+ )
993
+ for column in table.columns
994
+ ]
995
+ )
996
+
997
+ ## Index.
998
+ if (table.indexes):
999
+ text += '\n' + '\n'.join(
1000
+ [
1001
+ (
1002
+ ' UNIQUE'
1003
+ if index.unique
1004
+ else ' NORMAL'
1005
+ ) + f' INDEX `{index.name}` : ' + ', '.join(
1006
+ [
1007
+ f'`{column.name}`'
1008
+ for column in index.expressions
1009
+ ]
1010
+ )
1011
+ for index in table.indexes
1012
+ ]
1013
+ )
1014
+
1015
+ return text
1016
+
1017
+
1018
+ def build(
1019
+ self,
1020
+ databases: list[dict] | None = None,
1021
+ tables: list[dict] | None = None,
1022
+ tables_orm: list[Type[DatabaseORMModel]] | None = None,
1023
+ views: list[dict] | None = None,
1024
+ views_stats: list[dict] | None = None,
1025
+ ask: bool = True,
1026
+ skip: bool = False
1027
+ ) -> None:
1028
+ """
1029
+ Build databases or tables.
1030
+
1031
+ Parameters
1032
+ ----------
1033
+ databases : Database build parameters, equivalent to the parameters of method `self.create_database`.
1034
+ tables : Tables build parameters, equivalent to the parameters of method `self.create_table`.
1035
+ tables_orm : Tables buile model, equivalent to the parameters of method `self.create_table_orm`.
1036
+ views : Views build parameters, equivalent to the parameters of method `self.create_view`.
1037
+ views_stats : Views stats build parameters, equivalent to the parameters of method `self.create_view_stats`.
1038
+ ask : Whether ask confirm execute.
1039
+ skip : Whether skip existing table.
1040
+ """
1041
+
1042
+ # Handle parameter.
1043
+ databases = databases or []
1044
+ tables = tables or []
1045
+ tables_orm = tables_orm or []
1046
+ views = views or []
1047
+ views_stats = views_stats or []
1048
+
1049
+ # Database.
1050
+ for params in databases:
1051
+ database = params['name']
1052
+
1053
+ ## Exist.
1054
+ if (
1055
+ skip
1056
+ and self.exist(database)
1057
+ ):
1058
+ continue
1059
+
1060
+ ## Create.
1061
+ sql = self.get_sql_create_database(**params)
1062
+
1063
+ ## Confirm.
1064
+ if ask:
1065
+ self.input_confirm_build(sql)
1066
+
1067
+ ## Execute.
963
1068
  self.db.execute(sql)
964
1069
 
965
- return sql
1070
+ ## Report.
1071
+ text = f"Database '{database}' build completed."
1072
+ print(text)
1073
+
1074
+ # Table.
1075
+ for params in tables:
1076
+ path = params['path']
1077
+ database, table, _ = extract_path(path)
1078
+
1079
+ ## Exist.
1080
+ if (
1081
+ skip
1082
+ and self.exist((database, table))
1083
+ ):
1084
+ continue
1085
+
1086
+ ## Create.
1087
+ sql = self.create_table(**params)
1088
+
1089
+ ## Confirm.
1090
+ if ask:
1091
+ self.input_confirm_build(sql)
1092
+
1093
+ ## Execute.
1094
+ self.db.execute(sql)
1095
+
1096
+ ## Report.
1097
+ text = f"Table '{table}' of database '{database}' build completed."
1098
+ print(text)
1099
+
1100
+ # Table ORM.
1101
+ for model in tables_orm:
1102
+ table = model.table()
1103
+
1104
+ ## Exist.
1105
+ if (
1106
+ skip
1107
+ and self.exist((self.db.database, table.name))
1108
+ ):
1109
+ continue
1110
+
1111
+ ## Confirm.
1112
+ if ask:
1113
+ text = self.get_orm_table_text(model)
1114
+ self.input_confirm_build(text)
1115
+
1116
+ ## Execute.
1117
+ self.create_orm_table(model)
1118
+
1119
+ ## Report.
1120
+ text = f"Table '{table.name}' of database '{self.db.database}' build completed."
1121
+ print(text)
1122
+
1123
+ # View.
1124
+ for params in views:
1125
+ path = params['path']
1126
+ database, view, _ = extract_path(path)
1127
+
1128
+ ## Exist.
1129
+ if (
1130
+ skip
1131
+ and self.exist((database, view))
1132
+ ):
1133
+ continue
1134
+
1135
+ ## Create.
1136
+ sql = self.create_view(**params)
1137
+
1138
+ ## Confirm.
1139
+ if ask:
1140
+ self.input_confirm_build(sql)
1141
+
1142
+ ## Execute.
1143
+ self.db.execute(sql)
1144
+
1145
+ ## Report.
1146
+ text = f"View '{view}' of database '{database}' build completed."
1147
+ print(text)
1148
+
1149
+ # View stats.
1150
+ for params in views_stats:
1151
+ path = params['path']
1152
+ database, view, _ = extract_path(path)
1153
+
1154
+ ## Exist.
1155
+ if (
1156
+ skip
1157
+ and self.exist((database, view))
1158
+ ):
1159
+ continue
1160
+
1161
+ ## Create.
1162
+ sql = self.create_view_stats(**params)
1163
+
1164
+ ## Confirm.
1165
+ if ask:
1166
+ self.input_confirm_build(sql)
1167
+
1168
+ ## Execute.
1169
+ self.db.execute(sql)
1170
+
1171
+ ## Report.
1172
+ text = f"View '{view}' of database '{database}' build completed."
1173
+ print(text)
1174
+
1175
+
1176
+ __call__ = build
1177
+
1178
+
1179
+ class DatabaseBuild(DatabaseBuildSuper['rdb.Database']):
1180
+ """
1181
+ Database build type.
1182
+ """
966
1183
 
967
1184
 
968
1185
  def exist(
@@ -1007,52 +1224,50 @@ class DatabaseBuild(DatabaseBase):
1007
1224
  return judge
1008
1225
 
1009
1226
 
1010
- def input_confirm_build(
1227
+ def create_orm_table(
1011
1228
  self,
1012
- sql: str
1229
+ *models: Type[DatabaseORMModel] | DatabaseORMModel,
1230
+ skip: bool = False
1013
1231
  ) -> None:
1014
1232
  """
1015
- Print tip text, and confirm execute SQL. If reject, throw exception.
1233
+ Create tables by ORM model.
1016
1234
 
1017
1235
  Parameters
1018
1236
  ----------
1019
- sql : SQL.
1237
+ models : ORM model instances.
1238
+ skip : Whether skip existing table.
1020
1239
  """
1021
1240
 
1022
- # Confirm.
1023
- text = 'Do you want to execute SQL to build the database? Otherwise stop program. (y/n) '
1024
- command = ask(
1025
- sql,
1026
- text,
1027
- title='SQL',
1028
- frame='top'
1029
- )
1241
+ # Create.
1242
+ self.db.orm.create(*models, skip=skip)
1030
1243
 
1031
- # Check.
1032
- while True:
1033
- command = command.lower()
1034
- match command:
1035
1244
 
1036
- ## Confirm.
1037
- case 'y':
1038
- break
1245
+ def drop_orm_table(
1246
+ self,
1247
+ *models: Type[DatabaseORMModel] | DatabaseORMModel,
1248
+ skip: bool = False
1249
+ ) -> None:
1250
+ """
1251
+ Delete tables by model.
1039
1252
 
1040
- ## Stop.
1041
- case 'n':
1042
- raise AssertionError('program stop')
1253
+ Parameters
1254
+ ----------
1255
+ models : ORM model instances.
1256
+ skip : Skip not exist table.
1257
+ """
1043
1258
 
1044
- ## Reenter.
1045
- case _:
1046
- text = 'Incorrect input, reenter. (y/n) '
1047
- command = input(text)
1259
+ # Drop.
1260
+ self.db.orm.drop(*models, skip=skip)
1048
1261
 
1049
1262
 
1050
1263
  def build(
1051
1264
  self,
1052
1265
  databases: list[dict] | None = None,
1053
- tables: list[dict] | None = None,
1266
+ tables: list[dict | Type[DatabaseORMModel] | DatabaseORMModel] | None = None,
1054
1267
  views: list[dict] | None = None,
1055
- views_stats: list[dict] | None = None
1268
+ views_stats: list[dict] | None = None,
1269
+ ask: bool = True,
1270
+ skip: bool = False
1056
1271
  ) -> None:
1057
1272
  """
1058
1273
  Build databases or tables.
@@ -1060,9 +1275,11 @@ class DatabaseBuild(DatabaseBase):
1060
1275
  Parameters
1061
1276
  ----------
1062
1277
  databases : Database build parameters, equivalent to the parameters of method `self.create_database`.
1063
- tables : Tables build parameters, equivalent to the parameters of method `self.create_table`.
1278
+ tables : Tables build parameters or model, equivalent to the parameters of method `self.create_table` or `self.create_orm_table`.
1064
1279
  views : Views build parameters, equivalent to the parameters of method `self.create_view`.
1065
1280
  views_stats : Views stats build parameters, equivalent to the parameters of method `self.create_view_stats`.
1281
+ ask : Whether ask confirm execute.
1282
+ skip : Whether skip existing table.
1066
1283
  """
1067
1284
 
1068
1285
  # Handle parameter.
@@ -1076,15 +1293,18 @@ class DatabaseBuild(DatabaseBase):
1076
1293
  database = params['name']
1077
1294
 
1078
1295
  ## Exist.
1079
- exist = self.db.build.exist((database, None, None))
1080
- if exist:
1296
+ if (
1297
+ skip
1298
+ and self.exist(database)
1299
+ ):
1081
1300
  continue
1082
1301
 
1083
- ## Create.
1084
- sql = self.create_database(**params, execute=False)
1302
+ ## SQL.
1303
+ sql = self.get_sql_create_database(**params)
1085
1304
 
1086
1305
  ## Confirm.
1087
- self.input_confirm_build(sql)
1306
+ if ask:
1307
+ self.input_confirm_build(sql)
1088
1308
 
1089
1309
  ## Execute.
1090
1310
  self.db.execute(sql)
@@ -1095,23 +1315,303 @@ class DatabaseBuild(DatabaseBase):
1095
1315
 
1096
1316
  # Table.
1097
1317
  for params in tables:
1318
+
1319
+ ## ORM.
1320
+ if (
1321
+ issubclass(params, DatabaseORMModel)
1322
+ or isinstance(params, DatabaseORMModel)
1323
+ ):
1324
+ database = self.db.database
1325
+ table = params.table().name
1326
+
1327
+ ## Exist.
1328
+ if (
1329
+ skip
1330
+ and self.exist((self.db.database, table))
1331
+ ):
1332
+ continue
1333
+
1334
+ ## Confirm.
1335
+ if ask:
1336
+ text = self.get_orm_table_text(params)
1337
+ self.input_confirm_build(text)
1338
+
1339
+ ## Execute.
1340
+ self.create_orm_table(params)
1341
+
1342
+ ## Parameter.
1343
+ else:
1344
+ path = params['path']
1345
+ database, table, _ = extract_path(path)
1346
+
1347
+ ### Exist.
1348
+ if (
1349
+ skip
1350
+ and self.exist((database, table))
1351
+ ):
1352
+ continue
1353
+
1354
+ ### SQL.
1355
+ sql = self.get_sql_create_table(**params)
1356
+
1357
+ ### Confirm.
1358
+ if ask:
1359
+ self.input_confirm_build(sql)
1360
+
1361
+ ### Execute.
1362
+ self.db.execute(sql)
1363
+
1364
+ ## Report.
1365
+ text = f"Table '{table}' of database '{database}' build completed."
1366
+ print(text)
1367
+
1368
+ # View.
1369
+ for params in views:
1098
1370
  path = params['path']
1099
- database, table, _ = extract_path(path)
1371
+ database, view, _ = extract_path(path)
1100
1372
 
1101
1373
  ## Exist.
1102
- exist = self.db.build.exist((database, table, None))
1103
- if exist:
1374
+ if (
1375
+ skip
1376
+ and self.exist((database, view))
1377
+ ):
1104
1378
  continue
1105
1379
 
1106
- ## Create.
1107
- sql = self.create_table(**params, execute=False)
1380
+ ## SQL.
1381
+ sql = self.get_sql_create_view(**params)
1108
1382
 
1109
1383
  ## Confirm.
1110
- self.input_confirm_build(sql)
1384
+ if ask:
1385
+ self.input_confirm_build(sql)
1111
1386
 
1112
1387
  ## Execute.
1113
1388
  self.db.execute(sql)
1114
1389
 
1390
+ ## Report.
1391
+ text = f"View '{view}' of database '{database}' build completed."
1392
+ print(text)
1393
+
1394
+ # View stats.
1395
+ for params in views_stats:
1396
+ path = params['path']
1397
+ database, view, _ = extract_path(path)
1398
+
1399
+ ## Exist.
1400
+ if (
1401
+ skip
1402
+ and self.exist((database, view))
1403
+ ):
1404
+ continue
1405
+
1406
+ ## SQL.
1407
+ sql = self.get_sql_create_view_stats(**params)
1408
+
1409
+ ## Confirm.
1410
+ if ask:
1411
+ self.input_confirm_build(sql)
1412
+
1413
+ ## Execute.
1414
+ self.db.execute(sql)
1415
+
1416
+ ## Report.
1417
+ text = f"View '{view}' of database '{database}' build completed."
1418
+ print(text)
1419
+
1420
+
1421
+ __call__ = build
1422
+
1423
+
1424
+ class DatabaseBuildAsync(DatabaseBuildSuper['rdb.DatabaseAsync']):
1425
+ """
1426
+ Asynchronous database build type.
1427
+ """
1428
+
1429
+
1430
+ async def exist(
1431
+ self,
1432
+ path: str | tuple[str] | tuple[str, str] | tuple[str, str, str]
1433
+ ) -> bool:
1434
+ """
1435
+ Asynchronous judge database or table or column exists.
1436
+
1437
+ Parameters
1438
+ ----------
1439
+ path : Database name and table name and column name.
1440
+ - `str`: Automatic extract.
1441
+ - `tuple`: Format is `(database[, table, column]).`
1442
+
1443
+ Returns
1444
+ -------
1445
+ Judge result.
1446
+ """
1447
+
1448
+ # Handle parameter.
1449
+ database, table, column = extract_path(path)
1450
+ if self._schema is None:
1451
+ self._schema = await self.db.schema(False)
1452
+
1453
+ # Judge.
1454
+ judge = (
1455
+ database in self._schema
1456
+ and (
1457
+ table is None
1458
+ or (
1459
+ (database_info := self._schema.get(database)) is not None
1460
+ and (table_info := database_info.get(table)) is not None
1461
+ )
1462
+ )
1463
+ and (
1464
+ column is None
1465
+ or column in table_info
1466
+ )
1467
+ )
1468
+
1469
+ return judge
1470
+
1471
+
1472
+ async def create_orm_table(
1473
+ self,
1474
+ *models: Type[DatabaseORMModel] | DatabaseORMModel,
1475
+ skip: bool = False
1476
+ ) -> None:
1477
+ """
1478
+ Asynchronous create tables by ORM model.
1479
+
1480
+ Parameters
1481
+ ----------
1482
+ models : ORM model instances.
1483
+ skip : Whether skip existing table.
1484
+ """
1485
+
1486
+ # Create.
1487
+ await self.db.orm.create(*models, skip=skip)
1488
+
1489
+
1490
+ async def drop_orm_table(
1491
+ self,
1492
+ *models: Type[DatabaseORMModel] | DatabaseORMModel,
1493
+ skip: bool = False
1494
+ ) -> None:
1495
+ """
1496
+ Asynchronous delete tables by model.
1497
+
1498
+ Parameters
1499
+ ----------
1500
+ models : ORM model instances.
1501
+ skip : Skip not exist table.
1502
+ """
1503
+
1504
+ # Drop.
1505
+ await self.db.orm.drop(*models, skip=skip)
1506
+
1507
+
1508
+ async def build(
1509
+ self,
1510
+ databases: list[dict] | None = None,
1511
+ tables: list[dict] | None = None,
1512
+ tables_orm: list[Type[DatabaseORMModel]] | None = None,
1513
+ views: list[dict] | None = None,
1514
+ views_stats: list[dict] | None = None,
1515
+ ask: bool = True,
1516
+ skip: bool = False
1517
+ ) -> None:
1518
+ """
1519
+ Asynchronous build databases or tables.
1520
+
1521
+ Parameters
1522
+ ----------
1523
+ databases : Database build parameters, equivalent to the parameters of method `self.create_database`.
1524
+ tables : Tables build parameters, equivalent to the parameters of method `self.create_table`.
1525
+ tables_orm : Tables buile model, equivalent to the parameters of method `self.create_table_orm`.
1526
+ views : Views build parameters, equivalent to the parameters of method `self.create_view`.
1527
+ views_stats : Views stats build parameters, equivalent to the parameters of method `self.create_view_stats`.
1528
+ ask : Whether ask confirm execute.
1529
+ skip : Whether skip existing table.
1530
+ """
1531
+
1532
+ # Handle parameter.
1533
+ databases = databases or []
1534
+ tables = tables or []
1535
+ tables_orm = tables_orm or []
1536
+ views = views or []
1537
+ views_stats = views_stats or []
1538
+
1539
+ # Database.
1540
+ for params in databases:
1541
+ database = params['name']
1542
+
1543
+ ## Exist.
1544
+ if (
1545
+ skip
1546
+ and await self.exist(database)
1547
+ ):
1548
+ continue
1549
+
1550
+ ## SQL.
1551
+ sql = self.get_sql_create_database(**params)
1552
+
1553
+ ## Confirm.
1554
+ if ask:
1555
+ self.input_confirm_build(sql)
1556
+
1557
+ ## Execute.
1558
+ await self.db.execute(sql)
1559
+
1560
+ ## Report.
1561
+ text = f"Database '{database}' build completed."
1562
+ print(text)
1563
+
1564
+ # Table.
1565
+ for params in tables:
1566
+ if is_instance(params):
1567
+ params_type = type(params)
1568
+
1569
+ ## ORM.
1570
+ if (
1571
+ is_instance(params)
1572
+ and isinstance(params, DatabaseORMModel)
1573
+ or issubclass(params, DatabaseORMModel)
1574
+ ):
1575
+ database = self.db.database
1576
+ table = params.table().name
1577
+
1578
+ ## Exist.
1579
+ if (
1580
+ skip
1581
+ and await self.exist((self.db.database, table))
1582
+ ):
1583
+ continue
1584
+
1585
+ ## Confirm.
1586
+ if ask:
1587
+ text = self.get_orm_table_text(params)
1588
+ self.input_confirm_build(text)
1589
+
1590
+ ## Execute.
1591
+ await self.create_orm_table(params)
1592
+
1593
+ ## Parameter.
1594
+ else:
1595
+ path = params['path']
1596
+ database, table, _ = extract_path(path)
1597
+
1598
+ ### Exist.
1599
+ if (
1600
+ skip
1601
+ and await self.exist((database, table))
1602
+ ):
1603
+ continue
1604
+
1605
+ ### SQL.
1606
+ sql = self.get_sql_create_table(**params)
1607
+
1608
+ ### Confirm.
1609
+ if ask:
1610
+ self.input_confirm_build(sql)
1611
+
1612
+ ### Execute.
1613
+ await self.db.execute(sql)
1614
+
1115
1615
  ## Report.
1116
1616
  text = f"Table '{table}' of database '{database}' build completed."
1117
1617
  print(text)
@@ -1122,18 +1622,21 @@ class DatabaseBuild(DatabaseBase):
1122
1622
  database, view, _ = extract_path(path)
1123
1623
 
1124
1624
  ## Exist.
1125
- exist = self.db.build.exist((database, view, None))
1126
- if exist:
1625
+ if (
1626
+ skip
1627
+ and await self.exist((database, view))
1628
+ ):
1127
1629
  continue
1128
1630
 
1129
- ## Create.
1130
- sql = self.create_view(**params, execute=False)
1631
+ ## SQL.
1632
+ sql = self.get_sql_create_view(**params)
1131
1633
 
1132
1634
  ## Confirm.
1133
- self.input_confirm_build(sql)
1635
+ if ask:
1636
+ self.input_confirm_build(sql)
1134
1637
 
1135
1638
  ## Execute.
1136
- self.db.execute(sql)
1639
+ await self.db.execute(sql)
1137
1640
 
1138
1641
  ## Report.
1139
1642
  text = f"View '{view}' of database '{database}' build completed."
@@ -1145,18 +1648,21 @@ class DatabaseBuild(DatabaseBase):
1145
1648
  database, view, _ = extract_path(path)
1146
1649
 
1147
1650
  ## Exist.
1148
- exist = self.db.build.exist((database, view, None))
1149
- if exist:
1651
+ if (
1652
+ skip
1653
+ and await self.exist((database, view))
1654
+ ):
1150
1655
  continue
1151
1656
 
1152
- ## Create.
1153
- sql = self.create_view_stats(**params, execute=False)
1657
+ ## SQL.
1658
+ sql = self.get_sql_create_view_stats(**params)
1154
1659
 
1155
1660
  ## Confirm.
1156
- self.input_confirm_build(sql)
1661
+ if ask:
1662
+ self.input_confirm_build(sql)
1157
1663
 
1158
1664
  ## Execute.
1159
- self.db.execute(sql)
1665
+ await self.db.execute(sql)
1160
1666
 
1161
1667
  ## Report.
1162
1668
  text = f"View '{view}' of database '{database}' build completed."