[#6488] Add support for Oracle's WIDTH_BUCKET() function

This commit is contained in:
lukaseder 2017-08-04 11:16:47 +02:00
parent 3a3cd95d47
commit a8b8b9aa1f
4 changed files with 126 additions and 0 deletions

View File

@ -572,6 +572,7 @@ term =
| ( 'UPPER' | 'UCASE' ) '(' field ')'
| 'VAR_POP' '(' field ')' [ over ]
| 'VAR_SAMP' '(' field ')' [ over ]
| 'WIDTH_BUCKET' '(' field, field, field, field ')'
| binaryLiteral
| 'YEAR' '(' field ')'
| unsignedNumericLiteral

View File

@ -20289,6 +20289,20 @@ public class DSL {
return new CurrentSchema();
}
@Support
public static <T extends Number> Field<T> widthBucket(Field<T> field, T low, T high, int buckets) {
return widthBucket(field, Tools.field(low, field.getDataType()), Tools.field(high, field.getDataType()), Tools.field(buckets));
}
@Support
public static <T extends Number> Field<T> widthBucket(Field<T> field, Field<T> low, Field<T> high, Field<Integer> buckets) {
return new WidthBucket<T>(field, low, high, buckets);
}
// -------------------------------------------------------------------------
// XXX utility API
// -------------------------------------------------------------------------
/**
* Get the default data type for the {@link DSLContext}'s underlying
* {@link SQLDialect} and a given Java type.

View File

@ -3098,6 +3098,14 @@ class ParserImpl implements Parser {
break;
case 'w':
case 'W':
if (N.is(type))
if ((field = parseFieldWidthBucketIf(ctx)) != null)
return field;
break;
case 'x':
case 'X':
if (X.is(type))
@ -3311,6 +3319,23 @@ class ParserImpl implements Parser {
return null;
}
private static final Field<?> parseFieldWidthBucketIf(ParserContext ctx) {
if (parseFunctionNameIf(ctx, "WIDTH_BUCKET")) {
parse(ctx, '(');
Field<?> f1 = parseField(ctx, N);
parse(ctx, ',');
Field<?> f2 = parseField(ctx, N);
parse(ctx, ',');
Field<?> f3 = parseField(ctx, N);
parse(ctx, ',');
Field<?> f4 = parseField(ctx, N);
parse(ctx, ')');
return DSL.widthBucket((Field) f1, (Field) f2, (Field) f3, (Field) f4);
}
return null;
}
private static final Field<?> parseFieldLeastIf(ParserContext ctx) {
if (parseFunctionNameIf(ctx, "LEAST")) {
parse(ctx, '(');

View File

@ -0,0 +1,86 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import static org.jooq.impl.DSL.one;
import static org.jooq.impl.DSL.zero;
import org.jooq.Context;
import org.jooq.Field;
/**
* @author Lukas Eder
*/
final class WidthBucket<T extends Number> extends AbstractField<T> {
/**
* Generated UID
*/
private static final long serialVersionUID = -4866100604361006859L;
private final Field<T> field;
private final Field<T> low;
private final Field<T> high;
private final Field<Integer> buckets;
WidthBucket(Field<T> field, Field<T> low, Field<T> high, Field<Integer> buckets) {
super(DSL.name("width_bucket"), field.getDataType());
this.field = field;
this.low = low;
this.high = high;
this.buckets = buckets;
}
@SuppressWarnings({ "unchecked" })
@Override
public void accept(Context<?> ctx) {
switch (ctx.family()) {
default:
ctx.visit(
DSL.when(field.lt(low), zero())
.when(field.ge(high), buckets.add(one()))
.otherwise((Field<Integer>) DSL.floor(field.sub(low).mul(buckets).div(high.sub(low))).add(one()))
);
break;
}
}
}