private void generateColumnsFromQuery() { int columnCount = asQuery.getColumnCount(); ArrayList<Expression> expressions = asQuery.getExpressions(); for (int i = 0; i < columnCount; i++) { Expression expr = expressions.get(i); int type = expr.getType(); String name = expr.getAlias(); long precision = expr.getPrecision(); int displaySize = expr.getDisplaySize(); DataType dt = DataType.getDataType(type); if (precision > 0 && (dt.defaultPrecision == 0 || (dt.defaultPrecision > precision && dt.defaultPrecision < Byte.MAX_VALUE))) { // dont' set precision to MAX_VALUE if this is the default precision = dt.defaultPrecision; } int scale = expr.getScale(); if (scale > 0 && (dt.defaultScale == 0 || (dt.defaultScale > scale && dt.defaultScale < precision))) { scale = dt.defaultScale; } if (scale > precision) { precision = scale; } Column col = new Column(name, type, precision, scale, displaySize); addColumn(col); } }
private void testResultSetOperation(Object obj) throws SQLException { SimpleResultSet rs = new SimpleResultSet(); rs.setAutoClose(false); int valueType = DataType.getTypeFromClass(obj.getClass()); int sqlType = DataType.convertTypeToSQLType(valueType); rs.addColumn("X", sqlType, 10, 0); rs.addRow(new Object[] {obj}); rs.next(); Value v = DataType.readValue(null, rs, 1, valueType); Value v2 = DataType.convertToValue(null, obj, valueType); if (v.getType() == Value.RESULT_SET) { assertEquals(v.toString(), v2.toString()); } else { assertTrue(v.equals(v2)); } }
private void testResultSetOperations() throws SQLException { SimpleResultSet rs = new SimpleResultSet(); rs.setAutoClose(false); rs.addColumn("X", Types.INTEGER, 10, 0); rs.addRow(new Object[] {null}); rs.next(); for (int type = Value.NULL; type < Value.TYPE_COUNT; type++) { Value v = DataType.readValue(null, rs, 1, type); assertTrue(v == ValueNull.INSTANCE); } testResultSetOperation(new byte[0]); testResultSetOperation(1); testResultSetOperation(Boolean.TRUE); testResultSetOperation((byte) 1); testResultSetOperation((short) 2); testResultSetOperation((long) 3); testResultSetOperation(4.0f); testResultSetOperation(5.0d); testResultSetOperation(new Date(6)); testResultSetOperation(new Time(7)); testResultSetOperation(new Timestamp(8)); testResultSetOperation(new BigDecimal("9")); SimpleResultSet rs2 = new SimpleResultSet(); rs2.setAutoClose(false); rs2.addColumn("X", Types.INTEGER, 10, 0); rs2.addRow(new Object[] {1}); rs2.next(); testResultSetOperation(rs2); }
/** * Returns the parameter type. java.sql.Types.VARCHAR is returned if the data type is not known. * * @param param the column index (1,2,...) * @return the data type */ public int getParameterType(int param) throws SQLException { try { debugCodeCall("getParameterType", param); ParameterInterface p = getParameter(param); int type = p.getType(); if (type == Value.UNKNOWN) { type = Value.STRING; } return DataType.getDataType(type).sqlType; } catch (Exception e) { throw logAndConvert(e); } }
/** * Returns the Java class name of the parameter. "java.lang.String" is returned if the type is not * known. * * @param param the column index (1,2,...) * @return the Java class name */ @Override public String getParameterClassName(int param) throws SQLException { try { debugCodeCall("getParameterClassName", param); ParameterInterface p = getParameter(param); int type = p.getType(); if (type == Value.UNKNOWN) { type = Value.STRING; } return DataType.getTypeClassName(type); } catch (Exception e) { throw logAndConvert(e); } }
@Override public Value getValue(Session session) { HashMap<Expression, Object> group = select.getCurrentGroup(); if (group == null) { throw DbException.get(ErrorCode.INVALID_USE_OF_AGGREGATE_FUNCTION_1, getSQL()); } try { Aggregate agg = (Aggregate) group.get(this); if (agg == null) { agg = getInstance(); } Object obj = agg.getResult(); if (obj == null) { return ValueNull.INSTANCE; } return DataType.convertToValue(session, obj, dataType); } catch (SQLException e) { throw DbException.convert(e); } }
JavaMethod(Method method, int id) throws SQLException { this.method = method; this.id = id; Class<?>[] paramClasses = method.getParameterTypes(); paramCount = paramClasses.length; if (paramCount > 0) { Class<?> paramClass = paramClasses[0]; if (Connection.class.isAssignableFrom(paramClass)) { hasConnectionParam = true; paramCount--; } } if (paramCount > 0) { Class<?> lastArg = paramClasses[paramClasses.length - 1]; if (lastArg.isArray() && ClassUtils.isVarArgs(method)) { varArgs = true; varArgClass = lastArg.getComponentType(); } } Class<?> returnClass = method.getReturnType(); dataType = DataType.getTypeFromClass(returnClass); }
/** * Call the user-defined function and return the value. * * @param session the session * @param args the argument list * @param columnList true if the function should only return the column list * @return the value */ public Value getValue(Session session, Expression[] args, boolean columnList) throws SQLException { Class<?>[] paramClasses = method.getParameterTypes(); Object[] params = new Object[paramClasses.length]; int p = 0; if (hasConnectionParam && params.length > 0) { params[p++] = session.createConnection(columnList); } // allocate array for varArgs parameters Object varArg = null; if (varArgs) { int len = args.length - params.length + 1 + (hasConnectionParam ? 1 : 0); varArg = Array.newInstance(varArgClass, len); params[params.length - 1] = varArg; } for (int a = 0; a < args.length; a++, p++) { boolean currentIsVarArg = varArgs && p >= paramClasses.length - 1; Class<?> paramClass; if (currentIsVarArg) { paramClass = varArgClass; } else { paramClass = paramClasses[p]; } int type = DataType.getTypeFromClass(paramClass); Value v = args[a].getValue(session); v = v.convertTo(type); Object o = v.getObject(); if (o == null) { if (paramClass.isPrimitive()) { if (columnList) { // if the column list is requested, the parameters may // be null // need to set to default value otherwise the function // can't be called at all o = DataType.getDefaultForPrimitiveType(paramClass); } else { // NULL for a java primitive: return NULL return ValueNull.INSTANCE; } } } else { if (!paramClass.isAssignableFrom(o.getClass()) && !paramClass.isPrimitive()) { o = DataType.convertTo(session, session.createConnection(false), v, paramClass); } } if (currentIsVarArg) { Array.set(varArg, p - params.length + 1, o); } else { params[p] = o; } } boolean old = session.getAutoCommit(); Value identity = session.getScopeIdentity(); try { session.setAutoCommit(false); try { Object returnValue; returnValue = method.invoke(null, params); if (returnValue == null) { return ValueNull.INSTANCE; } Value ret = DataType.convertToValue(session, returnValue, dataType); return ret.convertTo(dataType); } catch (Exception e) { throw Message.convert(e); } } finally { session.setScopeIdentity(identity); session.setAutoCommit(old); } }
@Override public int getScale() { return DataType.getDataType(dataType).defaultScale; }
public int getScale() { return DataType.getDataType(getType()).defaultScale; }
/** * Calculate the number of bytes required to encode the given value. * * @param v the value * @param handler the data handler for lobs * @return the number of bytes required to store this value */ public static int getValueLen(Value v, DataHandler handler) { if (v == ValueNull.INSTANCE) { return 1; } switch (v.getType()) { case Value.BOOLEAN: return 1; case Value.BYTE: return 2; case Value.SHORT: return 3; case Value.INT: { int x = v.getInt(); if (x < 0) { return 1 + getVarIntLen(-x); } else if (x < 16) { return 1; } else { return 1 + getVarIntLen(x); } } case Value.LONG: { long x = v.getLong(); if (x < 0) { return 1 + getVarLongLen(-x); } else if (x < 8) { return 1; } else { return 1 + getVarLongLen(x); } } case Value.DOUBLE: { double x = v.getDouble(); if (x == 1.0d) { return 1; } long d = Double.doubleToLongBits(x); if (d == ValueDouble.ZERO_BITS) { return 1; } return 1 + getVarLongLen(Long.reverse(d)); } case Value.FLOAT: { float x = v.getFloat(); if (x == 1.0f) { return 1; } int f = Float.floatToIntBits(x); if (f == ValueFloat.ZERO_BITS) { return 1; } return 1 + getVarIntLen(Integer.reverse(f)); } case Value.STRING: { String s = v.getString(); int len = s.length(); if (len < 32) { return 1 + getStringWithoutLengthLen(s, len); } return 1 + getStringLen(s); } case Value.STRING_IGNORECASE: case Value.STRING_FIXED: return 1 + getStringLen(v.getString()); case Value.DECIMAL: { BigDecimal x = v.getBigDecimal(); if (BigDecimal.ZERO.equals(x)) { return 1; } else if (BigDecimal.ONE.equals(x)) { return 1; } int scale = x.scale(); BigInteger b = x.unscaledValue(); int bits = b.bitLength(); if (bits <= 63) { if (scale == 0) { return 1 + getVarLongLen(b.longValue()); } return 1 + getVarIntLen(scale) + getVarLongLen(b.longValue()); } byte[] bytes = b.toByteArray(); return 1 + getVarIntLen(scale) + getVarIntLen(bytes.length) + bytes.length; } case Value.TIME: if (SysProperties.STORE_LOCAL_TIME) { long nanos = ((ValueTime) v).getNanos(); long millis = nanos / 1000000; nanos -= millis * 1000000; return 1 + getVarLongLen(millis) + getVarLongLen(nanos); } return 1 + getVarLongLen(DateTimeUtils.getTimeLocalWithoutDst(v.getTime())); case Value.DATE: { if (SysProperties.STORE_LOCAL_TIME) { long dateValue = ((ValueDate) v).getDateValue(); return 1 + getVarLongLen(dateValue); } long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate()); return 1 + getVarLongLen(x / MILLIS_PER_MINUTE); } case Value.TIMESTAMP: { if (SysProperties.STORE_LOCAL_TIME) { ValueTimestamp ts = (ValueTimestamp) v; long dateValue = ts.getDateValue(); long nanos = ts.getNanos(); long millis = nanos / 1000000; nanos -= millis * 1000000; return 1 + getVarLongLen(dateValue) + getVarLongLen(millis) + getVarLongLen(nanos); } Timestamp ts = v.getTimestamp(); return 1 + getVarLongLen(DateTimeUtils.getTimeLocalWithoutDst(ts)) + getVarIntLen(ts.getNanos()); } case Value.GEOMETRY: case Value.JAVA_OBJECT: { byte[] b = v.getBytesNoCopy(); return 1 + getVarIntLen(b.length) + b.length; } case Value.BYTES: { byte[] b = v.getBytesNoCopy(); int len = b.length; if (len < 32) { return 1 + b.length; } return 1 + getVarIntLen(b.length) + b.length; } case Value.UUID: return 1 + LENGTH_LONG + LENGTH_LONG; case Value.BLOB: case Value.CLOB: { int len = 1; if (v instanceof ValueLob) { ValueLob lob = (ValueLob) v; lob.convertToFileIfRequired(handler); byte[] small = lob.getSmall(); if (small == null) { int t = -1; if (!lob.isLinked()) { t = -2; } len += getVarIntLen(t); len += getVarIntLen(lob.getTableId()); len += getVarIntLen(lob.getObjectId()); len += getVarLongLen(lob.getPrecision()); len += 1; if (t == -2) { len += getStringLen(lob.getFileName()); } } else { len += getVarIntLen(small.length); len += small.length; } } else { ValueLobDb lob = (ValueLobDb) v; byte[] small = lob.getSmall(); if (small == null) { len += getVarIntLen(-3); len += getVarIntLen(lob.getTableId()); len += getVarLongLen(lob.getLobId()); len += getVarLongLen(lob.getPrecision()); } else { len += getVarIntLen(small.length); len += small.length; } } return len; } case Value.ARRAY: { Value[] list = ((ValueArray) v).getList(); int len = 1 + getVarIntLen(list.length); for (Value x : list) { len += getValueLen(x, handler); } return len; } case Value.RESULT_SET: { int len = 1; try { ResultSet rs = ((ValueResultSet) v).getResultSet(); rs.beforeFirst(); ResultSetMetaData meta = rs.getMetaData(); int columnCount = meta.getColumnCount(); len += getVarIntLen(columnCount); for (int i = 0; i < columnCount; i++) { len += getStringLen(meta.getColumnName(i + 1)); len += getVarIntLen(meta.getColumnType(i + 1)); len += getVarIntLen(meta.getPrecision(i + 1)); len += getVarIntLen(meta.getScale(i + 1)); } while (rs.next()) { len++; for (int i = 0; i < columnCount; i++) { int t = DataType.getValueTypeFromResultSet(meta, i + 1); Value val = DataType.readValue(null, rs, i + 1, t); len += getValueLen(val, handler); } } len++; rs.beforeFirst(); } catch (SQLException e) { throw DbException.convert(e); } return len; } default: throw DbException.throwInternalError("type=" + v.getType()); } }
/** * Append a value. * * @param v the value */ public void writeValue(Value v) { int start = pos; if (v == ValueNull.INSTANCE) { data[pos++] = 0; return; } int type = v.getType(); switch (type) { case Value.BOOLEAN: writeByte((byte) (v.getBoolean().booleanValue() ? BOOLEAN_TRUE : BOOLEAN_FALSE)); break; case Value.BYTE: writeByte((byte) type); writeByte(v.getByte()); break; case Value.SHORT: writeByte((byte) type); writeShortInt(v.getShort()); break; case Value.INT: { int x = v.getInt(); if (x < 0) { writeByte((byte) INT_NEG); writeVarInt(-x); } else if (x < 16) { writeByte((byte) (INT_0_15 + x)); } else { writeByte((byte) type); writeVarInt(x); } break; } case Value.LONG: { long x = v.getLong(); if (x < 0) { writeByte((byte) LONG_NEG); writeVarLong(-x); } else if (x < 8) { writeByte((byte) (LONG_0_7 + x)); } else { writeByte((byte) type); writeVarLong(x); } break; } case Value.DECIMAL: { BigDecimal x = v.getBigDecimal(); if (BigDecimal.ZERO.equals(x)) { writeByte((byte) DECIMAL_0_1); } else if (BigDecimal.ONE.equals(x)) { writeByte((byte) (DECIMAL_0_1 + 1)); } else { int scale = x.scale(); BigInteger b = x.unscaledValue(); int bits = b.bitLength(); if (bits <= 63) { if (scale == 0) { writeByte((byte) DECIMAL_SMALL_0); writeVarLong(b.longValue()); } else { writeByte((byte) DECIMAL_SMALL); writeVarInt(scale); writeVarLong(b.longValue()); } } else { writeByte((byte) type); writeVarInt(scale); byte[] bytes = b.toByteArray(); writeVarInt(bytes.length); write(bytes, 0, bytes.length); } } break; } case Value.TIME: if (SysProperties.STORE_LOCAL_TIME) { writeByte((byte) LOCAL_TIME); ValueTime t = (ValueTime) v; long nanos = t.getNanos(); long millis = nanos / 1000000; nanos -= millis * 1000000; writeVarLong(millis); writeVarLong(nanos); } else { writeByte((byte) type); writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(v.getTime())); } break; case Value.DATE: { if (SysProperties.STORE_LOCAL_TIME) { writeByte((byte) LOCAL_DATE); long x = ((ValueDate) v).getDateValue(); writeVarLong(x); } else { writeByte((byte) type); long x = DateTimeUtils.getTimeLocalWithoutDst(v.getDate()); writeVarLong(x / MILLIS_PER_MINUTE); } break; } case Value.TIMESTAMP: { if (SysProperties.STORE_LOCAL_TIME) { writeByte((byte) LOCAL_TIMESTAMP); ValueTimestamp ts = (ValueTimestamp) v; long dateValue = ts.getDateValue(); writeVarLong(dateValue); long nanos = ts.getNanos(); long millis = nanos / 1000000; nanos -= millis * 1000000; writeVarLong(millis); writeVarLong(nanos); } else { Timestamp ts = v.getTimestamp(); writeByte((byte) type); writeVarLong(DateTimeUtils.getTimeLocalWithoutDst(ts)); writeVarInt(ts.getNanos()); } break; } case Value.GEOMETRY: case Value.JAVA_OBJECT: { writeByte((byte) type); byte[] b = v.getBytesNoCopy(); int len = b.length; writeVarInt(len); write(b, 0, len); break; } case Value.BYTES: { byte[] b = v.getBytesNoCopy(); int len = b.length; if (len < 32) { writeByte((byte) (BYTES_0_31 + len)); write(b, 0, len); } else { writeByte((byte) type); writeVarInt(len); write(b, 0, len); } break; } case Value.UUID: { writeByte((byte) type); ValueUuid uuid = (ValueUuid) v; writeLong(uuid.getHigh()); writeLong(uuid.getLow()); break; } case Value.STRING: { String s = v.getString(); int len = s.length(); if (len < 32) { writeByte((byte) (STRING_0_31 + len)); writeStringWithoutLength(s, len); } else { writeByte((byte) type); writeString(s); } break; } case Value.STRING_IGNORECASE: case Value.STRING_FIXED: writeByte((byte) type); writeString(v.getString()); break; case Value.DOUBLE: { double x = v.getDouble(); if (x == 1.0d) { writeByte((byte) (DOUBLE_0_1 + 1)); } else { long d = Double.doubleToLongBits(x); if (d == ValueDouble.ZERO_BITS) { writeByte((byte) DOUBLE_0_1); } else { writeByte((byte) type); writeVarLong(Long.reverse(d)); } } break; } case Value.FLOAT: { float x = v.getFloat(); if (x == 1.0f) { writeByte((byte) (FLOAT_0_1 + 1)); } else { int f = Float.floatToIntBits(x); if (f == ValueFloat.ZERO_BITS) { writeByte((byte) FLOAT_0_1); } else { writeByte((byte) type); writeVarInt(Integer.reverse(f)); } } break; } case Value.BLOB: case Value.CLOB: { writeByte((byte) type); if (v instanceof ValueLob) { ValueLob lob = (ValueLob) v; lob.convertToFileIfRequired(handler); byte[] small = lob.getSmall(); if (small == null) { int t = -1; if (!lob.isLinked()) { t = -2; } writeVarInt(t); writeVarInt(lob.getTableId()); writeVarInt(lob.getObjectId()); writeVarLong(lob.getPrecision()); writeByte((byte) (lob.isCompressed() ? 1 : 0)); if (t == -2) { writeString(lob.getFileName()); } } else { writeVarInt(small.length); write(small, 0, small.length); } } else { ValueLobDb lob = (ValueLobDb) v; byte[] small = lob.getSmall(); if (small == null) { writeVarInt(-3); writeVarInt(lob.getTableId()); writeVarLong(lob.getLobId()); writeVarLong(lob.getPrecision()); } else { writeVarInt(small.length); write(small, 0, small.length); } } break; } case Value.ARRAY: { writeByte((byte) type); Value[] list = ((ValueArray) v).getList(); writeVarInt(list.length); for (Value x : list) { writeValue(x); } break; } case Value.RESULT_SET: { writeByte((byte) type); try { ResultSet rs = ((ValueResultSet) v).getResultSet(); rs.beforeFirst(); ResultSetMetaData meta = rs.getMetaData(); int columnCount = meta.getColumnCount(); writeVarInt(columnCount); for (int i = 0; i < columnCount; i++) { writeString(meta.getColumnName(i + 1)); writeVarInt(meta.getColumnType(i + 1)); writeVarInt(meta.getPrecision(i + 1)); writeVarInt(meta.getScale(i + 1)); } while (rs.next()) { writeByte((byte) 1); for (int i = 0; i < columnCount; i++) { int t = DataType.getValueTypeFromResultSet(meta, i + 1); Value val = DataType.readValue(null, rs, i + 1, t); writeValue(val); } } writeByte((byte) 0); rs.beforeFirst(); } catch (SQLException e) { throw DbException.convert(e); } break; } default: DbException.throwInternalError("type=" + v.getType()); } if (SysProperties.CHECK2) { if (pos - start != getValueLen(v, handler)) { throw DbException.throwInternalError( "value size error: got " + (pos - start) + " expected " + getValueLen(v, handler)); } } }
private void testDataType(int type, Class<?> clazz) { assertEquals(type, DataType.getTypeFromClass(clazz)); }