-- ============================================================================= -- pbl_domain_ext [M8] 基础域薄扩展 world/scene/entity -- ============================================================================= -- 铁律: -- 1. 本文件**只创建 1 张表** pbl_domain_ref(关联表,ref_type 区分 -- world / scene / entity)。world / scene / entity 三张基础域基表 -- 由各自基础模块维护,本模块**不建、不改、不写**(Q-OPEN-3)。 -- 2. 列名 / 类型 / 长度与 models/pbl_domain_ref.json、 -- pbl_domain_ext/base.py 的 FIELD_MAXLEN 三处同名同型, -- 由 tests/test_models_contract.py 机械校验。 -- 3. 幂等:CREATE TABLE IF NOT EXISTS + 下方 ext_json 列名收敛块 -- (历史遗留列名 domain_ext_json → 设计 §J1 权威列名 ext_json)。 -- RENAME 前先查 information_schema,重复执行不报错。 -- 4. collation 显式 utf8mb4_unicode_ci(与 xls2ddl/json2ddl 标准一致, -- 避免与 appcodes_kv JOIN 时 Illegal mix of collations)。 -- ============================================================================= CREATE TABLE IF NOT EXISTS `pbl_domain_ref` ( `id` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '主键ID', `tenant_id` VARCHAR(32) NOT NULL DEFAULT '0' COMMENT '租户ID', `ref_type` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '关联类型(world/scene/entity)', `ref_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '基础域对象ID', `ref_code` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '基础域对象编码', `ref_name` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '基础域对象名称', `blueprint_id` VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'PBL蓝图ID', `team_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '团队ID', `class_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '班级ID', `bind_state` VARCHAR(32) NOT NULL DEFAULT 'bound' COMMENT '绑定状态(bound/unbound)', `remark` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备注', `created_by` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '创建人', `updated_by` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '更新人', `ext_json` TEXT NULL COMMENT '扩展属性JSON(设计§J1权威列名)', `is_deleted` VARCHAR(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除标记(0正常/1已删)', `created_at` DATETIME NULL COMMENT '创建时间', `updated_at` DATETIME NULL COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_pbl_domain_ref_tenant_type` (`tenant_id`, `ref_type`, `is_deleted`), KEY `idx_pbl_domain_ref_object` (`tenant_id`, `ref_type`, `ref_id`), KEY `idx_pbl_domain_ref_blueprint` (`tenant_id`, `blueprint_id`), KEY `idx_pbl_domain_ref_team` (`tenant_id`, `class_id`, `team_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='PBL基础域关联表(world/scene/entity)'; -- ----------------------------------------------------------------------------- -- 幂等列名收敛(ext_json 为设计 §J1 权威列名) -- MySQL 8.0 不支持 ADD/RENAME COLUMN IF NOT EXISTS,用 prepared statement 兜底。 -- 执行顺序:① 旧列存在且新列不存在 -> CHANGE COLUMN 重命名; -- ② 两列都不存在 -> ADD COLUMN;③ 新列已存在 -> 什么都不做。 -- ----------------------------------------------------------------------------- SET @tbl := 'pbl_domain_ref'; SET @old_col := 'domain_ext_json'; SET @new_col := 'ext_json'; SET @has_old := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = @tbl AND COLUMN_NAME = @old_col); SET @has_new := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = @tbl AND COLUMN_NAME = @new_col); SET @sql := IF(@has_old = 1 AND @has_new = 0, CONCAT('ALTER TABLE `', @tbl, '` CHANGE COLUMN `', @old_col, '` `', @new_col, '` TEXT NULL COMMENT ''扩展属性JSON(设计§J1权威列名)'''), 'SELECT ''pbl_domain_ext: ext_json rename skipped (already converged or absent)'''); PREPARE pbl_ext_rename FROM @sql; EXECUTE pbl_ext_rename; DEALLOCATE PREPARE pbl_ext_rename; SET @sql := IF(@has_old = 0 AND @has_new = 0, CONCAT('ALTER TABLE `', @tbl, '` ADD COLUMN `', @new_col, '` TEXT NULL COMMENT ''扩展属性JSON(设计§J1权威列名)'''), 'SELECT ''pbl_domain_ext: ext_json present'''); PREPARE pbl_ext_add FROM @sql; EXECUTE pbl_ext_add; DEALLOCATE PREPARE pbl_ext_add; -- ----------------------------------------------------------------------------- -- 编码字典(appcodes 父记录 + appcodes_kv 子记录,与 init/data.json 同源) -- 说明:init/data.json 由 dbloader 幂等写入;此处 SQL 版供手工建库场景兜底。 -- 组 key 长度均 <= 22 字符(parentid + '_' + k <= 32)。 -- ----------------------------------------------------------------------------- INSERT INTO `appcodes` (`id`, `name`, `hierarchy_flg`) VALUES ('pbl_domain_ref_type', 'PBL基础域关联类型', '0'), ('pbl_bind_state', 'PBL绑定状态', '0') ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `hierarchy_flg` = VALUES(`hierarchy_flg`); INSERT INTO `appcodes_kv` (`id`, `parentid`, `k`, `v`) VALUES ('pbl_domain_ref_type_world', 'pbl_domain_ref_type', 'world', '世界'), ('pbl_domain_ref_type_scene', 'pbl_domain_ref_type', 'scene', '场景'), ('pbl_domain_ref_type_entity', 'pbl_domain_ref_type', 'entity', '实体'), ('pbl_bind_state_bound', 'pbl_bind_state', 'bound', '已绑定'), ('pbl_bind_state_unbound', 'pbl_bind_state', 'unbound', '已解绑') ON DUPLICATE KEY UPDATE `v` = VALUES(`v`);