Skip to content

Commit c64d50d

Browse files
committed
fix: keep trailing whitespace outside quoted hex tokens
Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent 60c8dc2 commit c64d50d

2 files changed

Lines changed: 83 additions & 1 deletion

File tree

‎src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2821,7 +2821,8 @@ TOKEN : /* Numeric Constants */
28212821
)>
28222822
| < S_LONG: ( <DIGIT> )+ >
28232823
| < #DIGIT: ["0" - "9"] >
2824-
| < S_HEX: ("X" ("'" ( <HEX_VALUE> )* "'" (" ")*)+ | "0x" ( <HEX_DIGIT> )+ ) >
2824+
| < S_HEX: ("X" <QUOTED_HEX> ( (" ")* <QUOTED_HEX> )* | "0x" ( <HEX_DIGIT> )+ ) >
2825+
| < #QUOTED_HEX: "'" ( <HEX_VALUE> )* "'" >
28252826
| < #HEX_VALUE: ["0"-"9","A"-"F", " "] >
28262827
| < #HEX_DIGIT: ["0"-"9","A"-"F"] >
28272828
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.expression;
11+
12+
import net.sf.jsqlparser.JSQLParserException;
13+
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
14+
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
15+
import net.sf.jsqlparser.statement.select.PlainSelect;
16+
import net.sf.jsqlparser.test.TestUtils;
17+
import org.junit.jupiter.api.Test;
18+
import org.junit.jupiter.params.ParameterizedTest;
19+
import org.junit.jupiter.params.provider.ValueSource;
20+
21+
import static org.junit.jupiter.api.Assertions.*;
22+
23+
class QuotedHexValueTest {
24+
@ParameterizedTest
25+
@ValueSource(strings = {
26+
"SELECT X'6162' AS v",
27+
"SELECT X'6162' AS v",
28+
"SELECT X'6162' FROM t",
29+
"SELECT X'6162' ",
30+
"SELECT X'6162'\tAS v",
31+
"SELECT X'6162'\nAS v"
32+
})
33+
void whitespaceIsNotPartOfHexLiteral(String sql) throws JSQLParserException {
34+
for (Dialect dialect : new Dialect[] {null, Dialect.MYSQL, Dialect.POSTGRESQL}) {
35+
PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sql,
36+
parser -> {
37+
if (dialect != null) {
38+
parser.withDialect(dialect);
39+
}
40+
});
41+
HexValue hex = (HexValue) select.getSelectItem(0).getExpression();
42+
assertEquals("X'6162'", hex.getValue());
43+
assertEquals("6162", hex.getDigits());
44+
assertEquals(24930L, hex.getLong());
45+
assertEquals("ab", hex.getStringValue().getValue());
46+
assertEquals("\\x61\\x62", hex.getBlob().getValue());
47+
String canonical = select.toString();
48+
for (int i = 0; i < 3; i++) {
49+
select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(canonical,
50+
false, parser -> {
51+
if (dialect != null) {
52+
parser.withDialect(dialect);
53+
}
54+
});
55+
assertEquals(canonical, select.toString());
56+
}
57+
}
58+
}
59+
60+
@ParameterizedTest
61+
@ValueSource(strings = {"X'61 62'", "X'61' '62'", "X'61''62'", "X''", "x'6162'", "0x6162"})
62+
void existingHexTokenFormsArePreserved(String literal) throws JSQLParserException {
63+
PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse("SELECT " + literal + " AS v");
64+
assertEquals(literal, ((HexValue) select.getSelectItem(0).getExpression()).getValue());
65+
TestUtils.assertSqlCanBeParsedAndDeparsed(select.toString(), false);
66+
}
67+
68+
@Test
69+
void jsonDefaultHexIsAccessibleAndEditable() throws JSQLParserException {
70+
String sql = "SELECT JSON_VALUE('{}', '$.v' DEFAULT X'6162' ON EMPTY)";
71+
PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sql, false);
72+
JsonFunction function = (JsonFunction) select.getSelectItem(0).getExpression();
73+
HexValue hex = (HexValue) function.getOnEmptyBehavior().getExpression();
74+
assertEquals("6162", hex.getDigits());
75+
assertEquals("ab", hex.getStringValue().getValue());
76+
hex.setValue("X'6364'");
77+
TestUtils.assertStatementCanBeDeparsedAs(select, sql.replace("6162", "6364"));
78+
TestUtils.assertSqlCanBeParsedAndDeparsed(select.toString(), false);
79+
assertEquals("cd", hex.getStringValue().getValue());
80+
}
81+
}

0 commit comments

Comments
 (0)