HHH-15745 Change string literal handling in HQL lexer
This commit is contained in:
parent
1109dfbb1c
commit
f2576d6b87
|
@ -75,10 +75,13 @@ HEX_LITERAL : '0' [xX] HEX_DIGIT+ LONG_SUFFIX?;
|
||||||
fragment SINGLE_QUOTE : '\'';
|
fragment SINGLE_QUOTE : '\'';
|
||||||
fragment DOUBLE_QUOTE : '"';
|
fragment DOUBLE_QUOTE : '"';
|
||||||
|
|
||||||
STRING_LITERAL
|
STRING_LITERAL : SINGLE_QUOTE ( SINGLE_QUOTE SINGLE_QUOTE | ~('\'') )* SINGLE_QUOTE;
|
||||||
: DOUBLE_QUOTE ( ESCAPE_SEQUENCE | DOUBLE_QUOTE DOUBLE_QUOTE | ~('"') )* DOUBLE_QUOTE
|
|
||||||
| SINGLE_QUOTE ( ESCAPE_SEQUENCE | SINGLE_QUOTE SINGLE_QUOTE | ~('\'') )* SINGLE_QUOTE
|
JAVA_STRING_LITERAL
|
||||||
;
|
: DOUBLE_QUOTE ( ESCAPE_SEQUENCE | ~('"') )* DOUBLE_QUOTE
|
||||||
|
| [jJ] SINGLE_QUOTE ( ESCAPE_SEQUENCE | ~('\'') )* SINGLE_QUOTE
|
||||||
|
| [jJ] DOUBLE_QUOTE ( ESCAPE_SEQUENCE | ~('\'') )* DOUBLE_QUOTE
|
||||||
|
;
|
||||||
|
|
||||||
fragment BACKSLASH : '\\';
|
fragment BACKSLASH : '\\';
|
||||||
|
|
||||||
|
@ -96,6 +99,7 @@ UNICODE_ESCAPE
|
||||||
|
|
||||||
BINARY_LITERAL
|
BINARY_LITERAL
|
||||||
: [xX] SINGLE_QUOTE (HEX_DIGIT HEX_DIGIT)* SINGLE_QUOTE
|
: [xX] SINGLE_QUOTE (HEX_DIGIT HEX_DIGIT)* SINGLE_QUOTE
|
||||||
|
| [xX] DOUBLE_QUOTE (HEX_DIGIT HEX_DIGIT)* DOUBLE_QUOTE
|
||||||
;
|
;
|
||||||
|
|
||||||
// ESCAPE start tokens
|
// ESCAPE start tokens
|
||||||
|
|
|
@ -665,7 +665,7 @@ inList
|
||||||
* A single character used to escape the '_' and '%' wildcards in a 'like' pattern
|
* A single character used to escape the '_' and '%' wildcards in a 'like' pattern
|
||||||
*/
|
*/
|
||||||
likeEscape
|
likeEscape
|
||||||
: ESCAPE (STRING_LITERAL | parameter)
|
: ESCAPE (STRING_LITERAL | JAVA_STRING_LITERAL | parameter)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@ -823,6 +823,7 @@ searchedCaseWhen
|
||||||
*/
|
*/
|
||||||
literal
|
literal
|
||||||
: STRING_LITERAL
|
: STRING_LITERAL
|
||||||
|
| JAVA_STRING_LITERAL
|
||||||
| NULL
|
| NULL
|
||||||
| booleanLiteral
|
| booleanLiteral
|
||||||
| numericLiteral
|
| numericLiteral
|
||||||
|
|
|
@ -74,7 +74,7 @@ public final class QuotingHelper {
|
||||||
final int end = text.length() - 1;
|
final int end = text.length() - 1;
|
||||||
final char delimiter = text.charAt( 0 );
|
final char delimiter = text.charAt( 0 );
|
||||||
assert delimiter == text.charAt( end );
|
assert delimiter == text.charAt( end );
|
||||||
// Unescape the parsed literal and handle escape sequences
|
// Unescape the parsed literal
|
||||||
final StringBuilder sb = new StringBuilder( text.length() - 2 );
|
final StringBuilder sb = new StringBuilder( text.length() - 2 );
|
||||||
for ( int i = 1; i < end; i++ ) {
|
for ( int i = 1; i < end; i++ ) {
|
||||||
char c = text.charAt( i );
|
char c = text.charAt( i );
|
||||||
|
@ -89,48 +89,6 @@ public final class QuotingHelper {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '\\':
|
|
||||||
if ( ( i + 1 ) < end ) {
|
|
||||||
char nextChar = text.charAt( ++i );
|
|
||||||
switch ( nextChar ) {
|
|
||||||
case 'b':
|
|
||||||
c = '\b';
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
c = '\t';
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
c = '\n';
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
c = '\f';
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
c = '\r';
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
c = '\\';
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
c = '\'';
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
c = '"';
|
|
||||||
break;
|
|
||||||
case '`':
|
|
||||||
c = '`';
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
c = (char) Integer.parseInt( text.substring( i + 1, i + 5 ), 16 );
|
|
||||||
i += 4;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sb.append( '\\' );
|
|
||||||
c = nextChar;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -138,4 +96,60 @@ public final class QuotingHelper {
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String unquoteJavaStringLiteral(String text) {
|
||||||
|
assert text.length() > 1;
|
||||||
|
final char firstChar = text.charAt( 0 );
|
||||||
|
final int start = firstChar == 'j' || firstChar == 'J' ? 1 : 0;
|
||||||
|
final int end = text.length() - 1;
|
||||||
|
final char delimiter = text.charAt( start );
|
||||||
|
assert delimiter == text.charAt( end );
|
||||||
|
// Handle escape sequences
|
||||||
|
final StringBuilder sb = new StringBuilder( text.length() - ( start + 2 ) );
|
||||||
|
for ( int i = start + 1; i < end; i++ ) {
|
||||||
|
char c = text.charAt( i );
|
||||||
|
if ( c == '\\' && ( i + 1 ) < end ) {
|
||||||
|
char nextChar = text.charAt( ++i );
|
||||||
|
switch ( nextChar ) {
|
||||||
|
case 'b':
|
||||||
|
c = '\b';
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
c = '\t';
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
c = '\n';
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
c = '\f';
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
c = '\r';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
c = '\\';
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
c = '\'';
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
c = '"';
|
||||||
|
break;
|
||||||
|
case '`':
|
||||||
|
c = '`';
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
c = (char) Integer.parseInt( text.substring( i + 1, i + 5 ), 16 );
|
||||||
|
i += 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sb.append( '\\' );
|
||||||
|
c = nextChar;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append( c );
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3275,6 +3275,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
switch ( node.getSymbol().getType() ) {
|
switch ( node.getSymbol().getType() ) {
|
||||||
case HqlParser.STRING_LITERAL:
|
case HqlParser.STRING_LITERAL:
|
||||||
return stringLiteral( node.getText() );
|
return stringLiteral( node.getText() );
|
||||||
|
case HqlParser.JAVA_STRING_LITERAL:
|
||||||
|
return javaStringLiteral( node.getText() );
|
||||||
case HqlParser.INTEGER_LITERAL:
|
case HqlParser.INTEGER_LITERAL:
|
||||||
return integerOrLongLiteral( node.getText() );
|
return integerOrLongLiteral( node.getText() );
|
||||||
case HqlParser.LONG_LITERAL:
|
case HqlParser.LONG_LITERAL:
|
||||||
|
@ -3587,6 +3589,15 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SqmLiteral<String> javaStringLiteral(String text) {
|
||||||
|
String unquoted = QuotingHelper.unquoteJavaStringLiteral( text );
|
||||||
|
return new SqmLiteral<>(
|
||||||
|
unquoted,
|
||||||
|
resolveExpressibleTypeBasic( String.class ),
|
||||||
|
creationContext.getNodeBuilder()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private SqmLiteral<byte[]> binaryLiteral(String text) {
|
private SqmLiteral<byte[]> binaryLiteral(String text) {
|
||||||
return new SqmLiteral<>(
|
return new SqmLiteral<>(
|
||||||
PrimitiveByteArrayJavaType.INSTANCE.fromString(
|
PrimitiveByteArrayJavaType.INSTANCE.fromString(
|
||||||
|
|
|
@ -60,6 +60,17 @@ public class LiteralTests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJavaString(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
assertThat( session.createQuery( "select \"\\n\"" ).getSingleResult(), is( "\n" ) );
|
||||||
|
assertThat( session.createQuery( "select J'\\n'" ).getSingleResult(), is( "\n" ) );
|
||||||
|
assertThat( session.createQuery( "select J'\\''" ).getSingleResult(), is( "'" ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testJdbcTimeLiteral(SessionFactoryScope scope) {
|
public void testJdbcTimeLiteral(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
|
@ -315,6 +326,4 @@ public class LiteralTests {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue