[#4985] Utils.executeImmediate() doesn't work when inlined SQL contains apostrophes
This commit is contained in:
parent
e5463bedc2
commit
381a07686f
@ -58,7 +58,7 @@ import org.jooq.exception.DataAccessException;
|
||||
public interface Context<C extends Context<C>> extends Scope {
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// General methods
|
||||
// Methods specifying the scope of the SQL being rendered
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@ -90,7 +90,7 @@ public interface Context<C extends Context<C>> 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<C extends Context<C>> 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<C extends Context<C>> 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<C extends Context<C>> 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<C extends Context<C>> extends Scope {
|
||||
|
||||
/**
|
||||
* Peek the next bind index. This won't increment the internal counter,
|
||||
* unlike {@link #nextIndex()}
|
||||
* unlike {@link #nextIndex()}.
|
||||
*/
|
||||
int peekIndex();
|
||||
|
||||
|
||||
@ -83,6 +83,8 @@ abstract class AbstractContext<C extends Context<C>> 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<C extends Context<C>> 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;
|
||||
|
||||
@ -186,13 +186,13 @@ class DefaultRenderContext extends AbstractContext<RenderContext> 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<RenderContext> 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<RenderContext> implements Ren
|
||||
return this;
|
||||
}
|
||||
|
||||
private Deque<Integer> indentLock() {
|
||||
private final Deque<Integer> indentLock() {
|
||||
if (indentLock == null) {
|
||||
indentLock = new ArrayDeque<Integer>();
|
||||
}
|
||||
|
||||
@ -2786,7 +2786,6 @@ final class Utils {
|
||||
* <code>BEGIN EXECUTE IMMEDIATE '...' EXCEPTION WHEN ... END;</code>, if
|
||||
* <code>IF EXISTS</code> 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 {
|
||||
* <code>IF EXISTS</code> 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");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user