feat: S0 主键改雪花(DDL 去 identity + 实体 ASSIGN_ID + 雪花配置)
为什么:自增主键把 ID 分配锁在单库序列上,分库分表时无法横向扩展。趁线上业务数据 近零(只有系统种子表有量)先改,代价最低。 - sql/schema.sql、sql/schema-phase1.sql、sql/partition-maintenance.sql:61 处 GENERATED BY DEFAULT AS IDENTITY 去掉,主键改 BIGINT 无默认值 - 52 个实体 @TableId IdType.AUTO -> IdType.ASSIGN_ID;两个入口 id-type: assign_id, 并加 global-config.sequence.worker-id/datacenter-id(单机固定值,多实例需按实例分配) - 新增 sql/migrate-s0-snowflake.sql:存量库幂等迁移,走 DROP IDENTITY 保留数据,不重建表 - 实测:三份建表脚本在新库连跑两遍幂等;线上 57 张表 identity 归零; watch_history/playback_ticket/order_event 的主键与唯一索引仍含分区键
This commit is contained in:
1 parent
6833e01e1f
commit
37c9a141d3
58 files changed
+174
-115
No files matched your search
@@ -26,10 +26,15 @@ mybatis-plus:
|
||||
global-config:
|
||||
banner: false
|
||||
db-config:
|
||||
id-type: auto
|
||||
# 主键由应用侧雪花算法生成(S0),数据库不再自增
|
||||
id-type: assign_id
|
||||
logic-delete-field: deleted
|
||||
logic-delete-value: 1
|
||||
logic-not-delete-value: 0
|
||||
sequence:
|
||||
# 单机开发用固定值;上多实例前必须改成按实例分配(环境变量注入),否则会撞 ID
|
||||
worker-id: 1
|
||||
datacenter-id: 1
|
||||
|
||||
fruitshorts:
|
||||
media:
|
||||
|
||||
@@ -21,10 +21,15 @@ mybatis-plus:
|
||||
global-config:
|
||||
banner: false
|
||||
db-config:
|
||||
id-type: auto
|
||||
# 主键由应用侧雪花算法生成(S0),数据库不再自增
|
||||
id-type: assign_id
|
||||
logic-delete-field: deleted
|
||||
logic-delete-value: 1
|
||||
logic-not-delete-value: 0
|
||||
sequence:
|
||||
# 单机开发用固定值;上多实例前必须改成按实例分配(环境变量注入),否则会撞 ID
|
||||
worker-id: 1
|
||||
datacenter-id: 1
|
||||
|
||||
fruitshorts:
|
||||
interaction:
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("coin_ledger")
|
||||
public class CoinLedger {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
/** 正数入账、负数出账 */
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("entitlement")
|
||||
public class Entitlement {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private Long dramaId;
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("order_event")
|
||||
public class OrderEvent {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String orderNo;
|
||||
private String event;
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("orders")
|
||||
public class Orders {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String orderNo;
|
||||
private Long userId;
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("product")
|
||||
public class Product {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String code;
|
||||
private String name;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("reconcile_task")
|
||||
public class ReconcileTask {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private LocalDate bizDate;
|
||||
private String platform;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("store_receipt")
|
||||
public class StoreReceipt {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String platform;
|
||||
private String transactionId;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("wallet")
|
||||
public class Wallet {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private Long coinBalance;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("content_banner")
|
||||
public class ContentBanner {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String imageUrl;
|
||||
/** 展示位置,列名为 slot(position 在 PostgreSQL 里是关键字) */
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("drama")
|
||||
public class Drama {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String code;
|
||||
private String title;
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import lombok.Data;
|
||||
@TableName("drama_category")
|
||||
public class DramaCategory {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String name;
|
||||
private Integer sort;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("drama_episode")
|
||||
public class DramaEpisode {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long dramaId;
|
||||
private Integer epNo;
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("drama_review_record")
|
||||
public class DramaReviewRecord {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String bizType;
|
||||
private Long bizId;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("content_submission")
|
||||
public class ContentSubmission {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long creatorId;
|
||||
private Long dramaId;
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("creator")
|
||||
public class Creator {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
/** 关联 C 端账号 app_user.id */
|
||||
private Long userId;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("creator_document")
|
||||
public class CreatorDocument {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long creatorId;
|
||||
/** ID_CARD / BUSINESS_LICENSE / CONTRACT */
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("content_audit_record")
|
||||
public class ContentAuditRecord {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
/** COMMENT/DRAMA/AVATAR/CREATOR */
|
||||
private String bizType;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("content_comment")
|
||||
public class ContentComment {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long dramaId;
|
||||
private Long episodeId;
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("content_like")
|
||||
public class ContentLike {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
/** DRAMA/EPISODE/COMMENT */
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("content_report")
|
||||
public class ContentReport {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long reporterId;
|
||||
/** COMMENT/USER/DRAMA */
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("content_share")
|
||||
public class ContentShare {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private Long dramaId;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("sensitive_word")
|
||||
public class SensitiveWord {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String word;
|
||||
/** POLITICS/PORN/ABUSE/AD/RELIGION */
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("user_blocklist")
|
||||
public class UserBlocklist {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private Long blockedUserId;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("media_asset")
|
||||
public class MediaAsset {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String bizType;
|
||||
private String fileName;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("media_rendition")
|
||||
public class MediaRendition {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long mediaAssetId;
|
||||
private Long dramaId;
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("media_upload_task")
|
||||
public class MediaUploadTask {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String uploadId;
|
||||
private String bizType;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("transcode_task")
|
||||
public class TranscodeTask {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long mediaAssetId;
|
||||
private Long dramaId;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("download_license")
|
||||
public class DownloadLicense {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private Long dramaId;
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("download_task")
|
||||
public class DownloadTask {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private String deviceId;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("playback_ticket")
|
||||
public class PlaybackTicket {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String ticketNo;
|
||||
private Long userId;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("user_favorite")
|
||||
public class UserFavorite {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private Long dramaId;
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("watch_history")
|
||||
public class WatchHistory {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private Long dramaId;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("watch_progress")
|
||||
public class WatchProgress {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private Long dramaId;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("sys_admin_user")
|
||||
public class AdminUser {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import lombok.NoArgsConstructor;
|
||||
@TableName("sys_admin_user_role")
|
||||
public class AdminUserRole {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private Long roleId;
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("audit_log")
|
||||
public class AuditLog {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
/** ORDER / ENTITLEMENT / USER / CREATOR / PRICE */
|
||||
private String bizType;
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("sys_menu")
|
||||
public class Menu {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long parentId;
|
||||
private String title;
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("sys_operation_log")
|
||||
public class OperationLog {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long adminUserId;
|
||||
private String username;
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import lombok.Data;
|
||||
@TableName("sys_permission")
|
||||
public class Permission {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String code;
|
||||
private String name;
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("sys_role")
|
||||
public class Role {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String name;
|
||||
private String code;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("sys_role_category")
|
||||
public class RoleCategory {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import lombok.NoArgsConstructor;
|
||||
@TableName("sys_role_menu")
|
||||
public class RoleMenu {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long roleId;
|
||||
private Long menuId;
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import lombok.NoArgsConstructor;
|
||||
@TableName("sys_role_permission")
|
||||
public class RolePermission {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long roleId;
|
||||
private Long permissionId;
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import lombok.Data;
|
||||
@TableName("sys_config")
|
||||
public class SysConfig {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String configKey;
|
||||
private String configValue;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("app_account_deletion")
|
||||
public class AppAccountDeletion {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
/** pending/cancelled/completed */
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("app_user")
|
||||
public class AppUser {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
/** 对外用户标识,接口只暴露 uid,不暴露自增 ID */
|
||||
private String uid;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("app_user_ban_record")
|
||||
public class AppUserBanRecord {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
/** BAN/LIMIT/MUTE */
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("app_user_consent")
|
||||
public class AppUserConsent {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private String scene;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("app_user_credential")
|
||||
public class AppUserCredential {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
/** PHONE/EMAIL/APPLE/GOOGLE */
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("app_user_device")
|
||||
public class AppUserDevice {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private String deviceId;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("app_user_otp")
|
||||
public class AppUserOtp {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String scene;
|
||||
private String targetType;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
|
||||
@TableName("app_user_session")
|
||||
public class AppUserSession {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private String refreshTokenHash;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
-- Author: fruit.com.cn
|
||||
--
|
||||
-- S0 主键改雪花 · 存量库迁移(PostgreSQL 18)
|
||||
--
|
||||
-- 背景:第一阶段建表用的是 GENERATED BY DEFAULT AS IDENTITY(数据库自增序列),
|
||||
-- 这会让 ID 分配集中在单库的序列上,一旦分库分表就无法横向扩展。
|
||||
-- S0 把主键改成应用侧雪花 ID(MyBatis-Plus IdType.ASSIGN_ID),
|
||||
-- DDL 侧只需要把 identity 去掉——序列不再需要。
|
||||
--
|
||||
-- 本脚本只做一件事:把所有 identity 列改成普通 BIGINT(**保留已有数据,不重建表**)。
|
||||
-- 刻意不用 DROP TABLE / TRUNCATE,避免误伤存量数据。
|
||||
-- 幂等:已经迁移过的库再跑一遍不做任何改动,NOTICE 里的数字会是 0。
|
||||
--
|
||||
-- 执行:psql -h 127.0.0.1 -U fruitshorts -d fruitshorts -f sql/migrate-s0-snowflake.sql
|
||||
-- 复查:脚本末尾的注释 SQL(改写后应返回 0 行)
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
r record;
|
||||
v_done int := 0;
|
||||
BEGIN
|
||||
-- relispartition = false 表示"只处理顶层表":
|
||||
-- 分区父表在 pg_class 里 relkind = 'p',月分区子表 relispartition = true;
|
||||
-- identity 定义在父表上,子表跟着继承,所以逐个改子表是多余的。
|
||||
FOR r IN
|
||||
SELECT c.oid::regclass AS tbl, a.attname AS col
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
JOIN pg_attribute a ON a.attrelid = c.oid
|
||||
WHERE n.nspname = 'public'
|
||||
AND c.relkind IN ('r', 'p')
|
||||
AND c.relispartition = false
|
||||
AND a.attidentity <> ''
|
||||
AND a.attnum > 0
|
||||
ORDER BY c.relname
|
||||
LOOP
|
||||
EXECUTE format('ALTER TABLE %s ALTER COLUMN %I DROP IDENTITY IF EXISTS', r.tbl, r.col);
|
||||
v_done := v_done + 1;
|
||||
END LOOP;
|
||||
RAISE NOTICE 'S0 迁移完成:处理 % 个 identity 列(重复执行时为 0)', v_done;
|
||||
END $$;
|
||||
|
||||
-- 复查用(结果应为 0 行):
|
||||
-- SELECT c.relname, a.attname
|
||||
-- FROM pg_class c
|
||||
-- JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
-- JOIN pg_attribute a ON a.attrelid = c.oid
|
||||
-- WHERE n.nspname = 'public' AND a.attidentity <> ''
|
||||
-- ORDER BY 1, 2;
|
||||
@@ -99,7 +99,7 @@ BEGIN
|
||||
END IF;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS playback_ticket (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
|
||||
id BIGINT,
|
||||
ticket_no VARCHAR(40) NOT NULL,
|
||||
user_id BIGINT NOT NULL DEFAULT 0,
|
||||
drama_id BIGINT NOT NULL,
|
||||
@@ -134,7 +134,7 @@ BEGIN
|
||||
END IF;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS order_event (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
|
||||
id BIGINT,
|
||||
order_no VARCHAR(40) NOT NULL,
|
||||
event VARCHAR(32) NOT NULL,
|
||||
from_status VARCHAR(16) NOT NULL DEFAULT '',
|
||||
|
||||
+41
-41
@@ -9,7 +9,7 @@
|
||||
-- 具体的月分区由 sql/partition-maintenance.sql 创建(并把已存在的普通表转成分区表)。
|
||||
--
|
||||
-- 命名与类型约定(与 sql/schema.sql 保持一致):
|
||||
-- BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
|
||||
-- BIGINT PRIMARY KEY(不设默认值;主键由应用侧雪花算法生成:MyBatis-Plus IdType.ASSIGN_ID)
|
||||
-- 布尔语义用 SMALLINT(1/0),时间用 TIMESTAMP(3),默认 CURRENT_TIMESTAMP
|
||||
-- 逻辑删除 deleted SMALLINT NOT NULL DEFAULT 0
|
||||
-- updated_at 由 set_updated_at() 触发器维护
|
||||
@@ -53,7 +53,7 @@ ALTER TABLE media_asset ADD COLUMN IF NOT EXISTS storage_type VARCHAR(16) NO
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app_user (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
uid VARCHAR(32) NOT NULL, -- 对外展示的用户标识,避免暴露自增 ID
|
||||
nickname VARCHAR(64) NOT NULL DEFAULT '',
|
||||
avatar_url VARCHAR(512) NOT NULL DEFAULT '',
|
||||
@@ -89,7 +89,7 @@ CREATE INDEX IF NOT EXISTS idx_app_user_created ON app_user (created_at DESC);
|
||||
COMMENT ON TABLE app_user IS 'C 端用户';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app_user_credential (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
type VARCHAR(16) NOT NULL, -- PHONE/EMAIL/APPLE/GOOGLE
|
||||
identifier VARCHAR(191) NOT NULL, -- E.164 手机号 / 邮箱 / 第三方唯一标识
|
||||
@@ -108,7 +108,7 @@ CREATE INDEX IF NOT EXISTS idx_app_credential_user ON app_user_credential (user_
|
||||
COMMENT ON TABLE app_user_credential IS 'C 端登录凭证(手机号/邮箱/第三方)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app_user_session (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
refresh_token_hash VARCHAR(64) NOT NULL, -- SHA-256,不存明文
|
||||
device_id VARCHAR(128) NOT NULL DEFAULT '',
|
||||
@@ -130,7 +130,7 @@ CREATE INDEX IF NOT EXISTS idx_app_session_user ON app_user_session (user_id, re
|
||||
COMMENT ON TABLE app_user_session IS 'C 端会话(可多设备)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app_user_otp (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
scene VARCHAR(16) NOT NULL, -- REGISTER/LOGIN/RESET_PWD/BIND
|
||||
target_type VARCHAR(16) NOT NULL, -- PHONE/EMAIL
|
||||
target VARCHAR(191) NOT NULL,
|
||||
@@ -150,7 +150,7 @@ CREATE INDEX IF NOT EXISTS idx_app_otp_ip ON app_user_otp (send_ip, created_at D
|
||||
COMMENT ON TABLE app_user_otp IS '验证码发送与校验记录(同时用于反刷频控)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app_user_consent (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
scene VARCHAR(32) NOT NULL, -- PRIVACY/TERMS/MARKETING/PERSONALIZED_AD
|
||||
version VARCHAR(32) NOT NULL DEFAULT '',
|
||||
@@ -165,7 +165,7 @@ CREATE INDEX IF NOT EXISTS idx_app_consent_user ON app_user_consent (user_id, sc
|
||||
COMMENT ON TABLE app_user_consent IS '同意管理记录,商店审核与隐私合规要求可追溯';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app_user_device (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
device_id VARCHAR(128) NOT NULL,
|
||||
platform VARCHAR(16) NOT NULL DEFAULT '',
|
||||
@@ -181,7 +181,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_app_device ON app_user_device (user_id, dev
|
||||
COMMENT ON TABLE app_user_device IS '用户设备,用于下载授权与并发播放数限制';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app_user_ban_record (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
type VARCHAR(16) NOT NULL, -- BAN/LIMIT/MUTE
|
||||
reason_code VARCHAR(32) NOT NULL DEFAULT '',
|
||||
@@ -205,7 +205,7 @@ CREATE INDEX IF NOT EXISTS idx_app_ban_user ON app_user_ban_record (user_id, sta
|
||||
COMMENT ON TABLE app_user_ban_record IS '封禁/限制与申诉记录';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app_account_deletion (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
status VARCHAR(16) NOT NULL DEFAULT 'pending', -- pending/cancelled/completed
|
||||
reason VARCHAR(255) NOT NULL DEFAULT '',
|
||||
@@ -226,7 +226,7 @@ COMMENT ON TABLE app_account_deletion IS '账号注销申请与冷静期';
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS watch_progress (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
drama_id BIGINT NOT NULL,
|
||||
episode_id BIGINT NOT NULL,
|
||||
@@ -246,7 +246,7 @@ COMMENT ON TABLE watch_progress IS '每用户每剧一条续看进度(跨端
|
||||
|
||||
-- 观看流水:量大,按 watched_at 做声明式月分区,便于按期归档与清理
|
||||
CREATE TABLE IF NOT EXISTS watch_history (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
|
||||
id BIGINT,
|
||||
user_id BIGINT NOT NULL,
|
||||
drama_id BIGINT NOT NULL,
|
||||
episode_id BIGINT NOT NULL,
|
||||
@@ -263,7 +263,7 @@ CREATE INDEX IF NOT EXISTS idx_watch_history_drama ON watch_history (drama_id, w
|
||||
COMMENT ON TABLE watch_history IS '观看流水(月分区,保留 12–24 个月)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_favorite (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
drama_id BIGINT NOT NULL,
|
||||
sort INT NOT NULL DEFAULT 0,
|
||||
@@ -280,7 +280,7 @@ COMMENT ON TABLE user_favorite IS '剧集收藏';
|
||||
-- 唯一索引是 (ticket_no, created_at);ticket_no 是 UUID,实际唯一性不受影响。
|
||||
-- 月分区本身由 sql/partition-maintenance.sql 建(含未来 3 个月)。
|
||||
CREATE TABLE IF NOT EXISTS playback_ticket (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
|
||||
id BIGINT,
|
||||
ticket_no VARCHAR(40) NOT NULL,
|
||||
user_id BIGINT NOT NULL DEFAULT 0, -- 0 表示未登录的免费集
|
||||
drama_id BIGINT NOT NULL,
|
||||
@@ -303,7 +303,7 @@ CREATE INDEX IF NOT EXISTS idx_playback_ticket_user
|
||||
COMMENT ON TABLE playback_ticket IS '播放票据签发审计;真正的鉴权在签名 URL 上(月分区)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS download_license (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
drama_id BIGINT NOT NULL,
|
||||
episode_id BIGINT NOT NULL,
|
||||
@@ -326,7 +326,7 @@ COMMENT ON TABLE download_license IS '离线下载授权与设备绑定(换机
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS content_comment (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
drama_id BIGINT NOT NULL,
|
||||
episode_id BIGINT NOT NULL DEFAULT 0,
|
||||
user_id BIGINT NOT NULL,
|
||||
@@ -352,7 +352,7 @@ CREATE INDEX IF NOT EXISTS idx_comment_user ON content_comment (user_id, created
|
||||
COMMENT ON TABLE content_comment IS '评论与回复(先审后发)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS content_like (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
target_type VARCHAR(16) NOT NULL, -- DRAMA/EPISODE/COMMENT
|
||||
target_id BIGINT NOT NULL,
|
||||
@@ -364,7 +364,7 @@ CREATE INDEX IF NOT EXISTS idx_content_like_target ON content_like (target_type,
|
||||
COMMENT ON TABLE content_like IS '点赞关系;计数值异步聚合';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS content_report (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
reporter_id BIGINT NOT NULL,
|
||||
target_type VARCHAR(16) NOT NULL, -- COMMENT/USER/DRAMA
|
||||
target_id BIGINT NOT NULL,
|
||||
@@ -383,7 +383,7 @@ CREATE INDEX IF NOT EXISTS idx_report_status ON content_report (status, created_
|
||||
COMMENT ON TABLE content_report IS '举报工单';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_blocklist (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
blocked_user_id BIGINT NOT NULL,
|
||||
source VARCHAR(16) NOT NULL DEFAULT 'MANUAL', -- MANUAL/COMMENT
|
||||
@@ -394,7 +394,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_user_blocklist ON user_blocklist (user_id,
|
||||
COMMENT ON TABLE user_blocklist IS '拉黑关系';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sensitive_word (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
word VARCHAR(64) NOT NULL,
|
||||
category VARCHAR(32) NOT NULL DEFAULT '', -- POLITICS/PORN/ABUSE/AD/RELIGION
|
||||
level VARCHAR(16) NOT NULL DEFAULT 'REVIEW', -- BLOCK/REVIEW/REPLACE
|
||||
@@ -409,7 +409,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_sensitive_word ON sensitive_word (language,
|
||||
COMMENT ON TABLE sensitive_word IS '敏感词库';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS content_audit_record (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
biz_type VARCHAR(16) NOT NULL, -- COMMENT/DRAMA/AVATAR/CREATOR
|
||||
biz_id BIGINT NOT NULL,
|
||||
round INT NOT NULL DEFAULT 1,
|
||||
@@ -427,7 +427,7 @@ CREATE INDEX IF NOT EXISTS idx_audit_biz ON content_audit_record (biz_type, biz_
|
||||
COMMENT ON TABLE content_audit_record IS '审核留证(机审 + 人审都记)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS content_share (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL DEFAULT 0,
|
||||
drama_id BIGINT NOT NULL,
|
||||
episode_id BIGINT NOT NULL DEFAULT 0,
|
||||
@@ -442,7 +442,7 @@ COMMENT ON TABLE content_share IS '分享事件,用于渠道效果与裂变分
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wallet (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
coin_balance BIGINT NOT NULL DEFAULT 0,
|
||||
total_recharged_coin BIGINT NOT NULL DEFAULT 0,
|
||||
@@ -457,7 +457,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_wallet_user ON wallet (user_id);
|
||||
COMMENT ON TABLE wallet IS '金币钱包;所有变动必须同时写 coin_ledger';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS product (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
code VARCHAR(64) NOT NULL,
|
||||
name VARCHAR(128) NOT NULL,
|
||||
type VARCHAR(16) NOT NULL DEFAULT 'COIN_PACK', -- COIN_PACK/VIP/EPISODE_PACK(VIP 为第二阶段预留)
|
||||
@@ -483,7 +483,7 @@ CREATE INDEX IF NOT EXISTS idx_product_platform ON product (platform, status);
|
||||
COMMENT ON TABLE product IS '商品配置(金币包;会员与活动价为后续阶段预留)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS orders (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
order_no VARCHAR(40) NOT NULL,
|
||||
user_id BIGINT NOT NULL,
|
||||
product_id BIGINT NOT NULL DEFAULT 0,
|
||||
@@ -522,7 +522,7 @@ COMMENT ON TABLE orders IS '订单;orders 为保留字规避(order 是 SQL
|
||||
|
||||
-- 订单状态流转流水,同样按月分区(同 playback_ticket,主键带分区键)
|
||||
CREATE TABLE IF NOT EXISTS order_event (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
|
||||
id BIGINT,
|
||||
order_no VARCHAR(40) NOT NULL,
|
||||
event VARCHAR(32) NOT NULL, -- CREATE/VERIFY_OK/VERIFY_FAIL/DELIVER/REFUND/NOTIFY
|
||||
from_status VARCHAR(16) NOT NULL DEFAULT '',
|
||||
@@ -537,7 +537,7 @@ CREATE INDEX IF NOT EXISTS idx_order_event_no ON order_event (order_no, created_
|
||||
COMMENT ON TABLE order_event IS '订单状态流转流水,支付争议时的证据链(月分区)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS store_receipt (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
platform VARCHAR(16) NOT NULL,
|
||||
transaction_id VARCHAR(128) NOT NULL,
|
||||
original_transaction_id VARCHAR(128) NOT NULL DEFAULT '',
|
||||
@@ -557,7 +557,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_store_receipt ON store_receipt (platform, t
|
||||
COMMENT ON TABLE store_receipt IS '商店票据去重与校验留证(重放防护)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS coin_ledger (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
change_amount BIGINT NOT NULL, -- 正数入账,负数出账
|
||||
balance_after BIGINT NOT NULL,
|
||||
@@ -573,7 +573,7 @@ CREATE INDEX IF NOT EXISTS idx_coin_ledger_user ON coin_ledger (user_id, created
|
||||
COMMENT ON TABLE coin_ledger IS '金币流水,钱包余额的唯一事实来源';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS entitlement (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
drama_id BIGINT NOT NULL DEFAULT 0,
|
||||
episode_id BIGINT NOT NULL DEFAULT 0, -- 0 表示整剧权益
|
||||
@@ -593,7 +593,7 @@ CREATE INDEX IF NOT EXISTS idx_entitlement_user ON entitlement (user_id, status)
|
||||
COMMENT ON TABLE entitlement IS '权益;播放判定优先读这里';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS refund_record (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
order_no VARCHAR(40) NOT NULL,
|
||||
platform VARCHAR(16) NOT NULL DEFAULT '',
|
||||
refund_id VARCHAR(128) NOT NULL DEFAULT '',
|
||||
@@ -613,7 +613,7 @@ CREATE INDEX IF NOT EXISTS idx_refund_status ON refund_record (status, created_a
|
||||
COMMENT ON TABLE refund_record IS '退款与撤销事件,触发权益回收';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS reconcile_task (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
biz_date DATE NOT NULL,
|
||||
platform VARCHAR(16) NOT NULL DEFAULT 'ALL',
|
||||
total_count INT NOT NULL DEFAULT 0,
|
||||
@@ -635,7 +635,7 @@ COMMENT ON TABLE reconcile_task IS '每日对账任务(与商店账单比对
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS creator (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL, -- 关联 C 端账号
|
||||
code VARCHAR(32) NOT NULL,
|
||||
name VARCHAR(128) NOT NULL,
|
||||
@@ -663,7 +663,7 @@ CREATE INDEX IF NOT EXISTS idx_creator_status ON creator (status, created_at DES
|
||||
COMMENT ON TABLE creator IS '创作者主体与资质';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS creator_document (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
creator_id BIGINT NOT NULL,
|
||||
type VARCHAR(32) NOT NULL, -- ID_CARD/BUSINESS_LICENSE/CONTRACT
|
||||
file_url VARCHAR(512) NOT NULL,
|
||||
@@ -678,7 +678,7 @@ CREATE INDEX IF NOT EXISTS idx_creator_doc ON creator_document (creator_id, type
|
||||
COMMENT ON TABLE creator_document IS '创作者资质文件';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS content_submission (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
creator_id BIGINT NOT NULL,
|
||||
drama_id BIGINT NOT NULL,
|
||||
type VARCHAR(16) NOT NULL DEFAULT 'CREATE', -- CREATE/UPDATE/PUBLISH/OFFLINE
|
||||
@@ -698,7 +698,7 @@ CREATE INDEX IF NOT EXISTS idx_submission_status ON content_submission (status,
|
||||
COMMENT ON TABLE content_submission IS '创作者内容提交与审核流转';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS creator_stat_daily (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
creator_id BIGINT NOT NULL,
|
||||
drama_id BIGINT NOT NULL DEFAULT 0,
|
||||
stat_date DATE NOT NULL,
|
||||
@@ -715,7 +715,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_creator_stat ON creator_stat_daily (creator
|
||||
COMMENT ON TABLE creator_stat_daily IS '创作者数据看板日汇总';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS creator_settlement (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
creator_id BIGINT NOT NULL,
|
||||
period VARCHAR(16) NOT NULL, -- 2026-10
|
||||
revenue BIGINT NOT NULL DEFAULT 0,
|
||||
@@ -737,7 +737,7 @@ COMMENT ON TABLE creator_settlement IS '预留:创作者结算(第二阶段
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS transcode_task (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
media_asset_id BIGINT NOT NULL DEFAULT 0,
|
||||
drama_id BIGINT NOT NULL DEFAULT 0,
|
||||
episode_id BIGINT NOT NULL DEFAULT 0,
|
||||
@@ -758,7 +758,7 @@ CREATE INDEX IF NOT EXISTS idx_transcode_episode ON transcode_task (episode_id);
|
||||
COMMENT ON TABLE transcode_task IS '转码任务队列(本地 worker / 云转码)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS media_rendition (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
media_asset_id BIGINT NOT NULL DEFAULT 0,
|
||||
drama_id BIGINT NOT NULL DEFAULT 0,
|
||||
episode_id BIGINT NOT NULL DEFAULT 0,
|
||||
@@ -787,7 +787,7 @@ COMMENT ON TABLE media_rendition IS '多码率产物;播放票据按此生成
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ops_notice (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
title VARCHAR(128) NOT NULL,
|
||||
content VARCHAR(2000) NOT NULL DEFAULT '',
|
||||
target VARCHAR(16) NOT NULL DEFAULT 'ALL', -- ALL/USER/CREATOR
|
||||
@@ -804,7 +804,7 @@ CREATE INDEX IF NOT EXISTS idx_notice_target ON ops_notice (target, status, publ
|
||||
COMMENT ON TABLE ops_notice IS '系统公告(创作者审核结果、活动、支付通知)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ops_daily_stat (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
stat_date DATE NOT NULL,
|
||||
new_user_count BIGINT NOT NULL DEFAULT 0,
|
||||
active_user_count BIGINT NOT NULL DEFAULT 0,
|
||||
@@ -824,7 +824,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_ops_daily_stat ON ops_daily_stat (stat_date
|
||||
COMMENT ON TABLE ops_daily_stat IS '经营大盘日汇总(含成本口径)';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS audit_log (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
biz_type VARCHAR(32) NOT NULL, -- ORDER/ENTITLEMENT/USER/CREATOR/PRICE
|
||||
biz_id VARCHAR(64) NOT NULL DEFAULT '',
|
||||
action VARCHAR(32) NOT NULL,
|
||||
@@ -878,7 +878,7 @@ ALTER TABLE app_user ADD COLUMN IF NOT EXISTS download_max_quality VARCHAR(16) N
|
||||
-- 下载任务与断点续传进度。分片由客户端直接向 CDN 拉取,服务端只记账:
|
||||
-- 用它实现"下载中/已暂停/已完成"的跨端展示、断点续传的进度恢复,以及配额统计。
|
||||
CREATE TABLE IF NOT EXISTS download_task (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
device_id VARCHAR(128) NOT NULL DEFAULT '',
|
||||
drama_id BIGINT NOT NULL,
|
||||
|
||||
+18
-18
@@ -1,7 +1,7 @@
|
||||
-- FruitShorts 短剧服务 · 建表脚本(PostgreSQL 18)
|
||||
--
|
||||
-- 与 MySQL 版本的对应关系:
|
||||
-- AUTO_INCREMENT -> GENERATED BY DEFAULT AS IDENTITY
|
||||
-- AUTO_INCREMENT -> 无(主键由应用侧雪花算法生成:MyBatis-Plus IdType.ASSIGN_ID)
|
||||
-- TINYINT -> SMALLINT
|
||||
-- DATETIME(3) -> TIMESTAMP(3)
|
||||
-- ON UPDATE CURRENT_TIMESTAMP -> set_updated_at() 触发器
|
||||
@@ -11,7 +11,7 @@
|
||||
-- ========== 系统域 ==========
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_admin_user (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
username VARCHAR(64) NOT NULL, -- 登录名
|
||||
password VARCHAR(100) NOT NULL, -- BCrypt 哈希
|
||||
real_name VARCHAR(64) NOT NULL DEFAULT '',
|
||||
@@ -31,7 +31,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_sys_admin_user_username ON sys_admin_user (
|
||||
COMMENT ON TABLE sys_admin_user IS '管理员';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_role_category (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
name VARCHAR(64) NOT NULL,
|
||||
description VARCHAR(255) NOT NULL DEFAULT '',
|
||||
sort INT NOT NULL DEFAULT 0,
|
||||
@@ -43,7 +43,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_sys_role_category_name ON sys_role_category
|
||||
COMMENT ON TABLE sys_role_category IS '角色分类';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_role (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
name VARCHAR(64) NOT NULL,
|
||||
code VARCHAR(64) NOT NULL, -- 如 super_admin
|
||||
category_id BIGINT NOT NULL DEFAULT 0,
|
||||
@@ -59,7 +59,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_sys_role_code ON sys_role (code);
|
||||
COMMENT ON TABLE sys_role IS '角色';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_admin_user_role (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
role_id BIGINT NOT NULL
|
||||
);
|
||||
@@ -68,7 +68,7 @@ CREATE INDEX IF NOT EXISTS idx_sys_admin_user_role_role ON sys_admin_user_role (
|
||||
COMMENT ON TABLE sys_admin_user_role IS '管理员-角色';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_permission (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
code VARCHAR(128) NOT NULL, -- 如 drama:create
|
||||
name VARCHAR(64) NOT NULL,
|
||||
group_name VARCHAR(64) NOT NULL DEFAULT '',
|
||||
@@ -79,7 +79,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_sys_permission_code ON sys_permission (code
|
||||
COMMENT ON TABLE sys_permission IS '权限点';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_menu (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
parent_id BIGINT NOT NULL DEFAULT 0,
|
||||
title VARCHAR(64) NOT NULL,
|
||||
route_path VARCHAR(128) NOT NULL DEFAULT '',
|
||||
@@ -101,7 +101,7 @@ CREATE INDEX IF NOT EXISTS idx_sys_menu_parent ON sys_menu (parent_id);
|
||||
COMMENT ON TABLE sys_menu IS '菜单';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_role_permission (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
role_id BIGINT NOT NULL,
|
||||
permission_id BIGINT NOT NULL
|
||||
);
|
||||
@@ -109,7 +109,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_sys_role_permission ON sys_role_permission
|
||||
COMMENT ON TABLE sys_role_permission IS '角色-权限';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_role_menu (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
role_id BIGINT NOT NULL,
|
||||
menu_id BIGINT NOT NULL
|
||||
);
|
||||
@@ -117,7 +117,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_sys_role_menu ON sys_role_menu (role_id, me
|
||||
COMMENT ON TABLE sys_role_menu IS '角色-菜单';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_config (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
config_key VARCHAR(128) NOT NULL,
|
||||
config_value VARCHAR(1024) NOT NULL DEFAULT '',
|
||||
remark VARCHAR(255) NOT NULL DEFAULT ''
|
||||
@@ -126,7 +126,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_sys_config_key ON sys_config (config_key);
|
||||
COMMENT ON TABLE sys_config IS '系统配置';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sys_operation_log (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
admin_user_id BIGINT NOT NULL DEFAULT 0,
|
||||
username VARCHAR(64) NOT NULL DEFAULT '',
|
||||
module VARCHAR(64) NOT NULL DEFAULT '',
|
||||
@@ -148,7 +148,7 @@ COMMENT ON TABLE sys_operation_log IS '操作日志';
|
||||
-- ========== 内容域 ==========
|
||||
|
||||
CREATE TABLE IF NOT EXISTS drama_category (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
name VARCHAR(64) NOT NULL,
|
||||
sort INT NOT NULL DEFAULT 0,
|
||||
status SMALLINT NOT NULL DEFAULT 1
|
||||
@@ -157,7 +157,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_drama_category_name ON drama_category (name
|
||||
COMMENT ON TABLE drama_category IS '短剧类型';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS drama (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
code VARCHAR(64) NOT NULL DEFAULT '',
|
||||
title VARCHAR(128) NOT NULL,
|
||||
subtitle VARCHAR(128) NOT NULL DEFAULT '',
|
||||
@@ -194,7 +194,7 @@ CREATE INDEX IF NOT EXISTS idx_drama_status_category ON drama (status, category_
|
||||
COMMENT ON TABLE drama IS '短剧';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS drama_episode (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
drama_id BIGINT NOT NULL,
|
||||
ep_no INT NOT NULL,
|
||||
title VARCHAR(128) NOT NULL DEFAULT '',
|
||||
@@ -217,7 +217,7 @@ CREATE INDEX IF NOT EXISTS idx_drama_episode_status ON drama_episode (drama_id,
|
||||
COMMENT ON TABLE drama_episode IS '剧集';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS drama_review_record (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
biz_type VARCHAR(16) NOT NULL, -- DRAMA/EPISODE
|
||||
biz_id BIGINT NOT NULL,
|
||||
action VARCHAR(16) NOT NULL, -- SUBMIT/APPROVE/REJECT/PUBLISH/OFFLINE
|
||||
@@ -230,7 +230,7 @@ CREATE INDEX IF NOT EXISTS idx_drama_review_biz ON drama_review_record (biz_type
|
||||
COMMENT ON TABLE drama_review_record IS '审核记录';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS content_banner (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
image_url VARCHAR(512) NOT NULL DEFAULT '',
|
||||
slot VARCHAR(32) NOT NULL DEFAULT 'HOME_TOP', -- 展示位置:HOME_TOP/DISCOVER
|
||||
link_type VARCHAR(16) NOT NULL DEFAULT 'NONE', -- NONE/DRAMA/URL
|
||||
@@ -249,7 +249,7 @@ COMMENT ON TABLE content_banner IS '轮播图';
|
||||
-- 本地存储版本:文件落在 fruitshorts.media.root-dir 下,通过 /files/** 访问
|
||||
|
||||
CREATE TABLE IF NOT EXISTS media_asset (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
biz_type VARCHAR(32) NOT NULL DEFAULT 'EPISODE',
|
||||
file_name VARCHAR(255) NOT NULL DEFAULT '',
|
||||
object_key VARCHAR(512) NOT NULL DEFAULT '',
|
||||
@@ -274,7 +274,7 @@ CREATE INDEX IF NOT EXISTS idx_media_asset_biz_type ON media_asset (biz_type);
|
||||
COMMENT ON TABLE media_asset IS '媒资';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS media_upload_task (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
id BIGINT PRIMARY KEY,
|
||||
upload_id VARCHAR(64) NOT NULL,
|
||||
biz_type VARCHAR(32) NOT NULL DEFAULT 'EPISODE',
|
||||
file_name VARCHAR(255) NOT NULL DEFAULT '',
|
||||
|
||||
Reference in new issue
Block a user