[#2396] Add DSL.function(Name, Class, Field...) and

DSL.function(Name, DataType, Field...) to allow for custom,
fully-qualified function references
This commit is contained in:
Lukas Eder 2013-04-12 09:47:29 +02:00
parent 28073c01db
commit bfbcbca33f
2 changed files with 73 additions and 12 deletions

View File

@ -3092,8 +3092,8 @@ public class DSL {
}
/**
* <code>function()</code> can be used to access native functions that are
* not yet or insufficiently supported by jOOQ.
* <code>function()</code> can be used to access native or user-defined
* functions that are not yet or insufficiently supported by jOOQ.
* <p>
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
* guarantee syntax integrity. You may also create the possibility of
@ -3110,8 +3110,8 @@ public class DSL {
}
/**
* <code>function()</code> can be used to access native functions that are
* not yet or insufficiently supported by jOOQ.
* <code>function()</code> can be used to access native or user-defined
* functions that are not yet or insufficiently supported by jOOQ.
* <p>
* <b>NOTE</b>: When inserting plain SQL into jOOQ objects, you must
* guarantee syntax integrity. You may also create the possibility of
@ -3127,6 +3127,32 @@ public class DSL {
return new Function<T>(name, type, nullSafe(arguments));
}
/**
* <code>function()</code> can be used to access native or user-defined
* functions that are not yet or insufficiently supported by jOOQ.
*
* @param name The function name (possibly qualified)
* @param type The function return type
* @param arguments The function arguments
*/
@Support
public static <T> Field<T> function(Name name, Class<T> type, Field<?>... arguments) {
return function(name, getDataType(type), nullSafe(arguments));
}
/**
* <code>function()</code> can be used to access native or user-defined
* functions that are not yet or insufficiently supported by jOOQ.
*
* @param name The function name (possibly qualified)
* @param type The function return type
* @param arguments The function arguments
*/
@Support
public static <T> Field<T> function(Name name, DataType<T> type, Field<?>... arguments) {
return new Function<T>(name, type, nullSafe(arguments));
}
/**
* Create a new condition holding plain SQL.
* <p>

View File

@ -55,6 +55,7 @@ import org.jooq.AggregateFunction;
import org.jooq.BindContext;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.Name;
import org.jooq.OrderedAggregateFunction;
import org.jooq.QueryPart;
import org.jooq.RenderContext;
@ -92,8 +93,12 @@ class Function<T> extends AbstractField<T> implements
private static final long serialVersionUID = 347252741712134044L;
private final QueryPartList<QueryPart> arguments;
// Mutually exclusive attributes: super.getName(), this.name, this.term
private final Name name;
private final Term term;
// Other attributes
private final QueryPartList<QueryPart> arguments;
private final boolean distinct;
private final SortFieldList withinGroupOrderBy;
private final SortFieldList keepDenseRankOrderBy;
@ -120,10 +125,15 @@ class Function<T> extends AbstractField<T> implements
this(term, false, type, arguments);
}
Function(Name name, DataType<T> type, QueryPart... arguments) {
this(name, false, type, arguments);
}
Function(String name, boolean distinct, DataType<T> type, QueryPart... arguments) {
super(name, type);
this.term = null;
this.name = null;
this.distinct = distinct;
this.arguments = new QueryPartList<QueryPart>(arguments);
this.keepDenseRankOrderBy = new SortFieldList();
@ -136,6 +146,7 @@ class Function<T> extends AbstractField<T> implements
super(term.name().toLowerCase(), type);
this.term = term;
this.name = null;
this.distinct = distinct;
this.arguments = new QueryPartList<QueryPart>(arguments);
this.keepDenseRankOrderBy = new SortFieldList();
@ -144,6 +155,27 @@ class Function<T> extends AbstractField<T> implements
this.orderBy = new SortFieldList();
}
Function(Name name, boolean distinct, DataType<T> type, QueryPart... arguments) {
super(last(name.getName()), type);
this.term = null;
this.name = name;
this.distinct = distinct;
this.arguments = new QueryPartList<QueryPart>(arguments);
this.keepDenseRankOrderBy = new SortFieldList();
this.withinGroupOrderBy = new SortFieldList();
this.partitionBy = new QueryPartList<Field<?>>();
this.orderBy = new SortFieldList();
}
private static String last(String... strings) {
if (strings != null && strings.length > 0) {
return strings[strings.length - 1];
}
return null;
}
// -------------------------------------------------------------------------
// XXX QueryPart API
// -------------------------------------------------------------------------
@ -238,7 +270,7 @@ class Function<T> extends AbstractField<T> implements
* [#1275] <code>LIST_AGG</code> simulation for Postgres, Sybase
*/
private void toSQLStringAgg(RenderContext context) {
context.sql(getFNName(context.configuration().dialect()));
toSQLFunctionName(context);
context.sql("(");
if (distinct) {
@ -269,7 +301,7 @@ class Function<T> extends AbstractField<T> implements
* [#1273] <code>LIST_AGG</code> simulation for MySQL and CUBRID
*/
private final void toSQLGroupConcat(RenderContext context) {
context.sql(getFNName(context.configuration().dialect()));
toSQLFunctionName(context);
context.sql("(");
if (distinct) {
@ -377,7 +409,7 @@ class Function<T> extends AbstractField<T> implements
* Render function arguments and argument modifiers
*/
private final void toSQLArguments(RenderContext context) {
context.sql(getFNName(context.configuration().dialect()));
toSQLFunctionName(context);
context.sql("(");
if (distinct) {
@ -408,12 +440,15 @@ class Function<T> extends AbstractField<T> implements
context.sql(")");
}
private final String getFNName(SQLDialect dialect) {
if (term != null) {
return term.translate(dialect);
private final void toSQLFunctionName(RenderContext ctx) {
if (name != null) {
ctx.sql(name);
}
else if (term != null) {
ctx.sql(term.translate(ctx.configuration().dialect()));
}
else {
return getName();
ctx.sql(getName());
}
}