Skip to content

Commit

Permalink
add changeset identifier to exceptions thrown from LiquibaseSqlParser…
Browse files Browse the repository at this point in the history
… (DAT-16397) (#5413)

* initial add of putting changeset into scope

* remove adding the changeset to the scope

* keep backwards compatibility

* remove unnecessary try/catch

---------

Co-authored-by: obovsunivskyii <baqaua@gmail.com>
  • Loading branch information
StevenMassaro and obovsunivskyii committed Dec 29, 2023
1 parent 44b6397 commit e2d06c5
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ public SqlStatement[] generateStatements(Database database) {
returnStatements.add(new RawSqlStatement(processedSQL, getEndDelimiter()));
return returnStatements.toArray(EMPTY_SQL_STATEMENT);
}
for (String statement : StringUtil.processMultiLineSQL(processedSQL, isStripComments(), isSplitStatements(), getEndDelimiter())) {
for (String statement : StringUtil.processMultiLineSQL(processedSQL, isStripComments(), isSplitStatements(), getEndDelimiter(), getChangeSet())) {
if (database instanceof MSSQLDatabase) {
statement = statement.replaceAll("\\n", "\r\n");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ protected void handleRollbackNode(ParsedNode rollbackNode, ResourceAccessor reso
if (value instanceof String) {
String finalValue = StringUtil.trimToNull((String) value);
if (finalValue != null) {
String[] strings = StringUtil.processMultiLineSQL(finalValue, true, true, ";");
String[] strings = StringUtil.processMultiLineSQL(finalValue, true, true, ";", this);
for (String string : strings) {
addRollbackChange(new RawSQLChange(string));
foundValue = true;
Expand Down Expand Up @@ -1209,7 +1209,7 @@ public void addRollBackSQL(String sql) {
return;
}

for (String statement : StringUtil.splitSQL(sql, null)) {
for (String statement : StringUtil.splitSQL(sql, null, this)) {
rollback.getChanges().add(new RawSQLChange(statement.trim()));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,13 @@ private static String getDatabaseInfo(Database database) {
return source;
}

private void logPrimaryExceptionToMdc(Exception exception, String source) {
private void logPrimaryExceptionToMdc(Throwable exception, String source) {
//
// Drill down to get the lowest level exception
//
Exception primaryException = exception;
Throwable primaryException = exception;
while (primaryException != null && primaryException.getCause() != null) {
primaryException = (Exception)primaryException.getCause();
primaryException = primaryException.getCause();
}
if (primaryException != null) {
if (primaryException instanceof LiquibaseException || source == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.*;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

public class ExecuteSqlCommandStep extends AbstractCommandStep {

Expand Down Expand Up @@ -64,7 +67,7 @@ public void run(CommandResultsBuilder resultsBuilder) throws Exception {
final Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database);
final String sqlText = getSqlScript(sql, sqlFile);
final StringBuilder out = new StringBuilder();
final String[] sqlStrings = StringUtil.processMultiLineSQL(sqlText, true, true, determineEndDelimiter(commandScope));
final String[] sqlStrings = StringUtil.processMultiLineSQL(sqlText, true, true, determineEndDelimiter(commandScope), null);

for (String sqlString : sqlStrings) {
if (sqlString.toLowerCase().matches("\\s*select .*")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package liquibase.parser;

import liquibase.changelog.ChangeSet;
import liquibase.plugin.Plugin;
import liquibase.util.StringClauses;

Expand All @@ -9,5 +10,13 @@ public interface LiquibaseSqlParser extends Plugin {

StringClauses parse(String sqlBlock, boolean preserveWhitespace, boolean preserveComments);

/**
* @param changeSet the changeset associated with the sql being parsed. If not null, the changeset identifying
* information should be included in any exceptions thrown if the sql cannot be parsed.
*/
default StringClauses parse(String sqlBlock, boolean preserveWhitespace, boolean preserveComments, ChangeSet changeSet) {
return parse(sqlBlock, preserveWhitespace, preserveComments);
}

int getPriority();
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
package liquibase.util;

import liquibase.changelog.ChangeSet;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.parser.LiquibaseSqlParser;
import liquibase.util.grammar.*;

import java.io.StringReader;

public class StandardSqlParser implements LiquibaseSqlParser {

@Override
public StringClauses parse(String sqlBlock) {
return parse(sqlBlock, false, false);
}

@Override
public StringClauses parse(String sqlBlock, boolean preserveWhitespace, boolean preserveComments) {
return parse(sqlBlock, preserveWhitespace, preserveComments, null);
}

@Override
public StringClauses parse(String sqlBlock, boolean preserveWhitespace, boolean preserveComments, ChangeSet changeSet) {
StringClauses clauses = new StringClauses(preserveWhitespace?"":" ");

SimpleSqlGrammarTokenManager tokenManager = new SimpleSqlGrammarTokenManager(new SimpleCharStream(new StringReader(sqlBlock)));
Expand Down Expand Up @@ -42,8 +49,12 @@ public StringClauses parse(String sqlBlock, boolean preserveWhitespace, boolean
token = t.getNextToken();
}

} catch (Exception e) {
throw new UnexpectedLiquibaseException(e);
} catch (Throwable e) {
if (changeSet != null) {
throw new UnexpectedLiquibaseException(changeSet.toString(), e);
} else {
throw new UnexpectedLiquibaseException(e);
}
}
return clauses;
}
Expand Down
76 changes: 62 additions & 14 deletions liquibase-standard/src/main/java/liquibase/util/StringUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import liquibase.ExtensibleObject;
import liquibase.GlobalConfiguration;
import liquibase.Scope;
import liquibase.changelog.ChangeSet;
import liquibase.parser.LiquibaseSqlParser;
import liquibase.parser.SqlParserFactory;

Expand Down Expand Up @@ -55,17 +56,29 @@ public static String trimToNull(String string) {
}

/**
* Removes any comments from multiple line SQL using {@link #stripComments(String)}
* and then extracts each individual statement using {@link #splitSQL(String, String)}.
* Removes any comments from multiple line SQL using {@link #stripComments(String, ChangeSet)}
* and then extracts each individual statement using {@link #splitSQL(String, String, ChangeSet)}.
*
* @param multiLineSQL A String containing all the SQL statements
* @param stripComments If true then comments will be stripped, if false then they will be left in the code
*/
public static String[] processMultiLineSQL(String multiLineSQL, boolean stripComments, boolean splitStatements, String endDelimiter) {
return processMultiLineSQL(multiLineSQL, stripComments, splitStatements, endDelimiter, null);
}

/**
* Removes any comments from multiple line SQL using {@link #stripComments(String, ChangeSet)}
* and then extracts each individual statement using {@link #splitSQL(String, String, ChangeSet)}.
*
* @param multiLineSQL A String containing all the SQL statements
* @param stripComments If true then comments will be stripped, if false then they will be left in the code
* @param changeSet the changeset associated with the sql being parsed
*/
public static String[] processMultiLineSQL(String multiLineSQL, boolean stripComments, boolean splitStatements, String endDelimiter, ChangeSet changeSet) {

SqlParserFactory sqlParserFactory = Scope.getCurrentScope().getSingleton(SqlParserFactory.class);
LiquibaseSqlParser sqlParser = sqlParserFactory.getSqlParser();
StringClauses parsed = sqlParser.parse(multiLineSQL, true, !stripComments);
StringClauses parsed = sqlParser.parse(multiLineSQL, true, !stripComments, changeSet);

List<String> returnArray = new ArrayList<>();

Expand All @@ -85,13 +98,13 @@ public static String[] processMultiLineSQL(String multiLineSQL, boolean stripCom
}

if (piece instanceof String && ((String) piece).equalsIgnoreCase("BEGIN")
&& (!"transaction".equalsIgnoreCase(nextPiece)
&& !"trans".equalsIgnoreCase(nextPiece)
&& !"tran".equalsIgnoreCase(nextPiece))) {
&& (!"transaction".equalsIgnoreCase(nextPiece)
&& !"trans".equalsIgnoreCase(nextPiece)
&& !"tran".equalsIgnoreCase(nextPiece))) {
isInClause++;
}
if (piece instanceof String && ((String) piece).equalsIgnoreCase("END") && isInClause > 0
&& (!"transaction".equalsIgnoreCase(nextPiece)
&& (!"transaction".equalsIgnoreCase(nextPiece)
&& !"trans".equalsIgnoreCase(nextPiece)
&& !"tran".equalsIgnoreCase(nextPiece))) {
isInClause--;
Expand Down Expand Up @@ -124,15 +137,28 @@ public static String[] processMultiLineSQL(String multiLineSQL, boolean stripCom
}

/**
* Removes any comments from multiple line SQL using {@link #stripComments(String)}
* and then extracts each individual statement using {@link #splitSQL(String, String)}.
* Removes any comments from multiple line SQL using {@link #stripComments(String, ChangeSet)}
* and then extracts each individual statement using {@link #splitSQL(String, String, ChangeSet)}.
*
* @param multiLineSQL A String containing all the SQL statements
* @param stripComments If true then comments will be stripped, if false then they will be left in the code
* @deprecated The new method is {@link #processMultiLineSQL(String, boolean, boolean, String)} (String)}
* @deprecated The new method is {@link #processMultiLineSQL(String, boolean, boolean, String, ChangeSet)} (String)}
*/
public static String[] processMutliLineSQL(String multiLineSQL, boolean stripComments, boolean splitStatements, String endDelimiter) {
return processMultiLineSQL(multiLineSQL, stripComments, splitStatements, endDelimiter);
return processMultiLineSQL(multiLineSQL, stripComments, splitStatements, endDelimiter, null);
}

/**
* Removes any comments from multiple line SQL using {@link #stripComments(String, ChangeSet)}
* and then extracts each individual statement using {@link #splitSQL(String, String, ChangeSet)}.
*
* @param multiLineSQL A String containing all the SQL statements
* @param stripComments If true then comments will be stripped, if false then they will be left in the code
* @param changeSet the changeset associated with the sql being parsed
* @deprecated The new method is {@link #processMultiLineSQL(String, boolean, boolean, String, ChangeSet)} (String)}
*/
public static String[] processMutliLineSQL(String multiLineSQL, boolean stripComments, boolean splitStatements, String endDelimiter, ChangeSet changeSet) {
return processMultiLineSQL(multiLineSQL, stripComments, splitStatements, endDelimiter, changeSet);
}

/**
Expand Down Expand Up @@ -302,7 +328,16 @@ public static String wrap(final String inputStr, int wrapPoint, int extraLinePad
* Splits a candidate multi-line SQL statement along ;'s and "go"'s.
*/
public static String[] splitSQL(String multiLineSQL, String endDelimiter) {
return processMultiLineSQL(multiLineSQL, false, true, endDelimiter);
return splitSQL(multiLineSQL, endDelimiter, null);
}

/**
* Splits a candidate multi-line SQL statement along ;'s and "go"'s.
*
* @param changeSet the changeset associated with the sql being parsed
*/
public static String[] splitSQL(String multiLineSQL, String endDelimiter, ChangeSet changeSet) {
return processMultiLineSQL(multiLineSQL, false, true, endDelimiter, changeSet);
}

/**
Expand All @@ -314,12 +349,25 @@ public static String[] splitSQL(String multiLineSQL, String endDelimiter) {
* @return The String without the comments in
*/
public static String stripComments(String multiLineSQL) {
return stripComments(multiLineSQL, null);
}

/**
* Searches through a String which contains SQL code and strips out
* any comments that are between \/**\/ or anything that matches
* SP--SP<text>\n (to support the ANSI standard commenting of --
* at the end of a line).
*
* @param changeSet the changeset associated with the sql being parsed
* @return The String without the comments in
*/
public static String stripComments(String multiLineSQL, ChangeSet changeSet) {
if (StringUtil.isEmpty(multiLineSQL)) {
return multiLineSQL;
}
SqlParserFactory sqlParserFactory = Scope.getCurrentScope().getSingleton(SqlParserFactory.class);
LiquibaseSqlParser sqlParser = sqlParserFactory.getSqlParser();
return sqlParser.parse(multiLineSQL, true, false).toString().trim();
return sqlParser.parse(multiLineSQL, true, false, changeSet).toString().trim();
}

public static String join(Object[] array, String delimiter, StringUtilFormatter formatter) {
Expand Down Expand Up @@ -927,7 +975,7 @@ public static String getLastLineComment(String sqlString) {
} else if (c == '\r' || c == '\n') {
// new line found
startOfNewLine = true;
idxOfDoubleDash = -1;
idxOfDoubleDash = -1;
}

}
Expand Down

0 comments on commit e2d06c5

Please sign in to comment.