src.com.ibm.as400.access.SQLDataFactory Maven / Gradle / Ivy
Show all versions of jt400-jdk8 Show documentation
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: SQLDataFactory.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2003 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Types;
/**
A factory that generates appropriate SQLData objects given
various conditions.
**/
class SQLDataFactory
{
// @C2A
/**
Converts a String representation of a number in scientific
notation to a String representation without scientific
notation.
Also handles the use of a different character as the decimal separator.
This is indicated by the conversion settings.
@param scientificNotation The String representation of a number
in scientific notation.
@param settings The SQLConversionSettings to be used. The only
setting currently used is the decimalSeparator.
@return The String representation without
scientific notation.
**/
static String convertScientificNotation(String scientificNotation, SQLConversionSettings settings) /*@F5C*/
{
if ((settings !=null) && settings.getDecimalSeparator().equals(",")) { /* @F5A */
scientificNotation = scientificNotation.replace(',', '.');
}
// Check to see if it is indeed scientific notation.
int e = scientificNotation.indexOf('E');
if(e < 0)
return scientificNotation;
// Parse the exponent and ensure that we don't have a number starting with '+'
// as the parseInt function will throw a number format exception if we pass that.
// @F3D int exponent = Integer.parseInt(scientificNotation.substring(e + 1));
String tempValue = scientificNotation.substring(e + 1); // @F3a
if(tempValue.startsWith("+")) // @F3a
tempValue = tempValue.substring(1); // @F3a
int exponent = Integer.parseInt(tempValue); // @F3a
// Parse the sign.
boolean sign = (scientificNotation.charAt(0) != '-');
String mantissa = scientificNotation.substring(sign ? 0 : 1, e); //@K1A
//Check to see if the number contains a decimal point. If not, add a decimal point and a 0 to
//the end of the number.
int index = mantissa.indexOf('.'); //@K1A
if(index == -1) //@K1A
{ //@K1A
mantissa = mantissa + ".0"; //@K1A
index = mantissa.indexOf('.'); //@K1A
} //@K1A
StringBuffer buffer = new StringBuffer(); //@K1A
//Check if the exponent is positive. If it is, move the decimal to the right
if( exponent >= 0 ) //@K1A
{ //@k1A
//Determine the new position the decimal should be in
int newLocation = index + exponent; //@K1A
//Copy the numbers before the current decimal
buffer.append(mantissa.substring(0, index)); //@K1A
//Copy the numbers after the decimal
buffer.append(mantissa.substring(index + 1)); //@K1A
mantissa = buffer.toString(); //@K1A
//Determine the length of the string, if the length is less than the new position for the decimal
//must add 0's to the end of the number
int length = mantissa.length(); //@K1A
for (; length newLocation) //@K1A
{
//Copy the digits before the decimal
String temp = buffer.toString().substring(0, newLocation); //@K1A
//put in the decimal
temp = temp + "."; //@K1A
//Copy the rest of the digits to the number
temp = temp + buffer.toString().substring(newLocation); //@K1A
buffer = new StringBuffer(temp);
}
else //@K1A
buffer.append(".0"); //@K1A
} //@K1A
else //negative exponent //@K1A
{ //@K1A
//IF the decimal point will be at the beginning
if( (-exponent - index) > 0) //@K1A
{ //@K1A
buffer.append("0."); //@K1A
//Pad the number with 0's in front if we have to move the decimal to left more times
//than we currently have digits
for(int i = 0; i< (-exponent - index) ; i++) //@K1A
buffer.append("0"); //@K1A
//copy the digits before the current decimal
buffer.append(mantissa.substring(0, index)); //@K1A
//copy the digits after the current decimal
buffer.append(mantissa.substring(index+1)); //@K1A
} //@K1A
else //A number will be at the beginning //@K1A
{ //@K1A
//Copy the number without the current decimal point
String temp = mantissa.substring(0, index); //@K1A
temp = temp + mantissa.substring(index+1); //@K1A
//Copy the number from the beginning to the location of the new decimal point
buffer.append(temp.substring(0, index + exponent)); //@K1A
//Add the decimal point
buffer.append('.'); //@K1A
//Copy the rest of the number
buffer.append(temp.substring(index + exponent)); //@K1A
} //@K1A
} //@K1A
//Add the sign to the number and return
String number = (sign ? "" : "-") + buffer.toString(); //@K1A
return number; //@K1A
/** //@K1D
// Parse the mantissa and pad with either trailing
// or leading 0's based on the sign and magnitude
// of the exponent.
StringBuffer buffer = new StringBuffer();
if(exponent < 0)
{
int digits = -exponent;
for(int i = 1; i <= digits; ++i)
buffer.append('0');
buffer.append(scientificNotation.substring(sign ? 0 : 1, e));
}
else if(exponent >= 0)
{ //@G3C Added the equals.
buffer.append(scientificNotation.substring(sign ? 0 : 1, e));
for(int i = 1; i <= exponent; ++i)
buffer.append('0');
}
String mantissa = buffer.toString();
// All that is left is to move the decimal point.
// So we copy the digits, insert the decimal point
// at the correct place.
int decimalPoint = mantissa.indexOf('.') + exponent;
if(exponent > 0) // @C5A
++decimalPoint; // @C5A
buffer = new StringBuffer();
int mantissaLength = mantissa.length();
for(int i = 0; i < mantissaLength; ++i)
{
if(i == decimalPoint)
buffer.append('.');
char ch = mantissa.charAt(i);
if(ch != '.')
buffer.append(ch);
}
// Strip leading and trailing 0's, if any.
int start = 0;
for(; start < buffer.length() && buffer.charAt(start) == '0'; ++start); // @G3C
int end = buffer.length() - 1;
for(; end >= 0 && buffer.charAt(end) == '0'; --end); // @G3C
String result; // @G3C
if(end >= start)
{ // @G3A
result = buffer.toString().substring(start, end + 1); // @G3C
}
else
{ // @G3A
result = "0"; // @G3A
} // @G3A
// check to make sure we have more than just "."
if(result.equals("."))
result = "0.0";
// Add the sign and return.
return(sign ? "" : "-") + result;
**/
}
/**
Compute the scale of an object. This is the number
of digits to the right of the decimal point.
@param object A Java object.
@return the scale.
**/
static int getScale(Object value)
{
int scale = 0;
String toString = value.toString();
int point = toString.indexOf('.');
if(point != -1)
scale = toString.length() - point - 1;
return scale;
}
/**
Compute the precision of an object. This is the
total number of digits.
@param object A Java object.
@return the precision.
**/
static int getPrecision(Object value)
{
int precision = 0;
if(value instanceof Boolean)
precision = 1;
else
{
String toString = value.toString();
if(toString.charAt(0) == '-') // @F1a
toString = toString.substring(1); // @F1a
int length = toString.length();
// We need to truncate any padding zeroes. Without this, @E2A
// the precision of 0.1000 was getting computed as 5 rather @E2A
// than 1. // @E2A
int startIndex = -1; // @E2A
int endIndex = length; // @E2A
int pointIndex = toString.indexOf('.'); // @E2A
if(pointIndex >= 0)
{ // @E2A
while(toString.charAt(++startIndex) == '0'); // @E2A
while(toString.charAt(--endIndex) == '0'); // @E2A
} // @E2A
else
{ // @E2A
startIndex = 0; // @E2A
endIndex = length - 1; // @E2A
} // @E2A
// Count the characters that are actually digits. @E2A
for(int i = startIndex; i <= endIndex; ++i) // @E2C
if(Character.isDigit(toString.charAt(i)))
++precision;
}
return precision;
}
/**
Compute the decimal precision of an object. This is the
total number of digits. This also counts the trailing
zeros in the number. so 1.00 has a precision of 3.
@param object A Java object.
@return the precision.
**/
/* @H5A*/
static int getDecimalPrecision(Object value)
{
int precision = 0;
if(value instanceof Boolean)
precision = 1;
else
{
String toString = value.toString();
if(toString.charAt(0) == '-')
toString = toString.substring(1);
int length = toString.length();
int startIndex = 0;
int endIndex = length - 1;
// Count the characters that are actually digits.
for(int i = startIndex; i <= endIndex; ++i)
if(Character.isDigit(toString.charAt(i)))
++precision;
}
return precision;
}
//@DFA
/**
Compute the smallest possible precision of a BigDecimal. This is the
total number of digits, disregarding the trailing 0's. Needed so that we can use as
a comparison for truncation.
(ie. 9E17 in BigDecimal is represented as BigInt(900000000000000000), but we want
to calculate precision taking into account that trailing 0's can be represented in an exponent that
is not possible in the BigDecimal object as a negative scale.)
@param value BigDecimal object.
@param maxSize max size of precision (16 or 34 for decfloats)
@return the precision.
**/
static int[] getPrecisionForTruncation(BigDecimal value, int maxSize) //@rnd1
{
int precision = 0;
String toString = value.unscaledValue().toString(); //value.toString(); 1.6 returns "123E+4", 1.4 returns "1230000"
//int pointIndex = value.scale();//@rnd1 toString.indexOf('.');
if(toString.charAt(0) == '-')
toString = toString.substring(1);
int length = toString.length();
// We need to truncate any ending zeroes. Without this,
// the precision of 1e5 was getting computed as 5 rather
// than 1.
int endIndex = length;
//@rnd1 if(pointIndex != 0)
//@rnd1 maxSize++; //allow for extra '.' char
while((toString.charAt(--endIndex) == '0') && (endIndex > maxSize) );
int numberZeros = length - endIndex - 1; //@rnd1
if(endIndex == maxSize)
{
if(toString.charAt(endIndex) == '0')
{//@rnd1
precision = endIndex;
numberZeros++; //@rnd1
}//@rnd1
else
precision = endIndex + 1;
}
else
precision = endIndex + 1;
//@rnd1 if(pointIndex != -1)
//@rnd1 precision--;
int[] retVal = new int[2]; //@rnd1
retVal[0] = precision; //@rnd1
retVal[1] = numberZeros; //@rnd1
return retVal; //@rnd1
}
/**
Return a SQLData object corresponding to the
specific IBM i native type identifier.
@param connection The connection.
@param id The id.
@param nativeType An IBM i native type identifier.
@param length Length of data (in bytes). For an array, this is the size of the array elements.
@param precision Precision of data.
@param scale Scale of data.
@param ccsid CCSID of data field.
@param translateBinary Indicates if binary fields should
be translated.
@param settings The conversion settings.
@param lobMaxSize The lob max size. @C3A
@param columnIndex The columnIndex
@param dateFormat The dateFormat
@param timeFormat The timeFormat
@param compositeContentType The compositeContentType (type of data in composite type (array, structs or associative-array) NativeType specifies if array or struct etc.
@return A SQLData object.
@exception SQLException If no valid type can be
mapped.
**/
//@array comment: we are assuming here that all of the metadata parms (except sqlType) is for the array content type
static SQLData newData(AS400JDBCConnection connection,
int id,
int nativeType,
int length,
int precision,
int scale,
int ccsid,
boolean translateBinary,
SQLConversionSettings settings,
int lobMaxSize, // @C3A
int columnIndex, //@F2A
int dateFormat, // @550A
int timeFormat, // @550A
int compositeContentType, //@array this corresponds to the nativeType numbering system //@datarray 0 = array element, -1 = nonarray, other = that type of an array.
int xmlCharType) //@xml3 SB or DB XML
throws SQLException
{
if (Trace.traceJDBC_) {
Trace.log(Trace.DIAGNOSTIC, "SQLDataFactory.newData(nativeType="+nativeType+",length="+length+",precision="+precision+",scale="+scale+",ccsid="+ccsid+")");
}
switch(nativeType)
{
case SQLNativeType.DATE_384: // Date.
{ //@datarray
if(compositeContentType == 0) //@datarray
dateFormat = 5; //@datarray always iso for input and output for arrays of dates due to zda constraint
return new SQLDate(settings, dateFormat); // @550
} //@datarray
case SQLNativeType.TIME_388: // Time.
return new SQLTime(settings, timeFormat);
case SQLNativeType.TIMESTAMP_392: // Timestamp. 0x188
return new SQLTimestamp(length, settings);
case SQLNativeType.DATALINK_396: // Datalink.
return new SQLDatalink(length - 2, settings);
case SQLNativeType.BLOB_404: // Blob.
return new SQLBlob(length - 4, settings); // @D1C
case SQLNativeType.CLOB_408: // Clob.
if((ccsid == 65535) && (translateBinary == false)) //@E4C
return new SQLBlob(length - 4, settings); // @D1C
else
return new SQLClob(length - 4, settings); // @D1C @E1C
//return new SQLClob(length - 4, false, settings); // @D1C @E1C
case SQLNativeType.DBCLOB_412: // Dbclob.
{
SQLDBClob dbclob = new SQLDBClob(length - 4, settings);
dbclob.setCcsid(ccsid); /*@P3A*/
return dbclob;
//return new SQLClob(length - 4, true, settings); // @D1C
}
case SQLNativeType.VARCHAR_448: // Varchar.
if((ccsid == 65535) && (translateBinary == false)) //@E4C
return new SQLVarcharForBitData(length - 2, settings); // @M0C - changed from SQLVarbinary
else
return new SQLVarchar(length - 2, settings);
case SQLNativeType.LONGVARCHAR_456: // Varchar long.
if((ccsid == 65535) && (translateBinary == false)) //@E4C
return new SQLLongVarcharForBitData(length - 2, settings); // @M0C - changed from SQLVarbinary
else
return new SQLLongVarchar(length - 2, settings);
case SQLNativeType.CHAR_452: // Char.
if((ccsid == 65535) && (translateBinary == false)) //@E4C
return new SQLCharForBitData(length, settings); // @M0C - changed from SQLBinary
else
return new SQLChar(length, settings);
case SQLNativeType.VARGRAPHIC_464: // Graphic (pure DBCS).
if(ccsid == 65535) //@bingra
return new SQLVargraphic((length-2)/2, settings, ccsid); //@bingra
/* ifdef JDBC40
if (ccsid == 1200)
return new SQLNVarchar(length - 2, settings); //@REA
endif */
return new SQLVargraphic(length - 2, settings, ccsid); // @C1C @C4C @cca1
case SQLNativeType.LONGVARGRAPHIC_472: // Graphic long (pure DBCS).
return new SQLLongVargraphic(length - 2, settings, ccsid); // @C1C @C4C
case SQLNativeType.GRAPHIC_468: // Graphic fix (pure DBCS).
if(ccsid == 65535) //@bingra
return new SQLGraphic(length/2, settings, ccsid); //@bingra
/* ifdef JDBC40
if (ccsid == 1200)
return new SQLNChar(length, settings); //@REA
endif */
return new SQLGraphic(length, settings, ccsid); // @C1C @C4C @cca1
case SQLNativeType.FLOAT_480: // Float.
if(length == 4)
return new SQLReal(settings);
else
return new SQLDouble(settings);
case SQLNativeType.PACKED_DECIMAL_484: // Packed decimal.
if(settings != null) // @E0A
if(! settings.useBigDecimal()) // @E0A
return new SQLDecimal2(precision, scale, settings, connection.getVRM(), connection.getProperties()); // @M0C - pass the JDProperties object so we can get the precision
return new SQLDecimal(precision, scale, settings, connection.getVRM(), connection.getProperties()); // @M0C // @E0A
case SQLNativeType.ZONED_DECIMAL_488: // Zoned decimal.
if(settings != null) // @E0A
if(! settings.useBigDecimal()) // @E0A
return new SQLNumeric2(precision, scale, settings, connection.getVRM(), connection.getProperties()); // @M0C - pass the JDProperties object so we can get the precision
return new SQLNumeric(precision, scale, settings, connection.getVRM(), connection.getProperties()); // @M0C // @E0A
case SQLNativeType.BIGINT_492: // Bigint. // @D0A
return new SQLBigint(connection.getVRM(), settings); // @D0A //trunc3
case SQLNativeType.INTEGER_496: // Integer.
return new SQLInteger(scale, connection.getVRM(), settings); // @A0C //trunc3
case SQLNativeType.SMALLINT_500: // Smallint.
return new SQLSmallint(scale, connection.getVRM(), settings); // @A0C //trunc3
case SQLNativeType.ROWID_904: // Rowid. // @M0A - Added support for the ROWID data type
return new SQLRowID(settings); // @M0A
case SQLNativeType.VARBINARY_908: // Varbinary. // @M0A - added support for VARBINARY type
return new SQLVarbinary(length-2, settings); // @M0A
case SQLNativeType.BINARY_912: // Binary. // @M0A - added support for BINARY type
return new SQLBinary(length, settings); // @M0A
case SQLNativeType.BLOB_LOCATOR_960: // Blob locator.
return new SQLBlobLocator(connection, id, lobMaxSize, settings, connection.getConverter(ccsid), columnIndex); //@F2C //@J0M added converter
case SQLNativeType.CLOB_LOCATOR_964: // Clob locator.
if((ccsid == 65535) && (translateBinary == false)) //@E4C
return new SQLBlobLocator(connection, id, lobMaxSize, settings, connection.getConverter(ccsid), columnIndex); //@F2C //@J0M added converter
else
return new SQLClobLocator(connection, id, lobMaxSize, settings, connection.getConverter(ccsid), columnIndex); // @E1C //@F2C
//return new SQLClobLocator(connection, id, lobMaxSize, false, settings, connection.getConverter(ccsid), columnIndex); // @E1C //@F2C
case SQLNativeType.DBCLOB_LOCATOR_968: // Dbclob locator.
{
if (ccsid == 1200) {
SQLNClobLocator nclob = new SQLNClobLocator(connection, id, lobMaxSize, settings, connection.getConverter(ccsid), columnIndex); // @E1C //@F2C
return nclob;
} else {
SQLDBClobLocator dbclob = new SQLDBClobLocator(connection, id, lobMaxSize, settings, connection.getConverter(ccsid), columnIndex); // @E1C //@F2C
dbclob.setCcsid(ccsid); /*@P3A*/
return dbclob;
}
//return new SQLClobLocator(connection, id, lobMaxSize, true, settings, connection.getConverter(ccsid), columnIndex); // @E1C //@F2C
}
case SQLNativeType.DECFLOAT_996: // Decimal float. //@DFA
if(precision == 16) //@DFA
return new SQLDecFloat16(settings, connection.getVRM(), connection.getProperties() ); //@DFA
else
return new SQLDecFloat34(settings, connection.getVRM(), connection.getProperties() ); //@DFA
case SQLData.NATIVE_ARRAY: //@array
return new SQLArray( length, newData( connection,
id,
compositeContentType,
length,
precision,
scale,
ccsid,
translateBinary,
settings,
lobMaxSize,
columnIndex,
dateFormat,
timeFormat,
0, 0) , connection.getVRM()); //@array create SQLData array wrapper of actual datatype
case SQLNativeType.XML_LOCATOR_2452: //@xml3 xml returned in bloblocator
case SQLNativeType.XML_988: // the xml type will be seen when a parameter is retrieved from a cached package. We'll change
// this to an SQLXML Locator 01/27/2010
if(ccsid == 65535)
xmlCharType = 2; //sb=0 or db=1 binary=2
return new SQLXMLLocator(connection, id, lobMaxSize, settings, connection.getConverter(ccsid), columnIndex, xmlCharType); //@xml3
case SQLNativeType.BOOLEAN_2436: // boolean
return new SQLBoolean(connection.getVRM(),settings);
default:
JDError.throwSQLException(JDError.EXC_INTERNAL, new IllegalArgumentException(Integer.toString(nativeType))); // @E3C
return null;
}
}
/**
Return a SQLData object corresponding to the
specific IBM i native type string.
@param nativeType An IBM i native type.
@param length Length of data (in bytes).
@param precision Precision of data.
@param scale Scale of data.
@param settings The conversion settings.
@return A SQLData object.
@exception SQLException If no valid type can be
mapped.
**/
//
// In some cases, there are several different strings
// that match a particular data type. This is because,
// different functions refer to the types with
// different strings.
//
static SQLData newData(String nativeType,
int length,
int precision,
int scale,
int ccsid, //@KKB
SQLConversionSettings settings,
int vrm, // @M0C - added vrm parm
JDProperties properties) // @M0C - added JDProperties parm
throws SQLException
{
if(properties == null) //@array7
properties = new JDProperties(); //@array7
if(nativeType.equals("BINARY"))
{ // @M0C - changed to return SQLBinary
if(vrm >= JDUtilities.vrm530) // @M0C - only for v5r3 and newer
return new SQLBinary(length, settings); // @M0C - because the original function
else // @M0C - from SQLBinary has been moved
return new SQLCharForBitData(length, settings); // @M0C - to SQLCharForBitData in order
} // @M0C - to add support for real BINARY
else if(nativeType.equals("BIGINT")) // @D0A
return new SQLBigint(vrm, settings); // @D0A //trunc3
else if(nativeType.equals("BLOB"))
return new SQLBlob(length, settings); // @D1C @G1C Remove length-4
else if(nativeType.equals("BINARY LARGE OBJECT")) //@KKB
return new SQLBlob(length, settings); //@KKB
else if(nativeType.equals("CHAR"))
{
if(ccsid == 65535 && !properties.getBoolean(JDProperties.TRANSLATE_BINARY)) //@KKB
return new SQLCharForBitData(length, settings); //@KKB
else //@KKB
return new SQLChar(length, settings);
}
else if(nativeType.equals("CHARACTE"))
{
if(ccsid == 65535 && !properties.getBoolean(JDProperties.TRANSLATE_BINARY)) //@KKB
return new SQLCharForBitData(length, settings); //@KKB
else //@KKB
return new SQLChar(length, settings);
}
else if(nativeType.equals("CHARACTER"))
{
if(ccsid == 65535 && !properties.getBoolean(JDProperties.TRANSLATE_BINARY)) //@KKB
return new SQLCharForBitData(length, settings); //@KKB
else //@KKB
return new SQLChar(length, settings);
}
else if(nativeType.equals("CHARACTER VARYING"))
{
if(ccsid == 65535 && !properties.getBoolean(JDProperties.TRANSLATE_BINARY)) //@KKB
return new SQLVarcharForBitData(length, settings); //@KKB
else //@KKB
return new SQLVarchar(length, settings); // @E1C
}
else if(nativeType.equals("CLOB"))
return new SQLClob(length, settings); // @D1C @E1C @G1C Remove length-4
//return new SQLClob(length, false, settings); // @D1C @E1C @G1C Remove length-4
else if(nativeType.equals("CHARACTER LARGE OBJECT")) //@KKB
return new SQLClob(length, settings); //@KKB
else if(nativeType.equals("DATALINK"))
return new SQLDatalink(length, settings);
else if(nativeType.equals("DBCLOB")) // @G2A
return new SQLDBClob(length, settings); // @G2A
else if(nativeType.equals("NCLOB")) // @G2A
return new SQLNClob(length, settings); // @P3A
//return new SQLClob(length, true, settings); // @G2A
else if(nativeType.equals("DOUBLE-BYTE CHARACTER LARGE OBJECT")) //@KKB
return new SQLDBClob(length, settings); //@KKB
else if(nativeType.equals("DATE"))
return new SQLDate(settings, -1); // @550
else if(nativeType.equals("DECIMAL"))
{
if(settings != null) // @E0A
if(! settings.useBigDecimal()) // @E0A
return new SQLDecimal2(precision, scale, settings, vrm, properties); // @M0C - pass the JDProperties so we can get the scale
return new SQLDecimal(precision, scale, settings, vrm, properties); // @M0C // @E0A
}
else if(nativeType.equals("DECFLOAT")) //@DFA
{ //@DFA
if(precision == 16) //@DFA
return new SQLDecFloat16(settings, vrm, properties); //@DFA
else //@DFA
return new SQLDecFloat34(settings, vrm, properties); //@DFA
} //@DFA
else if(nativeType.equals("DOUBLE"))
return new SQLDouble(settings);
else if(nativeType.equals("DOUBLE P"))
return new SQLDouble(settings);
else if(nativeType.equals("DOUBLE PRECISION"))
return new SQLDouble(settings);
else if(nativeType.equals("FLOAT"))
{
if(length == 4)
return new SQLReal(settings);
else
return new SQLDouble(settings);
}
else if(nativeType.equals("GRAPHIC") || nativeType.equals("NCHAR")) //@j40type
return new SQLGraphic(length, settings, ccsid); // @C1C @C4C @cca1
else if(nativeType.equals("GRAPHIC VARYING"))
return new SQLVargraphic(length, settings, ccsid); // @C1C @C4C @E1C @cca1
else if(nativeType.equals("INTEGER"))
return new SQLInteger(vrm, settings); //trunc3
else if(nativeType.equals("NUMERIC"))
{
if(settings != null) // @E0A
if(! settings.useBigDecimal()) // @E0A
return new SQLNumeric2(precision, scale, settings, vrm, properties); // @M0C - pass the JDProperties so we can get the scale
return new SQLNumeric(precision, scale, settings, vrm, properties); // @M0C // @E0A
}
else if(nativeType.equals("REAL"))
return new SQLReal(settings);
else if(nativeType.equals("ROWID")) // @M0A - added support for the ROWID type
return new SQLRowID(settings); // @M0A
else if(nativeType.equals("SMALLINT"))
return new SQLSmallint(vrm, settings); //trunc3
else if(nativeType.equals("TIME"))
return new SQLTime(settings, -1); // @550C
else if(nativeType.equals("TIMESTAM"))
return new SQLTimestamp(length, settings);
else if(nativeType.equals("TIMESTAMP"))
return new SQLTimestamp(length, settings);
else if(nativeType.equals("TIMESTMP"))
return new SQLTimestamp(length, settings);
else if(nativeType.equals("VARBINARY"))
{ // @M0C - changed to return SQLVarbinary
if(vrm >= JDUtilities.vrm530) // @M0C - only for v5r3 and newer
return new SQLVarbinary(length, settings); // @M0C - because the original function
else // @M0C - from SQLVarbinary has been moved
return new SQLVarcharForBitData(length, settings); // @M0C - to SQLVarcharForBitData in order
} // @M0C - to add support for real VARBINARY
else if(nativeType.equals("VARBIN")) //@K1A
{
if(vrm >= JDUtilities.vrm530)
return new SQLVarbinary(length, settings);
else
return new SQLVarcharForBitData(length, settings);
}
else if(nativeType.equals("BINARY VARYING")) //@K1A
{
if(vrm >= JDUtilities.vrm530)
return new SQLVarbinary(length, settings);
else
return new SQLVarcharForBitData(length, settings);
}
else if(nativeType.equals("VARCHAR"))
{
if(ccsid == 65535 && !properties.getBoolean(JDProperties.TRANSLATE_BINARY)) //@KKB
return new SQLVarcharForBitData(length, settings); //@KKB
else //@KKB
return new SQLVarchar(length, settings); // @E1C
}
else if(nativeType.equals("VARG"))
return new SQLVargraphic(length, settings, ccsid); // @E1C @cca1
else if(nativeType.equals("VARGRAPH"))
return new SQLVargraphic(length, settings, ccsid); // @E1C @cca1
else if(nativeType.equals("VARGRAPHIC") || nativeType.equals("NVARCHAR")) //@j40type
return new SQLVargraphic(length, settings, ccsid); //@KKB @cca1
else if(nativeType.equals("ARRAY"))
return new SQLArray( length, newData( nativeType,
length,
precision,
scale,
ccsid,
settings,
vrm,
properties) , vrm); //@array create SQLData array wrapper of actual datatype //length is element length
else if (nativeType.equals("BOOLEAN")) {
return new SQLBoolean(vrm, settings);
}
else
{
JDError.throwSQLException(JDError.EXC_INTERNAL, new IllegalArgumentException(nativeType)); // @E3C
return null;
}
}
/**
Truncates the precision of a BigDecimal by removing digits from
the left side of the decimal point.
* @param bd
* @param precision
* @return truncated BigDecimal
**/
public static BigDecimal truncatePrecision(BigDecimal bd, int precision)
{
boolean positive = bd.longValue() > 0;
StringBuffer buffer = new StringBuffer(positive ? "" : "-");
buffer.append(bd.toString().substring(positive ? precision : precision + 1));
return new BigDecimal(buffer.toString());
}
/**
Truncates the precision of a String representation of a number
by removing digits from the right side of the decimal point.
* @param value
* @param scale
* @return truncated String
**/
public static String truncateScale(String value, int scale)
{
int point = value.indexOf('.');
if(point >= 0)
{
StringBuffer buffer = new StringBuffer(value);
for(int i = 1; i <= scale; ++i)
buffer.append('0');
return buffer.toString().substring(0, point + scale + 1);
}
else
return value;
}
/* Calculate the maximum long value with the specified number of digits */
public static long getMaximumLong(int digits) {
long value = 0;
for (int i = 0; i < digits; i++) {
value = value * 10 + 9;
}
return value;
}
public static String getMaximumString(boolean positive, int precision,int scale) {
StringBuffer sb = new StringBuffer();
if (!positive)
sb.append("-");
int leftDigits = precision - scale;
if (leftDigits == 0) {
sb.append("0");
} else {
for (int i = 0; i < leftDigits; i++) {
sb.append("9");
}
}
if (scale > 0) {
sb.append(".");
for (int i = 0; i < scale; i++) {
sb.append("9");
}
}
return sb.toString();
}
public static BigDecimal getMaximumBigDecimal(int precision, int scale) {
/* The largest long containing 9s in all digits has 18 digits */
if (precision <= 18) {
return BigDecimal.valueOf(getMaximumLong(precision), scale);
} else {
return new BigDecimal(getMaximumString(true, precision,scale));
}
}
public static BigDecimal getMinimumBigDecimal(int precision, int scale) {
if (precision <= 18) {
return BigDecimal.valueOf(-getMaximumLong(precision), scale);
} else {
return new BigDecimal(getMaximumString(false, precision,scale));
}
}
}