diff --git a/src/main/java/net/snowflake/client/jdbc/ResultJsonParserV2.java b/src/main/java/net/snowflake/client/jdbc/ResultJsonParserV2.java index 795cf94ff..bf9e66205 100644 --- a/src/main/java/net/snowflake/client/jdbc/ResultJsonParserV2.java +++ b/src/main/java/net/snowflake/client/jdbc/ResultJsonParserV2.java @@ -328,7 +328,7 @@ private void continueParsingInternal(ByteBuffer in, boolean lastData, SFBaseSess // the last remaining data in the buffer), // there is not enough bytes to parse the codepoint. Move the position back 1, // so we can re-enter parsing at this position with the ESCAPE state. - ((Buffer) in).position(((Buffer) in).position() - 1); + in.position(in.position() - 1); state = State.ESCAPE; return; } diff --git a/src/test/java/net/snowflake/client/jdbc/ResultSetLatestIT.java b/src/test/java/net/snowflake/client/jdbc/ResultSetLatestIT.java index 1ef6a1f12..118d5ca1b 100644 --- a/src/test/java/net/snowflake/client/jdbc/ResultSetLatestIT.java +++ b/src/test/java/net/snowflake/client/jdbc/ResultSetLatestIT.java @@ -951,4 +951,55 @@ public void testGranularTimeFunctionsInUTC() throws SQLException { connection.close(); } } + + @Test + public void testJsonParsingOfAsciiCharacters() throws SQLException { + Connection connection = init(); + Statement statement = connection.createStatement(); + statement.execute("alter session set jdbc_query_result_format ='json'"); + // statement.execute("ALTER SESSION SET CLIENT_STAGE_ARRAY_BINDING_THRESHOLD = 0"); + statement.execute( + "create or replace table asciiTable (colA string, colB string, colC string, colD string, colE string, colF string, colG string, colH string, colI string, colJ string, colK string, colL string)"); + + PreparedStatement preparedStatement = + connection.prepareStatement( + "insert into asciiTable values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + for (int i = 0; i < 35000; i++) { + preparedStatement.setInt(1, i); + preparedStatement.setString(2, "123456"); + preparedStatement.setString(3, "dummy"); + preparedStatement.setString( + 4, + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000Ì\u0000\u0000\u0000\u0000\u0003ä\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"); + preparedStatement.setString(5, null); + preparedStatement.setString(6, " "); + preparedStatement.setString( + 7, + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000Ì\u0000\u0000\u0000\u0000\u0003ä\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"); + preparedStatement.setString(8, "021-436-5589"); + preparedStatement.setString(9, " "); + preparedStatement.setString(10, "dummy"); + preparedStatement.setString(11, "934-999-567"); + preparedStatement.setString(12, " "); + preparedStatement.addBatch(); + } + preparedStatement.executeBatch(); + + ResultSet resultSet = statement.executeQuery("select count(*) from asciiTable"); + resultSet.next(); + assertEquals("35000", resultSet.getString(1)); + + resultSet = statement.executeQuery("select * from asciiTable"); + while (resultSet.next()) { + String expectedHexVal = + "00 00 00 00 00 00 00 00 00 C3 8C 00 00 00 00 03 C3 A4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "; + assertEquals(expectedHexVal, ResultJsonParserV2Test.stringToHex(resultSet.getString(4))); + assertEquals(expectedHexVal, ResultJsonParserV2Test.stringToHex(resultSet.getString(7))); + } + + statement.execute("drop table if exists asciiTable"); + preparedStatement.close(); + statement.close(); + connection.close(); + } }