[jOOQ/jOOQ#11672] Function and QueryPartCollectionView formatting
improvements This includes: - [jOOQ/jOOQ#11673] Emulate NVL using COALESCE instead of CASE, where possible - [jOOQ/jOOQ9085] NVL should generate NVL for the DEFAULT dialect
This commit is contained in:
parent
fadd3aa05a
commit
d43fc234ef
@ -54,7 +54,7 @@ import org.jooq.WindowSpecification;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
abstract class AbstractName extends AbstractQueryPart implements Name {
|
||||
abstract class AbstractName extends AbstractQueryPart implements Name, SimpleQueryPart {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
|
||||
@ -64,7 +64,7 @@ import org.jooq.tools.StringUtils;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
abstract class AbstractParam<T> extends AbstractParamX<T> {
|
||||
abstract class AbstractParam<T> extends AbstractParamX<T> implements SimpleQueryPart {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
|
||||
@ -124,7 +124,7 @@ abstract class AbstractRow extends AbstractQueryPart implements Row {
|
||||
|
||||
|
||||
ctx.sql("(")
|
||||
.visit(wrap(fields.fields).indentSize(0))
|
||||
.visit(wrap(fields.fields))
|
||||
.sql(")");
|
||||
}
|
||||
|
||||
|
||||
@ -305,7 +305,7 @@ final class Alias<Q extends QueryPart> extends AbstractQueryPart {
|
||||
|
||||
if (context.declareTables() && o instanceof ArrayTable)
|
||||
context.sql('(')
|
||||
.visit(wrap(((ArrayTable) o).fields()).qualify(false).indentSize(0))
|
||||
.visit(wrap(((ArrayTable) o).fields()).qualify(false))
|
||||
.sql(')');
|
||||
|
||||
break;
|
||||
@ -352,7 +352,7 @@ final class Alias<Q extends QueryPart> extends AbstractQueryPart {
|
||||
}
|
||||
|
||||
private final void toSQLDerivedColumnList(Context<?> ctx) {
|
||||
ctx.sql(" (").visit(wrap(fieldAliases).indentSize(0)).sql(')');
|
||||
ctx.sql(" (").visit(wrap(fieldAliases)).sql(')');
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -80,7 +80,7 @@ final class Coalesce<T> extends AbstractField<T> {
|
||||
|
||||
|
||||
default: {
|
||||
ctx.visit(DSL.function("coalesce", getDataType(), fields));
|
||||
ctx.visit(DSL.function(N_COALESCE, getDataType(), fields));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ final class ForLock extends AbstractQueryPart {
|
||||
|
||||
// Render the OF [table-names] clause
|
||||
default:
|
||||
ctx.visit(wrap(forLockOfTables).qualify(false).indentSize(0));
|
||||
ctx.visit(wrap(forLockOfTables).qualify(false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,7 +170,7 @@ implements
|
||||
public final void accept(Context<?> ctx) {
|
||||
ctx.start(Clause.GRANT_PRIVILEGE)
|
||||
.visit(K_GRANT).sql(' ')
|
||||
.visit(QueryPartCollectionView.wrap(privileges).indentSize(0))
|
||||
.visit(QueryPartCollectionView.wrap(privileges))
|
||||
.end(Clause.GRANT_PRIVILEGE).sql(' ')
|
||||
.start(Clause.GRANT_ON)
|
||||
.visit(K_ON).sql(' ')
|
||||
|
||||
@ -475,7 +475,7 @@ implements
|
||||
ctx.formatSeparator()
|
||||
.start(TABLE_JOIN_USING)
|
||||
.visit(K_USING)
|
||||
.sql(" (").visit(wrap(using).indentSize(0).qualify(false)).sql(')')
|
||||
.sql(" (").visit(wrap(using).qualify(false)).sql(')')
|
||||
.end(TABLE_JOIN_USING);
|
||||
}
|
||||
|
||||
|
||||
@ -90,7 +90,6 @@ final class Keywords {
|
||||
static final Keyword K_CHANGE_COLUMN = keyword("change column");
|
||||
static final Keyword K_CHARACTER_SET = keyword("character set");
|
||||
static final Keyword K_CHECK = keyword("check");
|
||||
static final Keyword K_COALESCE = keyword("coalesce");
|
||||
static final Keyword K_COLLATE = keyword("collate");
|
||||
static final Keyword K_COLLATION = keyword("collation");
|
||||
static final Keyword K_COLUMN = keyword("column");
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.impl.DSL.function;
|
||||
import static org.jooq.impl.Keywords.K_NULL;
|
||||
import static org.jooq.impl.Names.N_IIF;
|
||||
import static org.jooq.impl.Names.N_NULLIF;
|
||||
@ -74,7 +75,7 @@ final class NullIf<T> extends AbstractField<T> {
|
||||
|
||||
|
||||
default:
|
||||
ctx.visit(N_NULLIF).sql('(').visit(arg1).sql(", ").visit(arg2).sql(')');
|
||||
ctx.visit(function(N_NULLIF, getDataType(), arg1, arg2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.impl.Keywords.K_COALESCE;
|
||||
import static org.jooq.impl.DSL.function;
|
||||
import static org.jooq.impl.Keywords.K_IS_NULL;
|
||||
import static org.jooq.impl.Names.N_IFNULL;
|
||||
import static org.jooq.impl.Names.N_IIF;
|
||||
@ -79,16 +79,22 @@ final class Nvl<T> extends AbstractField<T> {
|
||||
|
||||
|
||||
|
||||
case H2:
|
||||
case HSQLDB:
|
||||
ctx.visit(N_NVL).sql('(').visit(arg1).sql(", ").visit(arg2).sql(')');
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case CUBRID:
|
||||
case DERBY:
|
||||
case IGNITE:
|
||||
case FIREBIRD:
|
||||
case POSTGRES:
|
||||
ctx.visit(K_COALESCE).sql('(').visit(arg1).sql(", ").visit(arg2).sql(')');
|
||||
ctx.visit(DSL.coalesce(arg1, arg2));
|
||||
break;
|
||||
|
||||
|
||||
@ -97,11 +103,11 @@ final class Nvl<T> extends AbstractField<T> {
|
||||
case MARIADB:
|
||||
case MYSQL:
|
||||
case SQLITE:
|
||||
ctx.visit(N_IFNULL).sql('(').visit(arg1).sql(", ").visit(arg2).sql(')');
|
||||
ctx.visit(function(N_IFNULL, getDataType(), arg1, arg2));
|
||||
break;
|
||||
|
||||
default:
|
||||
ctx.visit(DSL.when(arg1.isNotNull(), arg1).otherwise(arg2));
|
||||
ctx.visit(function(N_NVL, getDataType(), arg1, arg2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ package org.jooq.impl;
|
||||
|
||||
import static org.jooq.conf.ParamType.INLINED;
|
||||
import static org.jooq.impl.DSL.inlined;
|
||||
import static org.jooq.impl.Keywords.K_COALESCE;
|
||||
import static org.jooq.impl.Names.N_COALESCE;
|
||||
import static org.jooq.impl.PositionalWindowFunction.PositionalFunctionType.LAG;
|
||||
import static org.jooq.impl.PositionalWindowFunction.PositionalFunctionType.LEAD;
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ import org.jooq.Privilege;
|
||||
/**
|
||||
* @author Timur Shaidullin
|
||||
*/
|
||||
final class PrivilegeImpl extends AbstractQueryPart implements Privilege {
|
||||
final class PrivilegeImpl extends AbstractQueryPart implements Privilege, SimpleQueryPart {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
|
||||
@ -65,7 +65,6 @@ class QueryPartCollectionView<T extends QueryPart> extends AbstractQueryPart imp
|
||||
|
||||
private static final long serialVersionUID = -2936922742534009564L;
|
||||
final Collection<T> wrapped;
|
||||
int indentSize;
|
||||
Boolean qualify;
|
||||
String separator;
|
||||
Function<? super T, ? extends T> mapper;
|
||||
@ -76,18 +75,9 @@ class QueryPartCollectionView<T extends QueryPart> extends AbstractQueryPart imp
|
||||
|
||||
QueryPartCollectionView(Collection<T> wrapped) {
|
||||
this.wrapped = wrapped != null ? wrapped : Collections.emptyList();
|
||||
this.indentSize = 2;
|
||||
this.separator = ",";
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to indent this list, and after what size indentation is applied.
|
||||
*/
|
||||
QueryPartCollectionView<T> indentSize(int newIndentSize) {
|
||||
this.indentSize = newIndentSize <= 0 ? Integer.MAX_VALUE : newIndentSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
QueryPartCollectionView<T> qualify(boolean newQualify) {
|
||||
this.qualify = newQualify;
|
||||
return this;
|
||||
@ -121,7 +111,7 @@ class QueryPartCollectionView<T extends QueryPart> extends AbstractQueryPart imp
|
||||
rendersContent.set(i++, ((QueryPartInternal) e).rendersContent(ctx));
|
||||
|
||||
int size = rendersContent.cardinality();
|
||||
boolean format = ctx.format() && size >= indentSize;
|
||||
boolean format = ctx.format() && (size >= 2 && requireIndentation());
|
||||
boolean previousQualify = ctx.qualify();
|
||||
boolean previousAlreadyIndented = TRUE.equals(ctx.data(DATA_LIST_ALREADY_INDENTED));
|
||||
boolean indent = format && !previousAlreadyIndented;
|
||||
@ -194,6 +184,14 @@ class QueryPartCollectionView<T extends QueryPart> extends AbstractQueryPart imp
|
||||
ctx.data(DATA_LIST_ALREADY_INDENTED, previousAlreadyIndented);
|
||||
}
|
||||
|
||||
private final boolean requireIndentation() {
|
||||
for (T t : this)
|
||||
if (!Tools.isSimple(t))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this method
|
||||
*/
|
||||
|
||||
@ -68,11 +68,6 @@ class QueryPartList<T extends QueryPart> extends QueryPartListView<T> {
|
||||
addAll(wrappedList);
|
||||
}
|
||||
|
||||
@Override
|
||||
QueryPartList<T> indentSize(int newIndentSize) {
|
||||
return (QueryPartList<T>) super.indentSize(newIndentSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
QueryPartList<T> qualify(boolean newQualify) {
|
||||
return (QueryPartList<T>) super.qualify(newQualify);
|
||||
|
||||
@ -76,11 +76,6 @@ class QueryPartListView<T extends QueryPart> extends QueryPartCollectionView<T>
|
||||
super(wrappedList);
|
||||
}
|
||||
|
||||
@Override
|
||||
QueryPartListView<T> indentSize(int newIndentSize) {
|
||||
return (QueryPartListView<T>) super.indentSize(newIndentSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
QueryPartListView<T> qualify(boolean newQualify) {
|
||||
return (QueryPartListView<T>) super.qualify(newQualify);
|
||||
|
||||
@ -169,7 +169,7 @@ implements
|
||||
ctx.visit(K_GRANT_OPTION_FOR)
|
||||
.sql(' ');
|
||||
|
||||
ctx.visit(QueryPartCollectionView.wrap(privileges).indentSize(0))
|
||||
ctx.visit(QueryPartCollectionView.wrap(privileges))
|
||||
.end(Clause.REVOKE_PRIVILEGE).sql(' ')
|
||||
.start(Clause.REVOKE_ON)
|
||||
.visit(K_ON).sql(' ')
|
||||
|
||||
@ -47,5 +47,4 @@ import org.jooq.QueryPartInternal;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
interface ScopeMappable extends QueryPartInternal {
|
||||
}
|
||||
interface ScopeMappable extends QueryPartInternal {}
|
||||
|
||||
@ -37,8 +37,6 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import org.jooq.Context;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.QueryPartInternal;
|
||||
|
||||
/**
|
||||
@ -46,5 +44,4 @@ import org.jooq.QueryPartInternal;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
interface ScopeNestable extends QueryPartInternal {
|
||||
}
|
||||
interface ScopeNestable extends QueryPartInternal {}
|
||||
|
||||
@ -67,7 +67,7 @@ import org.jooq.SQLDialect;
|
||||
import org.jooq.SortField;
|
||||
import org.jooq.SortOrder;
|
||||
|
||||
final class SortFieldImpl<T> extends AbstractQueryPart implements SortField<T> {
|
||||
final class SortFieldImpl<T> extends AbstractQueryPart implements SortField<T>, SimpleQueryPart {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
@ -87,6 +87,11 @@ final class SortFieldImpl<T> extends AbstractQueryPart implements SortField<T> {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSimple() {
|
||||
return !nullsFirst && !nullsLast && Tools.isSimple(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getName() {
|
||||
return field.getName();
|
||||
|
||||
@ -126,6 +126,7 @@ extends
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case MARIADB:
|
||||
|
||||
@ -162,9 +162,9 @@ extends
|
||||
}
|
||||
|
||||
if (length == null)
|
||||
ctx.visit(functionName).sql('(').visit(string).sql(", ").visit(startingPosition).sql(')');
|
||||
ctx.visit(function(functionName, getDataType(), string, startingPosition));
|
||||
else
|
||||
ctx.visit(functionName).sql('(').visit(string).sql(", ").visit(startingPosition).sql(", ").visit(length).sql(')');
|
||||
ctx.visit(function(functionName, getDataType(), string, startingPosition, length));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -58,7 +58,7 @@ import org.jooq.tools.StringUtils;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
class TableFieldImpl<R extends Record, T> extends AbstractField<T> implements TableField<R, T> {
|
||||
class TableFieldImpl<R extends Record, T> extends AbstractField<T> implements TableField<R, T>, SimpleQueryPart {
|
||||
|
||||
private static final long serialVersionUID = -2211214195583539735L;
|
||||
private static final Clause[] CLAUSES = { FIELD, FIELD_REFERENCE };
|
||||
|
||||
@ -84,7 +84,7 @@ import org.jooq.tools.StringUtils;
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
@org.jooq.Internal
|
||||
public class TableImpl<R extends Record> extends AbstractTable<R> implements ScopeMappable, ScopeNestable {
|
||||
public class TableImpl<R extends Record> extends AbstractTable<R> implements ScopeMappable, ScopeNestable, SimpleQueryPart {
|
||||
|
||||
private static final long serialVersionUID = 261033315221985068L;
|
||||
private static final Clause[] CLAUSES_TABLE_REFERENCE = { TABLE, TABLE_REFERENCE };
|
||||
|
||||
@ -3149,8 +3149,11 @@ final class Tools {
|
||||
}
|
||||
|
||||
static final boolean isWindow(Field<?> f) {
|
||||
return f instanceof AbstractWindowFunction
|
||||
&& ((AbstractWindowFunction<?>) f).isWindow();
|
||||
return f instanceof AbstractWindowFunction && ((AbstractWindowFunction<?>) f).isWindow();
|
||||
}
|
||||
|
||||
static final boolean isSimple(QueryPart part) {
|
||||
return part instanceof SimpleQueryPart && ((SimpleQueryPart) part).isSimple();
|
||||
}
|
||||
|
||||
static final Val<?> extractVal(Field<?> field) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user