reydb 1.2.17__py3-none-any.whl → 1.2.19__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
@@ -970,1486 +970,6 @@ class DatabaseBuildSuper(DatabaseBase, Generic[DatabaseT]):
970
970
  command = input(text)
971
971
 
972
972
 
973
- def get_orm_table_text(self, model: DatabaseORMModel) -> str:
974
- """
975
- Get table text from ORM model.
976
-
977
- Parameters
978
- ----------
979
- model : ORM model instances.
980
-
981
- Returns
982
- -------
983
- Table text.
984
- """
985
-
986
- # Get.
987
- table = model._get_table()
988
- text = f'TABLE `{self.db.database}`.`{table}`'
989
- if 'mysql_charset' in table.kwargs:
990
- text += f" | CHARSET '{table.kwargs['mysql_charset']}'"
991
- if table.comment:
992
- text += f" | COMMENT '{table.comment}'"
993
-
994
- ## Field.
995
- text += '\n' + '\n'.join(
996
- [
997
- f' FIELD `{column.name}` : {column.type}' + (
998
- ' | NOT NULL'
999
- if (
1000
- not column.nullable
1001
- or column.primary_key
1002
- )
1003
- else ' | NULL'
1004
- ) + (
1005
- ''
1006
- if not column.primary_key
1007
- else ' | KEY AUTO'
1008
- if column.autoincrement
1009
- else ' | KEY'
1010
- ) + (
1011
- f" | DEFAULT '{column.server_default.arg}'"
1012
- if column.server_default
1013
- else ''
1014
- ) + (
1015
- f" | COMMMENT '{column.comment}'"
1016
- if column.comment
1017
- else ''
1018
- )
1019
- for column in table.columns
1020
- ]
1021
- )
1022
-
1023
- ## Index.
1024
- if (table.indexes):
1025
- text += '\n' + '\n'.join(
1026
- [
1027
- (
1028
- ' UNIQUE'
1029
- if index.unique
1030
- else ' NORMAL'
1031
- ) + f' INDEX `{index.name}` : ' + ', '.join(
1032
- [
1033
- f'`{column.name}`'
1034
- for column in index.expressions
1035
- ]
1036
- )
1037
- for index in table.indexes
1038
- ]
1039
- )
1040
-
1041
- return text
1042
-
1043
-
1044
- class DatabaseBuild(DatabaseBuildSuper['rdb.Database']):
1045
- """
1046
- Database build type.
1047
- """
1048
-
1049
-
1050
- def create_orm_table(
1051
- self,
1052
- *models: Type[DatabaseORMModel] | DatabaseORMModel,
1053
- skip: bool = False
1054
- ) -> None:
1055
- """
1056
- Create tables by ORM model.
1057
-
1058
- Parameters
1059
- ----------
1060
- models : ORM model instances.
1061
- skip : Whether skip existing table.
1062
- """
1063
-
1064
- # Create.
1065
- self.db.orm.create(*models, skip=skip)
1066
-
1067
-
1068
- def drop_orm_table(
1069
- self,
1070
- *models: Type[DatabaseORMModel] | DatabaseORMModel,
1071
- skip: bool = False
1072
- ) -> None:
1073
- """
1074
- Delete tables by model.
1075
-
1076
- Parameters
1077
- ----------
1078
- models : ORM model instances.
1079
- skip : Skip not exist table.
1080
- """
1081
-
1082
- # Drop.
1083
- self.db.orm.drop(*models, skip=skip)
1084
-
1085
-
1086
- def build(
1087
- self,
1088
- databases: list[dict] | None = None,
1089
- tables: list[dict | Type[DatabaseORMModel] | DatabaseORMModel] | None = None,
1090
- views: list[dict] | None = None,
1091
- views_stats: list[dict] | None = None,
1092
- ask: bool = True,
1093
- skip: bool = False
1094
- ) -> None:
1095
- """
1096
- Build databases or tables.
1097
-
1098
- Parameters
1099
- ----------
1100
- databases : Database build parameters, equivalent to the parameters of method `self.create_database`.
1101
- tables : Tables build parameters or model, equivalent to the parameters of method `self.create_table` or `self.create_orm_table`.
1102
- views : Views build parameters, equivalent to the parameters of method `self.create_view`.
1103
- views_stats : Views stats build parameters, equivalent to the parameters of method `self.create_view_stats`.
1104
- ask : Whether ask confirm execute.
1105
- skip : Whether skip existing table.
1106
- """
1107
-
1108
- # Parameter.
1109
- databases = databases or []
1110
- tables = tables or []
1111
- views = views or []
1112
- views_stats = views_stats or []
1113
- refresh_schema = False
1114
-
1115
- # Database.
1116
- for params in databases:
1117
- database = params['name']
1118
-
1119
- ## Exist.
1120
- if (
1121
- skip
1122
- and self.db.schema.exist(database)
1123
- ):
1124
- continue
1125
-
1126
- ## SQL.
1127
- sql = self.get_sql_create_database(**params)
1128
-
1129
- ## Confirm.
1130
- if ask:
1131
- self.input_confirm_build(sql)
1132
-
1133
- ## Execute.
1134
- self.db.execute(sql)
1135
-
1136
- ## Report.
1137
- text = f"Database '{database}' build completed."
1138
- print(text)
1139
-
1140
- # Table.
1141
- for params in tables:
1142
-
1143
- ## ORM.
1144
- if (
1145
- is_instance(params)
1146
- and isinstance(params, DatabaseORMModel)
1147
- or issubclass(params, DatabaseORMModel)
1148
- ):
1149
- database = self.db.database
1150
- table = params._get_table().name
1151
-
1152
- ## Exist.
1153
- if (
1154
- skip
1155
- and self.db.schema.exist(self.db.database, table)
1156
- ):
1157
- continue
1158
-
1159
- ## Confirm.
1160
- if ask:
1161
- text = self.get_orm_table_text(params)
1162
- self.input_confirm_build(text)
1163
-
1164
- ## Execute.
1165
- self.create_orm_table(params)
1166
-
1167
- ## Parameter.
1168
- else:
1169
- path: str | tuple[str, str] = params['path']
1170
- if type(path) == str:
1171
- database, table = self.db.database, path
1172
- else:
1173
- database, table = path
1174
-
1175
- ### Exist.
1176
- if (
1177
- skip
1178
- and self.db.schema.exist(database, table)
1179
- ):
1180
- continue
1181
-
1182
- ### SQL.
1183
- sql = self.get_sql_create_table(**params)
1184
-
1185
- ### Confirm.
1186
- if ask:
1187
- self.input_confirm_build(sql)
1188
-
1189
- ### Execute.
1190
- self.db.execute(sql)
1191
-
1192
- ## Report.
1193
- text = f"Table '{table}' of database '{database}' build completed."
1194
- print(text)
1195
- refresh_schema = True
1196
-
1197
- # Refresh schema.
1198
- if refresh_schema:
1199
- self.db.schema()
1200
-
1201
- # View.
1202
- for params in views:
1203
- path = params['path']
1204
- if type(path) == str:
1205
- database, table = self.db.database, path
1206
- else:
1207
- database, table = path
1208
-
1209
- ## Exist.
1210
- if (
1211
- skip
1212
- and self.db.schema.exist(database, table)
1213
- ):
1214
- continue
1215
-
1216
- ## SQL.
1217
- sql = self.get_sql_create_view(**params)
1218
-
1219
- ## Confirm.
1220
- if ask:
1221
- self.input_confirm_build(sql)
1222
-
1223
- ## Execute.
1224
- self.db.execute(sql)
1225
-
1226
- ## Report.
1227
- text = f"View '{table}' of database '{database}' build completed."
1228
- print(text)
1229
-
1230
- # View stats.
1231
- for params in views_stats:
1232
- path = params['path']
1233
- if type(path) == str:
1234
- database, table = self.db.database, path
1235
- else:
1236
- database, table = path
1237
-
1238
- ## Exist.
1239
- if (
1240
- skip
1241
- and self.db.schema.exist(database, table)
1242
- ):
1243
- continue
1244
-
1245
- ## SQL.
1246
- sql = self.get_sql_create_view_stats(**params)
1247
-
1248
- ## Confirm.
1249
- if ask:
1250
- self.input_confirm_build(sql)
1251
-
1252
- ## Execute.
1253
- self.db.execute(sql)
1254
-
1255
- ## Report.
1256
- text = f"View '{table}' of database '{database}' build completed."
1257
- print(text)
1258
-
1259
-
1260
- __call__ = build
1261
-
1262
-
1263
- class DatabaseBuildAsync(DatabaseBuildSuper['rdb.DatabaseAsync']):
1264
- """
1265
- Asynchronous database build type.
1266
- """
1267
-
1268
-
1269
- async def create_orm_table(
1270
- self,
1271
- *models: Type[DatabaseORMModel] | DatabaseORMModel,
1272
- skip: bool = False
1273
- ) -> None:
1274
- """
1275
- Asynchronous create tables by ORM model.
1276
-
1277
- Parameters
1278
- ----------
1279
- models : ORM model instances.
1280
- skip : Whether skip existing table.
1281
- """
1282
-
1283
- # Create.
1284
- await self.db.orm.create(*models, skip=skip)
1285
-
1286
-
1287
- async def drop_orm_table(
1288
- self,
1289
- *models: Type[DatabaseORMModel] | DatabaseORMModel,
1290
- skip: bool = False
1291
- ) -> None:
1292
- """
1293
- Asynchronous delete tables by model.
1294
-
1295
- Parameters
1296
- ----------
1297
- models : ORM model instances.
1298
- skip : Skip not exist table.
1299
- """
1300
-
1301
- # Drop.
1302
- await self.db.orm.drop(*models, skip=skip)
1303
-
1304
-
1305
- async def build(
1306
- self,
1307
- databases: list[dict] | None = None,
1308
- tables: list[dict] | None = None,
1309
- tables_orm: list[Type[DatabaseORMModel]] | None = None,
1310
- views: list[dict] | None = None,
1311
- views_stats: list[dict] | None = None,
1312
- ask: bool = True,
1313
- skip: bool = False
1314
- ) -> None:
1315
- """
1316
- Asynchronous build databases or tables.
1317
-
1318
- Parameters
1319
- ----------
1320
- databases : Database build parameters, equivalent to the parameters of method `self.create_database`.
1321
- tables : Tables build parameters, equivalent to the parameters of method `self.create_table`.
1322
- views : Views build parameters, equivalent to the parameters of method `self.create_view`.
1323
- views_stats : Views stats build parameters, equivalent to the parameters of method `self.create_view_stats`.
1324
- ask : Whether ask confirm execute.
1325
- skip : Whether skip existing table.
1326
- """
1327
-
1328
- # Parameter.
1329
- databases = databases or []
1330
- tables = tables or []
1331
- tables_orm = tables_orm or []
1332
- views = views or []
1333
- views_stats = views_stats or []
1334
- refresh_schema = False
1335
-
1336
- # Database.
1337
- for params in databases:
1338
- database = params['name']
1339
-
1340
- ## Exist.
1341
- if (
1342
- skip
1343
- and await self.db.schema.exist(database)
1344
- ):
1345
- continue
1346
-
1347
- ## SQL.
1348
- sql = self.get_sql_create_database(**params)
1349
-
1350
- ## Confirm.
1351
- if ask:
1352
- self.input_confirm_build(sql)
1353
-
1354
- ## Execute.
1355
- await self.db.execute(sql)
1356
-
1357
- ## Report.
1358
- text = f"Database '{database}' build completed."
1359
- print(text)
1360
-
1361
- # Table.
1362
- for params in tables:
1363
-
1364
- ## ORM.
1365
- if (
1366
- is_instance(params)
1367
- and isinstance(params, DatabaseORMModel)
1368
- or issubclass(params, DatabaseORMModel)
1369
- ):
1370
- database = self.db.database
1371
- table = params._get_table().name
1372
-
1373
- ## Exist.
1374
- if (
1375
- skip
1376
- and await self.db.schema.exist(self.db.database, table)
1377
- ):
1378
- continue
1379
-
1380
- ## Confirm.
1381
- if ask:
1382
- text = self.get_orm_table_text(params)
1383
- self.input_confirm_build(text)
1384
-
1385
- ## Execute.
1386
- await self.create_orm_table(params)
1387
-
1388
- ## Parameter.
1389
- else:
1390
- path: str | tuple[str, str] = params['path']
1391
- if type(path) == str:
1392
- database, table = self.db.database, path
1393
- else:
1394
- database, table = path
1395
-
1396
- ### Exist.
1397
- if (
1398
- skip
1399
- and await self.db.schema.exist(database, table)
1400
- ):
1401
- continue
1402
-
1403
- ### SQL.
1404
- sql = self.get_sql_create_table(**params)
1405
-
1406
- ### Confirm.
1407
- if ask:
1408
- self.input_confirm_build(sql)
1409
-
1410
- ### Execute.
1411
- await self.db.execute(sql)
1412
- refresh_schema = True
1413
-
1414
- ## Report.
1415
- text = f"Table '{table}' of database '{database}' build completed."
1416
- print(text)
1417
-
1418
- # Refresh schema.
1419
- if refresh_schema:
1420
- self.db.schema()
1421
-
1422
- # View.
1423
- for params in views:
1424
- path = params['path']
1425
- if type(path) == str:
1426
- database, table = self.db.database, path
1427
- else:
1428
- database, table = path
1429
-
1430
- ## Exist.
1431
- if (
1432
- skip
1433
- and await self.db.schema.exist(database, table)
1434
- ):
1435
- continue
1436
-
1437
- ## SQL.
1438
- sql = self.get_sql_create_view(**params)
1439
-
1440
- ## Confirm.
1441
- if ask:
1442
- self.input_confirm_build(sql)
1443
-
1444
- ## Execute.
1445
- await self.db.execute(sql)
1446
-
1447
- ## Report.
1448
- text = f"View '{table}' of database '{database}' build completed."
1449
- print(text)
1450
-
1451
- # View stats.
1452
- for params in views_stats:
1453
- path = params['path']
1454
- if type(path) == str:
1455
- database, table = self.db.database, path
1456
- else:
1457
- database, table = path
1458
-
1459
- ## Exist.
1460
- if (
1461
- skip
1462
- and await self.db.schema.exist(database, table)
1463
- ):
1464
- continue
1465
-
1466
- ## SQL.
1467
- sql = self.get_sql_create_view_stats(**params)
1468
-
1469
- ## Confirm.
1470
- if ask:
1471
- self.input_confirm_build(sql)
1472
-
1473
- ## Execute.
1474
- await self.db.execute(sql)
1475
-
1476
- ## Report.
1477
- text = f"View '{table}' of database '{database}' build completed."
1478
- print(text)
1479
-
1480
-
1481
- __call__ = build
1482
- # !/usr/bin/env python
1483
- # -*- coding: utf-8 -*-
1484
-
1485
- """
1486
- @Time : 2023-10-14 23:05:35
1487
- @Author : Rey
1488
- @Contact : reyxbo@163.com
1489
- @Explain : Database build methods.
1490
- """
1491
-
1492
-
1493
- from typing import TypedDict, NotRequired, Literal, Type, TypeVar, Generic
1494
- from copy import deepcopy
1495
- from reykit.rbase import throw, is_instance
1496
- from reykit.rstdout import ask
1497
-
1498
- from . import rdb
1499
- from .rbase import DatabaseBase
1500
- from .rorm import DatabaseORMModel
1501
-
1502
-
1503
- __all__ = (
1504
- 'DatabaseBuildSuper',
1505
- 'DatabaseBuild',
1506
- 'DatabaseBuildAsync'
1507
- )
1508
-
1509
-
1510
- FieldSet = TypedDict(
1511
- 'FieldSet',
1512
- {
1513
- 'name': str,
1514
- 'type': str,
1515
- 'constraint': NotRequired[str | None],
1516
- 'comment': NotRequired[str | None],
1517
- 'position': NotRequired[Literal['first'] | str | None]
1518
- }
1519
- )
1520
- type IndexType = Literal['noraml', 'unique', 'fulltext', 'spatial']
1521
- IndexSet = TypedDict(
1522
- 'IndexSet',
1523
- {
1524
- 'name': str,
1525
- 'fields' : str | list[str],
1526
- 'type': IndexType,
1527
- 'comment': NotRequired[str | None]
1528
- }
1529
- )
1530
- DatabaseT = TypeVar('DatabaseT', 'rdb.Database', 'rdb.DatabaseAsync')
1531
-
1532
-
1533
- class DatabaseBuildSuper(DatabaseBase, Generic[DatabaseT]):
1534
- """
1535
- Database build super type.
1536
- """
1537
-
1538
-
1539
- def __init__(self, db: DatabaseT) -> None:
1540
- """
1541
- Build instance attributes.
1542
-
1543
- Parameters
1544
- ----------
1545
- db: Database instance.
1546
- """
1547
-
1548
- # Set attribute.
1549
- self.db = db
1550
-
1551
-
1552
- def get_sql_create_database(
1553
- self,
1554
- name: str,
1555
- character: str = 'utf8mb4',
1556
- collate: str = 'utf8mb4_0900_ai_ci'
1557
- ) -> str:
1558
- """
1559
- Get SQL of create database.
1560
-
1561
- Parameters
1562
- ----------
1563
- name : Database name.
1564
- character : Character set.
1565
- collate : Collate rule.
1566
- execute : Whether directly execute.
1567
-
1568
- Returns
1569
- -------
1570
- SQL.
1571
- """
1572
-
1573
- # Generate.
1574
- sql = f'CREATE DATABASE `{name}` CHARACTER SET {character} COLLATE {collate}'
1575
-
1576
- return sql
1577
-
1578
-
1579
- def __get_field_sql(
1580
- self,
1581
- name: str,
1582
- type_: str,
1583
- constraint: str = 'DEFAULT NULL',
1584
- comment: str | None = None,
1585
- position: str | None = None,
1586
- old_name: str | None = None
1587
- ) -> str:
1588
- """
1589
- Get a field set SQL.
1590
-
1591
- Parameters
1592
- ----------
1593
- name : Field name.
1594
- type_ : Field type.
1595
- constraint : Field constraint.
1596
- comment : Field comment.
1597
- position : Field position.
1598
- old_name : Field old name.
1599
-
1600
- Returns
1601
- -------
1602
- Field set SQL.
1603
- """
1604
-
1605
- # Parameter.
1606
-
1607
- ## Constraint.
1608
- constraint = ' ' + constraint
1609
-
1610
- ## Comment.
1611
- if comment is None:
1612
- comment = ''
1613
- else:
1614
- comment = f" COMMENT '{comment}'"
1615
-
1616
- ## Position.
1617
- match position:
1618
- case None:
1619
- position = ''
1620
- case 'first':
1621
- position = ' FIRST'
1622
- case _:
1623
- position = f' AFTER `{position}`'
1624
-
1625
- ## Old name.
1626
- if old_name is None:
1627
- old_name = ''
1628
- else:
1629
- old_name = f'`{old_name}` '
1630
-
1631
- # Generate.
1632
- sql = f'{old_name}`{name}` {type_}{constraint}{comment}{position}'
1633
-
1634
- return sql
1635
-
1636
-
1637
- def __get_index_sql(
1638
- self,
1639
- name: str,
1640
- fields: str | list[str],
1641
- type_: IndexType,
1642
- comment: str | None = None
1643
- ) -> str:
1644
- """
1645
- Get a index set SQL.
1646
-
1647
- Parameters
1648
- ----------
1649
- name : Index name.
1650
- fields : Index fileds.
1651
- type\\_ : Index type.
1652
- comment : Index comment.
1653
-
1654
- Returns
1655
- -------
1656
- Index set SQL.
1657
- """
1658
-
1659
- # Parameter.
1660
- if fields.__class__ == str:
1661
- fields = [fields]
1662
- match type_:
1663
- case 'noraml':
1664
- type_ = 'KEY'
1665
- method = ' USING BTREE'
1666
- case 'unique':
1667
- type_ = 'UNIQUE KEY'
1668
- method = ' USING BTREE'
1669
- case 'fulltext':
1670
- type_ = 'FULLTEXT KEY'
1671
- method = ''
1672
- case 'spatial':
1673
- type_ = 'SPATIAL KEY'
1674
- method = ''
1675
- case _:
1676
- throw(ValueError, type_)
1677
- if comment in (None, ''):
1678
- comment = ''
1679
- else:
1680
- comment = f" COMMENT '{comment}'"
1681
-
1682
- # Generate.
1683
-
1684
- ## Fields.
1685
- sql_fields = ', '.join(
1686
- [
1687
- f'`{field}`'
1688
- for field in fields
1689
- ]
1690
- )
1691
-
1692
- ## Join.
1693
- sql = f'{type_} `{name}` ({sql_fields}){method}{comment}'
1694
-
1695
- return sql
1696
-
1697
-
1698
- def get_sql_create_table(
1699
- self,
1700
- path: str | tuple[str, str],
1701
- fields: FieldSet | list[FieldSet],
1702
- primary: str | list[str] | None = None,
1703
- indexes: IndexSet | list[IndexSet] | None = None,
1704
- engine: str = 'InnoDB',
1705
- increment: int = 1,
1706
- charset: str = 'utf8mb4',
1707
- collate: str = 'utf8mb4_0900_ai_ci',
1708
- comment: str | None = None
1709
- ) -> str:
1710
- """
1711
- Get SQL of create table.
1712
-
1713
- Parameters
1714
- ----------
1715
- path : Path.
1716
- - `str`: Table name.
1717
- - `tuple[str, str]`: Database name and table name.
1718
- fields : Fields set table.
1719
- - `Key 'name'`: Field name, required.
1720
- - `Key 'type'`: Field type, required.
1721
- - `Key 'constraint'`: Field constraint.
1722
- `Empty or None`: Use 'DEFAULT NULL'.
1723
- `str`: Use this value.
1724
- - `Key 'comment'`: Field comment.
1725
- `Empty or None`: Not comment.
1726
- `str`: Use this value.
1727
- - `Key 'position'`: Field position.
1728
- `None`: Last.
1729
- `Literal['first']`: First.
1730
- `str`: After this field.
1731
- primary : Primary key fields.
1732
- - `str`: One field.
1733
- - `list[str]`: Multiple fileds.
1734
- indexes : Index set table.
1735
- - `Key 'name'`: Index name, required.
1736
- - `Key 'fields'`: Index fields, required.
1737
- `str`: One field.
1738
- `list[str]`: Multiple fileds.
1739
- - `Key 'type'`: Index type.
1740
- `Literal['noraml']`: Noraml key.
1741
- `Literal['unique']`: Unique key.
1742
- `Literal['fulltext']`: Full text key.
1743
- `Literal['spatial']`: Spatial key.
1744
- - `Key 'comment'`: Field comment.
1745
- `Empty or None`: Not comment.
1746
- `str`: Use this value.
1747
- engine : Engine type.
1748
- increment : Automatic Increment start value.
1749
- charset : Charset type.
1750
- collate : Collate type.
1751
- comment : Table comment.
1752
- execute : Whether directly execute.
1753
-
1754
- Returns
1755
- -------
1756
- SQL.
1757
- """
1758
-
1759
- # Parameter.
1760
- if type(path) == str:
1761
- database, table = self.db.database, path
1762
- else:
1763
- database, table = path
1764
- if fields.__class__ == dict:
1765
- fields = [fields]
1766
- if primary.__class__ == str:
1767
- primary = [primary]
1768
- if primary in ([], ['']):
1769
- primary = None
1770
- if indexes.__class__ == dict:
1771
- indexes = [indexes]
1772
-
1773
- ## Compatible dictionary key name.
1774
- fields = deepcopy(fields)
1775
- for row in fields:
1776
- row['type_'] = row.pop('type')
1777
- if indexes is not None:
1778
- indexes = deepcopy(indexes)
1779
- for row in indexes:
1780
- row['type_'] = row.pop('type')
1781
-
1782
- # Generate.
1783
-
1784
- ## Fields.
1785
- sql_fields = [
1786
- self.__get_field_sql(**field)
1787
- for field in fields
1788
- ]
1789
-
1790
- ## Primary.
1791
- if primary is not None:
1792
- keys = ', '.join(
1793
- [
1794
- f'`{key}`'
1795
- for key in primary
1796
- ]
1797
- )
1798
- sql_primary = f'PRIMARY KEY ({keys}) USING BTREE'
1799
- sql_fields.append(sql_primary)
1800
-
1801
- ## Indexes.
1802
- if indexes is not None:
1803
- sql_indexes = [
1804
- self.__get_index_sql(**index)
1805
- for index in indexes
1806
- ]
1807
- sql_fields.extend(sql_indexes)
1808
-
1809
- ## Comment.
1810
- if comment is None:
1811
- sql_comment = ''
1812
- else:
1813
- sql_comment = f" COMMENT='{comment}'"
1814
-
1815
- ## Join.
1816
- sql_fields = ',\n '.join(sql_fields)
1817
- sql = (
1818
- f'CREATE TABLE `{database}`.`{table}`(\n'
1819
- f' {sql_fields}\n'
1820
- f') ENGINE={engine} AUTO_INCREMENT={increment} CHARSET={charset} COLLATE={collate}{sql_comment}'
1821
- )
1822
-
1823
- return sql
1824
-
1825
-
1826
- def get_sql_create_view(
1827
- self,
1828
- path: str | tuple[str, str],
1829
- select: str
1830
- ) -> str:
1831
- """
1832
- Get SQL of create view.
1833
-
1834
- Parameters
1835
- ----------
1836
- path : Path.
1837
- - `str`: Table name.
1838
- - `tuple[str, str]`: Database name and table name.
1839
- select : View select SQL.
1840
- execute : Whether directly execute.
1841
-
1842
- Returns
1843
- -------
1844
- SQL.
1845
- """
1846
-
1847
- # Parameter.
1848
- if type(path) == str:
1849
- database, table = self.db.database, path
1850
- else:
1851
- database, table = path
1852
-
1853
- # Generate SQL.
1854
- select = select.replace('\n', '\n ')
1855
- sql = f'CREATE VIEW `{database}`.`{table}` AS (\n {select}\n)'
1856
-
1857
- return sql
1858
-
1859
-
1860
- def get_sql_create_view_stats(
1861
- self,
1862
- path: str | tuple[str, str],
1863
- items: list[dict]
1864
- ) -> str:
1865
- """
1866
- Get SQL of create stats view.
1867
-
1868
- Parameters
1869
- ----------
1870
- path : Path.
1871
- - `str`: Table name.
1872
- - `tuple[str, str]`: Database name and table name.
1873
- items : Items set table.
1874
- - `Key 'name'`: Item name, required.
1875
- - `Key 'select'`: Item select SQL, must only return one value, required.
1876
- - `Key 'comment'`: Item comment.
1877
- execute : Whether directly execute.
1878
-
1879
- Returns
1880
- -------
1881
- SQL.
1882
- """
1883
-
1884
- # Check.
1885
- if items == []:
1886
- throw(ValueError, items)
1887
-
1888
- # Generate select SQL.
1889
- item_first = items[0]
1890
- select_first = "SELECT '%s' AS `item`,\n(\n %s\n) AS `value`,\n%s AS `comment`" % (
1891
- item_first['name'],
1892
- item_first['select'].replace('\n', '\n '),
1893
- (
1894
- 'NULL'
1895
- if 'comment' not in item_first
1896
- else "'%s'" % item_first['comment']
1897
- )
1898
- )
1899
- selects = [
1900
- "SELECT '%s',\n(\n %s\n),\n%s" % (
1901
- item['name'],
1902
- item['select'].replace('\n', '\n '),
1903
- (
1904
- 'NULL'
1905
- if 'comment' not in item
1906
- else "'%s'" % item['comment']
1907
- )
1908
- )
1909
- for item in items[1:]
1910
- ]
1911
- selects[0:0] = [select_first]
1912
- select = '\nUNION\n'.join(selects)
1913
-
1914
- # Create.
1915
- sql = self.get_sql_create_view(path, select)
1916
-
1917
- return sql
1918
-
1919
-
1920
- def get_sql_drop_database(
1921
- self,
1922
- database: str
1923
- ) -> str:
1924
- """
1925
- Get SQL of drop database.
1926
-
1927
- Parameters
1928
- ----------
1929
- database : Database name.
1930
- execute : Whether directly execute.
1931
-
1932
- Returns
1933
- -------
1934
- SQL.
1935
- """
1936
-
1937
- # Generate.
1938
- sql = f'DROP DATABASE `{database}`'
1939
-
1940
- return sql
1941
-
1942
-
1943
- def get_sql_drop_table(
1944
- self,
1945
- path: str | tuple[str, str]
1946
- ) -> str:
1947
- """
1948
- Get SQL of drop table.
1949
-
1950
- Parameters
1951
- ----------
1952
- path : Path.
1953
- - `str`: Table name.
1954
- - `tuple[str, str]`: Database name and table name.
1955
- execute : Whether directly execute.
1956
-
1957
- Returns
1958
- -------
1959
- SQL.
1960
- """
1961
-
1962
- # Parameter.
1963
- if type(path) == str:
1964
- database, table = self.db.database, path
1965
- else:
1966
- database, table = path
1967
-
1968
- # Generate.
1969
- sql = f'DROP TABLE `{database}`.`{table}`'
1970
-
1971
- return sql
1972
-
1973
-
1974
- def get_sql_drop_view(
1975
- self,
1976
- path: str | tuple[str, str]
1977
- ) -> str:
1978
- """
1979
- Get SQL of drop view.
1980
-
1981
- Parameters
1982
- ----------
1983
- path : Path.
1984
- - `str`: Table name.
1985
- - `tuple[str, str]`: Database name and table name.
1986
- execute : Whether directly execute.
1987
-
1988
- Returns
1989
- -------
1990
- SQL.
1991
- """
1992
-
1993
- # Parameter.
1994
- if type(path) == str:
1995
- database, table = self.db.database, path
1996
- else:
1997
- database, table = path
1998
-
1999
- # Generate SQL.
2000
- sql = 'DROP VIEW `%s`.`%s`' % (database, table)
2001
-
2002
- return sql
2003
-
2004
-
2005
- def get_sql_alter_database(
2006
- self,
2007
- database: str,
2008
- character: str | None = None,
2009
- collate: str | None = None
2010
- ) -> str:
2011
- """
2012
- Get SQL of alter database.
2013
-
2014
- Parameters
2015
- ----------
2016
- database : Database name.
2017
- character : Character set.
2018
- - `None`: Not alter.
2019
- - `str`: Alter to this value.
2020
- collate : Collate rule.
2021
- - `None`: Not alter.
2022
- - `str`: Alter to this value.
2023
- execute : Whether directly execute.
2024
-
2025
- Returns
2026
- -------
2027
- SQL.
2028
- """
2029
-
2030
- # Generate.
2031
-
2032
- ## Character.
2033
- if character is None:
2034
- sql_character = ''
2035
- else:
2036
- sql_character = f' CHARACTER SET {character}'
2037
-
2038
- ## Collate.
2039
- if collate is None:
2040
- sql_collate = ''
2041
- else:
2042
- sql_collate = f' COLLATE {collate}'
2043
-
2044
- ## Join.
2045
- sql = f'ALTER DATABASE `{database}`{sql_character}{sql_collate}'
2046
-
2047
- return sql
2048
-
2049
-
2050
- def get_sql_alter_table_add(
2051
- self,
2052
- path: str | tuple[str, str],
2053
- fields: FieldSet | list[FieldSet] | None = None,
2054
- primary: str | list[str] | None = None,
2055
- indexes: IndexSet | list[IndexSet] | None = None
2056
- ) -> str:
2057
- """
2058
- Get SQL of alter table add filed.
2059
-
2060
- Parameters
2061
- ----------
2062
- path : Path.
2063
- - `str`: Table name.
2064
- - `tuple[str, str]`: Database name and table name.
2065
- fields : Fields set table.
2066
- - `Key 'name'`: Field name, required.
2067
- - `Key 'type'`: Field type, required.
2068
- - `Key 'constraint'`: Field constraint.
2069
- `Empty or None`: Use 'DEFAULT NULL'.
2070
- `str`: Use this value.
2071
- - `Key 'comment'`: Field comment.
2072
- `Empty or None`: Not comment.
2073
- `str`: Use this value.
2074
- - `Key 'position'`: Field position.
2075
- `None`: Last.
2076
- `Literal['first']`: First.
2077
- `str`: After this field.
2078
- primary : Primary key fields.
2079
- - `str`: One field.
2080
- - `list[str]`: Multiple fileds.
2081
- indexes : Index set table.
2082
- - `Key 'name'`: Index name, required.
2083
- - `Key 'fields'`: Index fields, required.
2084
- `str`: One field.
2085
- `list[str]`: Multiple fileds.
2086
- - `Key 'type'`: Index type.
2087
- `Literal['noraml']`: Noraml key.
2088
- `Literal['unique']`: Unique key.
2089
- `Literal['fulltext']`: Full text key.
2090
- `Literal['spatial']`: Spatial key.
2091
- - `Key 'comment'`: Field comment.
2092
- `Empty or None`: Not comment.
2093
- `str`: Use this value.
2094
-
2095
- Returns
2096
- -------
2097
- SQL.
2098
- """
2099
-
2100
- # Parameter.
2101
- if type(path) == str:
2102
- database, table = self.db.database, path
2103
- else:
2104
- database, table = path
2105
- if fields.__class__ == dict:
2106
- fields = [fields]
2107
- if primary.__class__ == str:
2108
- primary = [primary]
2109
- if primary in ([], ['']):
2110
- primary = None
2111
- if indexes.__class__ == dict:
2112
- indexes = [indexes]
2113
-
2114
- ## Compatible dictionary key name.
2115
- fields = deepcopy(fields)
2116
- for row in fields:
2117
- row['type_'] = row.pop('type')
2118
- if indexes is not None:
2119
- indexes = deepcopy(indexes)
2120
- for row in indexes:
2121
- row['type_'] = row.pop('type')
2122
-
2123
- # Generate.
2124
- sql_content = []
2125
-
2126
- ## Fields.
2127
- if fields is not None:
2128
- sql_fields = [
2129
- 'COLUMN ' + self.__get_field_sql(**field)
2130
- for field in fields
2131
- ]
2132
- sql_content.extend(sql_fields)
2133
-
2134
- ## Primary.
2135
- if primary is not None:
2136
- keys = ', '.join(
2137
- [
2138
- f'`{key}`'
2139
- for key in primary
2140
- ]
2141
- )
2142
- sql_primary = f'PRIMARY KEY ({keys}) USING BTREE'
2143
- sql_content.append(sql_primary)
2144
-
2145
- ## Indexes.
2146
- if indexes is not None:
2147
- sql_indexes = [
2148
- self.__get_index_sql(**index)
2149
- for index in indexes
2150
- ]
2151
- sql_content.extend(sql_indexes)
2152
-
2153
- ## Join.
2154
- sql_content = ',\n ADD '.join(sql_content)
2155
- sql = (
2156
- f'ALTER TABLE `{database}`.`{table}`\n'
2157
- f' ADD {sql_content}'
2158
- )
2159
-
2160
- return sql
2161
-
2162
-
2163
- def get_sql_alter_table_drop(
2164
- self,
2165
- path: str | tuple[str, str],
2166
- fields: str | list[str] | None = None,
2167
- primary: bool = False,
2168
- indexes: str | list[str] | None = None
2169
- ) -> str:
2170
- """
2171
- Get SQL of alter table drop field.
2172
-
2173
- Parameters
2174
- ----------
2175
- path : Path.
2176
- - `str`: Table name.
2177
- - `tuple[str, str]`: Database name and table name.
2178
- fields : Delete fields name.
2179
- primary : Whether delete primary key.
2180
- indexes : Delete indexes name.
2181
- execute : Whether directly execute.
2182
-
2183
- Returns
2184
- -------
2185
- SQL.
2186
- """
2187
-
2188
- # Parameter.
2189
- if type(path) == str:
2190
- database, table = self.db.database, path
2191
- else:
2192
- database, table = path
2193
- if fields.__class__ == str:
2194
- fields = [fields]
2195
- if indexes.__class__ == str:
2196
- indexes = [indexes]
2197
-
2198
- # Generate.
2199
- sql_content = []
2200
-
2201
- ## Fields.
2202
- if fields is not None:
2203
- sql_fields = [
2204
- 'COLUMN ' + field
2205
- for field in fields
2206
- ]
2207
- sql_content.extend(sql_fields)
2208
-
2209
- ## Primary.
2210
- if primary:
2211
- sql_primary = 'PRIMARY KEY'
2212
- sql_content.append(sql_primary)
2213
-
2214
- ## Indexes.
2215
- if indexes is not None:
2216
- sql_indexes = [
2217
- 'INDEX ' + index
2218
- for index in indexes
2219
- ]
2220
- sql_content.extend(sql_indexes)
2221
-
2222
- ## Join.
2223
- sql_content = ',\n DROP '.join(sql_content)
2224
- sql = (
2225
- f'ALTER TABLE `{database}`.`{table}`\n'
2226
- f' DROP {sql_content}'
2227
- )
2228
-
2229
- return sql
2230
-
2231
-
2232
- def get_sql_alter_table_change(
2233
- self,
2234
- path: str | tuple[str, str],
2235
- fields: FieldSet | list[FieldSet] | None = None,
2236
- rename: str | None = None,
2237
- engine: str | None = None,
2238
- increment: int | None = None,
2239
- charset: str | None = None,
2240
- collate: str | None = None
2241
- ) -> str:
2242
- """
2243
- Get SQL of alter database.
2244
-
2245
- Parameters
2246
- ----------
2247
- path : Path.
2248
- - `str`: Table name.
2249
- - `tuple[str, str]`: Database name and table name.
2250
- fields : Fields set table.
2251
- - `Key 'name'`: Field name, required.
2252
- - `Key 'type'`: Field type, required.
2253
- - `Key 'constraint'`: Field constraint.
2254
- `Empty or None`: Use 'DEFAULT NULL'.
2255
- `str`: Use this value.
2256
- - `Key 'comment'`: Field comment.
2257
- `Empty or None`: Not comment.
2258
- `str`: Use this value.
2259
- - `Key 'position'`: Field position.
2260
- `None`: Last.
2261
- `Literal['first']`: First.
2262
- `str`: After this field.
2263
- - `Key 'old_name'`: Field old name.
2264
- rename : Table new name.
2265
- engine : Engine type.
2266
- increment : Automatic Increment start value.
2267
- charset : Charset type.
2268
- collate : Collate type.
2269
- execute : Whether directly execute.
2270
-
2271
- Returns
2272
- -------
2273
- SQL.
2274
- """
2275
-
2276
- # Parameter.
2277
- if type(path) == str:
2278
- database, table = self.db.database, path
2279
- else:
2280
- database, table = path
2281
- if fields.__class__ == dict:
2282
- fields = [fields]
2283
-
2284
- ## Compatible dictionary key name.
2285
- fields = deepcopy(fields)
2286
- for row in fields:
2287
- row['type_'] = row.pop('type')
2288
-
2289
- # Generate.
2290
- sql_content = []
2291
-
2292
- ## Rename.
2293
- if rename is not None:
2294
- sql_rename = f'RENAME `{database}`.`{rename}`'
2295
- sql_content.append(sql_rename)
2296
-
2297
- ## Fields.
2298
- if fields is not None:
2299
- sql_fields = [
2300
- '%s %s' % (
2301
- (
2302
- 'MODIFY'
2303
- if 'old_name' not in field
2304
- else 'CHANGE'
2305
- ),
2306
- self.__get_field_sql(**field)
2307
- )
2308
- for field in fields
2309
- ]
2310
- sql_content.extend(sql_fields)
2311
-
2312
- ## Attribute.
2313
- sql_attr = []
2314
-
2315
- ### Engine.
2316
- if engine is not None:
2317
- sql_engine = f'ENGINE={engine}'
2318
- sql_attr.append(sql_engine)
2319
-
2320
- ### Increment.
2321
- if increment is not None:
2322
- sql_increment = f'AUTO_INCREMENT={increment}'
2323
- sql_attr.append(sql_increment)
2324
-
2325
- ### Charset.
2326
- if charset is not None:
2327
- sql_charset = f'CHARSET={charset}'
2328
- sql_attr.append(sql_charset)
2329
-
2330
- ### Collate.
2331
- if collate is not None:
2332
- sql_collate = f'COLLATE={collate}'
2333
- sql_attr.append(sql_collate)
2334
-
2335
- if sql_attr != []:
2336
- sql_attr = ' '.join(sql_attr)
2337
- sql_content.append(sql_attr)
2338
-
2339
- ## Join.
2340
- sql_content = ',\n '.join(sql_content)
2341
- sql = (
2342
- f'ALTER TABLE `{database}`.`{table}`\n'
2343
- f' {sql_content}'
2344
- )
2345
-
2346
- return sql
2347
-
2348
-
2349
- def get_sql_alter_view(
2350
- self,
2351
- path: str | tuple[str, str],
2352
- select: str
2353
- ) -> str:
2354
- """
2355
- Get SQL of alter view.
2356
-
2357
- Parameters
2358
- ----------
2359
- path : Path.
2360
- - `str`: Table name.
2361
- - `tuple[str, str]`: Database name and table name.
2362
- select : View select SQL.
2363
- execute : Whether directly execute.
2364
-
2365
- Returns
2366
- -------
2367
- SQL.
2368
- """
2369
-
2370
- # Parameter.
2371
- if type(path) == str:
2372
- database, table = self.db.database, path
2373
- else:
2374
- database, table = path
2375
-
2376
- # Generate SQL.
2377
- sql = 'ALTER VIEW `%s`.`%s` AS\n%s' % (database, table, select)
2378
-
2379
- return sql
2380
-
2381
-
2382
- def get_sql_truncate_table(
2383
- self,
2384
- path: str | tuple[str, str]
2385
- ) -> str:
2386
- """
2387
- Get SQL of truncate table.
2388
-
2389
- Parameters
2390
- ----------
2391
- path : Path.
2392
- - `str`: Table name.
2393
- - `tuple[str, str]`: Database name and table name.
2394
- execute : Whether directly execute.
2395
-
2396
- Returns
2397
- -------
2398
- SQL.
2399
- """
2400
-
2401
- # Parameter.
2402
- if type(path) == str:
2403
- database, table = self.db.database, path
2404
- else:
2405
- database, table = path
2406
-
2407
- # Generate.
2408
- sql = f'TRUNCATE TABLE `{database}`.`{table}`'
2409
-
2410
- return sql
2411
-
2412
-
2413
- def input_confirm_build(
2414
- self,
2415
- sql: str
2416
- ) -> None:
2417
- """
2418
- Print tip text, and confirm execute SQL. If reject, throw exception.
2419
-
2420
- Parameters
2421
- ----------
2422
- sql : SQL.
2423
- """
2424
-
2425
- # Confirm.
2426
- text = 'Do you want to execute SQL to build the database? Otherwise stop program. (y/n) '
2427
- command = ask(
2428
- sql,
2429
- text,
2430
- title='SQL',
2431
- frame='top'
2432
- )
2433
-
2434
- # Check.
2435
- while True:
2436
- command = command.lower()
2437
- match command:
2438
-
2439
- ## Confirm.
2440
- case 'y':
2441
- break
2442
-
2443
- ## Stop.
2444
- case 'n':
2445
- raise AssertionError('program stop')
2446
-
2447
- ## Reenter.
2448
- case _:
2449
- text = 'Incorrect input, reenter. (y/n) '
2450
- command = input(text)
2451
-
2452
-
2453
973
  def get_orm_table_text(self, model: DatabaseORMModel) -> str:
2454
974
  """
2455
975
  Get table text from ORM model.