[jOOQ/jOOQ#8418] Add support for vendor specific DateParts in DSL.trunc()

This commit is contained in:
Lukas Eder 2024-01-17 17:30:58 +01:00
parent e00feb08ec
commit 2ef003eee2

View File

@ -37,6 +37,7 @@
*/
package org.jooq.impl;
import static org.jooq.DatePart.YEAR;
import static org.jooq.impl.DSL.function;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.keyword;
@ -44,6 +45,7 @@ import static org.jooq.impl.Keywords.K_CAST;
import static org.jooq.impl.Names.N_DATETIME_TRUNC;
import static org.jooq.impl.Names.N_DATE_TRUNC;
import static org.jooq.impl.Names.N_TRUNC;
import static org.jooq.impl.SQLDataType.VARCHAR;
import static org.jooq.impl.Tools.castIfNeeded;
import java.sql.Date;
@ -73,6 +75,7 @@ final class TruncDate<T> extends AbstractField<T> implements UNotYetImplemented
String keyword = null;
String format = null;
familySwitch:
switch (ctx.family()) {
// [http://jira.cubrid.org/browse/ENGINE-120] This currently doesn't work for all date parts in CUBRID
@ -85,7 +88,7 @@ final class TruncDate<T> extends AbstractField<T> implements UNotYetImplemented
case HOUR: keyword = "HH"; break;
case MINUTE: keyword = "MI"; break;
case SECOND: keyword = "SS"; break;
default: throwUnsupported();
default: acceptDefaultEmulation(ctx); break familySwitch;
}
ctx.visit(N_TRUNC).sql('(').visit(date).sql(", ").visit(inline(keyword)).sql(')');
@ -100,7 +103,7 @@ final class TruncDate<T> extends AbstractField<T> implements UNotYetImplemented
case HOUR: format = "yyyy-MM-dd HH"; break;
case MINUTE: format = "yyyy-MM-dd HH:mm"; break;
case SECOND: format = "yyyy-MM-dd HH:mm:ss"; break;
default: throwUnsupported();
default: acceptDefaultEmulation(ctx); break familySwitch;
}
ctx.visit(DSL.keyword("parsedatetime")).sql('(')
@ -129,17 +132,7 @@ final class TruncDate<T> extends AbstractField<T> implements UNotYetImplemented
case POSTGRES:
case YUGABYTEDB: {
switch (part) {
case YEAR: keyword = "year"; break;
case MONTH: keyword = "month"; break;
case DAY: keyword = "day"; break;
case HOUR: keyword = "hour"; break;
case MINUTE: keyword = "minute"; break;
case SECOND: keyword = "second"; break;
default: throwUnsupported();
}
ctx.visit(N_DATE_TRUNC).sql('(').visit(inline(keyword)).sql(", ").visit(date).sql(')');
ctx.visit(N_DATE_TRUNC).sql('(').visit(inline(part.toKeyword().toString())).sql(", ").visit(date).sql(')');
break;
}
@ -256,6 +249,45 @@ final class TruncDate<T> extends AbstractField<T> implements UNotYetImplemented
}
}
private final void acceptDefaultEmulation(Context<?> ctx) {
switch (part) {
case DECADE:
ctx.visit(padYear(ctx, 3, DSL.extract(date, part)).concat(dateOrTimestampLiteral("0-01-01")).cast(getDataType()));
break;
case CENTURY:
ctx.visit(padYear(ctx, 2, DSL.extract(date, part).minus(inline(1))).concat(dateOrTimestampLiteral("01-01-01")).cast(getDataType()));
break;
case MILLENNIUM:
ctx.visit(DSL.extract(date, part).minus(inline(1)).cast(VARCHAR(10)).concat(dateOrTimestampLiteral("001-01-01")).cast(getDataType()));
break;
case QUARTER:
ctx.visit(padYear(ctx, 4, DSL.extract(date, YEAR)).concat(inline("-")).concat(DSL.extract(date, part).minus(inline(1)).times(inline(3)).plus(inline(1)).cast(VARCHAR(10))).concat(dateOrTimestampLiteral("-01")).cast(getDataType()));
break;
default:
throwUnsupported();
break;
}
}
private final Field<String> padYear(Context<?> ctx, int length, Field<Integer> year) {
switch (ctx.family()) {
case HSQLDB:
return DSL.lpad(year.cast(VARCHAR(10)), inline(length), inline("0"));
default:
return year.cast(VARCHAR(10));
}
}
private final Field<String> dateOrTimestampLiteral(String string) {
return DSL.inline(getDataType().isDate() ? string : string + " 00:00:00");
}
private final void throwUnsupported() {
throw new UnsupportedOperationException("Unknown date part : " + part);
}