Skip to content

Commit dd2d28a

Browse files
committed
#921 Do not parse escapes within double quotes
1 parent 1754888 commit dd2d28a

2 files changed

Lines changed: 38 additions & 18 deletions

File tree

src/main/org/firebirdsql/jdbc/escape/FBEscapedParser.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
SPDX-FileCopyrightText: Copyright 2001-2002 David Jencks
33
SPDX-FileCopyrightText: Copyright 2002-2005 Roman Rokytskyy
44
SPDX-FileCopyrightText: Copyright 2003 Blas Rodriguez Somoza
5-
SPDX-FileCopyrightText: Copyright 2012-2025 Mark Rotteveel
5+
SPDX-FileCopyrightText: Copyright 2012-2026 Mark Rotteveel
66
SPDX-License-Identifier: LGPL-2.1-or-later
77
*/
88
package org.firebirdsql.jdbc.escape;
@@ -133,9 +133,9 @@ public String toNative(String sql) throws SQLException {
133133
case INITIAL_STATE -> {
134134
// Ignore leading whitespace
135135
}
136-
case NORMAL_STATE, LITERAL_STATE,
137-
START_LINE_COMMENT, LINE_COMMENT, START_BLOCK_COMMENT, BLOCK_COMMENT, END_BLOCK_COMMENT,
138-
POSSIBLE_Q_LITERAL_ENTER -> buffer.append(currentChar);
136+
case NORMAL_STATE, LITERAL_STATE, DELIMITED_IDENTIFIER,
137+
START_LINE_COMMENT, LINE_COMMENT, START_BLOCK_COMMENT, BLOCK_COMMENT, END_BLOCK_COMMENT,
138+
POSSIBLE_Q_LITERAL_ENTER -> buffer.append(currentChar);
139139
case ESCAPE_ENTER_STATE -> {
140140
bufferStack.push(buffer);
141141
buffer = new StringBuilder();
@@ -393,6 +393,7 @@ protected ParserState nextState(char inputChar) throws FBSQLParseException {
393393
protected ParserState nextState(char inputChar) {
394394
return switch (inputChar) {
395395
case '\'' -> LITERAL_STATE;
396+
case '"' -> DELIMITED_IDENTIFIER;
396397
case '{' -> ESCAPE_ENTER_STATE;
397398
case '}' -> ESCAPE_EXIT_STATE;
398399
case '-' -> START_LINE_COMMENT;
@@ -411,6 +412,15 @@ protected ParserState nextState(char inputChar) {
411412
return (inputChar == '\'') ? NORMAL_STATE : LITERAL_STATE;
412413
}
413414
},
415+
/**
416+
* Dialect 3 delimited identifier or dialect 1 literal text (text inside double quotes).
417+
*/
418+
DELIMITED_IDENTIFIER {
419+
@Override
420+
protected ParserState nextState(char inputChar) {
421+
return (inputChar == '"') ? NORMAL_STATE : DELIMITED_IDENTIFIER;
422+
}
423+
},
414424
/**
415425
* Start of JDBC escape ({ character encountered).
416426
*/

src/test/org/firebirdsql/jdbc/escape/FBEscapedParserTest.java

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: Copyright 2012-2025 Mark Rotteveel
1+
// SPDX-FileCopyrightText: Copyright 2012-2026 Mark Rotteveel
22
// SPDX-License-Identifier: LGPL-2.1-or-later
33
package org.firebirdsql.jdbc.escape;
44

@@ -331,21 +331,31 @@ void testQLiteral_InLiteralEndOfString_throwsParseException() {
331331
"Unexpected end of string at parser state Q_LITERAL_START");
332332
}
333333

334-
@Test
335-
void testQLiteralSpecials() throws Exception {
336-
checkQLiteralSpecialsBalancedStartEnd('(', ')');
337-
checkQLiteralSpecialsBalancedStartEnd(')', ')');
338-
checkQLiteralSpecialsBalancedStartEnd('{', '}');
339-
checkQLiteralSpecialsBalancedStartEnd('}', '}');
340-
checkQLiteralSpecialsBalancedStartEnd('[', ']');
341-
checkQLiteralSpecialsBalancedStartEnd(']', ']');
342-
checkQLiteralSpecialsBalancedStartEnd('<', '>');
343-
checkQLiteralSpecialsBalancedStartEnd('>', '>');
344-
}
345-
346-
private void checkQLiteralSpecialsBalancedStartEnd(char start, char end) throws Exception {
334+
@ParameterizedTest
335+
@CsvSource(useHeadersInDisplayName = true, textBlock = """
336+
start, end
337+
(, )
338+
), )
339+
{, }
340+
[, ]
341+
], ]
342+
<, >
343+
>, >
344+
""")
345+
void checkQLiteralSpecialsBalancedStartEnd(char start, char end) throws Exception {
347346
final String input = "q'" + start + " {fn EXP(2)} " + end + "'";
348347

349348
assertEquals(input, toNative(input), "Unexpected output");
350349
}
350+
351+
@ParameterizedTest
352+
@ValueSource(strings = {
353+
"'{fn EXP(2)}'",
354+
"q'{{fn EXP(2)}}'",
355+
"\"{fn EXP(2)}\""
356+
})
357+
void escapesInLiteralsOrDelimitedIdentifiers_notAnEscape(String input) throws Exception {
358+
assertEquals(input, toNative(input), "Unexpected output");
359+
}
360+
351361
}

0 commit comments

Comments
 (0)