public Expression visitLeave(AddParseNode node, List<Expression> children) throws SQLException {
return visitLeave(node, children,
new ArithmeticExpressionBinder() {
@Override
public PDatum getBindMetaData(int i, List<Expression> children, final Expression expression) {
PDataType type = expression.getDataType();
if (type != null && type.isCoercibleTo(PDataType.DATE)) {
return new PDatum() {
@Override
public boolean isNullable() {
return expression.isNullable();
}
@Override
public PDataType getDataType() {
return PDataType.DECIMAL;
}
@Override
public Integer getByteSize() {
return null;
}
@Override
public Integer getMaxLength() {
return expression.getMaxLength();
}
@Override
public Integer getScale() {
return expression.getScale();
}
@Override
public ColumnModifier getColumnModifier() {
return expression.getColumnModifier();
}
};
}
return expression;
}
},
new ArithmeticExpressionFactory() {
@Override
public Expression create(ArithmeticParseNode node, List<Expression> children) throws SQLException {
boolean foundDate = false;
boolean isDeterministic = true;
PDataType theType = null;
for(int i = 0; i < children.size(); i++) {
Expression e = children.get(i);
isDeterministic &= e.isDeterministic();
PDataType type = e.getDataType();
if (type == null) {
continue;
} else if (type.isCoercibleTo(PDataType.TIMESTAMP)) {
if (foundDate) {
throw TypeMismatchException.newException(type, node.toString());
}
if (theType == null || (theType != PDataType.TIMESTAMP && theType != PDataType.UNSIGNED_TIMESTAMP)) {
theType = type;
}
foundDate = true;
}else if (type == PDataType.DECIMAL) {
if (theType == null || !theType.isCoercibleTo(PDataType.TIMESTAMP)) {
theType = PDataType.DECIMAL;
}
} else if (type.isCoercibleTo(PDataType.LONG)) {
if (theType == null) {
theType = PDataType.LONG;
}
} else if (type.isCoercibleTo(PDataType.DOUBLE)) {
if (theType == null) {
theType = PDataType.DOUBLE;
}
} else {
throw TypeMismatchException.newException(type, node.toString());