Fix for ScriptUtils failure when '--' occurs inside a multi-line comment on the same line as '*/' (#22392)
* Test for multi-line comment block where the comment end delimiter occurs on a line starting with the single-line comment prefix * ScriptUtils successfully parses a SQL script containing a multi-line comment block where the comment-end delimiter occurs on a line starting with the single-line comment prefix.
This commit is contained in:
		
							parent
							
								
									a698adf125
								
							
						
					
					
						commit
						82dbde13b6
					
				|  | @ -259,7 +259,7 @@ public abstract class ScriptUtils { | |||
| 	 * @throws IOException in case of I/O errors | ||||
| 	 */ | ||||
| 	static String readScript(EncodedResource resource) throws IOException { | ||||
| 		return readScript(resource, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR); | ||||
| 		return readScript(resource, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR, DEFAULT_BLOCK_COMMENT_END_DELIMITER); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  | @ -273,15 +273,16 @@ public abstract class ScriptUtils { | |||
| 	 * @param commentPrefix the prefix that identifies comments in the SQL script — | ||||
| 	 * typically "--" | ||||
| 	 * @param separator the statement separator in the SQL script — typically ";" | ||||
| 	 * @param blockCommentEndDelimiter the <em>end</em> block comment delimiter | ||||
| 	 * @return a {@code String} containing the script lines | ||||
| 	 * @throws IOException in case of I/O errors | ||||
| 	 */ | ||||
| 	private static String readScript(EncodedResource resource, @Nullable String commentPrefix, | ||||
| 			@Nullable String separator) throws IOException { | ||||
| 									 @Nullable String separator, @Nullable String blockCommentEndDelimiter) throws IOException { | ||||
| 
 | ||||
| 		LineNumberReader lnr = new LineNumberReader(resource.getReader()); | ||||
| 		try { | ||||
| 			return readScript(lnr, commentPrefix, separator); | ||||
| 			return readScript(lnr, commentPrefix, separator, blockCommentEndDelimiter); | ||||
| 		} | ||||
| 		finally { | ||||
| 			lnr.close(); | ||||
|  | @ -297,19 +298,21 @@ public abstract class ScriptUtils { | |||
| 	 * a statement — will be included in the results. | ||||
| 	 * @param lineNumberReader the {@code LineNumberReader} containing the script | ||||
| 	 * to be processed | ||||
| 	 * @param commentPrefix the prefix that identifies comments in the SQL script — | ||||
| 	 * @param lineCommentPrefix the prefix that identifies comments in the SQL script — | ||||
| 	 * typically "--" | ||||
| 	 * @param separator the statement separator in the SQL script — typically ";" | ||||
| 	 * @param blockCommentEndDelimiter the <em>end</em> block comment delimiter | ||||
| 	 * @return a {@code String} containing the script lines | ||||
| 	 * @throws IOException in case of I/O errors | ||||
| 	 */ | ||||
| 	public static String readScript(LineNumberReader lineNumberReader, @Nullable String commentPrefix, | ||||
| 			@Nullable String separator) throws IOException { | ||||
| 	public static String readScript(LineNumberReader lineNumberReader, @Nullable String lineCommentPrefix, | ||||
| 									@Nullable String separator, @Nullable String blockCommentEndDelimiter) throws IOException { | ||||
| 
 | ||||
| 		String currentStatement = lineNumberReader.readLine(); | ||||
| 		StringBuilder scriptBuilder = new StringBuilder(); | ||||
| 		while (currentStatement != null) { | ||||
| 			if (commentPrefix != null && !currentStatement.startsWith(commentPrefix)) { | ||||
| 			if ((blockCommentEndDelimiter != null && currentStatement.contains(blockCommentEndDelimiter)) || | ||||
| 				(lineCommentPrefix != null && !currentStatement.startsWith(lineCommentPrefix))) { | ||||
| 				if (scriptBuilder.length() > 0) { | ||||
| 					scriptBuilder.append('\n'); | ||||
| 				} | ||||
|  | @ -460,7 +463,7 @@ public abstract class ScriptUtils { | |||
| 
 | ||||
| 			String script; | ||||
| 			try { | ||||
| 				script = readScript(resource, commentPrefix, separator); | ||||
| 				script = readScript(resource, commentPrefix, separator, blockCommentEndDelimiter); | ||||
| 			} | ||||
| 			catch (IOException ex) { | ||||
| 				throw new CannotReadScriptException(resource, ex); | ||||
|  |  | |||
|  | @ -162,6 +162,20 @@ public class ScriptUtilsUnitTests { | |||
| 		assertEquals("statement 2 not split correctly", statement2, statements.get(1)); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void readAndSplitScriptContainingMultiLineNestedComments() throws Exception { | ||||
| 		String script = readScript("test-data-with-multi-line-nested-comments.sql"); | ||||
| 		List<String> statements = new ArrayList<>(); | ||||
| 		splitSqlScript(script, ';', statements); | ||||
| 
 | ||||
| 		String statement1 = "INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller')"; | ||||
| 		String statement2 = "INSERT INTO users(first_name, last_name) VALUES( 'Sam' , 'Brannen' )"; | ||||
| 
 | ||||
| 		assertEquals("wrong number of statements", 2, statements.size()); | ||||
| 		assertEquals("statement 1 not split correctly", statement1, statements.get(0)); | ||||
| 		assertEquals("statement 2 not split correctly", statement2, statements.get(1)); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void containsDelimiters() { | ||||
| 		assertFalse(containsSqlScriptDelimiters("select 1\n select ';'", ";")); | ||||
|  |  | |||
|  | @ -0,0 +1,23 @@ | |||
| /* This is a multi line comment | ||||
|  * The next comment line has no text | ||||
| 
 | ||||
|  * The next comment line starts with a space. | ||||
|  *  x, y, z... | ||||
|  */ | ||||
| 
 | ||||
| INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller'); | ||||
| -- This is also a comment. | ||||
| /*------------------------------------------- | ||||
| -- A fancy multi-line comments that puts | ||||
| -- single line comments inside of a multi-line | ||||
| -- comment block. | ||||
| Moreover, the block commend end delimiter | ||||
| appears on a line that can potentially also | ||||
| be a single-line comment if we weren't | ||||
| already inside a multi-line comment run. | ||||
| -------------------------------------------*/ | ||||
|  INSERT INTO | ||||
| users(first_name, last_name)    -- This is a single line comment containing the block-end-comment sequence here */ but it's still a single-line comment | ||||
| VALUES( 'Sam'     -- first_name | ||||
|       , 'Brannen' -- last_name | ||||
| );-- | ||||
		Loading…
	
		Reference in New Issue