diff --git a/src/main/java/com/impossibl/postgres/jdbc/SQLText.java b/src/main/java/com/impossibl/postgres/jdbc/SQLText.java index 792987d0f..bf432b6ad 100644 --- a/src/main/java/com/impossibl/postgres/jdbc/SQLText.java +++ b/src/main/java/com/impossibl/postgres/jdbc/SQLText.java @@ -128,8 +128,22 @@ public static MultiStatementNode parse(final String sql, boolean standardConform ndx = consumeQuotedIdentifier(sql, ndx, parents.peek()); continue; case '?': - ParameterPiece parameterPiece = new ParameterPiece(paramId++, ndx); - parents.peek().add(parameterPiece); + char nextChar = lookAhead(sql, ndx); + if (nextChar == '|' || nextChar == '&' || nextChar == '?') { + final GrammarPiece grammarPiece; + if (nextChar == '?') { + grammarPiece = new GrammarPiece("?", ndx); + } + else { + grammarPiece = new GrammarPiece("?" + nextChar, ndx); + } + parents.peek().add(grammarPiece); + ++ndx; + } + else { + ParameterPiece parameterPiece = new ParameterPiece(paramId++, ndx); + parents.peek().add(parameterPiece); + } break; case '$': ndx = consumeDollar(sql, ndx, parents.peek()); diff --git a/src/test/java/com/impossibl/postgres/jdbc/StatementTest.java b/src/test/java/com/impossibl/postgres/jdbc/StatementTest.java index 2da162f42..c58eebafa 100644 --- a/src/test/java/com/impossibl/postgres/jdbc/StatementTest.java +++ b/src/test/java/com/impossibl/postgres/jdbc/StatementTest.java @@ -609,4 +609,28 @@ public void testDefaultFetchSize() throws SQLException { ((PGConnection)con).setDefaultFetchSize(oldValue); } + + @Test + public void testQuestionMarkExcaping() throws SQLException { + if (!((PGConnection)con).isServerMinimumVersion(9, 4)) + return; + + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT '{\"a\":1, \"b\":2}'::jsonb ?? 'b'"); + assertTrue(rs.next()); + assertEquals(true, rs.getBoolean(1)); + rs.close(); + + rs = stmt.executeQuery("SELECT '{\"a\":1, \"b\":2, \"c\":3}'::jsonb ?| array['b', 'd']"); + assertTrue(rs.next()); + assertEquals(true, rs.getBoolean(1)); + rs.close(); + + rs = stmt.executeQuery("SELECT '{\"a\":1, \"b\":2, \"c\":3}'::jsonb ?& array['b', 'd']"); + assertTrue(rs.next()); + assertEquals(false, rs.getBoolean(1)); + rs.close(); + + stmt.close(); + } }