📄 column.java
字号:
} return enforceSize(o, type, precision, scale, true); case Types.TIMESTAMP : if (o instanceof Time) { long millis = session.currentDate.getTime() + ((Time) o).getTime(); o = HsqlDateTime.getTimestamp(millis); } if (o instanceof Timestamp) { return enforceSize(o, type, precision, scale, false); } } return convertObject(o, type); } static int[] tenPower = { 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000 }; /** * Check an object for type CHAR and VARCHAR and truncate/pad based on * the size * * @param obj object to check * @param type the object type * @param size size to enforce * @param check throw if too long * @return the altered object if the right type, else the object * passed in unaltered * @throws HsqlException if data too long */ static Object enforceSize(Object obj, int type, int size, int scale, boolean check) throws HsqlException { if (obj == null) { return obj; } if (size == 0 && type != Types.TIMESTAMP) { return obj; } // todo: need to handle BINARY like this as well switch (type) { case Types.CHAR : return checkChar((String) obj, size, check); case Types.VARCHAR : case Types.VARCHAR_IGNORECASE : return checkVarchar((String) obj, size, check); case Types.NUMERIC : case Types.DECIMAL : BigDecimal dec = (BigDecimal) obj; dec = dec.setScale(scale, BigDecimal.ROUND_HALF_DOWN); BigInteger big = JavaSystem.getUnscaledValue(dec); int sign = big.signum() == -1 ? 1 : 0; if (big.toString().length() - sign > size) { throw Trace.error(Trace.STRING_DATA_TRUNCATION); } return dec; case Types.TIMESTAMP : if (size == 6) { return obj; } Timestamp ts = (Timestamp) obj; int nanos = ts.getNanos(); int divisor = tenPower[size]; int newNanos = (nanos / divisor) * divisor; ts.setNanos(newNanos); return ts; default : return obj; } } /** * Checks the length of a VARCHAR string. * * @param s the string to pad to truncate * @param len the len to make the string * @param check if true, throw an exception if truncation takes place * @return the string of size len */ static String checkVarchar(String s, int len, boolean check) throws HsqlException { int slen = s.length(); if (slen > len) { if (check) { throw Trace.error(Trace.STRING_DATA_TRUNCATION); } return s.substring(0, len); } return s; } /** * Checks and pads a CHARACTER string to len size * * @param s the string to pad to truncate * @param len the len to make the string * @param check if true, throw an exception if truncation takes place * @return the string of size len */ static String checkChar(String s, int len, boolean check) throws HsqlException { int slen = s.length(); if (slen == len) { return s; } if (slen > len) { if (check) { throw Trace.error(Trace.STRING_DATA_TRUNCATION); } return s.substring(0, len); } char[] b = new char[len]; s.getChars(0, slen, b, 0); for (int i = slen; i < len; i++) { b[i] = ' '; } return new String(b); } /** * Type narrowing from DOUBLE/DECIMAL/NUMERIC to BIGINT / INT / SMALLINT / TINYINT * following the SQL rules. When conversion is from a non-integral type, * digits to the right of the decimal point are lost. */ /** * Converter from a numeric object to Integer. Input is checked to be * within range represented by Integer. */ static Integer convertToInt(Object o) throws HsqlException { if (o instanceof BigDecimal) { BigInteger bi = ((BigDecimal) o).toBigInteger(); if (bi.compareTo(MAX_INT) > 0 || bi.compareTo(MIN_INT) < 0) { throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE); } return ValuePool.getInt(bi.intValue()); } if (o instanceof Double || o instanceof Float) { double d = ((Number) o).doubleValue(); if (Double.isNaN(d) || d >= (double) Integer.MAX_VALUE + 1 || d <= (double) Integer.MIN_VALUE - 1) { throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE); } return ValuePool.getInt((int) d); } throw Trace.error(Trace.INVALID_CONVERSION); } /** * Converter from a numeric object to Long. Input is checked to be * within range represented by Long. */ static Long convertToLong(Object o) throws HsqlException { if (o instanceof BigDecimal) { BigInteger bi = ((BigDecimal) o).toBigInteger(); if (bi.compareTo(MAX_LONG) > 0 || bi.compareTo(MIN_LONG) < 0) { throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE); } return ValuePool.getLong(bi.longValue()); } if (o instanceof Double || o instanceof Float) { double d = ((Number) o).doubleValue(); if (Double.isNaN(d) || d >= (double) Long.MAX_VALUE + 1 || d <= (double) Long.MIN_VALUE - 1) { throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE); } return ValuePool.getLong((long) d); } throw Trace.error(Trace.INVALID_CONVERSION); } /** * Converter from a numeric object to Double. Input is checked to be * within range represented by Double */ static Double convertToDouble(Object o) throws HsqlException { double val; if (o instanceof BigDecimal) { BigDecimal bd = (BigDecimal) o; val = bd.doubleValue(); int signum = bd.signum(); BigDecimal bo = new BigDecimal(val + signum); if (bo.compareTo(bd) != signum) { throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE); } } else { val = ((Number) o).doubleValue(); } return ValuePool.getDouble(Double.doubleToLongBits(val)); }// fredt@users 20020408 - patch 442993 by fredt - arithmetic expressions /** * Arithmetic expression terms are promoted to a type that can * represent the resulting values and avoid incorrect results.<p> * When the result or the expression is converted to the * type of the target column for storage, an exception is thrown if the * resulting value cannot be stored in the column<p> * Returns a SQL type "wide" enough to represent the result of the * expression.<br> * A type is "wider" than the other if it can represent all its * numeric values.<BR> * Types narrower than INTEGER (int) are promoted to * INTEGER. The order is as follows<p> * * INTEGER, BIGINT, DOUBLE, DECIMAL<p> * * TINYINT and SMALLINT in any combination return INTEGER<br> * INTEGER and INTEGER return BIGINT<br> * BIGINT and INTEGER return NUMERIC/DECIMAL<br> * BIGINT and BIGINT return NUMERIC/DECIMAL<br> * DOUBLE and INTEGER return DOUBLE<br> * DOUBLE and BIGINT return DOUBLE<br> * NUMERIC/DECIMAL and any type returns NUMERIC/DECIMAL<br> * * @author fredt@users * @param type1 java.sql.Types value for the first numeric type * @param type2 java.sql.Types value for the second numeric type * @return either type1 or type2 on the basis of the above order */ static int getCombinedNumberType(int type1, int type2, int expType) { int typeWidth1 = getNumTypeWidth(type1); int typeWidth2 = getNumTypeWidth(type2); if (typeWidth1 == 16 || typeWidth2 == 16) { return Types.DOUBLE; } switch (expType) { case Expression.EQUAL : case Expression.BIGGER : case Expression.BIGGER_EQUAL : case Expression.SMALLER_EQUAL : case Expression.SMALLER : case Expression.NOT_EQUAL : case Expression.ALTERNATIVE : case Expression.DIVIDE : return (typeWidth1 > typeWidth2) ? type1 : type2; default : int sum = typeWidth1 + typeWidth2; if (sum <= 4) { return Types.INTEGER; } if (sum <= 8) { return Types.BIGINT; } return Types.NUMERIC; } } /** * @param type java.sql.Types int for a numeric type * @return relative width */ static int getNumTypeWidth(int type) { switch (type) { case Types.TINYINT : return 1; case Types.SMALLINT : return 2; case Types.INTEGER : return 4; case Types.BIGINT : return 8; case Types.REAL : case Types.FLOAT : case Types.DOUBLE : return 16; case Types.NUMERIC : case Types.DECIMAL : return 32; default : return 32; } } /** * returns -1, 0 , +1 */ static int compareToTypeRange(Object o, int targettype) { if (!(o instanceof Number)) { return 0; } if (o instanceof Integer || o instanceof Long) { long temp = ((Number) o).longValue(); int min; int max; switch (targettype) { case Types.TINYINT : min = Byte.MIN_VALUE; max = Byte.MAX_VALUE; break; case Types.SMALLINT : min = Short.MIN_VALUE; max = Short.MAX_VALUE; break; case Types.INTEGER : min = Integer.MIN_VALUE; max = Integer.MAX_VALUE; break; case Types.BIGINT : case Types.DECIMAL : case Types.NUMERIC : default : return 0; } if (max < temp) { return 1; } if (temp < min) { return -1; } return 0; } else { try { o = convertToLong(o); return compareToTypeRange(o, targettype); } catch (HsqlException e) { if (e.getErrorCode() == -Trace.NUMERIC_VALUE_OUT_OF_RANGE) { if (o instanceof BigDecimal) { return ((BigDecimal) o).signum(); } else if (o instanceof Double) { return ((Double) o).doubleValue() > 0 ? 1 : -1; } } } } return 0; } /** * Converts the specified hexadecimal digit <CODE>String</CODE> * to an equivalent array of bytes. * * @param hexString a <CODE>String</CODE> of hexadecimal digits * @throws HsqlException if the specified string contains non-hexadecimal digits. * @return a byte array equivalent to the specified string of hexadecimal digits */ public static byte[] hexToByteArray(String hexString) throws HsqlException { try { return StringConverter.hexToByte(hexString); } catch (IOException e) { throw Trace.error(Trace.INVALID_CHARACTER_ENCODING); } } /** * Compares a <CODE>byte[]</CODE> with another specified * <CODE>byte[]</CODE> for order. Returns a negative integer, zero, * or a positive integer as the first object is less than, equal to, or * greater than the specified second <CODE>byte[]</CODE>.<p> * * @param o1 the first byte[] to be compared * @param o2 the second byte[] to be compared * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. */ static int compareTo(byte[] o1, byte[] o2) { int len = o1.length; int lenb = o2.length; for (int i = 0; ; i++) { int a = 0; int b = 0; if (i < len) { a = ((int) o1[i]) & 0xff; } else if (i >= lenb) { return 0; } if (i < lenb) { b = ((int) o2[i]) & 0xff; } if (a > b) { return 1; } if (b > a) { return -1; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -