Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
//---------------------------------------------------------------------------------------------------------------------------------
// File: DDC.java
//
//
// Microsoft JDBC Driver for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
package com.microsoft.sqlserver.jdbc;
import java.math.*;
import java.io.*;
import java.nio.charset.*;
import java.nio.*;
import java.text.*;
import java.util.*;
/**
* Utility class for all Data Dependant Conversions (DDC).
*/
final class DDC
{
/**
* Convert an Integer object to desired target user type.
* @param intvalue the value to convert.
* @param valueLength the value to convert.
* @param jdbcType the jdbc type required.
* @param streamType the type of stream required.
* @return the required object.
*/
static final Object convertIntegerToObject(
int intValue,
int valueLength,
JDBCType jdbcType,
StreamType streamType)
{
switch (jdbcType)
{
case INTEGER:
return new Integer(intValue);
case SMALLINT: //2.21 small and tinyint returned as short
case TINYINT:
return new Short((short) intValue);
case BIT:
case BOOLEAN:
return new Boolean(0 != intValue);
case BIGINT:
return new Long(intValue);
case DECIMAL:
case NUMERIC:
case MONEY:
case SMALLMONEY:
return new BigDecimal(Integer.toString(intValue));
case FLOAT:
case DOUBLE:
return new Double(intValue);
case REAL:
return new Float(intValue);
case BINARY:
return convertIntToBytes(intValue, valueLength);
default:
return Integer.toString(intValue);
}
}
/**
* Convert a Long object to desired target user type.
* @param longVal the value to convert.
* @param jdbcType the jdbc type required.
* @param baseSSType the base SQLServer type.
* @param streamType the stream type.
* @return the required object.
*/
static final Object convertLongToObject(long longVal, JDBCType jdbcType, SSType baseSSType, StreamType streamType)
{
switch (jdbcType)
{
case BIGINT:
return new Long(longVal);
case INTEGER:
return new Integer((int) longVal);
case SMALLINT: // small and tinyint returned as short
case TINYINT:
return new Short((short) longVal);
case BIT:
case BOOLEAN:
return new Boolean(0 != longVal);
case DECIMAL:
case NUMERIC:
case MONEY:
case SMALLMONEY:
return new BigDecimal(Long.toString(longVal));
case FLOAT:
case DOUBLE:
return new Double(longVal);
case REAL:
return new Float(longVal);
case BINARY:
byte[] convertedBytes = convertLongToBytes(longVal);
int bytesToReturnLength = 0;
byte[] bytesToReturn;
switch(baseSSType){
case BIT:
case TINYINT:
bytesToReturnLength = 1;
bytesToReturn = new byte[bytesToReturnLength];
System.arraycopy(convertedBytes, convertedBytes.length - bytesToReturnLength, bytesToReturn, 0, bytesToReturnLength);
return bytesToReturn;
case SMALLINT:
bytesToReturnLength = 2;
bytesToReturn = new byte[bytesToReturnLength];
System.arraycopy(convertedBytes, convertedBytes.length - bytesToReturnLength, bytesToReturn, 0, bytesToReturnLength);
return bytesToReturn;
case INTEGER:
bytesToReturnLength = 4;
bytesToReturn = new byte[bytesToReturnLength];
System.arraycopy(convertedBytes, convertedBytes.length - bytesToReturnLength, bytesToReturn, 0, bytesToReturnLength);
return bytesToReturn;
case BIGINT:
bytesToReturnLength = 8;
bytesToReturn = new byte[bytesToReturnLength];
System.arraycopy(convertedBytes, convertedBytes.length - bytesToReturnLength, bytesToReturn, 0, bytesToReturnLength);
return bytesToReturn;
default:
return convertedBytes;
}
case VARBINARY:
switch(baseSSType)
{
case BIGINT:
return new Long(longVal);
case INTEGER:
return new Integer((int) longVal);
case SMALLINT: // small and tinyint returned as short
case TINYINT:
return new Short((short) longVal);
case BIT:
return new Boolean(0 != longVal);
case DECIMAL:
case NUMERIC:
case MONEY:
case SMALLMONEY:
return new BigDecimal(Long.toString(longVal));
case FLOAT:
return new Double(longVal);
case REAL:
return new Float(longVal);
case BINARY:
return convertLongToBytes(longVal);
default:
return Long.toString(longVal);
}
default:
return Long.toString(longVal);
}
}
/**
* Encodes an integer value to a byte array in big-endian order.
* @param intValue the integer value to encode.
* @param valueLength the number of bytes to encode.
* @return the byte array containing the big-endian encoded value.
*/
static final byte[] convertIntToBytes(int intValue, int valueLength)
{
byte bytes[] = new byte[valueLength];
for (int i = valueLength; i-- > 0; )
{
bytes[i] = (byte)(intValue & 0xFF);
intValue >>= 8;
}
return bytes;
}
/**
* Convert a Float object to desired target user type.
* @param floatVal the value to convert.
* @param jdbcType the jdbc type required.
* @param streamType the stream type.
* @return the required object.
*/
static final Object convertFloatToObject(float floatVal, JDBCType jdbcType, StreamType streamType)
{
switch (jdbcType)
{
case REAL:
return new Float(floatVal);
case INTEGER:
return new Integer((int) floatVal);
case SMALLINT: // small and tinyint returned as short
case TINYINT:
return new Short((short) floatVal);
case BIT:
case BOOLEAN:
return new Boolean(0 != Float.compare(0.0f, floatVal));
case BIGINT:
return new Long((long) floatVal);
case DECIMAL:
case NUMERIC:
case MONEY:
case SMALLMONEY:
return new BigDecimal(Float.toString(floatVal));
case FLOAT:
case DOUBLE:
return new Double((new Float(floatVal)).doubleValue());
case BINARY:
return convertIntToBytes(Float.floatToRawIntBits(floatVal), 4);
default:
return Float.toString(floatVal);
}
}
/**
* Encodes a long value to a byte array in big-endian order.
* @param longValue the long value to encode.
* @return the byte array containing the big-endian encoded value.
*/
static final byte[] convertLongToBytes(long longValue)
{
byte bytes[] = new byte[8];
for (int i = 8; i-- > 0; )
{
bytes[i] = (byte)(longValue & 0xFF);
longValue >>= 8;
}
return bytes;
}
/**
* Convert a Double object to desired target user type.
* @param doubleVal the value to convert.
* @param jdbcType the jdbc type required.
* @param streamType the stream type.
* @return the required object.
*/
static final Object convertDoubleToObject(double doubleVal, JDBCType jdbcType, StreamType streamType)
{
switch (jdbcType)
{
case FLOAT:
case DOUBLE:
return new Double(doubleVal);
case REAL:
return new Float((new Double(doubleVal)).floatValue());
case INTEGER:
return new Integer((int) doubleVal);
case SMALLINT: // small and tinyint returned as short
case TINYINT:
return new Short((short) doubleVal);
case BIT:
case BOOLEAN:
return new Boolean(0 != Double.compare(0.0d, doubleVal));
case BIGINT:
return new Long((long) doubleVal);
case DECIMAL:
case NUMERIC:
case MONEY:
case SMALLMONEY:
return new BigDecimal(Double.toString(doubleVal));
case BINARY:
return convertLongToBytes(Double.doubleToRawLongBits(doubleVal));
default:
return Double.toString(doubleVal);
}
}
static final byte[] convertBigDecimalToBytes(BigDecimal bigDecimalVal, int scale)
{
byte[] valueBytes;
if (bigDecimalVal==null)
{
valueBytes = new byte[2];
valueBytes[0] = (byte) scale;
valueBytes[1] = 0; // data length
}
else
{
boolean isNegative = (bigDecimalVal.signum() < 0);
// NOTE: Handle negative scale as a special case for JDK 1.5 and later VMs.
if (bigDecimalVal.scale() < 0)
bigDecimalVal = bigDecimalVal.setScale(0);
BigInteger bi = bigDecimalVal.unscaledValue();
if (isNegative)
bi=bi.negate();
byte[] unscaledBytes = bi.toByteArray();
valueBytes = new byte[unscaledBytes.length + 3];
int j = 0;
valueBytes[j++] = (byte) bigDecimalVal.scale();
valueBytes[j++] = (byte) (unscaledBytes.length + 1); // data length + sign
valueBytes[j++] = (byte) (isNegative ? 0 : 1); // 1 = +ve, 0 = -ve
for (int i = unscaledBytes.length - 1; i >= 0; i--)
valueBytes[j++] = unscaledBytes[i];
}
return valueBytes;
}
/**
* Convert a BigDecimal object to desired target user type.
* @param bigDecimalVal the value to convert.
* @param jdbcType the jdbc type required.
* @param streamType the stream type.
* @return the required object.
*/
static final Object convertBigDecimalToObject(BigDecimal bigDecimalVal, JDBCType jdbcType, StreamType streamType)
{
switch (jdbcType)
{
case DECIMAL:
case NUMERIC:
case MONEY:
case SMALLMONEY:
return bigDecimalVal;
case FLOAT:
case DOUBLE:
return new Double(bigDecimalVal.doubleValue());
case REAL:
return new Float(bigDecimalVal.floatValue());
case INTEGER:
return new Integer(bigDecimalVal.intValue());
case SMALLINT: // small and tinyint returned as short
case TINYINT:
return new Short(bigDecimalVal.shortValue());
case BIT:
case BOOLEAN:
return new Boolean(0 != bigDecimalVal.compareTo(BigDecimal.valueOf(0)));
case BIGINT:
return new Long(bigDecimalVal.longValue());
case BINARY:
return convertBigDecimalToBytes(bigDecimalVal, bigDecimalVal.scale());
default:
return bigDecimalVal.toString();
}
}
static final Object convertMoneyToObject(BigDecimal bigDecimalVal, JDBCType jdbcType, StreamType streamType, int numberOfBytes)
{
switch (jdbcType)
{
case DECIMAL:
case NUMERIC:
case MONEY:
case SMALLMONEY:
return bigDecimalVal;
case FLOAT:
case DOUBLE:
return new Double(bigDecimalVal.doubleValue());
case REAL:
return new Float(bigDecimalVal.floatValue());
case INTEGER:
return new Integer(bigDecimalVal.intValue());
case SMALLINT: // small and tinyint returned as short
case TINYINT:
return new Short(bigDecimalVal.shortValue());
case BIT:
case BOOLEAN:
return new Boolean(0 != bigDecimalVal.compareTo(BigDecimal.valueOf(0)));
case BIGINT:
return new Long(bigDecimalVal.longValue());
case BINARY:
return convertToBytes(bigDecimalVal, bigDecimalVal.scale(), numberOfBytes);
default:
return bigDecimalVal.toString();
}
}
//this is how fx framework converts big decimal to money and smallmoney
private static byte[] convertToBytes(BigDecimal value, int scale, int numBytes)
{
boolean isNeg = value.signum() < 0;
value = value.setScale(scale, RoundingMode.DOWN);
BigInteger bigInt = value.unscaledValue();
byte[] unscaledBytes = bigInt.toByteArray();
byte[] ret = new byte[numBytes];
if (unscaledBytes.length < numBytes)
{
for (int i = 0; i < numBytes - unscaledBytes.length; ++i)
{
ret[i] = (byte) (isNeg ? -1 : 0);
}
}
int offset = numBytes - unscaledBytes.length;
for (int i = offset; i < numBytes; ++i)
{
ret[i] = unscaledBytes[i - offset];
}
return ret;
}
/**
* Convert a byte array to desired target user type.
* @param bytesValue the value to convert.
* @param jdbcType the jdbc type required.
* @param baseTypeInfo the type information associated with bytesValue.
* @return the required object.
* @throws SQLServerException
*/
static final Object convertBytesToObject(byte[] bytesValue, JDBCType jdbcType, TypeInfo baseTypeInfo) throws SQLServerException
{
switch(jdbcType)
{
case CHAR:
String str = Util.bytesToHexString(bytesValue, bytesValue.length);
if((SSType.BINARY ==baseTypeInfo.getSSType())
&& (str.length() < (baseTypeInfo.getPrecision()*2))){
StringBuffer strbuf = new StringBuffer(str);
while(strbuf.length() < (baseTypeInfo.getPrecision()*2)){
strbuf.append('0');
}
return strbuf.toString();
}
return str;
case BINARY:
case VARBINARY:
case LONGVARBINARY:
if((SSType.BINARY == baseTypeInfo.getSSType())
&& (bytesValue.length < baseTypeInfo.getPrecision())){
byte[] newBytes = new byte[baseTypeInfo.getPrecision()];
System.arraycopy(bytesValue, 0, newBytes, 0, bytesValue.length);
return newBytes;
}
return bytesValue;
default:
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_unsupportedConversionFromTo"));
throw new SQLServerException(form.format(new Object[] {baseTypeInfo.getSSType().name(), jdbcType}), null, 0, null);
}
}
/**
* Convert a String object to desired target user type.
* @param stringVal the value to convert.
* @param charset the character set.
* @param jdbcType the jdbc type required.
* @return the required object.
*/
static final Object convertStringToObject(
String stringVal,
String charset,
JDBCType jdbcType,
StreamType streamType) throws UnsupportedEncodingException, IllegalArgumentException
{
switch (jdbcType)
{
// Convert String to Numeric types.
case DECIMAL:
case NUMERIC:
case MONEY:
case SMALLMONEY:
return new BigDecimal(stringVal.trim());
case FLOAT:
case DOUBLE:
return Double.valueOf(stringVal.trim());
case REAL:
return Float.valueOf(stringVal.trim());
case INTEGER:
return Integer.valueOf(stringVal.trim());
case SMALLINT: // small and tinyint returned as short
case TINYINT:
return Short.valueOf(stringVal.trim());
case BIT:
case BOOLEAN:
String trimmedString = stringVal.trim();
return (1 == trimmedString.length()) ?
Boolean.valueOf('1' == trimmedString.charAt(0)) :
Boolean.valueOf(trimmedString);
case BIGINT:
return Long.valueOf(stringVal.trim());
// Convert String to Temporal types.
case TIMESTAMP:
return java.sql.Timestamp.valueOf(stringVal.trim());
case DATE:
return java.sql.Date.valueOf(getDatePart(stringVal.trim()));
case TIME:
{
// Accepted character formats for conversion to java.sql.Time are:
// hh:mm:ss[.nnnnnnnnn]
// YYYY-MM-DD hh:mm:ss[.nnnnnnnnn]
//
// To handle either of these formats:
// 1) Normalize and parse as a Timestamp
// 2) Round fractional seconds up to the nearest millisecond (max resolution of java.sql.Time)
// 3) Renormalize (as rounding may have changed the date) to a java.sql.Time
java.sql.Timestamp ts = java.sql.Timestamp.valueOf(TDS.BASE_DATE_1970 +" "+ getTimePart(stringVal.trim()));
GregorianCalendar cal = new GregorianCalendar(Locale.US);
cal.clear();
cal.setTimeInMillis(ts.getTime());
if (ts.getNanos() % Nanos.PER_MILLISECOND >= Nanos.PER_MILLISECOND / 2)
cal.add(Calendar.MILLISECOND, 1);
cal.set(TDS.BASE_YEAR_1970, Calendar.JANUARY, 1);
return new java.sql.Time(cal.getTimeInMillis());
}
case BINARY:
return stringVal.getBytes(charset);
default:
// For everything else, just return either a string or appropriate stream.
switch (streamType)
{
case CHARACTER:
return new StringReader(stringVal);
case ASCII:
return new ByteArrayInputStream(stringVal.getBytes("US-ASCII"));
case BINARY:
return new ByteArrayInputStream(stringVal.getBytes());
default:
return stringVal;
}
}
}
static final Object convertStreamToObject(
BaseInputStream stream,
TypeInfo typeInfo,
JDBCType jdbcType,
InputStreamGetterArgs getterArgs) throws SQLServerException
{
// Need to handle the simple case of a null value here, as it is not done
// outside this function.
if (null == stream)
return null;
assert null != typeInfo;
assert null != getterArgs;
SSType ssType = typeInfo.getSSType();
try
{
switch (jdbcType)
{
case CHAR:
case VARCHAR:
case LONGVARCHAR:
case NCHAR:
case NVARCHAR:
case LONGNVARCHAR:
default:
// Binary streams to character types:
// - Direct conversion to ASCII stream
// - Convert as hexized value to other character types
if (SSType.BINARY == ssType ||
SSType.VARBINARY == ssType ||
SSType.VARBINARYMAX == ssType ||
SSType.TIMESTAMP == ssType ||
SSType.IMAGE == ssType ||
SSType.UDT == ssType)
{
if (StreamType.ASCII == getterArgs.streamType)
{
return stream;
}
else
{
assert StreamType.CHARACTER == getterArgs.streamType ||
StreamType.NONE == getterArgs.streamType;
byte[] byteValue = stream.getBytes();
if(JDBCType.GUID == jdbcType)
{
return Util.readGUID(byteValue);
}
else
{
String hexString = Util.bytesToHexString(byteValue, byteValue.length);
if (StreamType.NONE == getterArgs.streamType)
return hexString;
return new StringReader(hexString);
}
}
}
// Handle streams converting to ASCII
if (StreamType.ASCII == getterArgs.streamType)
{
// Fast path for SBCS data that converts directly/easily to ASCII
if (typeInfo.supportsFastAsciiConversion())
return new AsciiFilteredInputStream(stream);
// Slightly less fast path for MBCS data that converts directly/easily to ASCII
if (getterArgs.isAdaptive)
{
return AsciiFilteredUnicodeInputStream.MakeAsciiFilteredUnicodeInputStream(
stream,
new BufferedReader(new InputStreamReader(stream, typeInfo.getCharset())));
}
else
{
return new ByteArrayInputStream((new String(stream.getBytes(), typeInfo.getCharset())).getBytes("US-ASCII"));
}
}
else if (StreamType.CHARACTER == getterArgs.streamType ||
StreamType.NCHARACTER == getterArgs.streamType)
{
if (getterArgs.isAdaptive)
return new BufferedReader(new InputStreamReader(stream, typeInfo.getCharset()));
else
return new StringReader(new String(stream.getBytes(), typeInfo.getCharset()));
}
// None of the special/fast textual conversion cases applied. Just go the normal route of converting via String.
return convertStringToObject(new String(stream.getBytes(), typeInfo.getCharset()), typeInfo.getCharset(), jdbcType, getterArgs.streamType);
case CLOB:
return new SQLServerClob(stream, typeInfo);
case NCLOB:
return new SQLServerNClob(stream, typeInfo);
case SQLXML:
return new SQLServerSQLXML(stream, getterArgs, typeInfo);
case BINARY:
case VARBINARY:
case LONGVARBINARY:
case BLOB:
// Where allowed, streams convert directly to binary representation
if (StreamType.BINARY == getterArgs.streamType)
return stream;
if (JDBCType.BLOB == jdbcType)
return new SQLServerBlob(stream);
return stream.getBytes();
}
}
// Conversion can throw either of these exceptions:
//
// UnsupportedEncodingException (binary conversions)
// IllegalArgumentException (any conversion - note: numerics throw NumberFormatException subclass)
//
// Catch them and translate them to a SQLException so that we don't propagate an unexpected exception
// type all the way up to the app, which may not catch it either...
catch (IllegalArgumentException e)
{
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_errorConvertingValue"));
throw new SQLServerException(form.format(new Object[] {typeInfo.getSSType(), jdbcType}), null, 0, e);
}
catch (UnsupportedEncodingException e)
{
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_errorConvertingValue"));
throw new SQLServerException(form.format(new Object[] {typeInfo.getSSType(), jdbcType}), null, 0, e);
}
}
// Returns date portion of string.
// Expects one of "" or "