Skip to content

Commit 0761427

Browse files
committed
fix: support character set introduced string literals
1 parent 98bd01d commit 0761427

2 files changed

Lines changed: 61 additions & 0 deletions

File tree

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,19 @@ public class CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> {
301301
}
302302
}
303303

304+
/**
305+
* Whether the next two tokens form a character-set-introduced string literal,
306+
* for example {@code _utf8mb4'text'} or {@code _ISO8859_1 'text'}.
307+
*/
308+
private boolean isCharacterSetIntroducedStringAhead() {
309+
Token introducer = getToken(1);
310+
Token literal = getToken(2);
311+
return introducer.kind == S_IDENTIFIER
312+
&& introducer.image != null
313+
&& introducer.image.length() > 1
314+
&& introducer.image.charAt(0) == '_'
315+
&& literal.kind == S_CHAR_LITERAL;
316+
}
304317

305318
/**
306319
* Tokens that have dedicated branches in PrimaryExpression AFTER the Function branch.
@@ -8067,6 +8080,18 @@ Expression SimpleExpression():
80678080
}
80688081
}
80698082

8083+
StringValue CharacterSetIntroducedString():
8084+
{
8085+
Token introducer;
8086+
Token literal;
8087+
}
8088+
{
8089+
introducer=<S_IDENTIFIER> literal=<S_CHAR_LITERAL>
8090+
{
8091+
return new StringValue(literal.image).withPrefix(introducer.image);
8092+
}
8093+
}
8094+
80708095
/** Multiplicative/bitwise-shift — higher precedence */
80718096
Expression MulChain():
80728097
{
@@ -8243,6 +8268,9 @@ Expression PrimaryExpression() #PrimaryExpression:
82438268

82448269
| LOOKAHEAD(2, {!interrupted}) <K_ALL> { retval = new AllValue(); }
82458270

8271+
| LOOKAHEAD({ !interrupted && isCharacterSetIntroducedStringAhead() })
8272+
retval=CharacterSetIntroducedString()
8273+
82468274
| LOOKAHEAD(2, {!interrupted}) retval=Column()
82478275
[
82488276
LOOKAHEAD( "(" "+" ")" ("," | ")") )

src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import net.sf.jsqlparser.expression.Alias;
3737
import net.sf.jsqlparser.expression.AllValue;
3838
import net.sf.jsqlparser.expression.BinaryExpression;
39+
import net.sf.jsqlparser.expression.CollateExpression;
3940
import net.sf.jsqlparser.expression.DoubleValue;
4041
import net.sf.jsqlparser.expression.Expression;
4142
import net.sf.jsqlparser.expression.Function;
@@ -4183,6 +4184,38 @@ public void testEscaped() throws JSQLParserException {
41834184
assertSqlCanBeParsedAndDeparsed("SELECT _utf8'testvalue'");
41844185
}
41854186

4187+
@ParameterizedTest
4188+
@ValueSource(strings = {"_utf8mb4'testvalue'", "_utf8mb4 'testvalue'",
4189+
"_utf8 'testvalue'", "_latin1'testvalue'", "_binary'testvalue'",
4190+
"_ISO8859_1 'testvalue'"})
4191+
public void testCharacterSetIntroducedString(String expression) throws JSQLParserException {
4192+
Select select = (Select) CCJSqlParserUtil.parse("SELECT " + expression);
4193+
SelectItem<?> selectItem = select.getPlainSelect().getSelectItem(0);
4194+
StringValue stringValue = assertInstanceOf(StringValue.class, selectItem.getExpression());
4195+
4196+
assertEquals(expression.substring(0, expression.indexOf('\'')).trim(),
4197+
stringValue.getPrefix());
4198+
assertEquals("testvalue", stringValue.getValue());
4199+
assertNull(selectItem.getAlias());
4200+
}
4201+
4202+
@Test
4203+
public void testCharacterSetIntroducedStringWithCollate() throws JSQLParserException {
4204+
String sql = "SELECT _utf8mb4'some text' COLLATE utf8mb4_unicode_ci AS custom_string";
4205+
Select select = (Select) CCJSqlParserUtil.parse(sql);
4206+
SelectItem<?> selectItem = select.getPlainSelect().getSelectItem(0);
4207+
CollateExpression collateExpression =
4208+
assertInstanceOf(CollateExpression.class, selectItem.getExpression());
4209+
StringValue stringValue = assertInstanceOf(StringValue.class,
4210+
collateExpression.getLeftExpression());
4211+
4212+
assertEquals("_utf8mb4", stringValue.getPrefix());
4213+
assertEquals("some text", stringValue.getValue());
4214+
assertEquals("utf8mb4_unicode_ci", collateExpression.getCollate());
4215+
assertEquals("custom_string", selectItem.getAlias().getName());
4216+
assertEquals(sql, select.toString());
4217+
}
4218+
41864219
@Test
41874220
public void testIssue563MultiSubJoin() throws JSQLParserException {
41884221
assertSqlCanBeParsedAndDeparsed(

0 commit comments

Comments
 (0)