Skip to content

Commit 6f77ab0

Browse files
Fix split sql concatenated limit exceptions by semicolon (#5245)
* Fix split sql concatenated limit exceptions by semicolon * Add sql to split abnormal problem test classes by semicolons * Update SQLExplainTest.java
1 parent 5fbc4a1 commit 6f77ab0

File tree

2 files changed

+68
-1
lines changed
  • linkis-computation-governance/linkis-entrance/src

2 files changed

+68
-1
lines changed

linkis-computation-governance/linkis-entrance/src/main/scala/org/apache/linkis/entrance/interceptor/impl/Explain.scala

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ object SQLExplain extends Explain {
176176
}
177177
}
178178
} else {
179-
tempCode.split(";") foreach { singleCode =>
179+
splitSqlWithRealSemicolon(tempCode) foreach { singleCode =>
180180
if (isSelectCmd(singleCode)) {
181181
val trimCode = singleCode.trim
182182
if (isSelectCmdNoLimit(trimCode) && !isNoLimitAllowed) {
@@ -230,6 +230,50 @@ object SQLExplain extends Explain {
230230
array.toArray
231231
}
232232

233+
private def splitSqlWithRealSemicolon(tempCode: String): Array[String] = {
234+
// sql has been split by semicolons, but the semicolons within single quotes, double quotes, and backquotes are ignored
235+
val splitSql = new ArrayBuffer[String]
236+
val current = new StringBuilder
237+
var inSingleQuote = false
238+
var inDoubleQuote = false
239+
var inBackQuote = false
240+
var escapeNext = false
241+
242+
for (char <- tempCode) {
243+
if (escapeNext) {
244+
current.append(char)
245+
escapeNext = false
246+
} else {
247+
char match {
248+
case '\\' =>
249+
current.append(char)
250+
escapeNext = true
251+
case '\'' if !inDoubleQuote && !inBackQuote =>
252+
current.append(char)
253+
inSingleQuote = !inSingleQuote
254+
case '"' if !inSingleQuote && !inBackQuote =>
255+
current.append(char)
256+
inDoubleQuote = !inDoubleQuote
257+
case '`' if !inSingleQuote && !inDoubleQuote =>
258+
current.append(char)
259+
inBackQuote = !inBackQuote
260+
case ';' if !inSingleQuote && !inDoubleQuote && !inBackQuote =>
261+
splitSql += current.toString()
262+
current.clear()
263+
case _ =>
264+
current.append(char)
265+
}
266+
}
267+
}
268+
269+
// Add the last fragment
270+
if (current.nonEmpty) {
271+
splitSql += current.toString()
272+
}
273+
splitSql.toArray
274+
275+
}
276+
233277
private def addNoLimit(code: String) = code + NO_LIMIT_STRING
234278

235279
protected def needNoLimit(code: String): Boolean = code.endsWith(NO_LIMIT_STRING)

linkis-computation-governance/linkis-entrance/src/test/java/org/apache/linkis/entrance/interceptor/impl/SQLExplainTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.apache.linkis.entrance.interceptor.impl;
1919

20+
import org.apache.linkis.governance.common.entity.job.JobRequest;
2021
import org.junit.jupiter.api.Assertions;
2122
import org.junit.jupiter.api.Test;
2223

@@ -52,4 +53,26 @@ void isSelectOverLimit() {
5253
res = SQLExplain.isSelectOverLimit(code);
5354
Assertions.assertEquals(false, res);
5455
}
56+
57+
/**
58+
* 未修复前代码进行拼接sql时,输出的sql为
59+
* select
60+
* id,
61+
* name,
62+
* array_join(array_intersect(map_keys(info),array['abs','oda'],' limit 5000;
63+
* ') as infos
64+
* from ods.dim_ep22
65+
*/
66+
@Test
67+
void splicingLimitSql() {
68+
String code = "select\n" +
69+
"id,\n" +
70+
"name,\n" +
71+
"array_join(array_intersect(map_keys(info),array['abs','oda'],';') as infos\n" +
72+
"from ods.dim_ep22";
73+
StringBuilder logAppender = new StringBuilder();
74+
JobRequest jobRequest = new JobRequest();
75+
SQLExplain.dealSQLLimit(code, jobRequest, logAppender);
76+
Assertions.assertEquals(code+" limit 5000", jobRequest.getExecutionCode());
77+
}
5578
}

0 commit comments

Comments
 (0)