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 DOUBLE_QUOTE : '"';
|
||||
|
||||
STRING_LITERAL
|
||||
: DOUBLE_QUOTE ( ESCAPE_SEQUENCE | DOUBLE_QUOTE DOUBLE_QUOTE | ~('"') )* DOUBLE_QUOTE
|
||||
| SINGLE_QUOTE ( ESCAPE_SEQUENCE | SINGLE_QUOTE SINGLE_QUOTE | ~('\'') )* SINGLE_QUOTE
|
||||
;
|
||||
STRING_LITERAL : SINGLE_QUOTE ( 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 : '\\';
|
||||
|
||||
|
@ -96,6 +99,7 @@ UNICODE_ESCAPE
|
|||
|
||||
BINARY_LITERAL
|
||||
: [xX] SINGLE_QUOTE (HEX_DIGIT HEX_DIGIT)* SINGLE_QUOTE
|
||||
| [xX] DOUBLE_QUOTE (HEX_DIGIT HEX_DIGIT)* DOUBLE_QUOTE
|
||||
;
|
||||
|
||||
// ESCAPE start tokens
|
||||
|
|
|
@ -665,7 +665,7 @@ inList
|
|||
* A single character used to escape the '_' and '%' wildcards in a 'like' pattern
|
||||
*/
|
||||
likeEscape
|
||||
: ESCAPE (STRING_LITERAL | parameter)
|
||||
: ESCAPE (STRING_LITERAL | JAVA_STRING_LITERAL | parameter)
|
||||
;
|
||||
|
||||
|
||||
|
@ -823,6 +823,7 @@ searchedCaseWhen
|
|||
*/
|
||||
literal
|
||||
: STRING_LITERAL
|
||||
| JAVA_STRING_LITERAL
|
||||
| NULL
|
||||
| booleanLiteral
|
||||
| numericLiteral
|
||||
|
|
|
@ -74,7 +74,7 @@ public final class QuotingHelper {
|
|||
final int end = text.length() - 1;
|
||||
final char delimiter = text.charAt( 0 );
|
||||
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 );
|
||||
for ( int i = 1; i < end; i++ ) {
|
||||
char c = text.charAt( i );
|
||||
|
@ -89,48 +89,6 @@ public final class QuotingHelper {
|
|||
i++;
|
||||
}
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -138,4 +96,60 @@ public final class QuotingHelper {
|
|||
}
|
||||
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() ) {
|
||||
case HqlParser.STRING_LITERAL:
|
||||
return stringLiteral( node.getText() );
|
||||
case HqlParser.JAVA_STRING_LITERAL:
|
||||
return javaStringLiteral( node.getText() );
|
||||
case HqlParser.INTEGER_LITERAL:
|
||||
return integerOrLongLiteral( node.getText() );
|
||||
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) {
|
||||
return new SqmLiteral<>(
|
||||
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
|
||||
public void testJdbcTimeLiteral(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
|
@ -315,6 +326,4 @@ public class LiteralTests {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue