From f6de8f83a2b284ecaa67a196311588dbda98ea9e Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 9 Nov 2015 09:18:42 -0600 Subject: [PATCH] HHH-1706 - Named parameters ignored when single apostrophe encountered within an SQL comment (cherry picked from commit e4d102c5b1460a056ee9fec8f74f660ef764fde9) --- .../engine/query/spi/ParameterParser.java | 62 +++++++++++++++++-- .../engine/query/ParameterParserTest.java | 29 +++++++++ 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/ParameterParser.java b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/ParameterParser.java index 39deac89e4..f63f2c483c 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/query/spi/ParameterParser.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/query/spi/ParameterParser.java @@ -84,17 +84,71 @@ public class ParameterParser { boolean foundMainOutputParam = false; final int stringLength = sqlString.length(); - boolean inQuote = false; + + boolean inSingleQuotes = false; + boolean inDoubleQuotes = false; + boolean inLineComment = false; + boolean inDelimitedComment = false; + for ( int indx = 0; indx < stringLength; indx++ ) { final char c = sqlString.charAt( indx ); - if ( inQuote ) { + final boolean lastCharacter = indx == stringLength-1; + + if ( inLineComment ) { + // see if the character ends the line + if ( '\n' == c ) { + inLineComment = false; + recognizer.other( c ); + } + else if ( '\r' == c ) { + inLineComment = false; + recognizer.other( c ); + if ( !lastCharacter && '\n' == sqlString.charAt( indx+1 ) ) { + recognizer.other( sqlString.charAt( indx+1 ) ); + indx++; + } + } + } + else if ( '-' == c ) { + recognizer.other( c ); + if ( !lastCharacter && '-' == sqlString.charAt( indx+1 ) ) { + inLineComment = true; + recognizer.other( sqlString.charAt( indx+1 ) ); + indx++; + } + } + else if ( inDelimitedComment ) { + recognizer.other( c ); + if ( !lastCharacter && '*' == c && '/' == sqlString.charAt( indx+1 ) ) { + inDelimitedComment = true; + recognizer.other( sqlString.charAt( indx+1 ) ); + indx++; + } + } + else if ( !lastCharacter && '/' == c && '*' == sqlString.charAt( indx+1 ) ) { + inDelimitedComment = true; + recognizer.other( c ); + recognizer.other( sqlString.charAt( indx+1 ) ); + indx++; + } + else if ( inDoubleQuotes ) { + if ( '\"' == c ) { + inDoubleQuotes = false; + } + recognizer.other( c ); + } + else if ( '\"' == c ) { + inDoubleQuotes = true; + recognizer.other( c ); + } + else if ( inSingleQuotes ) { if ( '\'' == c ) { - inQuote = false; + inSingleQuotes = false; } recognizer.other( c ); } else if ( '\'' == c ) { - inQuote = true; + inSingleQuotes = true; recognizer.other( c ); } else if ( '\\' == c ) { diff --git a/hibernate-core/src/test/java/org/hibernate/engine/query/ParameterParserTest.java b/hibernate-core/src/test/java/org/hibernate/engine/query/ParameterParserTest.java index 9ac3b98df9..abe02e7193 100644 --- a/hibernate-core/src/test/java/org/hibernate/engine/query/ParameterParserTest.java +++ b/hibernate-core/src/test/java/org/hibernate/engine/query/ParameterParserTest.java @@ -8,6 +8,7 @@ package org.hibernate.engine.query; import org.junit.Test; +import org.hibernate.engine.query.spi.ParamLocationRecognizer; import org.hibernate.engine.query.spi.ParameterParser; import org.hibernate.testing.junit4.BaseUnitTestCase; @@ -27,4 +28,32 @@ public class ParameterParserTest extends BaseUnitTestCase { "from User u where u.userName = ? and u.userType = 'call'" ) ); } + @Test + public void testQuotedTextInComment() { + ParamLocationRecognizer recognizer = new ParamLocationRecognizer(); + + ParameterParser.parse("-- 'This' should not fail the test.\n" + + "SELECT column FROM Table WHERE column <> :param", recognizer); + + assertTrue(recognizer.getNamedParameterDescriptionMap().containsKey("param")); + } + + @Test + public void testContractionInComment() { + ParamLocationRecognizer recognizer = new ParamLocationRecognizer(); + + ParameterParser.parse("-- This shouldn't fail the test.\n" + "SELECT column FROM Table WHERE column <> :param", + recognizer); + + assertTrue(recognizer.getNamedParameterDescriptionMap().containsKey("param")); + } + + @Test + public void testApostropheInOracleAlias() { + ParamLocationRecognizer recognizer = new ParamLocationRecognizer(); + + ParameterParser.parse("SELECT column as \"Table's column\" FROM Table WHERE column <> :param", recognizer); + + assertTrue(recognizer.getNamedParameterDescriptionMap().containsKey("param")); + } }