Skip to content

Commit 7afd841

Browse files
authored
Add support for snowflake ID primary key (#670)
* fix: 修复PostgreSQL SQL语法错误,将反引号替换为双引号 * feat: 新增雪花算法ID实现 * 优化雪花算法和主键类型 * 修复错误引用 * 添加雪花详情链接 * feat: add snowflake ID parser method * 修复独立执行异常 * 更新系统时间错误类
1 parent 845f2f0 commit 7afd841

File tree

12 files changed

+625
-324
lines changed

12 files changed

+625
-324
lines changed

backend/app/admin/model/dept.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from typing import TYPE_CHECKING, Optional
66

7-
from sqlalchemy import Boolean, ForeignKey, String
7+
from sqlalchemy import BigInteger, Boolean, ForeignKey, String
88
from sqlalchemy.dialects.postgresql import INTEGER
99
from sqlalchemy.orm import Mapped, mapped_column, relationship
1010

@@ -32,7 +32,7 @@ class Dept(Base):
3232

3333
# 父级部门一对多
3434
parent_id: Mapped[int | None] = mapped_column(
35-
ForeignKey('sys_dept.id', ondelete='SET NULL'), default=None, index=True, comment='父部门ID'
35+
BigInteger, ForeignKey('sys_dept.id', ondelete='SET NULL'), default=None, index=True, comment='父部门ID'
3636
)
3737
parent: Mapped[Optional['Dept']] = relationship(init=False, back_populates='children', remote_side=[id])
3838
children: Mapped[Optional[list['Dept']]] = relationship(init=False, back_populates='parent')

backend/app/admin/model/m2m.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3-
from sqlalchemy import INT, Column, ForeignKey, Integer, Table
3+
from sqlalchemy import BigInteger, Column, ForeignKey, Table
44

55
from backend.common.model import MappedBase
66

77
sys_user_role = Table(
88
'sys_user_role',
99
MappedBase.metadata,
10-
Column('id', INT, primary_key=True, unique=True, index=True, autoincrement=True, comment='主键ID'),
11-
Column('user_id', Integer, ForeignKey('sys_user.id', ondelete='CASCADE'), primary_key=True, comment='用户ID'),
12-
Column('role_id', Integer, ForeignKey('sys_role.id', ondelete='CASCADE'), primary_key=True, comment='角色ID'),
10+
Column('id', BigInteger, primary_key=True, unique=True, index=True, autoincrement=True, comment='主键ID'),
11+
Column('user_id', BigInteger, ForeignKey('sys_user.id', ondelete='CASCADE'), primary_key=True, comment='用户ID'),
12+
Column('role_id', BigInteger, ForeignKey('sys_role.id', ondelete='CASCADE'), primary_key=True, comment='角色ID'),
1313
)
1414

1515
sys_role_menu = Table(
1616
'sys_role_menu',
1717
MappedBase.metadata,
18-
Column('id', INT, primary_key=True, unique=True, index=True, autoincrement=True, comment='主键ID'),
19-
Column('role_id', Integer, ForeignKey('sys_role.id', ondelete='CASCADE'), primary_key=True, comment='角色ID'),
20-
Column('menu_id', Integer, ForeignKey('sys_menu.id', ondelete='CASCADE'), primary_key=True, comment='菜单ID'),
18+
Column('id', BigInteger, primary_key=True, unique=True, index=True, autoincrement=True, comment='主键ID'),
19+
Column('role_id', BigInteger, ForeignKey('sys_role.id', ondelete='CASCADE'), primary_key=True, comment='角色ID'),
20+
Column('menu_id', BigInteger, ForeignKey('sys_menu.id', ondelete='CASCADE'), primary_key=True, comment='菜单ID'),
2121
)
2222

2323
sys_role_data_scope = Table(
2424
'sys_role_data_scope',
2525
MappedBase.metadata,
26-
Column('id', INT, primary_key=True, unique=True, index=True, autoincrement=True, comment='主键 ID'),
27-
Column('role_id', Integer, ForeignKey('sys_role.id', ondelete='CASCADE'), primary_key=True, comment='角色 ID'),
26+
Column('id', BigInteger, primary_key=True, unique=True, index=True, autoincrement=True, comment='主键 ID'),
27+
Column('role_id', BigInteger, ForeignKey('sys_role.id', ondelete='CASCADE'), primary_key=True, comment='角色 ID'),
2828
Column(
2929
'data_scope_id',
30-
Integer,
30+
BigInteger,
3131
ForeignKey('sys_data_scope.id', ondelete='CASCADE'),
3232
primary_key=True,
3333
comment='数据范围 ID',
@@ -37,17 +37,17 @@
3737
sys_data_scope_rule = Table(
3838
'sys_data_scope_rule',
3939
MappedBase.metadata,
40-
Column('id', INT, primary_key=True, unique=True, index=True, autoincrement=True, comment='主键ID'),
40+
Column('id', BigInteger, primary_key=True, unique=True, index=True, autoincrement=True, comment='主键ID'),
4141
Column(
4242
'data_scope_id',
43-
Integer,
43+
BigInteger,
4444
ForeignKey('sys_data_scope.id', ondelete='CASCADE'),
4545
primary_key=True,
4646
comment='数据范围 ID',
4747
),
4848
Column(
4949
'data_rule_id',
50-
Integer,
50+
BigInteger,
5151
ForeignKey('sys_data_rule.id', ondelete='CASCADE'),
5252
primary_key=True,
5353
comment='数据规则 ID',

backend/app/admin/model/menu.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from typing import TYPE_CHECKING, Optional
66

7-
from sqlalchemy import ForeignKey, String
7+
from sqlalchemy import BigInteger, ForeignKey, String
88
from sqlalchemy.dialects.mysql import LONGTEXT
99
from sqlalchemy.dialects.postgresql import TEXT
1010
from sqlalchemy.orm import Mapped, mapped_column, relationship
@@ -42,7 +42,7 @@ class Menu(Base):
4242

4343
# 父级菜单一对多
4444
parent_id: Mapped[int | None] = mapped_column(
45-
ForeignKey('sys_menu.id', ondelete='SET NULL'), default=None, index=True, comment='父菜单ID'
45+
BigInteger, ForeignKey('sys_menu.id', ondelete='SET NULL'), default=None, index=True, comment='父菜单ID'
4646
)
4747
parent: Mapped[Optional['Menu']] = relationship(init=False, back_populates='children', remote_side=[id])
4848
children: Mapped[Optional[list['Menu']]] = relationship(init=False, back_populates='parent')

backend/common/dataclasses.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,12 @@ class TokenPayload:
6464
@dataclasses.dataclass
6565
class UploadUrl:
6666
url: str
67+
68+
69+
@dataclasses.dataclass
70+
class SnowflakeInfo:
71+
timestamp: int
72+
datetime: str
73+
cluster_id: int
74+
node_id: int
75+
sequence: int

backend/common/model.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,43 @@
33
from datetime import datetime
44
from typing import Annotated
55

6-
from sqlalchemy import DateTime
6+
from sqlalchemy import BigInteger, DateTime
77
from sqlalchemy.ext.asyncio import AsyncAttrs
88
from sqlalchemy.orm import DeclarativeBase, Mapped, MappedAsDataclass, declared_attr, mapped_column
99

10+
from backend.utils.snowflake import snowflake
1011
from backend.utils.timezone import timezone
1112

1213
# 通用 Mapped 类型主键, 需手动添加,参考以下使用方式
1314
# MappedBase -> id: Mapped[id_key]
1415
# DataClassBase && Base -> id: Mapped[id_key] = mapped_column(init=False)
1516
id_key = Annotated[
16-
int, mapped_column(primary_key=True, index=True, autoincrement=True, sort_order=-999, comment='主键 ID')
17+
int,
18+
mapped_column(
19+
BigInteger,
20+
primary_key=True,
21+
unique=True,
22+
index=True,
23+
autoincrement=True,
24+
sort_order=-999,
25+
comment='主键 ID',
26+
),
27+
]
28+
29+
30+
# 雪花算法 Mapped 类型主键,使用方法与 id_key 相同
31+
# 详情:https://fastapi-practices.github.io/fastapi_best_architecture_docs/backend/reference/pk.html
32+
snowflake_id_key = Annotated[
33+
int,
34+
mapped_column(
35+
BigInteger,
36+
primary_key=True,
37+
unique=True,
38+
index=True,
39+
default=snowflake.generate,
40+
sort_order=-999,
41+
comment='雪花算法主键 ID',
42+
),
1743
]
1844

1945

backend/plugin/code_generator/model/column.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# -*- coding: utf-8 -*-
33
from typing import TYPE_CHECKING, Union
44

5-
from sqlalchemy import ForeignKey, String
5+
from sqlalchemy import BigInteger, ForeignKey, String
66
from sqlalchemy.dialects.mysql import LONGTEXT
77
from sqlalchemy.dialects.postgresql import TEXT
88
from sqlalchemy.orm import Mapped, mapped_column, relationship
@@ -33,6 +33,6 @@ class GenColumn(DataClassBase):
3333

3434
# 代码生成业务模型一对多
3535
gen_business_id: Mapped[int] = mapped_column(
36-
ForeignKey('gen_business.id', ondelete='CASCADE'), default=0, comment='代码生成业务ID'
36+
BigInteger, ForeignKey('gen_business.id', ondelete='CASCADE'), default=0, comment='代码生成业务ID'
3737
)
3838
gen_business: Mapped[Union['GenBusiness', None]] = relationship(init=False, back_populates='gen_column')

backend/plugin/oauth2/model/user_social.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from typing import TYPE_CHECKING
66

7-
from sqlalchemy import ForeignKey, String
7+
from sqlalchemy import BigInteger, ForeignKey, String
88
from sqlalchemy.orm import Mapped, mapped_column, relationship
99

1010
from backend.common.model import Base, id_key
@@ -23,5 +23,7 @@ class UserSocial(Base):
2323
source: Mapped[str] = mapped_column(String(20), comment='第三方用户来源')
2424

2525
# 用户社交信息一对多
26-
user_id: Mapped[int] = mapped_column(ForeignKey('sys_user.id', ondelete='CASCADE'), comment='用户关联ID')
26+
user_id: Mapped[int] = mapped_column(
27+
BigInteger, ForeignKey('sys_user.id', ondelete='CASCADE'), comment='用户关联ID'
28+
)
2729
user: Mapped[User | None] = relationship(init=False, backref='socials')

backend/plugin/tools.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from backend.core.path_conf import PLUGIN_DIR
2323
from backend.database.redis import RedisCli, redis_client
2424
from backend.plugin.errors import PluginConfigError, PluginInjectError
25-
from backend.utils._asyncio import run_await
25+
from backend.utils._await import run_await
2626
from backend.utils.import_parse import import_module_cached
2727

2828

0 commit comments

Comments
 (0)