[jOOQ/jOOQ#11960] Add support for Redshift YEAR TO MONTH interval literals
This commit is contained in:
parent
57bf3e2524
commit
d2faa7c2df
@ -78,6 +78,14 @@ abstract class AbstractTypedNamed<T> extends AbstractNamed implements Typed<T> {
|
||||
return getDataType().getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* [#11959] A workaround to get access to the actual data type of an
|
||||
* expression.
|
||||
*/
|
||||
/* non-final */ DataType<?> getExpressionDataType() {
|
||||
return getDataType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> getDataType() {
|
||||
return type;
|
||||
|
||||
@ -200,7 +200,11 @@ extends
|
||||
default: throw unsupported();
|
||||
}
|
||||
|
||||
if (getDataType().isDate())
|
||||
// [#10258] [#11954]
|
||||
if (((AbstractField<?>) interval).getExpressionDataType().isInterval())
|
||||
ctx.sql('(').visit(date).sql(" + ").visit(interval).sql(')');
|
||||
|
||||
else if (getDataType().isDate())
|
||||
|
||||
// [#10258] Special case for DATE + INTEGER arithmetic
|
||||
if (datePart == DatePart.DAY)
|
||||
|
||||
@ -686,6 +686,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
|
||||
|
||||
|
||||
case H2:
|
||||
case HSQLDB:
|
||||
case POSTGRES:
|
||||
@ -698,6 +699,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
switch (ctx.family()) {
|
||||
|
||||
|
||||
|
||||
case POSTGRES:
|
||||
return true;
|
||||
}
|
||||
@ -2232,8 +2234,8 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
}
|
||||
|
||||
static final class DefaultDayToSecondBinding<U> extends AbstractBinding<DayToSecond, U> {
|
||||
private static final Set<SQLDialect> REQUIRE_PG_INTERVAL_SYNTAX = SQLDialect.supportedBy(POSTGRES);
|
||||
private static final Set<SQLDialect> REQUIRE_STANDARD_INTERVAL = SQLDialect.supportedBy(H2);
|
||||
private static final Set<SQLDialect> REQUIRE_PG_INTERVAL = SQLDialect.supportedBy(POSTGRES);
|
||||
private static final Set<SQLDialect> REQUIRE_STANDARD_INTERVAL = SQLDialect.supportedBy(H2);
|
||||
|
||||
DefaultDayToSecondBinding(DataType<DayToSecond> dataType, Converter<DayToSecond, U> converter) {
|
||||
super(dataType, converter);
|
||||
@ -2241,32 +2243,25 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
@Override
|
||||
void sqlInline0(BindingSQLContext<U> ctx, DayToSecond value) throws SQLException {
|
||||
|
||||
// [#566] Interval data types are best bound as Strings
|
||||
if (REQUIRE_PG_INTERVAL_SYNTAX.contains(ctx.dialect())) {
|
||||
int sign = value.getSign();
|
||||
int days = sign * value.getDays();
|
||||
ctx.render().sql('\'')
|
||||
.sql(days >= 0 ? '+' : '-')
|
||||
.sql(Math.abs(days))
|
||||
.sql(' ')
|
||||
.sql(sign * value.getHours())
|
||||
.sql(':')
|
||||
.sql(sign * value.getMinutes())
|
||||
.sql(':')
|
||||
.sql(sign * value.getSeconds())
|
||||
.sql('.')
|
||||
.sql(StringUtils.leftPad(Integer.toString(value.getNano()), 9, '0'))
|
||||
.sql('\'');
|
||||
}
|
||||
if (REQUIRE_PG_INTERVAL.contains(ctx.dialect()))
|
||||
ctx.render().visit(inline(toPGInterval(value).toString()));
|
||||
else
|
||||
ctx.render().sql('\'').sql(value.toString()).sql('\'');
|
||||
super.sqlInline0(ctx, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
final void set0(BindingSetStatementContext<U> ctx, DayToSecond value) throws SQLException {
|
||||
|
||||
// [#566] Interval data types are best bound as Strings
|
||||
if (REQUIRE_PG_INTERVAL_SYNTAX.contains(ctx.dialect()))
|
||||
if (REQUIRE_PG_INTERVAL.contains(ctx.dialect()))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ctx.statement().setObject(ctx.index(), toPGInterval(value));
|
||||
else
|
||||
ctx.statement().setString(ctx.index(), renderDTS(ctx, value));
|
||||
@ -2279,7 +2274,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
@Override
|
||||
final DayToSecond get0(BindingGetResultSetContext<U> ctx) throws SQLException {
|
||||
if (REQUIRE_PG_INTERVAL_SYNTAX.contains(ctx.dialect())) {
|
||||
if (REQUIRE_PG_INTERVAL.contains(ctx.dialect())) {
|
||||
Object object = ctx.resultSet().getObject(ctx.index());
|
||||
return object == null ? null : PostgresUtils.toDayToSecond(object);
|
||||
}
|
||||
@ -2289,7 +2284,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
@Override
|
||||
final DayToSecond get0(BindingGetStatementContext<U> ctx) throws SQLException {
|
||||
if (REQUIRE_PG_INTERVAL_SYNTAX.contains(ctx.dialect())) {
|
||||
if (REQUIRE_PG_INTERVAL.contains(ctx.dialect())) {
|
||||
Object object = ctx.statement().getObject(ctx.index());
|
||||
return object == null ? null : PostgresUtils.toDayToSecond(object);
|
||||
}
|
||||
@ -4609,11 +4604,27 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
super(dataType, converter);
|
||||
}
|
||||
|
||||
@Override
|
||||
final void sqlInline0(BindingSQLContext<U> ctx, YearToSecond value) throws SQLException {
|
||||
|
||||
// [#566] Interval data types are best bound as Strings
|
||||
if (REQUIRE_PG_INTERVAL.contains(ctx.dialect()))
|
||||
ctx.render().visit(inline(toPGInterval(value).toString()));
|
||||
else
|
||||
super.sqlInline0(ctx, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
final void set0(BindingSetStatementContext<U> ctx, YearToSecond value) throws SQLException {
|
||||
|
||||
// [#566] Interval data types are best bound as Strings
|
||||
if (REQUIRE_PG_INTERVAL.contains(ctx.dialect()))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ctx.statement().setObject(ctx.index(), toPGInterval(value));
|
||||
else
|
||||
ctx.statement().setString(ctx.index(), value.toString());
|
||||
@ -4668,11 +4679,27 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
super(dataType, converter);
|
||||
}
|
||||
|
||||
@Override
|
||||
final void sqlInline0(BindingSQLContext<U> ctx, YearToMonth value) throws SQLException {
|
||||
|
||||
// [#566] Interval data types are best bound as Strings
|
||||
if (REQUIRE_PG_INTERVAL.contains(ctx.dialect()))
|
||||
ctx.render().visit(inline(toPGInterval(value).toString()));
|
||||
else
|
||||
super.sqlInline0(ctx, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
final void set0(BindingSetStatementContext<U> ctx, YearToMonth value) throws SQLException {
|
||||
|
||||
// [#566] Interval data types are best bound as Strings
|
||||
if (REQUIRE_PG_INTERVAL.contains(ctx.dialect()))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ctx.statement().setObject(ctx.index(), toPGInterval(value));
|
||||
else
|
||||
ctx.statement().setString(ctx.index(), renderYTM(ctx, value));
|
||||
|
||||
@ -166,6 +166,28 @@ final class Expression<T> extends AbstractTransformable<T> {
|
||||
this.rhs = rhs;
|
||||
}
|
||||
|
||||
@Override
|
||||
DataType<?> getExpressionDataType() {
|
||||
|
||||
// [#11959] Workaround for lack of proper data type information for interval based expressions
|
||||
AbstractField<?> l = (AbstractField<?>) lhs;
|
||||
AbstractField<?> r = (AbstractField<?>) rhs;
|
||||
|
||||
DataType<?> lt = l.getExpressionDataType();
|
||||
DataType<?> rt = r.getExpressionDataType();
|
||||
|
||||
switch (operator) {
|
||||
case MULTIPLY:
|
||||
case DIVIDE:
|
||||
return rt.isInterval() ? rt : lt;
|
||||
|
||||
case ADD:
|
||||
return lt.isInterval() ? rt : lt;
|
||||
}
|
||||
|
||||
return lt;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
final void accept0(Context<?> ctx) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user