package jef.database.query.function;
import java.util.List;
import jef.database.jsqlparser.expression.Function;
import jef.database.jsqlparser.expression.Interval;
import jef.database.jsqlparser.expression.InverseExpression;
import jef.database.jsqlparser.expression.StringValue;
import jef.database.jsqlparser.visitor.Expression;
import jef.database.query.Func;
import jef.database.support.SQL_TSI;
/**
*
* 举例、在derby上用timestampadd来模拟adddate subdate两个函数。
* 原先的样式:
* select adddate(dateExpr, interval n unit) from dual
* 修改后
* select {fn timestampadd(SQL_TSI_DAY,1,timestamp('2013-01-01 12:00:00'))} from dual;
* 要点:1 必须用{fn }转义
* 2 必须指定单位SQL_TSI_*
* 3 偏差值单位,偏差值在中,时间值在后 (参数顺序变化)
* 4 不会隐式将char转换为timestamp,需要手工转换
*
* @author jiyi
*
*/
public class EmuDateAddSubByTimesatmpadd extends BaseArgumentSqlFunction{
private Func name;
private boolean isSub;
public EmuDateAddSubByTimesatmpadd(Func name){
this.name=name;
this.isSub=name==Func.subdate;
}
public String getName() {
return name.name();
}
public Expression renderExpression(List<Expression> arguments) {
Expression adjust=arguments.get(1);
Expression unitExpr=SQL_TSI.DAY.get();
if(adjust instanceof Interval){
Interval interval=(Interval)adjust;
interval.toMySqlMode();
String unit=interval.getUnit().toLowerCase();
Expression value=interval.getValue();
if("day".equals(unit)){
unitExpr=SQL_TSI.DAY.get();
}else if("hour".equals(unit)){
unitExpr=SQL_TSI.HOUR.get();
}else if("minute".equals(unit)){
unitExpr=SQL_TSI.MINUTE.get();
}else if("second".equals(unit)){
unitExpr=SQL_TSI.SECOND.get();
}else if("month".equals(unit)){
unitExpr=SQL_TSI.MONTH.get();
}else if("quarter".equals(unit)){
unitExpr=SQL_TSI.QUARTER.get();
}else if("year".equals(unit)){
unitExpr=SQL_TSI.YEAR.get();
}else{
throw new UnsupportedOperationException("The current Dialect can't handle datetime unit ["+unit+"] for now.");
}
adjust=isSub?InverseExpression.getInverse(value):value;
}else{
adjust=isSub?InverseExpression.getInverse(adjust):adjust;
}
Expression dateExpr=arguments.get(0);
if(dateExpr instanceof StringValue){
dateExpr=new Function("timestamp",dateExpr);
}
Function func=new Function("timestampadd",unitExpr, adjust,dateExpr);
func.setEscaped(true);
return func;
}
}