Skip to content

Commit 95ebda5

Browse files
fix: return Dollar quoted text as StringValue
- fixes #2267 Signed-off-by: Andreas Reichel <[email protected]>
1 parent 12600fb commit 95ebda5

File tree

4 files changed

+30
-4
lines changed

4 files changed

+30
-4
lines changed

src/main/java/net/sf/jsqlparser/expression/StringValue.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public final class StringValue extends ASTNodeAccessImpl implements Expression {
2424
Arrays.asList("N", "U", "E", "R", "B", "RB", "_utf8", "Q");
2525
private String value = "";
2626
private String prefix = null;
27+
private String quoteStr = "'";
2728

2829
public StringValue() {
2930
// empty constructor
@@ -35,6 +36,11 @@ public StringValue(String escapedValue) {
3536
&& escapedValue.endsWith("'")) {
3637
value = escapedValue.substring(1, escapedValue.length() - 1);
3738
return;
39+
} else if (escapedValue.length() >= 4 && escapedValue.startsWith("$$")
40+
&& escapedValue.endsWith("$$")) {
41+
value = escapedValue.substring(2, escapedValue.length() - 2);
42+
quoteStr = "$$";
43+
return;
3844
}
3945

4046
if (escapedValue.length() > 2) {
@@ -68,6 +74,15 @@ public void setPrefix(String prefix) {
6874
this.prefix = prefix;
6975
}
7076

77+
public String getQuoteStr() {
78+
return quoteStr;
79+
}
80+
81+
public StringValue setQuoteStr(String quoteStr) {
82+
this.quoteStr = quoteStr;
83+
return this;
84+
}
85+
7186
public String getNotExcapedValue() {
7287
StringBuilder buffer = new StringBuilder(value);
7388
int index = 0;
@@ -87,7 +102,7 @@ public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
87102

88103
@Override
89104
public String toString() {
90-
return (prefix != null ? prefix : "") + "'" + value + "'";
105+
return (prefix != null ? prefix : "") + quoteStr + value + quoteStr;
91106
}
92107

93108
public StringValue withPrefix(String prefix) {

src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,8 @@ public <S> StringBuilder visit(StringValue stringValue, S context) {
642642
if (stringValue.getPrefix() != null) {
643643
builder.append(stringValue.getPrefix());
644644
}
645-
builder.append("'").append(stringValue.getValue()).append("'");
645+
builder.append(stringValue.getQuoteStr()).append(stringValue.getValue())
646+
.append(stringValue.getQuoteStr());
646647

647648
return builder;
648649
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,7 @@ TOKEN:
820820
| < S_CHAR_LITERAL: (
821821
(["U","E","N","R","B"]|"RB"|"_utf8")?
822822
(
823-
("'" ( <ESC> | <SPECIAL_ESC> | ~["'", "\\"] )* "'") | ("'" ("''" | ~["'"])* "'")
823+
("'" ( <ESC> | <SPECIAL_ESC> | ~["'", "\\"] )* "'") | ("'" ("''" | ~["'"])* "'" | "$$" (~["$"])* "$$")
824824
// Alternative Oracle Escape Modes
825825
| ("q'{" (~[])* "}'")
826826
| ("q'(" (~[])* ")'")
@@ -856,7 +856,7 @@ TOKEN:
856856
}
857857
}
858858
}
859-
| < S_QUOTED_IDENTIFIER: "\"" ( "\"\"" | ~["\n","\r","\""])* "\"" | "$$" (~["$"])* "$$" | ("`" (~["\n","\r","`"])+ "`") | ( "[" (~["\n","\r","]"])* "]" ) >
859+
| < S_QUOTED_IDENTIFIER: "\"" ( "\"\"" | ~["\n","\r","\""])* "\"" | ("`" (~["\n","\r","`"])+ "`") | ( "[" (~["\n","\r","]"])* "]" ) >
860860
{
861861
if ( !configuration.getAsBoolean(Feature.allowSquareBracketQuotation)
862862
&& matchedToken.image.charAt(0) == '[' ) {

src/test/java/net/sf/jsqlparser/expression/StringValueTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
package net.sf.jsqlparser.expression;
1111

1212
import net.sf.jsqlparser.JSQLParserException;
13+
import net.sf.jsqlparser.statement.select.PlainSelect;
1314
import net.sf.jsqlparser.test.TestUtils;
15+
import org.junit.jupiter.api.Assertions;
1416
import org.junit.jupiter.api.Test;
1517

1618
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -93,4 +95,12 @@ public void testParseInput_BYTEA() throws Exception {
9395
String sqlStr = "VALUES (X'', X'01FF', X'01 bc 2a', X'01' '02')";
9496
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
9597
}
98+
99+
@Test
100+
void testDollarQuotesIssue2267() throws JSQLParserException {
101+
String sqlStr = "SELECT $$this is a string$$, test, 'text' FROM tbl;";
102+
PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
103+
104+
Assertions.assertInstanceOf(StringValue.class, select.getSelectItem(0).getExpression());
105+
}
96106
}

0 commit comments

Comments
 (0)