From 9792c616b5538b7fc13b9f92f85844afbeb9494e Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 4 Jun 2026 01:14:21 +0800 Subject: [PATCH] =?UTF-8?q?build:=20=E6=95=B0=E6=8D=AE=E5=BA=93=E8=BF=81?= =?UTF-8?q?=E7=A7=BB=E8=84=9A=E6=9C=AC=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v10047__access_subtype_dns_persist.sql | 31 ++++++ .../v10048__activation_code.sql | 29 +++++ .../v10049__cert_apply_template.sql | 16 +++ .../v10047__access_subtype_dns_persist.sql | 31 ++++++ .../migration-pg/v10048__activation_code.sql | 29 +++++ .../v10049__cert_apply_template.sql | 16 +++ packages/ui/certd-server/db/transform.js | 101 +++++++++++++++--- packages/ui/certd-server/src/configuration.ts | 2 + 8 files changed, 241 insertions(+), 14 deletions(-) create mode 100644 packages/ui/certd-server/db/migration-mysql/v10047__access_subtype_dns_persist.sql create mode 100644 packages/ui/certd-server/db/migration-mysql/v10048__activation_code.sql create mode 100644 packages/ui/certd-server/db/migration-mysql/v10049__cert_apply_template.sql create mode 100644 packages/ui/certd-server/db/migration-pg/v10047__access_subtype_dns_persist.sql create mode 100644 packages/ui/certd-server/db/migration-pg/v10048__activation_code.sql create mode 100644 packages/ui/certd-server/db/migration-pg/v10049__cert_apply_template.sql diff --git a/packages/ui/certd-server/db/migration-mysql/v10047__access_subtype_dns_persist.sql b/packages/ui/certd-server/db/migration-mysql/v10047__access_subtype_dns_persist.sql new file mode 100644 index 000000000..93decbaf2 --- /dev/null +++ b/packages/ui/certd-server/db/migration-mysql/v10047__access_subtype_dns_persist.sql @@ -0,0 +1,31 @@ +ALTER TABLE cd_access ADD COLUMN subtype varchar(100); +CREATE INDEX `index_access_subtype` ON `cd_access` (`subtype`); + +CREATE TABLE `cd_dns_persist_record` +( + `id` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL, + `user_id` bigint NOT NULL, + `project_id` bigint, + `domain` varchar(255) NOT NULL, + `main_domain` varchar(255) NOT NULL, + `ca_type` varchar(50) NOT NULL, + `acme_account_access_id` bigint NOT NULL, + `account_uri` varchar(512) NOT NULL, + `host_record` varchar(255) NOT NULL, + `record_value` longtext NOT NULL, + `policy` varchar(50), + `persist_until` bigint, + `status` varchar(50) NOT NULL DEFAULT 'pending', + `dns_provider_type` varchar(50), + `dns_provider_access` bigint, + `record_res` longtext, + `disabled` bigint NOT NULL DEFAULT 0, + `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE = InnoDB ROW_FORMAT = DYNAMIC; + +CREATE INDEX `index_dns_persist_user_id` ON `cd_dns_persist_record` (`user_id`); +CREATE INDEX `index_dns_persist_project_id` ON `cd_dns_persist_record` (`project_id`); +CREATE INDEX `index_dns_persist_domain` ON `cd_dns_persist_record` (`domain`(191)); +CREATE INDEX `index_dns_persist_main_domain` ON `cd_dns_persist_record` (`main_domain`(191)); +CREATE INDEX `index_dns_persist_account` ON `cd_dns_persist_record` (`acme_account_access_id`); diff --git a/packages/ui/certd-server/db/migration-mysql/v10048__activation_code.sql b/packages/ui/certd-server/db/migration-mysql/v10048__activation_code.sql new file mode 100644 index 000000000..548d6fa58 --- /dev/null +++ b/packages/ui/certd-server/db/migration-mysql/v10048__activation_code.sql @@ -0,0 +1,29 @@ +-- 激活码表 +CREATE TABLE `cd_product_activation_code` +( + `id` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL, + `code` varchar(50) NOT NULL, + `product_id` bigint NOT NULL, + `duration` bigint NOT NULL, + `batch_no` varchar(50) NOT NULL DEFAULT '', + `status` varchar(20) NOT NULL DEFAULT 'unused', + `used_user_id` bigint, + `used_time` bigint, + `expire_time` bigint, + `disabled_time` bigint, + `exported` bigint NOT NULL DEFAULT 0, + `export_time` bigint, + `remark` varchar(500) NOT NULL DEFAULT '', + `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE = InnoDB ROW_FORMAT = DYNAMIC; + +CREATE UNIQUE INDEX `index_activation_code_code` ON `cd_product_activation_code` (`code`); +CREATE INDEX `index_activation_code_batch_no` ON `cd_product_activation_code` (`batch_no`); +CREATE INDEX `index_activation_code_status` ON `cd_product_activation_code` (`status`); +CREATE INDEX `index_activation_code_expire_time` ON `cd_product_activation_code` (`expire_time`); +CREATE INDEX `index_activation_code_exported` ON `cd_product_activation_code` (`exported`); + +-- cd_user_suite 增加激活码来源追溯 +ALTER TABLE `cd_user_suite` + ADD COLUMN `activation_code_id` bigint; diff --git a/packages/ui/certd-server/db/migration-mysql/v10049__cert_apply_template.sql b/packages/ui/certd-server/db/migration-mysql/v10049__cert_apply_template.sql new file mode 100644 index 000000000..913ea09af --- /dev/null +++ b/packages/ui/certd-server/db/migration-mysql/v10049__cert_apply_template.sql @@ -0,0 +1,16 @@ +CREATE TABLE `cd_cert_apply_template` +( + `id` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL, + `user_id` bigint NOT NULL, + `project_id` bigint NULL, + `name` varchar(100) NOT NULL, + `content` longtext NOT NULL, + `is_default` boolean NOT NULL DEFAULT false, + `disabled` boolean NOT NULL DEFAULT false, + `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE = InnoDB ROW_FORMAT = DYNAMIC; + +CREATE INDEX `index_cert_apply_template_user_id` ON `cd_cert_apply_template` (`user_id`); +CREATE INDEX `index_cert_apply_template_project_id` ON `cd_cert_apply_template` (`project_id`); +CREATE INDEX `index_cert_apply_template_default` ON `cd_cert_apply_template` (`user_id`, `project_id`, `is_default`); diff --git a/packages/ui/certd-server/db/migration-pg/v10047__access_subtype_dns_persist.sql b/packages/ui/certd-server/db/migration-pg/v10047__access_subtype_dns_persist.sql new file mode 100644 index 000000000..d6b056117 --- /dev/null +++ b/packages/ui/certd-server/db/migration-pg/v10047__access_subtype_dns_persist.sql @@ -0,0 +1,31 @@ +ALTER TABLE cd_access ADD COLUMN subtype varchar(100); +CREATE INDEX "index_access_subtype" ON "cd_access" ("subtype"); + +CREATE TABLE "cd_dns_persist_record" +( + "id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY NOT NULL, + "user_id" bigint NOT NULL, + "project_id" bigint, + "domain" varchar(255) NOT NULL, + "main_domain" varchar(255) NOT NULL, + "ca_type" varchar(50) NOT NULL, + "acme_account_access_id" bigint NOT NULL, + "account_uri" varchar(512) NOT NULL, + "host_record" varchar(255) NOT NULL, + "record_value" text NOT NULL, + "policy" varchar(50), + "persist_until" bigint, + "status" varchar(50) NOT NULL DEFAULT 'pending', + "dns_provider_type" varchar(50), + "dns_provider_access" bigint, + "record_res" text, + "disabled" bigint NOT NULL DEFAULT 0, + "create_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP), + "update_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP) +); + +CREATE INDEX "index_dns_persist_user_id" ON "cd_dns_persist_record" ("user_id"); +CREATE INDEX "index_dns_persist_project_id" ON "cd_dns_persist_record" ("project_id"); +CREATE INDEX "index_dns_persist_domain" ON "cd_dns_persist_record" ("domain"); +CREATE INDEX "index_dns_persist_main_domain" ON "cd_dns_persist_record" ("main_domain"); +CREATE INDEX "index_dns_persist_account" ON "cd_dns_persist_record" ("acme_account_access_id"); diff --git a/packages/ui/certd-server/db/migration-pg/v10048__activation_code.sql b/packages/ui/certd-server/db/migration-pg/v10048__activation_code.sql new file mode 100644 index 000000000..fa3e85b7a --- /dev/null +++ b/packages/ui/certd-server/db/migration-pg/v10048__activation_code.sql @@ -0,0 +1,29 @@ +-- 激活码表 +CREATE TABLE "cd_product_activation_code" +( + "id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY NOT NULL, + "code" varchar(50) NOT NULL, + "product_id" bigint NOT NULL, + "duration" bigint NOT NULL, + "batch_no" varchar(50) NOT NULL DEFAULT '', + "status" varchar(20) NOT NULL DEFAULT 'unused', + "used_user_id" bigint, + "used_time" bigint, + "expire_time" bigint, + "disabled_time" bigint, + "exported" bigint NOT NULL DEFAULT 0, + "export_time" bigint, + "remark" varchar(500) NOT NULL DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP), + "update_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP) +); + +CREATE UNIQUE INDEX "index_activation_code_code" ON "cd_product_activation_code" ("code"); +CREATE INDEX "index_activation_code_batch_no" ON "cd_product_activation_code" ("batch_no"); +CREATE INDEX "index_activation_code_status" ON "cd_product_activation_code" ("status"); +CREATE INDEX "index_activation_code_expire_time" ON "cd_product_activation_code" ("expire_time"); +CREATE INDEX "index_activation_code_exported" ON "cd_product_activation_code" ("exported"); + +-- cd_user_suite 增加激活码来源追溯 +ALTER TABLE "cd_user_suite" + ADD COLUMN "activation_code_id" bigint; diff --git a/packages/ui/certd-server/db/migration-pg/v10049__cert_apply_template.sql b/packages/ui/certd-server/db/migration-pg/v10049__cert_apply_template.sql new file mode 100644 index 000000000..56187a745 --- /dev/null +++ b/packages/ui/certd-server/db/migration-pg/v10049__cert_apply_template.sql @@ -0,0 +1,16 @@ +CREATE TABLE "cd_cert_apply_template" +( + "id" bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY NOT NULL, + "user_id" bigint NOT NULL, + "project_id" bigint NULL, + "name" varchar(100) NOT NULL, + "content" text NOT NULL, + "is_default" boolean NOT NULL DEFAULT (false), + "disabled" boolean NOT NULL DEFAULT (false), + "create_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP), + "update_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP) +); + +CREATE INDEX "index_cert_apply_template_user_id" ON "cd_cert_apply_template" ("user_id"); +CREATE INDEX "index_cert_apply_template_project_id" ON "cd_cert_apply_template" ("project_id"); +CREATE INDEX "index_cert_apply_template_default" ON "cd_cert_apply_template" ("user_id", "project_id", "is_default"); diff --git a/packages/ui/certd-server/db/transform.js b/packages/ui/certd-server/db/transform.js index 606529c9d..37374d23f 100644 --- a/packages/ui/certd-server/db/transform.js +++ b/packages/ui/certd-server/db/transform.js @@ -1,4 +1,7 @@ import fs from "fs"; + +const MYSQL_INDEX_PREFIX_LENGTH = 191; +const MYSQL_TABLE_OPTIONS = "ENGINE = InnoDB ROW_FORMAT = DYNAMIC"; /** * ## sqlite与postgres不同点 * 1. @@ -55,6 +58,88 @@ function transformPG() { } } +function buildMysqlTableColumnMap(sql) { + const tableColumnMap = new Map(); + const createTableReg = /CREATE TABLE `([^`]*)`[\s\S]*?;/gi; + for (const match of sql.matchAll(createTableReg)) { + const [statement, tableName] = match; + const tableBody = getCreateTableBody(statement); + const columnMap = new Map(); + const columnReg = /`([^`]*)`\s+varchar\((\d+)\)/gi; + for (const columnMatch of tableBody.matchAll(columnReg)) { + const [, columnName, length] = columnMatch; + columnMap.set(columnName, Number(length)); + } + tableColumnMap.set(tableName, columnMap); + } + + const alterAddColumnReg = /ALTER TABLE\s+`?([^`\s]+)`?\s+ADD COLUMN\s+`?([^`\s]+)`?\s+varchar\((\d+)\)/gi; + for (const match of sql.matchAll(alterAddColumnReg)) { + const [, tableName, columnName, length] = match; + const columnMap = tableColumnMap.get(tableName) || new Map(); + columnMap.set(columnName, Number(length)); + tableColumnMap.set(tableName, columnMap); + } + + return tableColumnMap; +} + +function getCreateTableBody(statement) { + const start = statement.indexOf("("); + const end = statement.lastIndexOf(")"); + if (start === -1 || end === -1 || end <= start) { + return ""; + } + return statement.substring(start + 1, end); +} + +function appendMysqlTableOptions(sql) { + const createTableReg = /CREATE TABLE `([^`]*)`[\s\S]*?;/gi; + return sql.replace(createTableReg, statement => { + const sqlWithoutSemicolon = statement.replace(/;\s*$/, ""); + const sqlWithoutOptions = sqlWithoutSemicolon.replace(/\s+ENGINE\s*=\s*\w+(?:\s+ROW_FORMAT\s*=\s*\w+)?\s*$/i, ""); + return `${sqlWithoutOptions} ${MYSQL_TABLE_OPTIONS};`; + }); +} + +function addMysqlIndexPrefix(sql) { + const tableColumnMap = buildMysqlTableColumnMap(sql); + const createIndexReg = /CREATE\s+(UNIQUE\s+)?INDEX\s+`([^`]*)`\s+ON\s+`([^`]*)`\s*\(([^;]*)\);/gi; + return sql.replace(createIndexReg, (statement, uniqueKeyword, indexName, tableName, columns) => { + const columnMap = tableColumnMap.get(tableName); + if (!columnMap) { + return statement; + } + + const parsedColumns = columns.split(",").map(item => { + const columnMatch = item.trim().match(/^`([^`]*)`(?:\((\d+)\))?$/); + if (!columnMatch) { + return item.trim(); + } + + const [, columnName, prefixLength] = columnMatch; + const columnLength = columnMap.get(columnName); + if (!columnLength || columnLength <= MYSQL_INDEX_PREFIX_LENGTH) { + return item.trim(); + } + + if (prefixLength && Number(prefixLength) <= MYSQL_INDEX_PREFIX_LENGTH) { + return item.trim(); + } + + // MySQL 5.7 老配置下 utf8mb4 varchar(255) 完整索引可能超过 767/1000 字节限制。 + if (uniqueKeyword) { + throw new Error(`唯一索引 ${indexName} 的字段 ${tableName}.${columnName} 长度超过 ${MYSQL_INDEX_PREFIX_LENGTH},不能自动改成前缀索引,请缩短字段长度或增加 hash 字段`); + } + + return `\`${columnName}\`(${MYSQL_INDEX_PREFIX_LENGTH})`; + }); + + const unique = uniqueKeyword || ""; + return `CREATE ${unique}INDEX \`${indexName}\` ON \`${tableName}\` (${parsedColumns.join(", ")});`; + }); +} + function transformMysql() { // 读取文件列表 const sqliteFiles = fs.readdirSync("./migration/"); @@ -76,20 +161,8 @@ function transformMysql() { //双引号 替换成反引号 pgSql = pgSql.replaceAll(/"/g, "`"); - //提取所有的 create table 的表格name - const tableNames = pgSql.match(/CREATE TABLE `([^`]*)`/g); - if (tableNames && tableNames.length > 0) { - for (const item of tableNames) { - /** - * CREATE TABLE `cd_project` -CREATE TABLE `cd_project_member` -CREATE TABLE `cd_audit_log` - */ - //提取表名 - const tableName = item.match(/`([^`]*)`/)[1]; - pgSql += `\nALTER TABLE \`${tableName}\` ENGINE = InnoDB;`; - } - } + pgSql = appendMysqlTableOptions(pgSql); + pgSql = addMysqlIndexPrefix(pgSql); fs.writeFileSync(`./migration-mysql/${notFile}`, pgSql); } diff --git a/packages/ui/certd-server/src/configuration.ts b/packages/ui/certd-server/src/configuration.ts index 8eaaef70c..55bb01d0e 100644 --- a/packages/ui/certd-server/src/configuration.ts +++ b/packages/ui/certd-server/src/configuration.ts @@ -134,5 +134,7 @@ export class MainConfiguration { }); logger.info("当前环境:", this.app.getEnv()); // prod + + } }