DateRepeatExpression.java
/*
* Copyright 2015 Gregory Graham
*
* 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.
*/
package nz.co.gregs.dbvolution.expressions;
import java.util.Collection;
import nz.co.gregs.dbvolution.results.DateRepeatResult;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import nz.co.gregs.dbvolution.databases.definitions.DBDefinition;
import nz.co.gregs.dbvolution.DBRow;
import nz.co.gregs.dbvolution.datatypes.DBBoolean;
import nz.co.gregs.dbvolution.datatypes.DBDateRepeat;
import static nz.co.gregs.dbvolution.expressions.AnyExpression.nullInteger;
import static nz.co.gregs.dbvolution.expressions.IntegerExpression.*;
import nz.co.gregs.dbvolution.expressions.windows.CanBeWindowingFunctionWithFrame;
import nz.co.gregs.dbvolution.expressions.windows.WindowFunctionFramable;
import nz.co.gregs.dbvolution.results.AnyResult;
import nz.co.gregs.dbvolution.results.StringResult;
import org.joda.time.Period;
/**
*
* @author gregory.graham
*/
public class DateRepeatExpression extends RangeExpression<Period, DateRepeatResult, DBDateRepeat> implements DateRepeatResult {
private final static long serialVersionUID = 1l;
/**
* DateRepeat values are often stored as Strings of the format
* P2015Y12M30D23h59n59.0s
*/
public static final String INTERVAL_PREFIX = "P";
/**
* DateRepeat values are often stored as Strings of the format
* P2015Y12M30D23h59n59.0s
*/
public static final String YEAR_SUFFIX = "Y";
/**
* DateRepeat values are often stored as Strings of the format
* P2015Y12M30D23h59n59.0s
*/
public static final String MONTH_SUFFIX = "M";
/**
* DateRepeat values are often stored as Strings of the format
* P2015Y12M30D23h59n59.0s
*/
public static final String DAY_SUFFIX = "D";
/**
* DateRepeat values are often stored as Strings of the format
* P2015Y12M30D23h59n59.0s
*/
public static final String HOUR_SUFFIX = "h";
/**
* DateRepeat values are often stored as Strings of the format
* P2015Y12M30D23h59n59.0s
*/
public static final String MINUTE_SUFFIX = "n";
/**
* DateRepeat values are often stored as Strings of the format
* P2015Y12M30D23h59n59.0s
*/
public static final String SECOND_SUFFIX = "s";
/**
* Default constructor
*
*/
protected DateRepeatExpression() {
super();
}
/**
* Creates a new DateRepeatExression that represents the value supplied.
*
* @param interval the value to use in the expression
*/
public DateRepeatExpression(Period interval) {
super(new DBDateRepeat(interval));
}
/**
* Creates a new DateRepeatExression that represents the DateRepeat value
* supplied.
*
* @param interval the time period from which to create a DateRepeat value
*/
public DateRepeatExpression(DateRepeatResult interval) {
super(interval);
}
/**
* Creates a new DateRepeatExression that represents the DateRepeat value
* supplied.
*
* @param interval the time period from which to create a DateRepeat value
*/
protected DateRepeatExpression(AnyResult<?> interval) {
super(interval);
}
@Override
public DateRepeatExpression copy() {
return isNullSafetyTerminator()
? nullDateRepeat()
: new DateRepeatExpression((AnyResult<?>) getInnerResult().copy());
}
@Override
public DBDateRepeat getQueryableDatatypeForExpressionValue() {
return new DBDateRepeat();
}
/**
* Creates an expression that will return the most common value of the column
* supplied.
*
* <p>
* MODE: The number which appears most often in a set of numbers. For example:
* in {6, 3, 9, 6, 6, 5, 9, 3} the Mode is 6.</p>
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a number expression.
*/
public DateRepeatExpression modeSimple() {
@SuppressWarnings("unchecked")
DateRepeatExpression modeExpr = new DateRepeatExpression(
new ModeSimpleExpression<>(this));
return modeExpr;
}
/**
* Creates an expression that will return the most common value of the column
* supplied.
*
* <p>
* MODE: The number which appears most often in a set of numbers. For example:
* in {6, 3, 9, 6, 6, 5, 9, 3} the Mode is 6.</p>
*
* <p>
* This version of Mode implements a stricter definition that will return null
* if the mode is undefined. The mode can be undefined if there are 2 or more
* values with the highest frequency value. </p>
*
* <p>
* For example in the list {0,0,0,0,1,1,2,2,2,2,3,4} both 0 and 2 occur four
* times and no other value occurs more frequently so the mode is undefined.
* {@link #modeSimple() The modeSimple()} method would return either 0 or 2
* randomly for the same set.</p>
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the mode or null if undefined.
*/
public DateRepeatExpression modeStrict() {
@SuppressWarnings("unchecked")
DateRepeatExpression modeExpr = new DateRepeatExpression(
new ModeStrictExpression<>(this));
return modeExpr;
}
/**
* Returns TRUE if this expression evaluates to NULL, otherwise FALSE.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a BooleanExpression
*/
@Override
public BooleanExpression isNull() {
return BooleanExpression.isNull(this);
}
/**
* Returns FALSE if this expression evaluates to NULL, otherwise TRUE.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a BooleanExpression
*/
@Override
public BooleanExpression isNotNull() {
return BooleanExpression.isNotNull(this);
}
/**
* Returns TRUE if this expression evaluates to a smaller or more negative
* offset than the provided value, otherwise FALSE.
*
* @param period the time period that might be greater in duration than this
* expression
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isLessThan(Period period) {
return this.isLessThan(value(period));
}
/**
* Returns TRUE if this expression evaluates to a smaller or more negative
* offset than the provided value, otherwise FALSE.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @param anotherInstance the value to compare with
* @return a BooleanExpression
*/
@Override
public BooleanExpression isLessThan(DateRepeatResult anotherInstance) {
return new IsLessThanExpression(this, anotherInstance);
}
/**
* Returns TRUE if this expression evaluates to a greater or less negative
* offset than the provided value, otherwise FALSE.
*
* @param period the time period that might be lesser in duration than this
* expression
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isGreaterThan(Period period) {
return this.isGreaterThan(value(period));
}
/**
* Returns TRUE if this expression evaluates to a smaller or more negative
* offset than the provided value, otherwise FALSE.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @param anotherInstance the value to compare with
* @return a BooleanExpression
*/
@Override
public BooleanExpression isGreaterThan(DateRepeatResult anotherInstance) {
return new BooleanExpression(new IsGreaterThanExpression(this, anotherInstance));
}
/**
* Returns TRUE if this expression evaluates to an equal or smaller offset
* than the provided value, otherwise FALSE.
*
* @param period the time period that might be greater in duration than this
* expression
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isLessThanOrEqual(Period period) {
return this.isLessThanOrEqual(value(period));
}
/**
* Returns TRUE if this expression evaluates to an equal or smaller offset
* than the provided value, otherwise FALSE.
*
* @param anotherInstance the time period that might be greater in duration
* than this expression
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isLessThanOrEqual(DateRepeatResult anotherInstance) {
return new BooleanExpression(new IsLessThanOrEqualExpression(this, anotherInstance));
}
/**
* Returns TRUE if this expression evaluates to an equal or greater offset
* than the provided value, otherwise FALSE.
*
* @param period the time period that might be lesser in duration than this
* expression
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isGreaterThanOrEqual(Period period) {
return this.isGreaterThanOrEqual(value(period));
}
/**
* Returns TRUE if this expression evaluates to an equal or greater offset
* than the provided value, otherwise FALSE.
*
* @param anotherInstance the time period that might be lesser in duration
* than this expression
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isGreaterThanOrEqual(DateRepeatResult anotherInstance) {
return new BooleanExpression(new IsGreaterThanOrEqualExpression(this, anotherInstance));
}
/**
* Returns TRUE if this expression evaluates to an smaller offset than the
* provided value, FALSE when it is greater than the provided value, and the
* value of the fallBackWhenEqual parameter when the 2 values are the same.
*
* @param period the time period that might be greater in duration than this
* expression
* @param fallBackWhenEqual the expression to be evaluated when the DateRepeat
* values are equal
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isLessThan(Period period, BooleanExpression fallBackWhenEqual) {
return this.isLessThan(value(period), fallBackWhenEqual);
}
/**
* Returns TRUE if this expression evaluates to an smaller offset than the
* provided value, FALSE when the it is greater than the provided value, and
* the value of the fallBackWhenEqual parameter when the 2 values are the
* same.
*
* @param anotherInstance the time period that might be greater in duration
* than this expression
* @param fallBackWhenEqual the expression to be evaluated when the values are
* equal
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isLessThan(DateRepeatResult anotherInstance, BooleanExpression fallBackWhenEqual) {
return this.isLessThan(anotherInstance).or(this.is(anotherInstance).and(fallBackWhenEqual));
}
/**
* Returns TRUE if this expression evaluates to an greater offset than the
* provided value, FALSE when the it is smaller than the provided value, and
* the value of the fallBackWhenEqual parameter when the 2 values are the
* same.
*
* @param period the time period that might be lesser in duration than this
* expression.
* @param fallBackWhenEqual the expression to be evaluated when the values are
* equal.
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isGreaterThan(Period period, BooleanExpression fallBackWhenEqual) {
return this.isGreaterThan(value(period), fallBackWhenEqual);
}
/**
* Returns TRUE if this expression evaluates to an greater offset than the
* provided value, FALSE when the it is smaller than the provided value, and
* the value of the fallBackWhenEqual parameter when the 2 values are the
* same.
*
* @param anotherInstance the time period that might be lesser in duration
* than this expression.
* @param fallBackWhenEqual the expression to be evaluated when the values are
* equal.
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isGreaterThan(DateRepeatResult anotherInstance, BooleanExpression fallBackWhenEqual) {
return this.isGreaterThan(anotherInstance).or(this.is(anotherInstance).and(fallBackWhenEqual));
}
/**
* Returns TRUE if this expression and the provided value are the same.
*
* @param period the required value of the DateRepeat
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression is(Period period) {
return this.is(value(period));
}
/**
* Returns TRUE if this expression and the provided value are the same.
*
* @param anotherInstance the value that is to be found.
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression is(DateRepeatResult anotherInstance) {
return new BooleanExpression(new IsExpression(this, anotherInstance));
}
/**
* Returns FALSE if this expression and the provided value are the same.
*
* @param anotherInstance a value that the expression should not match.
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isNot(Period anotherInstance) {
return isNot(value(anotherInstance));
}
/**
* Returns FALSE if this expression and the provided value are the same.
*
* @param anotherInstance a value that the expression should not match.
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
* @return a BooleanExpression
*/
@Override
public BooleanExpression isNot(DateRepeatResult anotherInstance) {
return BooleanExpression.allOf(
is(anotherInstance).not(),
isNotNull());
}
/**
* Returns the YEARS part of this DateRepeat value.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a number expression
*/
public IntegerExpression getYears() {
return new IntegerExpression(new GetYearsExpression(this)
);
}
/**
* Returns the MONTHS part of this DateRepeat value.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a number expression
*/
public IntegerExpression getMonths() {
return new IntegerExpression(new GetMonthsExpression(this)
);
}
/**
* Returns the DAYS part of this DateRepeat value.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a number expression
*/
public IntegerExpression getDays() {
return new IntegerExpression(new GetDaysExpression(this)
);
}
/**
* Returns the HOURS part of this DateRepeat value.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a number expression
*/
public IntegerExpression getHours() {
return new IntegerExpression(new GetHoursExpression(this)
);
}
/**
* Returns the MINUTES part of this DateRepeat value.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a number expression
*/
public IntegerExpression getMinutes() {
return new IntegerExpression(new GetMinutesExpression(this)
);
}
/**
* Returns the SECONDS part of this DateRepeat value.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a number expression
*/
public NumberExpression getSeconds() {
return new NumberExpression(new GetSecondsExpression(this)
);
}
/**
* Converts the interval expression into a string/character expression.
*
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return a StringExpression of the interval expression.
*/
@Override
public StringExpression stringResult() {
return new StringExpression(new StringResultExpression(this));
}
@Override
public DBDateRepeat asExpressionColumn() {
return new DBDateRepeat(this);
}
@Override
public BooleanExpression isBetween(DateRepeatResult anotherInstance, DateRepeatResult largerExpression) {
return BooleanExpression.allOf(
this.isGreaterThanOrEqual(anotherInstance),
this.isLessThan(anotherInstance)
);
}
@Override
public BooleanExpression isBetweenInclusive(DateRepeatResult anotherInstance, DateRepeatResult largerExpression) {
return BooleanExpression.allOf(
this.isGreaterThanOrEqual(anotherInstance),
this.isLessThanOrEqual(anotherInstance)
);
}
@Override
public BooleanExpression isBetweenExclusive(DateRepeatResult anotherInstance, DateRepeatResult largerExpression) {
return BooleanExpression.allOf(
this.isGreaterThan(anotherInstance),
this.isLessThan(anotherInstance)
);
}
@Override
public BooleanExpression isInCollection(Collection<DateRepeatResult> otherInstances) {
List<StringResult> collect = otherInstances.stream().map(v->v.stringResult()).collect(Collectors.toList());
return this.stringResult().isInCollection(collect);
// StringResult[] strs = new StringResult[otherInstances.length];
// int i = 0;
// for (DateRepeatResult otherInstance : otherInstances) {
// strs[i] = otherInstance.stringResult();
// i++;
// }
// return this.stringResult().isIn(strs);
}
@Override
public BooleanExpression isNotInCollection(Collection<DateRepeatResult> otherInstances) {
List<StringResult> collect = otherInstances.stream().map(v->v.stringResult()).collect(Collectors.toList());
return this.stringResult().isNotInCollection(collect);
// StringResult[] strs = new StringResult[otherInstances.length];
// int i = 0;
// for (DateRepeatResult otherInstance : otherInstances) {
// strs[i] = otherInstance.stringResult();
// i++;
// }
// return this.stringResult().isNotIn(strs);
}
@Override
public DateRepeatExpression nullExpression() {
return new NullExpression();
}
@Override
public DateRepeatResult expression(Period value) {
return new DateRepeatExpression(value);
}
@Override
public DateRepeatResult expression(DateRepeatResult value) {
return new DateRepeatExpression(value);
}
@Override
public DateRepeatResult expression(DBDateRepeat value) {
return value;
}
public NumberExpression approximateDurationInSeconds() {
return this.getYears().times(12).plus(this.getMonths()).times(30).plus(this.getDays()).times(24).plus(this.getHours()).times(60).plus(this.getMinutes()).times(60).plus(this.getSeconds());
}
public Comparison comparison(DateRepeatExpression right) {
return new Comparison(this, right);
}
private static abstract class DateRepeatDateRepeatWithBooleanResult extends BooleanExpression {
private static final long serialVersionUID = 1L;
private final DateRepeatExpression first;
private final DateRepeatExpression second;
private boolean requiresNullProtection;
DateRepeatDateRepeatWithBooleanResult(DateRepeatExpression first, DateRepeatResult second) {
this.first = first;
this.second = new DateRepeatExpression(second);
if (this.second == null || this.second.getIncludesNull()) {
this.requiresNullProtection = true;
}
}
DateRepeatExpression getFirst() {
return first;
}
DateRepeatExpression getSecond() {
return second;
}
@Override
public DBBoolean getQueryableDatatypeForExpressionValue() {
return new DBBoolean();
}
@Override
public String toSQLString(DBDefinition db) {
if (this.getIncludesNull()) {
return BooleanExpression.isNull(first).toSQLString(db);
} else {
return doExpressionTransform(db);
}
}
protected abstract String doExpressionTransform(DBDefinition db);
@Override
public Set<DBRow> getTablesInvolved() {
HashSet<DBRow> hashSet = new HashSet<DBRow>();
if (first != null) {
hashSet.addAll(first.getTablesInvolved());
}
if (second != null) {
hashSet.addAll(second.getTablesInvolved());
}
return hashSet;
}
@Override
public boolean isAggregator() {
return first.isAggregator() || second.isAggregator();
}
@Override
public boolean getIncludesNull() {
return requiresNullProtection;
}
}
public static class Comparison extends IntegerExpression {
private static final long serialVersionUID = 1L;
private final DateRepeatExpression first;
private final DateRepeatExpression second;
private boolean requiresNullProtection;
Comparison(DateRepeatExpression first, DateRepeatResult second) {
this.first = first;
this.second = new DateRepeatExpression(second);
if (this.second == null || this.second.getIncludesNull()) {
this.requiresNullProtection = true;
}
}
DateRepeatExpression getFirst() {
return first;
}
DateRepeatExpression getSecond() {
return second;
}
@Override
public String toSQLString(DBDefinition db) {
if (this.getIncludesNull()) {
return BooleanExpression.isNull(first).toSQLString(db);
} else {
return doExpressionTransform(db);
}
}
@Override
public Set<DBRow> getTablesInvolved() {
HashSet<DBRow> hashSet = new HashSet<DBRow>();
if (first != null) {
hashSet.addAll(first.getTablesInvolved());
}
if (second != null) {
hashSet.addAll(second.getTablesInvolved());
}
return hashSet;
}
@Override
public boolean isAggregator() {
return first.isAggregator() || second.isAggregator();
}
@Override
public boolean getIncludesNull() {
return requiresNullProtection;
}
protected String doExpressionTransform(DBDefinition db) {
final DateRepeatExpression firstExpr = getFirst();
final DateRepeatExpression secondExpr = getSecond();
final IntegerExpression minusOne = IntegerExpression.value(-1);
final IntegerExpression zero = IntegerExpression.value(0);
final IntegerExpression one = IntegerExpression.value(1);
return firstExpr.isLessThan(secondExpr)
.ifTrueFalseNull(
minusOne,
firstExpr.is(secondExpr)
.ifTrueFalseNull(
zero,
one,
nullInteger()
),
nullInteger()
).toSQLString(db);
}
public BooleanExpression ifLesserEqualGreaterOrNull(BooleanExpression lesserResult, BooleanExpression equalResult, BooleanExpression greaterResult, BooleanExpression nullResult) {
return CaseExpression
.when(this.is(-1), lesserResult)
.when(this.is(0), equalResult)
.when(this.is(1), greaterResult)
.defaultValue(nullResult);
}
}
private static abstract class DateRepeatWithNumberResult extends NumberExpression {
private static final long serialVersionUID = 1L;
private final DateRepeatExpression first;
private boolean requiresNullProtection;
DateRepeatWithNumberResult(DateRepeatExpression first) {
this.first = first;
}
protected abstract String doExpressionTransform(DBDefinition db);
DateRepeatExpression getFirst() {
return first;
}
@Override
public String toSQLString(DBDefinition db) {
if (this.getIncludesNull()) {
return BooleanExpression.isNull(first).toSQLString(db);
} else {
return doExpressionTransform(db);
}
}
@Override
public Set<DBRow> getTablesInvolved() {
HashSet<DBRow> hashSet = new HashSet<DBRow>();
if (first != null) {
hashSet.addAll(first.getTablesInvolved());
}
return hashSet;
}
@Override
public boolean isAggregator() {
return first.isAggregator();
}
@Override
public boolean getIncludesNull() {
return requiresNullProtection;
}
}
private static abstract class DateRepeatWithIntegerResult extends IntegerExpression {
private static final long serialVersionUID = 1L;
private final DateRepeatExpression first;
private boolean requiresNullProtection;
DateRepeatWithIntegerResult(DateRepeatExpression first) {
this.first = first;
}
protected abstract String doExpressionTransform(DBDefinition db);
DateRepeatExpression getFirst() {
return first;
}
@Override
public String toSQLString(DBDefinition db) {
if (this.getIncludesNull()) {
return BooleanExpression.isNull(first).toSQLString(db);
} else {
return doExpressionTransform(db);
}
}
@Override
public Set<DBRow> getTablesInvolved() {
HashSet<DBRow> hashSet = new HashSet<DBRow>();
if (first != null) {
hashSet.addAll(first.getTablesInvolved());
}
return hashSet;
}
@Override
public boolean isAggregator() {
return first.isAggregator();
}
@Override
public boolean getIncludesNull() {
return requiresNullProtection;
}
}
private static abstract class DateRepeatWithStringResult extends StringExpression {
private static final long serialVersionUID = 1L;
private final DateRepeatExpression first;
private boolean requiresNullProtection;
DateRepeatWithStringResult(DateRepeatExpression first) {
this.first = first;
}
protected abstract String doExpressionTransform(DBDefinition db);
DateRepeatExpression getFirst() {
return first;
}
@Override
public String toSQLString(DBDefinition db) {
if (this.getIncludesNull()) {
return BooleanExpression.isNull(first).toSQLString(db);
} else {
return doExpressionTransform(db);
}
}
@Override
public Set<DBRow> getTablesInvolved() {
HashSet<DBRow> hashSet = new HashSet<DBRow>();
if (first != null) {
hashSet.addAll(first.getTablesInvolved());
}
return hashSet;
}
@Override
public boolean isAggregator() {
return first.isAggregator();
}
@Override
public boolean getIncludesNull() {
return requiresNullProtection;
}
}
private static class IsLessThanExpression extends DateRepeatDateRepeatWithBooleanResult {
public IsLessThanExpression(DateRepeatExpression first, DateRepeatResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
final DateRepeatExpression firstExpr = getFirst();
final DateRepeatExpression secondExpr = getSecond();
final String firstSQL = firstExpr.toSQLString(db);
final String secondSQL = secondExpr.toSQLString(db);
try {
return db.doDateRepeatLessThanTransform(firstSQL, secondSQL);
} catch (UnsupportedOperationException exp) {
return CaseExpression
.when(firstExpr.isNull().or(secondExpr.isNull()), nullInteger())
.when(firstExpr.stringResult().isEmpty().or(secondExpr.stringResult().isEmpty()), nullInteger())
.when(firstExpr.getYears().isLessThan(secondExpr.getYears()), ONE)
.when(firstExpr.getYears().isGreaterThan(secondExpr.getYears()), ZERO)
.when(firstExpr.getMonths().isLessThan(secondExpr.getMonths()), ONE)
.when(firstExpr.getMonths().isGreaterThan(secondExpr.getMonths()), ZERO)
.when(firstExpr.getDays().isLessThan(secondExpr.getDays()), ONE)
.when(firstExpr.getDays().isGreaterThan(secondExpr.getDays()), ZERO)
.when(firstExpr.getHours().isLessThan(secondExpr.getHours()), ONE)
.when(firstExpr.getHours().isGreaterThan(secondExpr.getHours()), ZERO)
.when(firstExpr.getMinutes().isLessThan(secondExpr.getMinutes()), ONE)
.when(firstExpr.getMinutes().isGreaterThan(secondExpr.getMinutes()), ZERO)
.when(firstExpr.getSeconds().isLessThan(secondExpr.getSeconds()), ONE)
.when(firstExpr.getSeconds().isGreaterThan(secondExpr.getSeconds()), ZERO)
.defaultValue(ZERO)
.is(ONE)
.toSQLString(db);
}
}
@Override
public IsLessThanExpression copy() {
return new IsLessThanExpression(
getFirst() == null ? null : getFirst().copy(),
getSecond() == null ? null : getSecond().copy()
);
}
}
private static class IsGreaterThanExpression extends DateRepeatDateRepeatWithBooleanResult {
public IsGreaterThanExpression(DateRepeatExpression first, DateRepeatResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
try {
return db.doDateRepeatGreaterThanTransform(getFirst().toSQLString(db), getSecond().toSQLString(db));
} catch (UnsupportedOperationException exp) {
final DateRepeatExpression firstExpr = this.getFirst();
final DateRepeatExpression secondExpr = this.getSecond();
return CaseExpression
.when(firstExpr.isNull().or(secondExpr.isNull()), nullInteger())
.when(firstExpr.stringResult().isEmpty().or(secondExpr.stringResult().isEmpty()), nullInteger())
.when(firstExpr.getYears().isLessThan(secondExpr.getYears()), ZERO)
.when(firstExpr.getYears().isGreaterThan(secondExpr.getYears()), ONE)
.when(firstExpr.getMonths().isLessThan(secondExpr.getMonths()), ZERO)
.when(firstExpr.getMonths().isGreaterThan(secondExpr.getMonths()), ONE)
.when(firstExpr.getDays().isLessThan(secondExpr.getDays()), ZERO)
.when(firstExpr.getDays().isGreaterThan(secondExpr.getDays()), ONE)
.when(firstExpr.getHours().isLessThan(secondExpr.getHours()), ZERO)
.when(firstExpr.getHours().isGreaterThan(secondExpr.getHours()), ONE)
.when(firstExpr.getMinutes().isLessThan(secondExpr.getMinutes()), ZERO)
.when(firstExpr.getMinutes().isGreaterThan(secondExpr.getMinutes()), ONE)
.when(firstExpr.getSeconds().isLessThan(secondExpr.getSeconds()), ZERO)
.when(firstExpr.getSeconds().isGreaterThan(secondExpr.getSeconds()), ONE)
.defaultValue(ZERO)
.is(ONE)
.toSQLString(db);
}
}
@Override
public IsGreaterThanExpression copy() {
return new IsGreaterThanExpression(
getFirst() == null ? null : getFirst().copy(),
getSecond() == null ? null : getSecond().copy()
);
}
}
private static class IsLessThanOrEqualExpression extends DateRepeatDateRepeatWithBooleanResult {
public IsLessThanOrEqualExpression(DateRepeatExpression first, DateRepeatResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
try {
return db.doDateRepeatLessThanEqualsTransform(getFirst().toSQLString(db), getSecond().toSQLString(db));
} catch (UnsupportedOperationException exp) {
final DateRepeatExpression firstExpr = this.getFirst();
final DateRepeatExpression secondExpr = this.getSecond();
return firstExpr.isGreaterThan(secondExpr).not().toSQLString(db);
}
}
@Override
public IsLessThanOrEqualExpression copy() {
return new IsLessThanOrEqualExpression(
getFirst() == null ? null : getFirst().copy(),
getSecond() == null ? null : getSecond().copy()
);
}
}
protected static class IsGreaterThanOrEqualExpression extends DateRepeatDateRepeatWithBooleanResult {
public IsGreaterThanOrEqualExpression(DateRepeatExpression first, DateRepeatResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
try {
return db.doDateRepeatGreaterThanEqualsTransform(getFirst().toSQLString(db), getSecond().toSQLString(db));
} catch (UnsupportedOperationException exp) {
final DateRepeatExpression firstExpr = this.getFirst();
final DateRepeatExpression secondExpr = this.getSecond();
return firstExpr.isLessThan(secondExpr).not().toSQLString(db);
}
}
@Override
public IsGreaterThanOrEqualExpression copy() {
return new IsGreaterThanOrEqualExpression(
getFirst() == null ? null : getFirst().copy(),
getSecond() == null ? null : getSecond().copy()
);
}
}
protected static class IsExpression extends DateRepeatDateRepeatWithBooleanResult {
public IsExpression(DateRepeatExpression first, DateRepeatResult second) {
super(first, second);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
try {
return db.doDateRepeatEqualsTransform(getFirst().toSQLString(db), getSecond().toSQLString(db));
} catch (UnsupportedOperationException exp) {
final DateRepeatExpression firstExpr = this.getFirst();
final DateRepeatExpression secondExpr = this.getSecond();
return CaseExpression
.when(firstExpr.isNull().or(secondExpr.isNull()), nullInteger())
.when(firstExpr.stringResult().isEmpty().or(secondExpr.stringResult().isEmpty()), nullInteger())
.when(firstExpr.getYears().is(secondExpr.getYears())
.and(firstExpr.getMonths().is(secondExpr.getMonths()))
.and(firstExpr.getDays().is(secondExpr.getDays()))
.and(firstExpr.getHours().is(secondExpr.getHours()))
.and(firstExpr.getMinutes().is(secondExpr.getMinutes()))
.and(firstExpr.getSeconds().is(secondExpr.getSeconds()))
, ONE)
.defaultValue(ZERO)
.is(ONE)
.toSQLString(db);
}
}
@Override
public DateRepeatExpression.IsExpression copy() {
return new DateRepeatExpression.IsExpression(
getFirst() == null ? null : getFirst().copy(),
getSecond() == null ? null : getSecond().copy()
);
}
}
protected static class GetYearsExpression extends DateRepeatWithIntegerResult {
public GetYearsExpression(DateRepeatExpression first) {
super(first);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
if (db.supportsDateRepeatDatatypeFunctions()) {
return db.doDateRepeatGetYearsTransform(getFirst().toSQLString(db));
} else {
return BooleanExpression.isNull(getFirst()).ifThenElse(
nullNumber(),
getFirst().stringResult().substringBefore(YEAR_SUFFIX).substringAfter(INTERVAL_PREFIX).numberResult()
).toSQLString(db);
}
}
@Override
public GetYearsExpression copy() {
return new GetYearsExpression(
getFirst() == null ? null : getFirst().copy()
);
}
}
private static class GetMonthsExpression extends DateRepeatWithIntegerResult {
public GetMonthsExpression(DateRepeatExpression first) {
super(first);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
if (db.supportsDateRepeatDatatypeFunctions()) {
return db.doDateRepeatGetMonthsTransform(getFirst().toSQLString(db));
} else {
return BooleanExpression.isNull(getFirst()).ifThenElse(
nullNumber(),
getFirst().stringResult().substringBefore(MONTH_SUFFIX).substringAfter(YEAR_SUFFIX).numberResult()
).toSQLString(db);
}
}
@Override
public GetMonthsExpression copy() {
return new GetMonthsExpression(
getFirst() == null ? null : getFirst().copy()
);
}
}
private static class GetDaysExpression extends DateRepeatWithIntegerResult {
public GetDaysExpression(DateRepeatExpression first) {
super(first);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
if (db.supportsDateRepeatDatatypeFunctions()) {
return db.doDateRepeatGetDaysTransform(getFirst().toSQLString(db));
} else {
return BooleanExpression.isNull(getFirst()).ifThenElse(
nullNumber(),
getFirst().stringResult().substringBefore(DAY_SUFFIX).substringAfter(MONTH_SUFFIX).numberResult()
).toSQLString(db);
}
}
@Override
public GetDaysExpression copy() {
return new GetDaysExpression(
getFirst() == null ? null : getFirst().copy()
);
}
}
private static class GetHoursExpression extends DateRepeatWithIntegerResult {
public GetHoursExpression(DateRepeatExpression first) {
super(first);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
if (db.supportsDateRepeatDatatypeFunctions()) {
return db.doDateRepeatGetHoursTransform(getFirst().toSQLString(db));
} else {
return BooleanExpression.isNull(getFirst()).ifThenElse(
nullNumber(),
getFirst().stringResult().substringBefore(HOUR_SUFFIX).substringAfter(DAY_SUFFIX).numberResult()
).toSQLString(db);
}
}
@Override
public GetHoursExpression copy() {
return new GetHoursExpression(
getFirst() == null ? null : getFirst().copy()
);
}
}
private static class GetMinutesExpression extends DateRepeatWithIntegerResult {
public GetMinutesExpression(DateRepeatExpression first) {
super(first);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
if (db.supportsDateRepeatDatatypeFunctions()) {
return db.doDateRepeatGetMinutesTransform(getFirst().toSQLString(db));
} else {
return BooleanExpression.isNull(getFirst()).ifThenElse(
nullNumber(),
getFirst().stringResult().substringBefore(MINUTE_SUFFIX).substringAfter(HOUR_SUFFIX).numberResult()
).toSQLString(db);
}
}
@Override
public GetMinutesExpression copy() {
return new GetMinutesExpression(
getFirst() == null ? null : getFirst().copy()
);
}
}
private static class GetSecondsExpression extends DateRepeatWithNumberResult {
public GetSecondsExpression(DateRepeatExpression first) {
super(first);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
if (db.supportsDateRepeatDatatypeFunctions()) {
return db.doDateRepeatGetSecondsTransform(getFirst().toSQLString(db));
} else {
return BooleanExpression.isNull(getFirst()).ifThenElse(
nullNumber(),
getFirst().stringResult().substringBefore(SECOND_SUFFIX).substringAfter(MINUTE_SUFFIX).numberResult()
).toSQLString(db);
}
}
@Override
public GetSecondsExpression copy() {
return new GetSecondsExpression(
getFirst() == null ? null : getFirst().copy()
);
}
}
private static class StringResultExpression extends DateRepeatWithStringResult {
public StringResultExpression(DateRepeatExpression first) {
super(first);
}
private final static long serialVersionUID = 1l;
@Override
protected String doExpressionTransform(DBDefinition db) {
return db.doDateRepeatToStringTransform(getFirst().toSQLString(db));
}
@Override
public StringResultExpression copy() {
return new StringResultExpression(
getFirst() == null ? null : getFirst().copy()
);
}
}
private static class NullExpression extends DateRepeatExpression {
public NullExpression() {
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.getNull();
}
@Override
public NullExpression copy() {
return new NullExpression();
}
}
public static WindowFunctionFramable<DateRepeatExpression> firstValue() {
return new FirstValueExpression().over();
}
public static class FirstValueExpression extends DateRepeatExpression implements CanBeWindowingFunctionWithFrame<DateRepeatExpression> {
public FirstValueExpression() {
super();
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.getFirstValueFunctionName() + "()";
}
@Override
public boolean isAggregator() {
return true;
}
@Override
@SuppressWarnings("unchecked")
public FirstValueExpression copy() {
return new FirstValueExpression();
}
@Override
public WindowFunctionFramable<DateRepeatExpression> over() {
return new WindowFunctionFramable<DateRepeatExpression>(new DateRepeatExpression(this));
}
}
public static WindowFunctionFramable<DateRepeatExpression> lastValue() {
return new LastValueExpression().over();
}
public static class LastValueExpression extends DateRepeatExpression implements CanBeWindowingFunctionWithFrame<DateRepeatExpression> {
public LastValueExpression() {
super();
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.getLastValueFunctionName() + "()";
}
@Override
public boolean isAggregator() {
return true;
}
@Override
@SuppressWarnings("unchecked")
public LastValueExpression copy() {
return new LastValueExpression();
}
@Override
public WindowFunctionFramable<DateRepeatExpression> over() {
return new WindowFunctionFramable<DateRepeatExpression>(new DateRepeatExpression(this));
}
}
public static WindowFunctionFramable<DateRepeatExpression> nthValue(IntegerExpression indexExpression) {
return new NthValueExpression(indexExpression).over();
}
public static class NthValueExpression extends DateRepeatExpression implements CanBeWindowingFunctionWithFrame<DateRepeatExpression> {
public NthValueExpression(IntegerExpression only) {
super(only);
}
private final static long serialVersionUID = 1l;
@Override
public String toSQLString(DBDefinition db) {
return db.getNthValueFunctionName() + "(" + getInnerResult().toSQLString(db) + ")";
}
@Override
public boolean isAggregator() {
return true;
}
@Override
@SuppressWarnings("unchecked")
public NthValueExpression copy() {
return new NthValueExpression(
(IntegerExpression) (getInnerResult() == null ? null : getInnerResult().copy()));
}
@Override
public WindowFunctionFramable<DateRepeatExpression> over() {
return new WindowFunctionFramable<DateRepeatExpression>(new DateRepeatExpression(this));
}
}
/**
* LAG() is a window function that provides access to a row at a specified
* physical offset which comes before the current row.
*
* <p>
* The function will "look" back one row and return the value there. If there
* is no previous row NULL will be returned.</p>
*
* @return a lag expression ready for additional configuration
*/
public WindowFunctionFramable<DateRepeatExpression> lag() {
return lag(IntegerExpression.value(1));
}
/**
* LAG() is a window function that provides access to a row at a specified
* physical offset which comes before the current row.
*
* <p>
* When there is no row at the offset NULL will be returned.</p>
*
* @param offset the number of rows to look backwards
* @return a lag expression ready for additional configuration
*/
public WindowFunctionFramable<DateRepeatExpression> lag(IntegerExpression offset) {
return lag(offset, NumberExpression.nullDateRepeat());
}
/**
* LAG() is a window function that provides access to a row at a specified
* physical offset which comes before the current row.
*
* @param offset the number of rows to look backwards
* @param defaultExpression the expression to return when there is no row at
* the offset
* @return a lag expression ready for additional configuration
*/
public WindowFunctionFramable<DateRepeatExpression> lag(IntegerExpression offset, DateRepeatExpression defaultExpression) {
return new LagExpression(this, offset, defaultExpression).over();
}
/**
* LEAD() is a window function that provides access to a row at a specified
* physical offset which comes after the current row.
*
* <p>
* The function will "look" forward one row and return the value there. If
* there is no next row NULL will be returned.</p>
*
* @return a lag expression ready for additional configuration
*/
public WindowFunctionFramable<DateRepeatExpression> lead() {
return lead(value(1));
}
/**
* LEAD() is a window function that provides access to a row at a specified
* physical offset which comes after the current row.
*
* <p>
* When there is no row at the offset NULL will be returned.</p>
*
* @param offset the number of rows to look backwards
* @return a lag expression ready for additional configuration
*/
public WindowFunctionFramable<DateRepeatExpression> lead(IntegerExpression offset) {
return lead(offset, nullDateRepeat());
}
/**
* LEAD() is a window function that provides access to a row at a specified
* physical offset which comes after the current row.
*
* @param offset the number of rows to look forwards
* @param defaultExpression the expression to use when there is no row at the
* offset
* @return a lag expression ready for additional configuration
*/
public WindowFunctionFramable<DateRepeatExpression> lead(IntegerExpression offset, DateRepeatExpression defaultExpression) {
return new LeadExpression(this, offset, defaultExpression).over();
}
private static abstract class LagLeadFunction extends DateRepeatExpression implements CanBeWindowingFunctionWithFrame<DateRepeatExpression> {
private static final long serialVersionUID = 1L;
protected DateRepeatExpression first;
protected IntegerExpression second;
protected DateRepeatExpression third;
LagLeadFunction(DateRepeatExpression first, IntegerExpression second, DateRepeatExpression third) {
this.first = first;
this.second = second == null ? value(1) : second;
this.third = third == null ? nullDateRepeat() : third;
}
@Override
public DBDateRepeat getQueryableDatatypeForExpressionValue() {
return new DBDateRepeat();
}
@Override
public String toSQLString(DBDefinition db) {
return this.beforeValue(db) + getFirst().toSQLString(db) + this.getSeparator(db) + (getSecond() == null ? "" : getSecond().toSQLString(db)) + this.afterValue(db);
}
abstract String getFunctionName(DBDefinition db);
protected String beforeValue(DBDefinition db) {
return " " + getFunctionName(db) + "( ";
}
protected String getSeparator(DBDefinition db) {
return ", ";
}
protected String afterValue(DBDefinition db) {
return ") ";
}
@Override
public Set<DBRow> getTablesInvolved() {
HashSet<DBRow> hashSet = new HashSet<DBRow>();
hashSet.addAll(getFirst().getTablesInvolved());
hashSet.addAll(getSecond().getTablesInvolved());
hashSet.addAll(getThird().getTablesInvolved());
return hashSet;
}
@Override
public boolean isAggregator() {
return getFirst().isAggregator() || getSecond().isAggregator() || getThird().isAggregator();
}
@Override
public boolean getIncludesNull() {
return false;
}
/**
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the first
*/
protected DateRepeatExpression getFirst() {
return first;
}
/**
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the second
*/
protected IntegerExpression getSecond() {
return second;
}
/**
* <p style="color: #F90;">Support DBvolution at
* <a href="http://patreon.com/dbvolution" target=new>Patreon</a></p>
*
* @return the second
*/
protected DateRepeatExpression getThird() {
return third;
}
@Override
public boolean isPurelyFunctional() {
return first.isPurelyFunctional() && second.isPurelyFunctional() && third.isPurelyFunctional();
}
@Override
public WindowFunctionFramable<DateRepeatExpression> over() {
return new WindowFunctionFramable<>(new DateRepeatExpression(this));
}
}
public class LagExpression extends LagLeadFunction {
private static final long serialVersionUID = 1L;
public LagExpression(DateRepeatExpression first, IntegerExpression second, DateRepeatExpression third) {
super(first, second, third);
}
@Override
String getFunctionName(DBDefinition db) {
return db.getLagFunctionName();
}
@Override
public LagExpression copy() {
return new LagExpression(first, second, third);
}
}
public class LeadExpression extends LagLeadFunction {
private static final long serialVersionUID = 1L;
public LeadExpression(DateRepeatExpression first, IntegerExpression second, DateRepeatExpression third) {
super(first, second, third);
}
@Override
String getFunctionName(DBDefinition db) {
return db.getLeadFunctionName();
}
@Override
public LeadExpression copy() {
return new LeadExpression(first, second, third);
}
}
}