Use TypeInfo in Expression implementations

上级 3f2932f9
......@@ -2440,7 +2440,7 @@ public class Parser {
SelectOrderBy order = new SelectOrderBy();
Expression expr = readExpression();
if (canBeNumber && expr instanceof ValueExpression &&
expr.getType() == Value.INT) {
expr.getValueType() == Value.INT) {
order.columnIndexExpr = expr;
} else if (expr instanceof Parameter) {
recompileAlways = true;
......@@ -3837,12 +3837,12 @@ public class Parser {
read();
if (currentTokenType == VALUE) {
r = ValueExpression.get(currentValue.negate());
if (r.getType() == Value.LONG &&
if (r.getValueType() == Value.LONG &&
r.getValue(session).getLong() == Integer.MIN_VALUE) {
// convert Integer.MIN_VALUE to type 'int'
// (Integer.MAX_VALUE+1 is of type 'long')
r = ValueExpression.get(ValueInt.get(Integer.MIN_VALUE));
} else if (r.getType() == Value.DECIMAL &&
} else if (r.getValueType() == Value.DECIMAL &&
r.getValue(session).getBigDecimal()
.compareTo(Value.MIN_LONG_DECIMAL) == 0) {
// convert Long.MIN_VALUE to type 'long'
......@@ -5841,7 +5841,7 @@ public class Parser {
do {
Expression expr = readExpression();
expr = expr.optimize(session);
int type = expr.getType();
int type = expr.getValueType();
long prec;
int scale, displaySize;
Column column;
......
......@@ -180,7 +180,7 @@ public class CreateTable extends CommandWithColumns {
ColumnNamer columnNamer= new ColumnNamer(session);
for (int i = 0; i < columnCount; i++) {
Expression expr = expressions.get(i);
int type = expr.getType();
int type = expr.getValueType();
String name = columnNamer.getColumnName(expr,i,expr.getAlias());
long precision = expr.getPrecision();
int displaySize = expr.getDisplaySize();
......
......@@ -76,7 +76,7 @@ public class Call extends Prepared {
public void prepare() {
expression = expression.optimize(session);
expressions = new Expression[] { expression };
isResultSet = expression.getType() == Value.RESULT_SET;
isResultSet = expression.getValueType() == Value.RESULT_SET;
if (isResultSet) {
prepareAlways = true;
}
......
......@@ -121,7 +121,7 @@ public class SelectUnion extends Query {
Mode mode = session.getDatabase().getMode();
for (int i = 0; i < columnCount; i++) {
Expression e = expressions.get(i);
newValues[i] = values[i].convertTo(e.getType(), mode);
newValues[i] = values[i].convertTo(e.getValueType(), mode);
}
return newValues;
}
......@@ -328,7 +328,7 @@ public class SelectUnion extends Query {
for (int i = 0; i < len; i++) {
Expression l = le.get(i);
Expression r = re.get(i);
int type = Value.getHigherOrder(l.getType(), r.getType());
int type = Value.getHigherOrder(l.getValueType(), r.getValueType());
long prec = Math.max(l.getPrecision(), r.getPrecision());
int scale = Math.max(l.getScale(), r.getScale());
int displaySize = Math.max(l.getDisplaySize(), r.getDisplaySize());
......
......@@ -9,6 +9,7 @@ import org.h2.command.Parser;
import org.h2.engine.Session;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
/**
......@@ -37,10 +38,15 @@ public class Alias extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
return expr.getType();
}
@Override
public int getValueType() {
return expr.getValueType();
}
@Override
public void mapColumns(ColumnResolver resolver, int level, int state) {
expr.mapColumns(resolver, level, state);
......
......@@ -14,6 +14,7 @@ import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.util.MathUtils;
import org.h2.value.DataType;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueNull;
......@@ -59,6 +60,7 @@ public class BinaryOperation extends Expression {
private OpType opType;
private Expression left, right;
private TypeInfo type;
private int dataType;
private boolean convertRight = true;
......@@ -164,6 +166,7 @@ public class BinaryOperation extends Expression {
right = right.optimize(session);
switch (opType) {
case CONCAT:
type = TypeInfo.TYPE_STRING_DEFAULT;
dataType = Value.STRING;
break;
case PLUS:
......@@ -171,17 +174,19 @@ public class BinaryOperation extends Expression {
case MULTIPLY:
case DIVIDE:
case MODULUS:
int l = left.getType();
int r = right.getType();
int l = left.getValueType();
int r = right.getValueType();
if ((l == Value.NULL && r == Value.NULL) ||
(l == Value.UNKNOWN && r == Value.UNKNOWN)) {
// (? + ?) - use decimal by default (the most safe data type) or
// string when text concatenation with + is enabled
if (opType == OpType.PLUS && session.getDatabase().
getMode().allowPlusForStringConcat) {
type = TypeInfo.TYPE_STRING_DEFAULT;
dataType = Value.STRING;
opType = OpType.CONCAT;
} else {
type = TypeInfo.TYPE_DECIMAL_DEFAULT;
dataType = Value.DECIMAL;
}
} else if (DataType.isIntervalType(l) || DataType.isIntervalType(r)) {
......@@ -191,10 +196,13 @@ public class BinaryOperation extends Expression {
} else {
dataType = Value.getHigherOrder(l, r);
if (dataType == Value.ENUM) {
type = TypeInfo.TYPE_INT;
dataType = Value.INT;
} else if (DataType.isStringType(dataType) &&
session.getDatabase().getMode().allowPlusForStringConcat) {
opType = OpType.CONCAT;
} else {
type = TypeInfo.getTypeInfo(dataType);
if (DataType.isStringType(dataType) && session.getDatabase().getMode().allowPlusForStringConcat) {
opType = OpType.CONCAT;
}
}
}
break;
......@@ -311,8 +319,10 @@ public class BinaryOperation extends Expression {
case Value.TIME:
if (r == Value.TIME || r == Value.TIMESTAMP_TZ) {
dataType = r;
type = TypeInfo.getTypeInfo(r);
return this;
} else { // DATE, TIMESTAMP
type = TypeInfo.TYPE_TIMESTAMP;
dataType = Value.TIMESTAMP;
return this;
}
......@@ -351,6 +361,7 @@ public class BinaryOperation extends Expression {
return f.optimize(session);
}
case Value.TIME:
type = TypeInfo.TYPE_TIMESTAMP;
dataType = Value.TIMESTAMP;
return this;
case Value.DATE:
......@@ -368,11 +379,13 @@ public class BinaryOperation extends Expression {
break;
case MULTIPLY:
if (l == Value.TIME) {
type = TypeInfo.TYPE_TIME;
dataType = Value.TIME;
convertRight = false;
return this;
} else if (r == Value.TIME) {
swap();
type = TypeInfo.TYPE_TIME;
dataType = Value.TIME;
convertRight = false;
return this;
......@@ -380,6 +393,7 @@ public class BinaryOperation extends Expression {
break;
case DIVIDE:
if (l == Value.TIME) {
type = TypeInfo.TYPE_TIME;
dataType = Value.TIME;
convertRight = false;
return this;
......@@ -408,7 +422,12 @@ public class BinaryOperation extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
return type;
}
@Override
public int getValueType() {
return dataType;
}
......
......@@ -13,6 +13,7 @@ import org.h2.result.ResultInterface;
import org.h2.table.Column;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueArray;
......@@ -84,12 +85,20 @@ public abstract class Expression {
public abstract Value getValue(Session session);
/**
* Return the data type. The data type may not be known before the
* Returns the data type. The data type may not be known before the
* optimization phase.
*
* @return the type
* @return the data type
*/
public abstract int getType();
public abstract TypeInfo getType();
/**
* Return the value type. The value type may not be known before the
* optimization phase.
*
* @return the value type
*/
public abstract int getValueType();
/**
* Map the columns of the resolver to expression columns.
......
......@@ -22,6 +22,7 @@ import org.h2.table.ColumnResolver;
import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.value.ExtTypeInfo;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueBoolean;
import org.h2.value.ValueNull;
......@@ -225,7 +226,12 @@ public class ExpressionColumn extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
return column == null ? TypeInfo.TYPE_UNKNOWN : column.getType();
}
@Override
public int getValueType() {
return column == null ? Value.UNKNOWN : column.getType().getValueType();
}
......
......@@ -9,6 +9,7 @@ import org.h2.engine.Session;
import org.h2.table.Column;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueRow;
......@@ -37,7 +38,12 @@ public class ExpressionList extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
return isArray ? TypeInfo.TYPE_ARRAY : TypeInfo.TYPE_ROW;
}
@Override
public int getValueType() {
return isArray ? Value.ARRAY : Value.ROW;
}
......@@ -125,7 +131,7 @@ public class ExpressionList extends Expression {
for (int i = 0; i < list.length; i++) {
Expression e = list[i];
Column col = new Column("C" + (i + 1),
e.getType(), e.getPrecision(), e.getScale(),
e.getValueType(), e.getPrecision(), e.getScale(),
e.getDisplaySize());
expr[i] = new ExpressionColumn(session.getDatabase(), col);
}
......
......@@ -26,6 +26,7 @@ import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.util.IntervalUtils;
import org.h2.value.DataType;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueDate;
import org.h2.value.ValueInterval;
......@@ -77,6 +78,7 @@ public class IntervalOperation extends Expression {
private final IntervalOpType opType;
private Expression left, right;
private TypeInfo type;
private int dataType;
private static BigInteger nanosFromValue(Value v) {
......@@ -89,24 +91,29 @@ public class IntervalOperation extends Expression {
this.opType = opType;
this.left = left;
this.right = right;
int l = left.getType(), r = right.getType();
int l = left.getValueType(), r = right.getValueType();
switch (opType) {
case INTERVAL_PLUS_INTERVAL:
case INTERVAL_MINUS_INTERVAL:
dataType = Value.getHigherOrder(l, r);
type = TypeInfo.getTypeInfo(dataType);
break;
case DATETIME_PLUS_INTERVAL:
case DATETIME_MINUS_INTERVAL:
case INTERVAL_MULTIPLY_NUMERIC:
case INTERVAL_DIVIDE_NUMERIC:
type = left.getType();
dataType = l;
break;
case DATETIME_MINUS_DATETIME:
if (l == Value.TIME && r == Value.TIME) {
type = TypeInfo.TYPE_INTERVAL_HOUR_TO_SECOND;
dataType = Value.INTERVAL_HOUR_TO_SECOND;
} else if (l == Value.DATE && r == Value.DATE) {
type = TypeInfo.TYPE_INTERVAL_DAY;
dataType = Value.INTERVAL_DAY;
} else {
type = TypeInfo.TYPE_INTERVAL_DAY_TO_SECOND;
dataType = Value.INTERVAL_DAY_TO_SECOND;
}
}
......@@ -277,7 +284,12 @@ public class IntervalOperation extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
return type;
}
@Override
public int getValueType() {
return dataType;
}
......
......@@ -12,6 +12,7 @@ import org.h2.message.DbException;
import org.h2.table.Column;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueBoolean;
import org.h2.value.ValueNull;
......@@ -61,7 +62,18 @@ public class Parameter extends Expression implements ParameterInterface {
}
@Override
public int getType() {
public TypeInfo getType() {
if (value != null) {
return value.getType();
}
if (column != null) {
return column.getType();
}
return TypeInfo.TYPE_UNKNOWN;
}
@Override
public int getValueType() {
if (value != null) {
return value.getValueType();
}
......
......@@ -48,7 +48,7 @@ public interface ParameterInterface {
*
* @return the data type
*/
int getType();
int getValueType();
/**
* Get the expected precision of this parameter.
......
......@@ -55,7 +55,7 @@ public class ParameterRemote implements ParameterInterface {
}
@Override
public int getType() {
public int getValueType() {
return value == null ? dataType : value.getValueType();
}
......@@ -94,7 +94,7 @@ public class ParameterRemote implements ParameterInterface {
*/
public static void writeMetaData(Transfer transfer, ParameterInterface p)
throws IOException {
transfer.writeInt(p.getType());
transfer.writeInt(p.getValueType());
transfer.writeLong(p.getPrecision());
transfer.writeInt(p.getScale());
transfer.writeInt(p.getNullable());
......
......@@ -10,6 +10,7 @@ import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueLong;
......@@ -33,7 +34,12 @@ public class Rownum extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
return TypeInfo.TYPE_LONG;
}
@Override
public int getValueType() {
return Value.LONG;
}
......
......@@ -10,6 +10,7 @@ import org.h2.message.DbException;
import org.h2.schema.Sequence;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueLong;
......@@ -32,7 +33,12 @@ public class SequenceValue extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
return TypeInfo.TYPE_LONG;
}
@Override
public int getValueType() {
return Value.LONG;
}
......
......@@ -13,6 +13,7 @@ import org.h2.message.DbException;
import org.h2.result.ResultInterface;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueNull;
import org.h2.value.ValueRow;
......@@ -53,10 +54,15 @@ public class Subquery extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
return getExpression().getType();
}
@Override
public int getValueType() {
return getExpression().getValueType();
}
@Override
public void mapColumns(ColumnResolver resolver, int level, int state) {
query.mapColumns(resolver, level + 1);
......
......@@ -8,6 +8,7 @@ package org.h2.expression;
import org.h2.engine.Session;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueNull;
......@@ -17,7 +18,7 @@ import org.h2.value.ValueNull;
public class UnaryOperation extends Expression {
private Expression arg;
private int dataType;
private TypeInfo type;
public UnaryOperation(Expression arg) {
this.arg = arg;
......@@ -33,7 +34,7 @@ public class UnaryOperation extends Expression {
@Override
public Value getValue(Session session) {
Value a = arg.getValue(session).convertTo(dataType, session.getDatabase().getMode());
Value a = arg.getValue(session).convertTo(type.getValueType(), session.getDatabase().getMode());
return a == ValueNull.INSTANCE ? a : a.negate();
}
......@@ -45,11 +46,11 @@ public class UnaryOperation extends Expression {
@Override
public Expression optimize(Session session) {
arg = arg.optimize(session);
dataType = arg.getType();
if (dataType == Value.UNKNOWN) {
dataType = Value.DECIMAL;
} else if (dataType == Value.ENUM) {
dataType = Value.INT;
type = arg.getType();
if (type.getValueType() == Value.UNKNOWN) {
type = TypeInfo.TYPE_DECIMAL_DEFAULT;
} else if (type.getValueType() == Value.ENUM) {
type = TypeInfo.TYPE_INT;
}
if (arg.isConstant()) {
return ValueExpression.get(getValue(session));
......@@ -63,8 +64,13 @@ public class UnaryOperation extends Expression {
}
@Override
public int getType() {
return dataType;
public TypeInfo getType() {
return type;
}
@Override
public int getValueType() {
return type.getValueType();
}
@Override
......
......@@ -11,6 +11,7 @@ import org.h2.index.IndexCondition;
import org.h2.message.DbException;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueBoolean;
......@@ -75,7 +76,12 @@ public class ValueExpression extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
return value.getType();
}
@Override
public int getValueType() {
return value.getValueType();
}
......@@ -177,7 +183,7 @@ public class ValueExpression extends Expression {
@Override
public Expression[] getExpressionColumns(Session session) {
if (getType() == Value.ARRAY) {
if (getValueType() == Value.ARRAY) {
return getExpressionColumns(session, (ValueArray) getValue(session));
}
return super.getExpressionColumns(session);
......
......@@ -10,6 +10,7 @@ import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
/**
......@@ -52,7 +53,12 @@ public class Variable extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
return lastValue.getType();
}
@Override
public int getValueType() {
return lastValue.getValueType();
}
......
......@@ -15,6 +15,7 @@ import org.h2.table.Column;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.util.StringUtils;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
/**
......@@ -67,7 +68,12 @@ public class Wildcard extends Expression {
}
@Override
public int getType() {
public TypeInfo getType() {
throw DbException.throwInternalError(toString());
}
@Override
public int getValueType() {
throw DbException.throwInternalError(toString());
}
......
......@@ -35,6 +35,7 @@ import org.h2.util.StatementBuilder;
import org.h2.util.ValueHashMap;
import org.h2.value.CompareMode;
import org.h2.value.DataType;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueBoolean;
......@@ -158,12 +159,13 @@ public class Aggregate extends AbstractAggregate {
private static final HashMap<String, AggregateType> AGGREGATES = new HashMap<>(64);
private final AggregateType type;
private final AggregateType aggregateType;
private Expression on;
private Expression groupConcatSeparator;
private ArrayList<SelectOrderBy> orderByList;
private SortOrder orderBySort;
private TypeInfo type;
private int dataType, scale;
private long precision;
private int displaySize;
......@@ -171,7 +173,7 @@ public class Aggregate extends AbstractAggregate {
/**
* Create a new aggregate object.
*
* @param type
* @param aggregateType
* the aggregate type
* @param on
* the aggregated expression
......@@ -180,12 +182,12 @@ public class Aggregate extends AbstractAggregate {
* @param distinct
* if distinct is used
*/
public Aggregate(AggregateType type, Expression on, Select select, boolean distinct) {
public Aggregate(AggregateType aggregateType, Expression on, Select select, boolean distinct) {
super(select, distinct);
if (distinct && type == AggregateType.COUNT_ALL) {
if (distinct && aggregateType == AggregateType.COUNT_ALL) {
throw DbException.throwInternalError();
}
this.type = type;
this.aggregateType = aggregateType;
this.on = on;
}
......@@ -272,7 +274,7 @@ public class Aggregate extends AbstractAggregate {
* @return the type of this aggregate
*/
public AggregateType getAggregateType() {
return type;
return aggregateType;
}
private void sortWithOrderBy(Value[] array) {
......@@ -297,11 +299,11 @@ public class Aggregate extends AbstractAggregate {
}
private void updateData(Session session, AggregateData data, Value v, Value[] remembered) {
if (type == AggregateType.GROUP_CONCAT) {
if (aggregateType == AggregateType.GROUP_CONCAT) {
if (v != ValueNull.INSTANCE) {
v = updateCollecting(session, v.convertTo(Value.STRING), remembered);
}
} else if (type == AggregateType.ARRAY_AGG) {
} else if (aggregateType == AggregateType.ARRAY_AGG) {
if (v != ValueNull.INSTANCE) {
v = updateCollecting(session, v, remembered);
}
......@@ -379,7 +381,7 @@ public class Aggregate extends AbstractAggregate {
@Override
protected Object createAggregateData() {
return AggregateData.create(type, distinct);
return AggregateData.create(aggregateType, distinct);
}
@Override
......@@ -388,14 +390,14 @@ public class Aggregate extends AbstractAggregate {
}
private Value getValueQuick(Session session) {
switch (type) {
switch (aggregateType) {
case COUNT:
case COUNT_ALL:
Table table = select.getTopTableFilter().getTable();
return ValueLong.get(table.getRowCount(session));
case MIN:
case MAX: {
boolean first = type == AggregateType.MIN;
boolean first = aggregateType == AggregateType.MIN;
Index index = getMinMaxColumnIndex();
int sortType = index.getIndexColumns()[0].sortType;
if ((sortType & SortOrder.DESCENDING) != 0) {
......@@ -416,7 +418,7 @@ public class Aggregate extends AbstractAggregate {
case ENVELOPE:
return ((MVSpatialIndex) AggregateDataEnvelope.getGeometryColumnIndex(on)).getBounds(session);
default:
throw DbException.throwInternalError("type=" + type);
throw DbException.throwInternalError("type=" + aggregateType);
}
}
......@@ -426,7 +428,7 @@ public class Aggregate extends AbstractAggregate {
if (data == null) {
data = (AggregateData) createAggregateData();
}
switch (type) {
switch (aggregateType) {
case COUNT:
if (distinct) {
return ValueLong.get(((AggregateDataCollecting) data).getCount());
......@@ -443,7 +445,7 @@ public class Aggregate extends AbstractAggregate {
if (c.getCount() == 0) {
return ValueNull.INSTANCE;
}
AggregateDataDefault d = new AggregateDataDefault(type);
AggregateDataDefault d = new AggregateDataDefault(aggregateType);
Database db = session.getDatabase();
for (Value v : c) {
d.add(db, dataType, v);
......@@ -579,7 +581,12 @@ public class Aggregate extends AbstractAggregate {
}
@Override
public int getType() {
public TypeInfo getType() {
return type;
}
@Override
public int getValueType() {
return dataType;
}
......@@ -604,7 +611,8 @@ public class Aggregate extends AbstractAggregate {
super.optimize(session);
if (on != null) {
on = on.optimize(session);
dataType = on.getType();
type = on.getType();
dataType = on.getValueType();
scale = on.getScale();
precision = on.getPrecision();
displaySize = on.getDisplaySize();
......@@ -618,26 +626,30 @@ public class Aggregate extends AbstractAggregate {
if (groupConcatSeparator != null) {
groupConcatSeparator = groupConcatSeparator.optimize(session);
}
switch (type) {
switch (aggregateType) {
case GROUP_CONCAT:
type = TypeInfo.TYPE_STRING_DEFAULT;
dataType = Value.STRING;
scale = 0;
precision = displaySize = Integer.MAX_VALUE;
break;
case COUNT_ALL:
case COUNT:
type = TypeInfo.TYPE_LONG;
dataType = Value.LONG;
scale = 0;
precision = ValueLong.PRECISION;
displaySize = ValueLong.DISPLAY_SIZE;
break;
case SELECTIVITY:
type = TypeInfo.TYPE_INT;
dataType = Value.INT;
scale = 0;
precision = ValueInt.PRECISION;
displaySize = ValueInt.DISPLAY_SIZE;
break;
case HISTOGRAM:
type = TypeInfo.TYPE_ARRAY;
dataType = Value.ARRAY;
scale = 0;
precision = displaySize = Integer.MAX_VALUE;
......@@ -645,11 +657,13 @@ public class Aggregate extends AbstractAggregate {
case SUM:
if (dataType == Value.BOOLEAN) {
// example: sum(id > 3) (count the rows)
type = TypeInfo.TYPE_LONG;
dataType = Value.LONG;
} else if (!DataType.supportsAdd(dataType)) {
throw DbException.get(ErrorCode.SUM_OR_AVG_ON_WRONG_DATATYPE_1, getSQL());
} else {
dataType = DataType.getAddProofType(dataType);
type = TypeInfo.getTypeInfo(dataType);
}
break;
case AVG:
......@@ -666,6 +680,7 @@ public class Aggregate extends AbstractAggregate {
case STDDEV_SAMP:
case VAR_POP:
case VAR_SAMP:
type = TypeInfo.TYPE_DOUBLE;
dataType = Value.DOUBLE;
precision = ValueDouble.PRECISION;
displaySize = ValueDouble.DISPLAY_SIZE;
......@@ -673,6 +688,7 @@ public class Aggregate extends AbstractAggregate {
break;
case EVERY:
case ANY:
type = TypeInfo.TYPE_BOOLEAN;
dataType = Value.BOOLEAN;
precision = ValueBoolean.PRECISION;
displaySize = ValueBoolean.DISPLAY_SIZE;
......@@ -685,17 +701,19 @@ public class Aggregate extends AbstractAggregate {
}
break;
case ARRAY_AGG:
type = TypeInfo.TYPE_ARRAY;
dataType = Value.ARRAY;
scale = 0;
precision = displaySize = Integer.MAX_VALUE;
break;
case ENVELOPE:
type = TypeInfo.TYPE_GEOMETRY;
dataType = Value.GEOMETRY;
scale = 0;
precision = displaySize = Integer.MAX_VALUE;
break;
default:
DbException.throwInternalError("type=" + type);
DbException.throwInternalError("type=" + aggregateType);
}
return this;
}
......@@ -760,7 +778,7 @@ public class Aggregate extends AbstractAggregate {
@Override
public StringBuilder getSQL(StringBuilder builder) {
String text;
switch (type) {
switch (aggregateType) {
case GROUP_CONCAT:
return getSQLGroupConcat(builder);
case COUNT_ALL:
......@@ -822,7 +840,7 @@ public class Aggregate extends AbstractAggregate {
text = "ENVELOPE";
break;
default:
throw DbException.throwInternalError("type=" + type);
throw DbException.throwInternalError("type=" + aggregateType);
}
builder.append(text);
if (distinct) {
......@@ -862,7 +880,7 @@ public class Aggregate extends AbstractAggregate {
return false;
}
if (visitor.getType() == ExpressionVisitor.OPTIMIZABLE_AGGREGATE) {
switch (type) {
switch (aggregateType) {
case COUNT:
if (!distinct && on.getNullable() == Column.NOT_NULLABLE) {
return visitor.getTable().canGetRowCount();
......
......@@ -18,6 +18,7 @@ import org.h2.message.DbException;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.DataType;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueBoolean;
......@@ -31,6 +32,7 @@ public class JavaAggregate extends AbstractAggregate {
private final UserAggregate userAggregate;
private final Expression[] args;
private int[] argTypes;
private TypeInfo type;
private int dataType;
private Connection userConnection;
......@@ -76,7 +78,12 @@ public class JavaAggregate extends AbstractAggregate {
}
@Override
public int getType() {
public TypeInfo getType() {
return type;
}
@Override
public int getValueType() {
return dataType;
}
......@@ -122,12 +129,13 @@ public class JavaAggregate extends AbstractAggregate {
for (int i = 0; i < len; i++) {
Expression expr = args[i];
args[i] = expr.optimize(session);
int type = expr.getType();
int type = expr.getValueType();
argTypes[i] = type;
}
try {
Aggregate aggregate = getInstance();
dataType = aggregate.getInternalType(argTypes);
type = TypeInfo.getTypeInfo(dataType);
} catch (SQLException e) {
throw DbException.convert(e);
}
......
......@@ -16,6 +16,7 @@ import org.h2.expression.Expression;
import org.h2.message.DbException;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueDouble;
import org.h2.value.ValueLong;
......@@ -286,7 +287,7 @@ public class WindowFunction extends DataAnalysisOperation {
int rowIdColumn) {
int size = ordered.size();
int numExpressions = getNumExpressions();
int dataType = args[0].getType();
int dataType = args[0].getValueType();
for (int i = 0; i < size; i++) {
Value[] row = ordered.get(i);
int rowId = row[rowIdColumn].getInt();
......@@ -475,7 +476,30 @@ public class WindowFunction extends DataAnalysisOperation {
}
@Override
public int getType() {
public TypeInfo getType() {
switch (type) {
case ROW_NUMBER:
case RANK:
case DENSE_RANK:
case NTILE:
return TypeInfo.TYPE_LONG;
case PERCENT_RANK:
case CUME_DIST:
case RATIO_TO_REPORT:
return TypeInfo.TYPE_DOUBLE;
case LEAD:
case LAG:
case FIRST_VALUE:
case LAST_VALUE:
case NTH_VALUE:
return args[0].getType();
default:
throw DbException.throwInternalError("type=" + type);
}
}
@Override
public int getValueType() {
switch (type) {
case ROW_NUMBER:
case RANK:
......@@ -491,7 +515,7 @@ public class WindowFunction extends DataAnalysisOperation {
case FIRST_VALUE:
case LAST_VALUE:
case NTH_VALUE:
return args[0].getType();
return args[0].getValueType();
default:
throw DbException.throwInternalError("type=" + type);
}
......
......@@ -100,7 +100,7 @@ public class CompareLike extends Condition {
public Expression optimize(Session session) {
left = left.optimize(session);
right = right.optimize(session);
if (left.getType() == Value.STRING_IGNORECASE) {
if (left.getValueType() == Value.STRING_IGNORECASE) {
ignoreCase = true;
}
if (left.isValueSet()) {
......
......@@ -206,7 +206,7 @@ public class Comparison extends Condition {
if (right != null) {
right = right.optimize(session);
// TODO check row values too
if (right.getType() == Value.ARRAY && left.getType() != Value.ARRAY) {
if (right.getValueType() == Value.ARRAY && left.getValueType() != Value.ARRAY) {
throw DbException.get(ErrorCode.COMPARING_ARRAY_TO_SCALAR);
}
if (right instanceof ExpressionColumn) {
......@@ -225,7 +225,7 @@ public class Comparison extends Condition {
return ValueExpression.getNull();
}
}
int colType = left.getType();
int colType = left.getValueType();
int constType = r.getValueType();
int resType = Value.getHigherOrder(colType, constType);
// If not, the column values will need to be promoted
......@@ -516,12 +516,12 @@ public class Comparison extends Condition {
}
if (addIndex) {
if (l != null) {
if (l.getType() == right.getType() || right.getType() != Value.STRING_IGNORECASE) {
if (l.getValueType() == right.getValueType() || right.getValueType() != Value.STRING_IGNORECASE) {
filter.addIndexCondition(
IndexCondition.get(compareType, l, right));
}
} else if (r != null) {
if (r.getType() == left.getType() || left.getType() != Value.STRING_IGNORECASE) {
if (r.getValueType() == left.getValueType() || left.getValueType() != Value.STRING_IGNORECASE) {
int compareRev = getReversedCompareType(compareType);
filter.addIndexCondition(
IndexCondition.get(compareRev, r, left));
......
......@@ -6,6 +6,7 @@
package org.h2.expression.condition;
import org.h2.expression.Expression;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueBoolean;
......@@ -15,7 +16,12 @@ import org.h2.value.ValueBoolean;
abstract class Condition extends Expression {
@Override
public int getType() {
public TypeInfo getType() {
return TypeInfo.TYPE_BOOLEAN;
}
@Override
public int getValueType() {
return Value.BOOLEAN;
}
......
......@@ -150,7 +150,7 @@ public class ConditionIn extends Condition {
return new Comparison(session, Comparison.EQUAL, left, values.get(0)).optimize(session);
}
if (allValuesConstant && !allValuesNull) {
int leftType = left.getType();
int leftType = left.getValueType();
if (leftType == Value.UNKNOWN) {
return this;
}
......
......@@ -54,7 +54,7 @@ public class ConditionInConstantSet extends Condition {
this.valueList = valueList;
Database database = session.getDatabase();
this.valueSet = new TreeSet<>(database.getCompareMode());
type = left.getType();
type = left.getValueType();
Mode mode = database.getMode();
if (type == Value.ENUM) {
extTypeInfo = ((ExpressionColumn) left).getColumn().getType().getExtTypeInfo();
......
......@@ -36,7 +36,7 @@ public interface FunctionCall {
*
* @return the data type
*/
int getType();
int getValueType();
/**
* Optimize the function if possible.
......
......@@ -15,6 +15,7 @@ import org.h2.expression.ValueExpression;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.DataType;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueNull;
......@@ -41,7 +42,12 @@ public class JavaFunction extends Expression implements FunctionCall {
}
@Override
public int getType() {
public TypeInfo getType() {
return TypeInfo.getTypeInfo(javaMethod.getDataType());
}
@Override
public int getValueType() {
return javaMethod.getDataType();
}
......@@ -77,7 +83,7 @@ public class JavaFunction extends Expression implements FunctionCall {
@Override
public int getScale() {
return DataType.getDataType(getType()).defaultScale;
return DataType.getDataType(getValueType()).defaultScale;
}
@Override
......@@ -166,7 +172,7 @@ public class JavaFunction extends Expression implements FunctionCall {
@Override
public Expression[] getExpressionColumns(Session session) {
switch (getType()) {
switch (getValueType()) {
case Value.RESULT_SET:
ValueResultSet rs = getValueForColumnList(session, getArgs());
return getExpressionColumns(session, rs.getResult());
......
......@@ -81,7 +81,7 @@ public class JdbcParameterMetaData extends TraceObject implements
try {
debugCodeCall("getParameterType", param);
ParameterInterface p = getParameter(param);
int type = p.getType();
int type = p.getValueType();
if (type == Value.UNKNOWN) {
type = Value.STRING;
}
......@@ -174,7 +174,7 @@ public class JdbcParameterMetaData extends TraceObject implements
try {
debugCodeCall("getParameterClassName", param);
ParameterInterface p = getParameter(param);
int type = p.getType();
int type = p.getValueType();
if (type == Value.UNKNOWN) {
type = Value.STRING;
}
......@@ -196,7 +196,7 @@ public class JdbcParameterMetaData extends TraceObject implements
try {
debugCodeCall("getParameterTypeName", param);
ParameterInterface p = getParameter(param);
int type = p.getType();
int type = p.getValueType();
if (type == Value.UNKNOWN) {
type = Value.STRING;
}
......
......@@ -19,7 +19,7 @@ import org.h2.expression.function.Function;
import org.h2.expression.function.FunctionInfo;
import org.h2.message.DbException;
import org.h2.util.StringUtils;
import org.h2.value.DataType;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueNull;
......@@ -203,10 +203,7 @@ public class FunctionsMySQL extends FunctionsBase {
return ValueExpression.get(getValue(session));
}
dataType = info.returnDataType;
DataType dt = DataType.getDataType(dataType);
precision = dt.defaultPrecision;
scale = dt.defaultScale;
displaySize = dt.defaultDisplaySize;
type = TypeInfo.getTypeInfo(dataType);
return this;
}
......
......@@ -140,7 +140,7 @@ public abstract class LazyResult implements ResultInterface {
@Override
public int getColumnType(int i) {
return expressions[i].getType();
return expressions[i].getValueType();
}
@Override
......
......@@ -539,7 +539,7 @@ public class LocalResultImpl implements LocalResult {
@Override
public int getColumnType(int i) {
return expressions[i].getType();
return expressions[i].getValueType();
}
@Override
......
......@@ -117,7 +117,7 @@ public class ResultTempTable implements ResultExternal {
CreateTableData data = new CreateTableData();
boolean containsLob = false;
for (int i = 0; i < expressions.length; i++) {
int type = expressions[i].getType();
int type = expressions[i].getValueType();
Column col = new Column(COLUMN_NAME + i, type);
if (DataType.isLargeObject(type)) {
containsLob = true;
......
......@@ -45,7 +45,7 @@ public class FunctionTable extends Table {
rowCount = Long.MAX_VALUE;
}
function.optimize(session);
int type = function.getType();
int type = function.getValueType();
if (type != Value.RESULT_SET) {
throw DbException.get(
ErrorCode.FUNCTION_MUST_RETURN_RESULT_SET_1, function.getName());
......
......@@ -1762,7 +1762,7 @@ public class MetaTable extends Table {
// CONSTANT_NAME
identifier(constant.getName()),
// DATA_TYPE
ValueInt.get(DataType.convertTypeToSQLType(expr.getType())),
ValueInt.get(DataType.convertTypeToSQLType(expr.getValueType())),
// REMARKS
replaceNullWithEmpty(constant.getComment()),
// SQL
......
......@@ -191,7 +191,7 @@ public class TableView extends Table {
}
name = columnNamer.getColumnName(expr, i, name);
if (type == Value.UNKNOWN) {
type = expr.getType();
type = expr.getValueType();
}
long precision = expr.getPrecision();
int scale = expr.getScale();
......@@ -818,7 +818,7 @@ public class TableView extends Table {
// expression
String columnName = columnNamer.getColumnName(columnExp, i, cols);
columnTemplateList.add(new Column(columnName,
columnExp.getType()));
columnExp.getValueType()));
}
return columnTemplateList;
......
......@@ -377,6 +377,7 @@ public class DataType {
32
);
dataType = new DataType();
dataType.maxPrecision = dataType.defaultPrecision = dataType.defaultDisplaySize = Integer.MAX_VALUE;
add(Value.RESULT_SET, DataType.TYPE_RESULT_SET,
dataType,
new String[]{"RESULT_SET"},
......
......@@ -8,12 +8,18 @@ package org.h2.value;
import org.h2.api.ErrorCode;
import org.h2.message.DbException;
import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils;
/**
* Data type with parameters.
*/
public class TypeInfo {
/**
* UNKNOWN type with parameters.
*/
public static final TypeInfo TYPE_UNKNOWN;
/**
* NULL type with parameters.
*/
......@@ -44,6 +50,11 @@ public class TypeInfo {
*/
public static final TypeInfo TYPE_LONG;
/**
* DECIMAL type with default parameters.
*/
public static final TypeInfo TYPE_DECIMAL_DEFAULT;
/**
* DOUBLE type with parameters.
*/
......@@ -69,6 +80,11 @@ public class TypeInfo {
*/
public static final TypeInfo TYPE_TIMESTAMP;
/**
* STRING type with default parameters.
*/
public static final TypeInfo TYPE_STRING_DEFAULT;
/**
* ARRAY type with parameters.
*/
......@@ -104,6 +120,21 @@ public class TypeInfo {
*/
public static final TypeInfo TYPE_ENUM_UNDEFINED;
/**
* INTERVAL DAY type with parameters.
*/
public static final TypeInfo TYPE_INTERVAL_DAY;
/**
* INTERVAL DAY TO SECOND type with parameters.
*/
public static final TypeInfo TYPE_INTERVAL_DAY_TO_SECOND;
/**
* INTERVAL HOUR TO SECOND type with parameters.
*/
public static final TypeInfo TYPE_INTERVAL_HOUR_TO_SECOND;
/**
* ROW (row value) type with parameters.
*/
......@@ -131,17 +162,20 @@ public class TypeInfo {
infos[i] = createTypeInfo(i, dt);
}
}
TYPE_UNKNOWN = new TypeInfo(Value.UNKNOWN, -1L, -1, -1, null);
TYPE_NULL = infos[Value.NULL];
TYPE_BOOLEAN = infos[Value.BOOLEAN];
TYPE_BYTE = infos[Value.BYTE];
TYPE_SHORT = infos[Value.SHORT];
TYPE_INT = infos[Value.INT];
TYPE_LONG = infos[Value.LONG];
TYPE_DECIMAL_DEFAULT = infos[Value.DECIMAL];
TYPE_DOUBLE = infos[Value.DOUBLE];
TYPE_FLOAT = infos[Value.FLOAT];
TYPE_TIME = infos[Value.TIME];
TYPE_DATE = infos[Value.DATE];
TYPE_TIMESTAMP = infos[Value.TIMESTAMP];
TYPE_STRING_DEFAULT = infos[Value.STRING];
TYPE_ARRAY = infos[Value.ARRAY];
TYPE_RESULT_SET = infos[Value.RESULT_SET];
TYPE_JAVA_OBJECT = infos[Value.JAVA_OBJECT];
......@@ -149,6 +183,9 @@ public class TypeInfo {
TYPE_GEOMETRY = infos[Value.GEOMETRY];
TYPE_TIMESTAMP_TZ = infos[Value.TIMESTAMP_TZ];
TYPE_ENUM_UNDEFINED = infos[Value.ENUM];
TYPE_INTERVAL_DAY = infos[Value.INTERVAL_DAY];
TYPE_INTERVAL_DAY_TO_SECOND = infos[Value.INTERVAL_DAY_TO_SECOND];
TYPE_INTERVAL_HOUR_TO_SECOND = infos[Value.INTERVAL_HOUR_TO_SECOND];
TYPE_ROW = infos[Value.ROW];
TYPE_INFOS_BY_VALUE_TYPE = infos;
}
......@@ -157,7 +194,8 @@ public class TypeInfo {
* Get the data type with parameters object for the given value type and
* maximum parameters.
*
* @param type the value type
* @param type
* the value type
* @return the data type with parameters object
*/
public static TypeInfo getTypeInfo(int type) {
......@@ -165,7 +203,7 @@ public class TypeInfo {
throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "?");
}
if (type >= Value.NULL && type < Value.TYPE_COUNT) {
TypeInfo t = TypeInfo.TYPE_INFOS_BY_VALUE_TYPE[type];
TypeInfo t = TYPE_INFOS_BY_VALUE_TYPE[type];
if (t != null) {
return t;
}
......@@ -176,7 +214,126 @@ public class TypeInfo {
return createTypeInfo(type, dt);
}
}
return TypeInfo.TYPE_INFOS_BY_VALUE_TYPE[Value.NULL];
return TYPE_NULL;
}
/**
* Get the data type with parameters object for the given value type and the
* specified parameters.
*
* @param type
* the value type
* @param precision
* the precision
* @param scale
* the scale
* @param displaySize
* the display size in characters
* @param extTypeInfo
* the extended type information, or null
* @return the data type with parameters object
*/
public static TypeInfo getTypeInfo(int type, long precision, int scale, int displaySize, ExtTypeInfo extTypeInfo) {
switch (type) {
case Value.NULL:
case Value.BOOLEAN:
case Value.BYTE:
case Value.SHORT:
case Value.INT:
case Value.DOUBLE:
case Value.FLOAT:
case Value.DATE:
case Value.ARRAY:
case Value.RESULT_SET:
case Value.JAVA_OBJECT:
case Value.UUID:
case Value.ROW:
return TYPE_INFOS_BY_VALUE_TYPE[type];
case Value.UNKNOWN:
return TYPE_UNKNOWN;
case Value.DECIMAL:
if (precision < 0) {
precision = ValueDecimal.DEFAULT_PRECISION;
}
if (scale < 0) {
scale = ValueDecimal.DEFAULT_SCALE;
}
return new TypeInfo(Value.DECIMAL, precision, scale, MathUtils.convertLongToInt(precision + 2), null);
case Value.TIME:
if (scale < 0 || scale >= ValueTime.MAXIMUM_SCALE) {
return TYPE_TIME;
}
return new TypeInfo(Value.TIME, ValueTime.MAXIMUM_PRECISION, scale, ValueTime.DEFAULT_PRECISION, null);
case Value.TIMESTAMP:
if (scale < 0 || scale >= ValueTimestamp.MAXIMUM_SCALE) {
return TYPE_TIMESTAMP;
}
return new TypeInfo(Value.TIMESTAMP, ValueTimestamp.MAXIMUM_PRECISION, scale,
ValueTimestamp.MAXIMUM_PRECISION, null);
case Value.TIMESTAMP_TZ:
if (scale < 0 || scale >= ValueTimestampTimeZone.MAXIMUM_SCALE) {
return TYPE_TIMESTAMP_TZ;
}
return new TypeInfo(Value.TIMESTAMP_TZ, ValueTimestampTimeZone.MAXIMUM_PRECISION, scale,
ValueTimestampTimeZone.MAXIMUM_PRECISION, null);
case Value.BYTES:
if (precision < 0) {
precision = Integer.MAX_VALUE;
}
return new TypeInfo(Value.BYTES, precision, scale, MathUtils.convertLongToInt(precision) * 2, null);
case Value.STRING:
if (precision < 0) {
return TYPE_STRING_DEFAULT;
}
//$FALL-THROUGH$
case Value.STRING_FIXED:
case Value.STRING_IGNORECASE:
case Value.BLOB:
case Value.CLOB:
return new TypeInfo(type, precision, 0, MathUtils.convertLongToInt(precision), null);
case Value.GEOMETRY:
if (extTypeInfo == null) {
return TYPE_GEOMETRY;
}
return new TypeInfo(Value.GEOMETRY, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, extTypeInfo);
case Value.ENUM:
if (extTypeInfo == null) {
return TYPE_ENUM_UNDEFINED;
}
return new TypeInfo(Value.ENUM, ValueEnum.PRECISION, 0, ValueEnum.DISPLAY_SIZE, extTypeInfo);
case Value.INTERVAL_YEAR:
case Value.INTERVAL_MONTH:
case Value.INTERVAL_DAY:
case Value.INTERVAL_HOUR:
case Value.INTERVAL_MINUTE:
case Value.INTERVAL_YEAR_TO_MONTH:
case Value.INTERVAL_DAY_TO_HOUR:
case Value.INTERVAL_DAY_TO_MINUTE:
case Value.INTERVAL_HOUR_TO_MINUTE:
if (precision < 0 || precision > ValueInterval.MAXIMUM_PRECISION) {
precision = ValueInterval.MAXIMUM_PRECISION;
}
return new TypeInfo(type, precision, 0, ValueInterval.getDisplaySize(type, (int) precision, 0), null);
case Value.INTERVAL_SECOND:
case Value.INTERVAL_DAY_TO_SECOND:
case Value.INTERVAL_HOUR_TO_SECOND:
case Value.INTERVAL_MINUTE_TO_SECOND:
if (precision < 0 || precision > ValueInterval.MAXIMUM_PRECISION) {
precision = ValueInterval.MAXIMUM_PRECISION;
}
if (scale < 0 || scale > ValueInterval.MAXIMUM_SCALE) {
scale = ValueInterval.MAXIMUM_SCALE;
}
return new TypeInfo(type, precision, scale, ValueInterval.getDisplaySize(type, (int) precision, scale),
null);
}
if (JdbcUtils.customDataTypesHandler != null) {
DataType dt = JdbcUtils.customDataTypesHandler.getDataTypeById(type);
if (dt != null) {
return createTypeInfo(type, dt);
}
}
return TYPE_NULL;
}
private static TypeInfo createTypeInfo(int valueType, DataType dataType) {
......
......@@ -61,11 +61,6 @@ public class ValueArray extends ValueCollectionBase {
return (ValueArray) EMPTY;
}
@Override
public TypeInfo getType() {
return TypeInfo.TYPE_ARRAY;
}
@Override
public int getValueType() {
return ARRAY;
......
......@@ -47,11 +47,6 @@ public class ValueRow extends ValueCollectionBase {
return (ValueRow) EMPTY;
}
@Override
public TypeInfo getType() {
return TypeInfo.TYPE_ROW;
}
@Override
public int getValueType() {
return ROW;
......
......@@ -143,7 +143,7 @@ public class TestDate extends TestBase {
assertEquals((int) ((nanos >>> 32) ^ nanos), t1.hashCode());
// Literals return maximum precision
TypeInfo type = t1.getType();
assertEquals(ValueTime.MAXIMUM_PRECISION, type.getDisplaySize());
assertEquals(ValueTime.DEFAULT_PRECISION, type.getDisplaySize());
assertEquals(ValueTime.MAXIMUM_PRECISION, type.getPrecision());
assertEquals("java.sql.Time", t1.getObject().getClass().getName());
ValueTime t1b = ValueTime.parse("11:11:11");
......@@ -221,7 +221,7 @@ public class TestDate extends TestBase {
t1.hashCode());
// Literals return maximum precision
TypeInfo type = t1.getType();
assertEquals(ValueTimestamp.MAXIMUM_PRECISION, type.getDisplaySize());
assertEquals(ValueTimestamp.DEFAULT_PRECISION, type.getDisplaySize());
assertEquals(ValueTimestamp.MAXIMUM_PRECISION, type.getPrecision());
assertEquals(9, type.getScale());
assertEquals("java.sql.Timestamp", t1.getObject().getClass().getName());
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论