[jOOQ/jOOQ#13631] Add Context.topLevel() and Context.topLevelForLanguageContext() to give access to the top level QueryPart type that is being rendered
This commit is contained in:
parent
91438c5122
commit
2bd740ecca
@ -272,6 +272,32 @@ public interface Context<C extends Context<C>> extends ExecuteScope {
|
||||
@NotNull
|
||||
C declareCTE(boolean declareCTE, Consumer<? super C> consumer);
|
||||
|
||||
/**
|
||||
* The top level {@link QueryPart} that is being rendered.
|
||||
*/
|
||||
@Nullable
|
||||
QueryPart topLevel();
|
||||
|
||||
/**
|
||||
* Set the top level {@link QueryPart} that is being rendered.
|
||||
*/
|
||||
@NotNull
|
||||
C topLevel(QueryPart topLevel);
|
||||
|
||||
/**
|
||||
* The top level {@link QueryPart} that is being rendered in the current
|
||||
* {@link #languageContext()}.
|
||||
*/
|
||||
@Nullable
|
||||
QueryPart topLevelForLanguageContext();
|
||||
|
||||
/**
|
||||
* Set the top level {@link QueryPart} that is being rendered in the current
|
||||
* {@link #languageContext()}.
|
||||
*/
|
||||
@NotNull
|
||||
C topLevelForLanguageContext(QueryPart topLevelForLanguageContext);
|
||||
|
||||
/**
|
||||
* Whether the current context is rendering a subquery (nested query).
|
||||
*/
|
||||
@ -895,6 +921,13 @@ public interface Context<C extends Context<C>> extends ExecuteScope {
|
||||
@NotNull
|
||||
C languageContext(LanguageContext languageContext, Consumer<? super C> consumer);
|
||||
|
||||
/**
|
||||
* Set the new language context for {@link #languageContext()} for the scope
|
||||
* of a {@link Consumer}.
|
||||
*/
|
||||
@NotNull
|
||||
C languageContext(LanguageContext languageContext, QueryPart topLevelForLanguageContext, Consumer<? super C> consumer);
|
||||
|
||||
/**
|
||||
* Set the new language context for {@link #languageContext()}, if a
|
||||
* condition is true.
|
||||
|
||||
@ -104,8 +104,6 @@ import org.jooq.impl.Tools.DataKey;
|
||||
import org.jooq.impl.Tools.DataKeyScopeStackPart;
|
||||
import org.jooq.tools.StringUtils;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
@ -158,6 +156,8 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
|
||||
boolean quote = true;
|
||||
boolean qualifySchema = true;
|
||||
boolean qualifyCatalog = true;
|
||||
QueryPart topLevel;
|
||||
QueryPart topLevelForLanguageContext;
|
||||
|
||||
// [#11711] Enforcing scientific notation
|
||||
private transient DecimalFormat doubleFormat;
|
||||
@ -257,6 +257,15 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
|
||||
@Override
|
||||
public final C visit(QueryPart part) {
|
||||
if (part != null) {
|
||||
if (topLevel == null) {
|
||||
topLevel = topLevelForLanguageContext = part;
|
||||
|
||||
if (TRUE.equals(settings().isTransformPatterns()) && configuration().requireCommercial(() -> "SQL transformations are a commercial only feature. Please consider upgrading to the jOOQ Professional Edition or jOOQ Enterprise Edition.")) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Issue start clause events
|
||||
// -----------------------------------------------------------------
|
||||
@ -680,6 +689,28 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
|
||||
return scopeStack.scopeLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final QueryPart topLevel() {
|
||||
return topLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final C topLevel(QueryPart t) {
|
||||
topLevel = t;
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final QueryPart topLevelForLanguageContext() {
|
||||
return topLevelForLanguageContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final C topLevelForLanguageContext(QueryPart t) {
|
||||
topLevelForLanguageContext = t;
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int subqueryLevel() {
|
||||
return subquery;
|
||||
@ -1036,6 +1067,20 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
|
||||
return toggle(context, this::languageContext, this::languageContext, consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final C languageContext(LanguageContext context, QueryPart newTopLevelForLanguageContext, Consumer<? super C> consumer) {
|
||||
return toggle(context,
|
||||
this::languageContext,
|
||||
this::languageContext,
|
||||
c -> toggle(
|
||||
newTopLevelForLanguageContext,
|
||||
this::topLevelForLanguageContext,
|
||||
this::topLevelForLanguageContext,
|
||||
consumer
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final C languageContextIf(LanguageContext context, boolean condition) {
|
||||
if (condition)
|
||||
|
||||
@ -410,73 +410,72 @@ final class BlockImpl extends AbstractRowCountQuery implements Block {
|
||||
}
|
||||
}
|
||||
else {
|
||||
DefaultRenderContext r = ctx instanceof DefaultRenderContext d
|
||||
? d
|
||||
: null;
|
||||
|
||||
statementLoop:
|
||||
for (Statement s : statements) {
|
||||
if (s instanceof NullStatement && !SUPPORTS_NULL_STATEMENT.contains(ctx.dialect()))
|
||||
continue statementLoop;
|
||||
|
||||
LanguageContext language = ctx.languageContext();
|
||||
ctx.languageContextIf(LanguageContext.QUERY, s instanceof Query && !(s instanceof Block));
|
||||
|
||||
ctx.formatSeparator();
|
||||
int position = r != null ? r.sql.length() : 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ctx.visit(s);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// [#11374] [#11367] TODO Improve this clunky semi colon decision logic
|
||||
if (position < (r != null ? r.sql.length() : 0))
|
||||
semicolonAfterStatement(ctx, s);
|
||||
|
||||
ctx.languageContext(language);
|
||||
if (s instanceof Query && !(s instanceof Block))
|
||||
ctx.languageContext(LanguageContext.QUERY, s, c -> accept2(c, s));
|
||||
else
|
||||
accept2(ctx, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final void accept2(Context<?> ctx, Statement s) {
|
||||
ctx.formatSeparator();
|
||||
int position = ctx instanceof DefaultRenderContext d ? d.sql.length() : 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ctx.visit(s);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// [#11374] [#11367] TODO Improve this clunky semi colon decision logic
|
||||
if (position < (ctx instanceof DefaultRenderContext d ? d.sql.length() : 0))
|
||||
semicolonAfterStatement(ctx, s);
|
||||
}
|
||||
|
||||
private static final void semicolonAfterStatement(Context<?> ctx, Statement s) {
|
||||
if (s instanceof Block)
|
||||
return;
|
||||
|
||||
@ -104,7 +104,6 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
|
||||
private boolean separatorRequired;
|
||||
private boolean separator;
|
||||
private boolean newline;
|
||||
private Boolean isQuery;
|
||||
|
||||
// [#1632] Cached values from Settings
|
||||
RenderKeywordCase cachedRenderKeywordCase;
|
||||
@ -385,7 +384,7 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
|
||||
String prepend = null;
|
||||
String append = null;
|
||||
|
||||
if (TRUE.equals(isQuery)) {
|
||||
if (topLevel instanceof Query) {
|
||||
prepend = (String) data(DATA_PREPEND_SQL);
|
||||
append = (String) data(DATA_APPEND_SQL);
|
||||
}
|
||||
@ -712,15 +711,6 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
|
||||
|
||||
@Override
|
||||
protected final void visit0(QueryPartInternal internal) {
|
||||
if (isQuery == null) {
|
||||
isQuery = internal instanceof Query;
|
||||
|
||||
if (TRUE.equals(settings().isTransformPatterns()) && configuration().requireCommercial(() -> "SQL transformations are a commercial only feature. Please consider upgrading to the jOOQ Professional Edition or jOOQ Enterprise Edition.")) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user