Pārlūkot izejas kodu

fix(backend): schema.sql 建表语句提取支持引号内分号

原用非贪婪正则 CREATE...IF NOT EXISTS .*?; 提取建表语句,
遇到 COMMENT 字符串字面量内的分号(task_reminder_config.offset_minutes
注释"截止前N分钟; after_timeout...")会提前截断,语句不完整导致
每次启动告警且该表无法由 schema.sql 创建。
改为按字符扫描、跳过单引号/反引号内分号,完整切分 338 条语句(与旧实现同集)。
Xiaogang Liao 1 dienu atpakaļ
vecāks
revīzija
232840dfd2

+ 30 - 12
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -21,7 +21,6 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 @Component
@@ -95,18 +94,37 @@ public class DatabaseInitializer implements CommandLineRunner {
             // Remove SQL single-line comments
             content = content.replaceAll("(?m)^\\s*--.*$", "");
 
-            // Extract all CREATE TABLE IF NOT EXISTS statements
-            Pattern pattern = Pattern.compile(
-                    "CREATE\\s+TABLE\\s+IF\\s+NOT\\s+EXISTS\\s+.*?;",
-                    Pattern.CASE_INSENSITIVE | Pattern.DOTALL
-            );
-            Matcher matcher = pattern.matcher(content);
-
+            // 提取所有 CREATE TABLE IF NOT EXISTS 语句。
+            // 不能用非贪婪 ".*?;" 匹配:COMMENT 字符串字面量中可能含分号(如
+            // task_reminder_config.offset_minutes 的注释 "截止前N分钟; after_timeout..."),
+            // 会被提前截断导致语句不完整而建表失败。此处按字符扫描,跳过引号内部的分号。
             List<String> createTableSQLs = new ArrayList<>();
-            while (matcher.find()) {
-                String sql = matcher.group().trim();
-                if (!sql.isEmpty()) {
-                    createTableSQLs.add(sql);
+            Pattern createTableHead = Pattern.compile(
+                    "^\\s*CREATE\\s+TABLE\\s+IF\\s+NOT\\s+EXISTS\\b", Pattern.CASE_INSENSITIVE);
+            StringBuilder stmt = new StringBuilder();
+            boolean inSingleQuote = false;
+            boolean inBacktick = false;
+            for (int i = 0; i < content.length(); i++) {
+                char c = content.charAt(i);
+                if (c == '\'' && !inBacktick) {
+                    if (inSingleQuote && i + 1 < content.length() && content.charAt(i + 1) == '\'') {
+                        stmt.append("''");
+                        i++;
+                        continue;
+                    }
+                    inSingleQuote = !inSingleQuote;
+                    stmt.append(c);
+                } else if (c == '`' && !inSingleQuote) {
+                    inBacktick = !inBacktick;
+                    stmt.append(c);
+                } else if (c == ';' && !inSingleQuote && !inBacktick) {
+                    String sql = stmt.toString().trim();
+                    if (!sql.isEmpty() && createTableHead.matcher(sql).find()) {
+                        createTableSQLs.add(sql + ";");
+                    }
+                    stmt.setLength(0);
+                } else {
+                    stmt.append(c);
                 }
             }