📄 support.java
字号:
// jTDS JDBC Driver for Microsoft SQL Server and Sybase// Copyright (C) 2004 The jTDS Project//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//package net.sourceforge.jtds.jdbc;import java.io.*;import java.lang.reflect.Method;import java.math.BigDecimal;import java.math.BigInteger;import java.sql.*;import java.util.Calendar;import java.util.GregorianCalendar;import java.util.HashMap;import net.sourceforge.jtds.util.Logger;/** * This class contains static utility methods designed to support the * main driver classes. * <p> * Implementation notes: * <ol> * <li>The methods in this class incorporate some code from previous versions * of jTDS to handle dates, BLobs etc. * <li>This class contains routines to generate runtime messages from the resource file. * <li>The key data conversion logic used in Statements and result sets is implemented here. * <li>There is nothing here which is TDS specific. * </ol> * * @author Mike Hutchinson * @author jTDS project * @version $Id: Support.java,v 1.47 2005/06/16 09:32:27 alin_sinpalean Exp $ */public class Support { // Constants used in datatype conversions to avoid object allocations. private static final Integer INTEGER_ZERO = new Integer(0); private static final Integer INTEGER_ONE = new Integer(1); private static final Long LONG_ZERO = new Long(0L); private static final Long LONG_ONE = new Long(1L); private static final Float FLOAT_ZERO = new Float(0.0); private static final Float FLOAT_ONE = new Float(1.0); private static final Double DOUBLE_ZERO = new Double(0.0); private static final Double DOUBLE_ONE = new Double(1.0); private static final BigDecimal BIG_DECIMAL_ZERO = new BigDecimal(0.0); private static final BigDecimal BIG_DECIMAL_ONE = new BigDecimal(1.0); private static final java.sql.Date DATE_ZERO = new java.sql.Date(0); private static final java.sql.Time TIME_ZERO = new java.sql.Time(0); private static final BigInteger maxValue28 = new BigInteger("9999999999999999999999999999"); private static final BigInteger maxValue38 = new BigInteger("99999999999999999999999999999999999999"); /** * Convert java clases to java.sql.Type constant. */ private static final HashMap typeMap = new HashMap(); static { typeMap.put(Byte.class, new Integer(java.sql.Types.TINYINT)); typeMap.put(Short.class, new Integer(java.sql.Types.SMALLINT)); typeMap.put(Integer.class, new Integer(java.sql.Types.INTEGER)); typeMap.put(Long.class, new Integer(java.sql.Types.BIGINT)); typeMap.put(Float.class, new Integer(java.sql.Types.REAL)); typeMap.put(Double.class, new Integer(java.sql.Types.DOUBLE)); typeMap.put(BigDecimal.class, new Integer(java.sql.Types.DECIMAL)); typeMap.put(Boolean.class, new Integer(JtdsStatement.BOOLEAN)); typeMap.put(byte[].class, new Integer(java.sql.Types.VARBINARY)); typeMap.put(java.sql.Date.class, new Integer(java.sql.Types.DATE)); typeMap.put(java.sql.Time.class, new Integer(java.sql.Types.TIME)); typeMap.put(java.sql.Timestamp.class, new Integer(java.sql.Types.TIMESTAMP)); typeMap.put(BlobImpl.class, new Integer(java.sql.Types.LONGVARBINARY)); typeMap.put(ClobImpl.class, new Integer(java.sql.Types.LONGVARCHAR)); typeMap.put(String.class, new Integer(java.sql.Types.VARCHAR)); typeMap.put(Blob.class, new Integer(java.sql.Types.LONGVARBINARY)); typeMap.put(Clob.class, new Integer(java.sql.Types.LONGVARCHAR)); } /** * Hex constants to use in conversion routines. */ private static final char hex[] = {'0', '1', '2', '3', '4', '5', '6','7', '8', '9', 'A', 'B', 'C', 'D', 'E','F' }; /** * Static utility Calendar object. */ private static final GregorianCalendar cal = new GregorianCalendar(); /** * Convert a byte[] object to a hex string. * * @param bytes The byte array to convert. * @return The hex equivalent as a <code>String</code>. */ public static String toHex(byte[] bytes) { int len = bytes.length; if (len > 0) { StringBuffer buf = new StringBuffer(len * 2); for (int i = 0; i < len; i++) { int b1 = bytes[i] & 0xFF; buf.append(hex[b1 >> 4]); buf.append(hex[b1 & 0x0F]); } return buf.toString(); } return ""; } /** * Normalize a BigDecimal value so that it fits within the * available precision. * * @param value The decimal value to normalize. * @param maxPrecision The decimal precision supported by the server * (assumed to be a value of either 28 or 38). * @return The possibly normalized decimal value as a <code>BigDecimal</code>. * @throws SQLException If the number is too big. */ static BigDecimal normalizeBigDecimal(BigDecimal value, int maxPrecision) throws SQLException { if (value == null) { return null; } if (value.scale() > maxPrecision) { // This is an optimization to quickly adjust the scale of a // very precise BD value. For example // BigDecimal((double)1.0/3.0) yields a BD 54 digits long! value = value.setScale(maxPrecision, BigDecimal.ROUND_HALF_UP); } BigInteger max = (maxPrecision == 28) ? maxValue28 : maxValue38; while (value.abs().unscaledValue().compareTo(max) > 0) { // OK we need to reduce the scale if possible to preserve // the integer part of the number and still fit within the // available precision. int scale = value.scale() - 1; if (scale < 0) { // Can't do it number just too big throw new SQLException(Messages.get("error.normalize.numtoobig", String.valueOf(maxPrecision)), "22000"); } value = value.setScale(scale, BigDecimal.ROUND_HALF_UP); } return value; } /** * Convert an existing data object to the specified JDBC type. * * @param callerReference an object reference to the caller of this method; * must be a <code>Connection</code>, * <code>Statement</code> or <code>ResultSet</code> * @param x the data object to convert * @param jdbcType the required type constant from * <code>java.sql.Types</code> * @return the converted data object * @throws SQLException if the conversion is not supported or fails */ static Object convert(Object callerReference, Object x, int jdbcType, String charSet) throws SQLException { try { switch (jdbcType) { case java.sql.Types.TINYINT: case java.sql.Types.SMALLINT: case java.sql.Types.INTEGER: if (x == null) { return INTEGER_ZERO; } else if (x instanceof Integer) { return x; } else if (x instanceof Byte) { return new Integer(((Byte)x).byteValue() & 0xFF); } else if (x instanceof Number) { return new Integer(((Number) x).intValue()); } else if (x instanceof String) { return new Integer(((String) x).trim()); } else if (x instanceof Boolean) { return ((Boolean) x).booleanValue() ? INTEGER_ONE : INTEGER_ZERO; } break; case java.sql.Types.BIGINT: if (x == null) { return LONG_ZERO; } else if (x instanceof Long) { return x; } else if (x instanceof Byte) { return new Long(((Byte)x).byteValue() & 0xFF); } else if (x instanceof Number) { return new Long(((Number) x).longValue()); } else if (x instanceof String) { return new Long(((String) x).trim()); } else if (x instanceof Boolean) { return ((Boolean) x).booleanValue() ? LONG_ONE : LONG_ZERO; } break; case java.sql.Types.REAL: if (x == null) { return FLOAT_ZERO; } else if (x instanceof Float) { return x; } else if (x instanceof Byte) { return new Float(((Byte)x).byteValue() & 0xFF); } else if (x instanceof Number) { return new Float(((Number) x).floatValue()); } else if (x instanceof String) { return new Float(((String) x).trim()); } else if (x instanceof Boolean) { return ((Boolean) x).booleanValue() ? FLOAT_ONE : FLOAT_ZERO; } break; case java.sql.Types.FLOAT: case java.sql.Types.DOUBLE: if (x == null) { return DOUBLE_ZERO; } else if (x instanceof Double) { return x; } else if (x instanceof Byte) { return new Double(((Byte)x).byteValue() & 0xFF); } else if (x instanceof Number) { return new Double(((Number) x).doubleValue()); } else if (x instanceof String) { return new Double(((String) x).trim()); } else if (x instanceof Boolean) { return ((Boolean) x).booleanValue() ? DOUBLE_ONE : DOUBLE_ZERO; } break; case java.sql.Types.NUMERIC: case java.sql.Types.DECIMAL: if (x == null) { return null; } else if (x instanceof BigDecimal) { return x; } else if (x instanceof Number) { return new BigDecimal(x.toString()); } else if (x instanceof String) { return new BigDecimal((String) x); } else if (x instanceof Boolean) { return ((Boolean) x).booleanValue() ? BIG_DECIMAL_ONE : BIG_DECIMAL_ZERO; } break; case java.sql.Types.VARCHAR: case java.sql.Types.CHAR: if (x == null) { return null; } else if (x instanceof String) { return x; } else if (x instanceof Number) { return x.toString(); } else if (x instanceof Boolean) { return((Boolean) x).booleanValue() ? "1" : "0"; } else if (x instanceof Clob) { Clob clob = (Clob) x; long length = clob.length(); if (length > Integer.MAX_VALUE) { throw new SQLException(Messages.get("error.normalize.lobtoobig"), "22000"); } return clob.getSubString(1, (int) length); } else if (x instanceof Blob) { Blob blob = (Blob) x; long length = blob.length(); if (length > Integer.MAX_VALUE) { throw new SQLException(Messages.get("error.normalize.lobtoobig"), "22000"); } x = blob.getBytes(1, (int) length); } if (x instanceof byte[]) { return toHex((byte[])x); } return x.toString(); // Last hope! case java.sql.Types.BIT: case JtdsStatement.BOOLEAN: if (x == null) { return Boolean.FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -