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