diff --git a/jOOQ/src/main/java/org/jooq/Context.java b/jOOQ/src/main/java/org/jooq/Context.java index 20d0409fb3..a27e7569b6 100644 --- a/jOOQ/src/main/java/org/jooq/Context.java +++ b/jOOQ/src/main/java/org/jooq/Context.java @@ -58,7 +58,7 @@ import org.jooq.exception.DataAccessException; public interface Context> extends Scope { // ------------------------------------------------------------------------ - // General methods + // Methods specifying the scope of the SQL being rendered // ------------------------------------------------------------------------ /** @@ -90,7 +90,7 @@ public interface Context> extends Scope { boolean declareFields(); /** - * Set the new context value for {@link #declareFields()} + * Set the new context value for {@link #declareFields()}. */ C declareFields(boolean declareFields); @@ -102,7 +102,7 @@ public interface Context> extends Scope { boolean declareTables(); /** - * Set the new context value for {@link #declareTables()} + * Set the new context value for {@link #declareTables()}. */ C declareTables(boolean declareTables); @@ -125,7 +125,7 @@ public interface Context> extends Scope { boolean declareWindows(); /** - * Set the new context value for {@link #declareWindows()} + * Set the new context value for {@link #declareWindows()}. */ C declareWindows(boolean declareWindows); @@ -137,20 +137,30 @@ public interface Context> extends Scope { boolean declareCTE(); /** - * Set the new context value for {@link #declareCTE()} + * Set the new context value for {@link #declareCTE()}. */ C declareCTE(boolean declareCTE); /** - * Whether the current context is rendering a sub-query (nested query) + * Whether the current context is rendering a sub-query (nested query). */ boolean subquery(); /** - * Set the new context value for {@link #subquery()} + * Set the new context value for {@link #subquery()}. */ C subquery(boolean subquery); + /** + * whether the current context is rendering a string literal. + */ + boolean stringLiteral(); + + /** + * Set the new context value for {@link #stringLiteral()}. + */ + C stringLiteral(boolean stringLiteral); + /** * Get the next bind index. This increments an internal counter. This is * relevant for two use-cases: @@ -166,7 +176,7 @@ public interface Context> extends Scope { /** * Peek the next bind index. This won't increment the internal counter, - * unlike {@link #nextIndex()} + * unlike {@link #nextIndex()}. */ int peekIndex(); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java b/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java index 6fc79c772e..2018462cee 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractContext.java @@ -83,6 +83,8 @@ abstract class AbstractContext> extends AbstractScope imple boolean declareWindows; boolean declareCTE; boolean subquery; + int stringLiteral; + String stringLiteralEscapedApos = "'"; int index; // [#2665] VisitListener API @@ -466,6 +468,25 @@ abstract class AbstractContext> extends AbstractScope imple return (C) this; } + @Override + public final boolean stringLiteral() { + return stringLiteral > 0; + } + + @Override + public final C stringLiteral(boolean s) { + if (s) { + stringLiteral++; + stringLiteralEscapedApos = stringLiteralEscapedApos + stringLiteralEscapedApos; + } + else { + stringLiteral--; + stringLiteralEscapedApos = stringLiteralEscapedApos.substring(0, stringLiteralEscapedApos.length() / 2); + } + + return (C) this; + } + @Override public final int nextIndex() { return ++index; diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java index 3081d66552..9f753914f3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java @@ -186,13 +186,13 @@ class DefaultRenderContext extends AbstractContext implements Ren @Override public final RenderContext sql(String s, boolean literal) { - if (literal) { - sql.append(s); - } - else { - sql.append(NEWLINE.matcher(s).replaceAll("$0" + indentation())); - } + if (!literal) + s = NEWLINE.matcher(s).replaceAll("$0" + indentation()); + if (stringLiteral()) + s = StringUtils.replace(s, "'", stringLiteralEscapedApos); + + sql.append(s); return this; } @@ -200,6 +200,10 @@ class DefaultRenderContext extends AbstractContext implements Ren @Override public final RenderContext sql(char c) { sql.append(c); + + if (c == '\'' && stringLiteral()) + sql.append(c); + return this; } @@ -285,7 +289,7 @@ class DefaultRenderContext extends AbstractContext implements Ren return this; } - private Deque indentLock() { + private final Deque indentLock() { if (indentLock == null) { indentLock = new ArrayDeque(); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Utils.java b/jOOQ/src/main/java/org/jooq/impl/Utils.java index 11ccb87647..9f8571e42e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Utils.java +++ b/jOOQ/src/main/java/org/jooq/impl/Utils.java @@ -2786,7 +2786,6 @@ final class Utils { * BEGIN EXECUTE IMMEDIATE '...' EXCEPTION WHEN ... END;, if * IF EXISTS is not supported. */ - @SuppressWarnings("unused") static final void executeImmediateBegin(Context ctx, DDLStatementType type) { switch (ctx.family()) { @@ -2824,6 +2823,10 @@ final class Utils { + + + + @@ -2833,7 +2836,7 @@ final class Utils { ctx.keyword("execute block").formatSeparator() .keyword("as").formatSeparator() .keyword("begin").formatIndentStart().formatSeparator() - .keyword("execute statement").sql(" '"); + .keyword("execute statement").sql(" '").stringLiteral(true).formatIndentStart().formatSeparator(); break; } @@ -2849,6 +2852,8 @@ final class Utils { * IF EXISTS is not supported. */ static final void executeImmediateEnd(Context ctx, DDLStatementType type) { + boolean drop = asList(DROP_INDEX, DROP_SEQUENCE, DROP_TABLE, DROP_VIEW).contains(type); + switch (ctx.family()) { @@ -2896,6 +2901,11 @@ final class Utils { + + + + + @@ -2903,7 +2913,7 @@ final class Utils { case FIREBIRD: { - ctx.sql("';").formatSeparator() + ctx.formatIndentEnd().formatSeparator().stringLiteral(false).sql("';").formatSeparator() .keyword("when").sql(" sqlcode -607 ").keyword("do").formatIndentStart().formatSeparator() .keyword("begin end").formatIndentEnd().formatIndentEnd().formatSeparator() .keyword("end");