|
|
@@ -32,8 +32,8 @@ public class TdEngineService {
|
|
32
|
32
|
private final Map<String, Set<String>> stableColumnCache = new ConcurrentHashMap<>();
|
|
33
|
33
|
private static final int MAX_CACHE_SIZE = 1000;
|
|
34
|
34
|
|
|
35
|
|
- // 允许的列名字符(仅 ASCII 字母、数字、下划线)
|
|
36
|
|
- private static final String ALLOWED_COLUMNS = "^[a-zA-Z_][a-zA-Z0-9_]*$";
|
|
|
35
|
+ // 允许的列名字符(支持中文、ASCII字母、数字、下划线)
|
|
|
36
|
+ private static final String ALLOWED_COLUMNS = "^[a-zA-Z_一-龥][a-zA-Z0-9_一-龥]*$";
|
|
37
|
37
|
|
|
38
|
38
|
// 允许的表名/数据库名字符(允许数字开头和连字符,如 UUID 格式的表名)
|
|
39
|
39
|
private static final String ALLOWED_TABLE_NAME = "^[a-zA-Z0-9][a-zA-Z0-9_-]*$";
|
|
|
@@ -122,7 +122,7 @@ public class TdEngineService {
|
|
122
|
122
|
if (name == null || name.isEmpty()) {
|
|
123
|
123
|
return "`unknown`";
|
|
124
|
124
|
}
|
|
125
|
|
- return "`" + name.replace("`", "") + "`";
|
|
|
125
|
+ return "`" + name.replaceAll("`", "") + "`";
|
|
126
|
126
|
}
|
|
127
|
127
|
|
|
128
|
128
|
private boolean isValidFieldName(String name) {
|
|
|
@@ -133,6 +133,18 @@ public class TdEngineService {
|
|
133
|
133
|
return name != null && name.matches(ALLOWED_TABLE_NAME);
|
|
134
|
134
|
}
|
|
135
|
135
|
|
|
|
136
|
+ private boolean isNumeric(String str) {
|
|
|
137
|
+ if (str == null || str.isEmpty()) {
|
|
|
138
|
+ return false;
|
|
|
139
|
+ }
|
|
|
140
|
+ try {
|
|
|
141
|
+ Double.parseDouble(str);
|
|
|
142
|
+ return true;
|
|
|
143
|
+ } catch (NumberFormatException e) {
|
|
|
144
|
+ return false;
|
|
|
145
|
+ }
|
|
|
146
|
+ }
|
|
|
147
|
+
|
|
136
|
148
|
// === 缓存工具方法 ===
|
|
137
|
149
|
private String getStableKey(String dbName, String stableName) {
|
|
138
|
150
|
return dbName + "." + stableName;
|
|
|
@@ -261,10 +273,13 @@ public class TdEngineService {
|
|
261
|
273
|
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
|
262
|
274
|
String key = entry.getKey();
|
|
263
|
275
|
if (isValidFieldName(key) && !isReservedColumn(key) && !columnTypes.containsKey(key)) {
|
|
264
|
|
- columnTypes.put(key, getValueType(entry.getValue()));
|
|
|
276
|
+ // 统一使用 VARCHAR,避免类型推断导致的问题
|
|
|
277
|
+ columnTypes.put(key, "VARCHAR");
|
|
265
|
278
|
}
|
|
266
|
279
|
}
|
|
267
|
280
|
}
|
|
|
281
|
+
|
|
|
282
|
+ log.debug("收集到的列: {} | 共 {} 列", columnTypes.keySet(), columnTypes.size());
|
|
268
|
283
|
return columnTypes;
|
|
269
|
284
|
}
|
|
270
|
285
|
|
|
|
@@ -305,7 +320,7 @@ public class TdEngineService {
|
|
305
|
320
|
if (!hasData) {
|
|
306
|
321
|
return null;
|
|
307
|
322
|
}
|
|
308
|
|
-
|
|
|
323
|
+ log.info("生成的 INSERT SQL | 列类型: {} | SQL 前100字符: {}", columnTypes, sql.toString().substring(0, Math.min(100, sql.toString().length())));
|
|
309
|
324
|
sql.setLength(sql.length() - 1);
|
|
310
|
325
|
return sql.toString();
|
|
311
|
326
|
}
|
|
|
@@ -329,7 +344,9 @@ public class TdEngineService {
|
|
329
|
344
|
return;
|
|
330
|
345
|
}
|
|
331
|
346
|
|
|
|
347
|
+ log.info("收集到的列类型: {}", columnTypes);
|
|
332
|
348
|
Set<String> existingColumns = getStableColumns(dbName, superTableName);
|
|
|
349
|
+ log.info("超级表已有列: {}", existingColumns);
|
|
333
|
350
|
// 计算实际新增列数(扣除已有列的交集)
|
|
334
|
351
|
int newColumns = 0;
|
|
335
|
352
|
for (String col : columnTypes.keySet()) {
|