diff --git a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithMiniLlap.java b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithMiniLlap.java index 4897364..de47412 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithMiniLlap.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithMiniLlap.java @@ -34,6 +34,7 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -195,6 +196,22 @@ public void testNonAsciiStrings() throws Exception { assertArrayEquals(new String[] {"val_0", nonAscii}, rowCollector.rows.get(2)); } + @Test(timeout = 60000) + public void testEscapedStrings() throws Exception { + createTestTable("testtab1"); + + RowCollector rowCollector = new RowCollector(); + String expectedVal1 = "'a',\"b\",\\c\\"; + String expectedVal2 = "multi\nline"; + String query = "select value, '\\'a\\',\"b\",\\\\c\\\\', 'multi\\nline' from testtab1 where under_col=0"; + int rowCount = processQuery(query, 1, rowCollector); + assertEquals(3, rowCount); + + assertArrayEquals(new String[] {"val_0", expectedVal1, expectedVal2}, rowCollector.rows.get(0)); + assertArrayEquals(new String[] {"val_0", expectedVal1, expectedVal2}, rowCollector.rows.get(1)); + assertArrayEquals(new String[] {"val_0", expectedVal1, expectedVal2}, rowCollector.rows.get(2)); + } + private interface RowProcessor { void process(Row row); } diff --git a/llap-ext-client/src/java/org/apache/hadoop/hive/llap/LlapBaseInputFormat.java b/llap-ext-client/src/java/org/apache/hadoop/hive/llap/LlapBaseInputFormat.java index c2fca54..7dae4fc 100644 --- a/llap-ext-client/src/java/org/apache/hadoop/hive/llap/LlapBaseInputFormat.java +++ b/llap-ext-client/src/java/org/apache/hadoop/hive/llap/LlapBaseInputFormat.java @@ -63,6 +63,7 @@ import org.apache.hadoop.mapreduce.TaskAttemptID; import org.apache.hadoop.security.Credentials; import org.apache.hadoop.security.token.Token; +import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.yarn.api.ApplicationConstants; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ApplicationId; @@ -207,7 +208,8 @@ public LlapBaseInputFormat() {} throw new IOException(e); } - String sql = String.format(SPLIT_QUERY, query, numSplits); + String escapedQuery = StringUtils.escapeString(query, ESCAPE_CHAR, escapedChars); + String sql = String.format(SPLIT_QUERY, escapedQuery, numSplits); try ( Connection con = DriverManager.getConnection(url,user,pwd); Statement stmt = con.createStatement(); @@ -342,6 +344,12 @@ private ByteBuffer serializeCredentials(Credentials credentials) throws IOExcept return ByteBuffer.wrap(containerTokens_dob.getData(), 0, containerTokens_dob.getLength()); } + private static final char ESCAPE_CHAR = '\\'; + + private static final char[] escapedChars = { + '"', ESCAPE_CHAR + }; + private static class LlapRecordReaderTaskUmbilicalExternalResponder implements LlapTaskUmbilicalExternalResponder { protected LlapBaseRecordReader recordReader = null; protected LinkedBlockingQueue queuedEvents = new LinkedBlockingQueue();