Skip to content

Commit b9bfe46

Browse files
authored
feat(parser): 支持多 SQL (#942)
2 parents b543bc2 + 0277bed commit b9bfe46

4 files changed

Lines changed: 79 additions & 9 deletions

File tree

core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParser.java

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,18 @@
77
import org.antlr.v4.runtime.CommonTokenStream;
88
import org.antlr.v4.runtime.tree.ParseTree;
99

10+
import java.util.ArrayList;
11+
import java.util.List;
12+
1013
public class SQLParser
1114
{
1215
public static SQLStatement parse(String sql)
16+
{
17+
List<SQLStatement> statements = parseMultiple(sql);
18+
return statements.isEmpty() ? null : statements.get(0);
19+
}
20+
21+
public static List<SQLStatement> parseMultiple(String sql)
1322
{
1423
try {
1524
// 创建词法分析器和语法分析器
@@ -23,17 +32,32 @@ public static SQLStatement parse(String sql)
2332
parser.removeErrorListeners();
2433
parser.addErrorListener(new SQLParserErrorListener());
2534

26-
// 获取解析树
27-
// Get parse tree
28-
ParseTree tree = parser.singleStatement();
35+
// 获取解析树 - 使用 sqlStatements 而不是 statement
36+
// Get parse tree - use sqlStatements instead of statement
37+
ParseTree tree = parser.sqlStatements();
2938

3039
// 访问解析树
3140
// Visit parse tree
3241
SQLVisitor visitor = new SQLVisitor();
33-
return visitor.visit(tree);
42+
43+
List<SQLStatement> statements = new ArrayList<>();
44+
45+
// 遍历所有的 singleStatement
46+
// Traverse all singleStatement
47+
for (int i = 0; i < tree.getChildCount(); i++) {
48+
ParseTree child = tree.getChild(i);
49+
if (child instanceof SqlBaseParser.SingleStatementContext) {
50+
SQLStatement stmt = visitor.visit(child);
51+
if (stmt != null) {
52+
statements.add(stmt);
53+
}
54+
}
55+
}
56+
57+
return statements;
3458
}
3559
catch (Exception e) {
3660
throw new SQLParseException("Failed to parse SQL: " + e.getMessage(), e);
3761
}
3862
}
39-
}
63+
}

core/datacap-ui/src/views/pages/admin/source/SourceInfo.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,11 @@ export default defineComponent({
287287
const pluginsResponse = await getPluginsPromise
288288
if (pluginsResponse.status) {
289289
this.plugins = pluginsResponse.data
290+
291+
const hasJsonConvert = this.plugins.filter(value => value.type === 'Convert' && value.name === 'JsonConvert').length > 0
292+
if (!hasJsonConvert) {
293+
this.testInfo.message = 'JsonConvert plugin is required'
294+
}
290295
}
291296
this.formState = SourceRequest.of()
292297
}

test/datacap-test-parser/src/test/java/io/edurt/datacap/test/basic/CreateStatementTest.java

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,52 @@ public void testFlinkSql()
5959
" COL4\n" +
6060
"FROM\n" +
6161
" transform_table;";
62-
SQLStatement stmt = SQLParser.parse(sql);
6362

63+
// 解析多个语句
64+
// Parse multiple statements
65+
List<SQLStatement> statements = SQLParser.parseMultiple(sql);
66+
67+
System.out.println("Total statements parsed: " + statements.size());
68+
69+
for (int i = 0; i < statements.size(); i++) {
70+
SQLStatement stmt = statements.get(i);
71+
System.out.println("Statement " + (i + 1) + ": " + stmt.getClass().getSimpleName());
72+
73+
if (stmt instanceof CreateTableStatement) {
74+
CreateTableStatement createStmt = (CreateTableStatement) stmt;
75+
System.out.println("Table name: " + createStmt.getTableName());
76+
List<TableOption> options = createStmt.getOptions();
77+
System.out.println("Options: " + options);
78+
System.out.println("---");
79+
}
80+
}
81+
}
82+
83+
@Test
84+
public void testSingleCreateTable()
85+
{
86+
String singleSql = "CREATE TABLE source_table (\n" +
87+
" COL1 INT,\n" +
88+
" COL2 TIMESTAMP(0),\n" +
89+
" COL3 VARCHAR(14),\n" +
90+
" COL4 CHAR(1),\n" +
91+
" PRIMARY KEY (COL1) NOT ENFORCED\n" +
92+
") WITH\n" +
93+
" (\n" +
94+
" 'connector' = 'mysql',\n" +
95+
" 'hostname' = '127.0.0.1',\n" +
96+
" 'port' = '3306',\n" +
97+
" 'username' = 'root',\n" +
98+
" 'password' = 'root',\n" +
99+
" 'database' = 'default',\n" +
100+
" 'table' = 'example'\n" +
101+
" );";
102+
103+
SQLStatement stmt = SQLParser.parse(singleSql);
64104
assertTrue(stmt instanceof CreateTableStatement);
65105
CreateTableStatement statement = (CreateTableStatement) stmt;
66106

67107
List<TableOption> options = statement.getOptions();
68-
System.out.println(options);
108+
System.out.println("Single statement options: " + options);
69109
}
70-
}
110+
}

test/datacap-test-parser/src/test/java/io/edurt/datacap/test/basic/SelectStatementTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.edurt.datacap.test.basic;
22

33
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4+
import io.edurt.datacap.sql.SQLParseException;
45
import io.edurt.datacap.sql.SQLParser;
56
import io.edurt.datacap.sql.node.Expression;
67
import io.edurt.datacap.sql.node.clause.JoinClause;
@@ -146,7 +147,7 @@ public void testSelectWithCaseWhen()
146147
assertEquals("age_group", selectElements.get(1).getAlias());
147148
}
148149

149-
@Test(expected = RuntimeException.class)
150+
@Test(expected = SQLParseException.class)
150151
public void testInvalidSQL()
151152
{
152153
String sql = "SELECT * FORM users";

0 commit comments

Comments
 (0)