This is an automated email from the ASF dual-hosted git repository. pdallig pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/master by this push: new c9c3437a11 [ZEPPELIN-5970][ZEPPELIN-5971] bugs occur when zeppelin.livy.tableWithUTFCharacters is enabled (#4675) c9c3437a11 is described below commit c9c3437a118bfdd472d474c22ae7393f21cf49b0 Author: levi0090 <147389858+levi0...@users.noreply.github.com> AuthorDate: Mon Nov 20 22:34:15 2023 +1300 [ZEPPELIN-5970][ZEPPELIN-5971] bugs occur when zeppelin.livy.tableWithUTFCharacters is enabled (#4675) * fix error occurs when non-select SQL statement is executed and tableWithUTFCharacter is True * fix error occurs when non-primitive type of data is within json response such as array and tableWithUTFCharacter is True * rename custom function * fix bug and improve the performance to iterate over the entrySet. * remove nit --------- Co-authored-by: Philipp Dallig <philipp.dal...@gmail.com> --- .../zeppelin/livy/LivySparkSQLInterpreter.java | 36 +++++++++++++++++++--- .../zeppelin/livy/LivySQLInterpreterTest.java | 14 ++++++++- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java index 40aa36349a..aec8146499 100644 --- a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java +++ b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java @@ -18,7 +18,8 @@ package org.apache.zeppelin.livy; import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import java.io.IOException; import java.io.StringWriter; @@ -180,15 +181,20 @@ public class LivySparkSQLInterpreter extends BaseLivyInterpreter { List<String> rows = new ArrayList<>(); String[] rowsOutput = output.split("(?<!\\\\)\\n"); + + if (rowsOutput.length < 2){ + return Arrays.asList(rowsOutput); + } + String[] header = rowsOutput[1].split("\t"); List<String> cells = new ArrayList<>(Arrays.asList(header)); rows.add(StringUtils.join(cells, "\t")); for (int i = 2; i < rowsOutput.length; i++) { - Map<String, String> retMap = new Gson().fromJson( - rowsOutput[i], new TypeToken<HashMap<String, String>>() { - }.getType() - ); + // one-by-one serialization to handle the case when + // the value is non-primitive such as: {"lang": ["java", "NodeJS"]}. + Map<String, String> retMap = deserialize(rowsOutput[i]); + cells = new ArrayList<>(); for (String s : header) { cells.add(retMap.getOrDefault(s, "null") @@ -200,6 +206,26 @@ public class LivySparkSQLInterpreter extends BaseLivyInterpreter { return rows; } + private Map<String, String> deserialize(String jsonString) { + Map<String, String> map = new HashMap<>(); + Gson gson = new Gson(); + JsonElement jsonElement = gson.fromJson(jsonString, JsonElement.class); + JsonObject jsonObject = jsonElement.getAsJsonObject(); + + for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { + String key = entry.getKey(); + JsonElement value = entry.getValue(); + + if (value.isJsonPrimitive()) { + map.put(key, value.getAsString()); + } else { + map.put(key, value.toString()); + } + + } + return map; + } + protected List<String> parseSQLOutput(String str) { // the regex is referred to org.apache.spark.util.Utils#fullWidthRegex // for spark every chinese character has two placeholder(one placeholder is one char) diff --git a/livy/src/test/java/org/apache/zeppelin/livy/LivySQLInterpreterTest.java b/livy/src/test/java/org/apache/zeppelin/livy/LivySQLInterpreterTest.java index d9ba3f6921..6294473371 100644 --- a/livy/src/test/java/org/apache/zeppelin/livy/LivySQLInterpreterTest.java +++ b/livy/src/test/java/org/apache/zeppelin/livy/LivySQLInterpreterTest.java @@ -174,9 +174,14 @@ class LivySQLInterpreterTest { @Test void parseSQLJsonOutput() { + + // Empty output + List<String> rows = sqlInterpreter.parseSQLJsonOutput("\n"); + assertEquals(0, rows.size()); + // Empty sql output // id name - List<String> rows = sqlInterpreter.parseSQLJsonOutput("\nid\tname\n"); + rows = sqlInterpreter.parseSQLJsonOutput("\nid\tname\n"); assertEquals(1, rows.size()); assertEquals("id\tname", rows.get(0)); @@ -274,5 +279,12 @@ class LivySQLInterpreterTest { assertEquals("1\t1a", rows.get(1)); assertEquals("2\tみんく", rows.get(2)); assertEquals("3\t3a", rows.get(3)); + + + rows = sqlInterpreter.parseSQLJsonOutput("\nid\tarray\tname\n" + + "{\"id\":1,\"array\":[\"1a\",\"2a\"],\"name\":\"1b\"}\n"); + assertEquals(2, rows.size()); + assertEquals("id\tarray\tname", rows.get(0)); + assertEquals("1\t[\"1a\",\"2a\"]\t1b", rows.get(1)); } }