📄 tds.java
字号:
{
throw new TdsException("Not fixed size column "
+ nativeColumnType);
}
}
} // lookupColumnSize()
/**
* determine if a given datatype is a fixed size
*
* @param nativeColumnType The SQLServer datatype to check
*
* @return <code>true</code> if the datatype is a fixed size,
* <code>false</code> if the datatype is a variable size
*
* @exception com.internetcds.jdbc.tds.TdsException
* If the <code>nativeColumnType</code> is not a knowm datatype.
*
*/
private boolean isFixedSizeColumn(byte nativeColumnType)
throws com.internetcds.jdbc.tds.TdsException
{
switch (nativeColumnType)
{
case SYBINT1:
case SYBINT2:
case SYBINT4:
case SYBFLT8:
case SYBDATETIME:
case SYBBIT:
case SYBMONEY:
case SYBMONEY4:
case SYBSMALLMONEY:
case SYBREAL:
case SYBDATETIME4:
{
return true;
}
case SYBINTN:
case SYBMONEYN:
case SYBVARCHAR:
case SYBNVARCHAR:
case SYBDATETIMN:
case SYBFLTN:
case SYBCHAR:
case SYBNCHAR:
case SYBNTEXT:
case SYBIMAGE:
case SYBVARBINARY:
case SYBBINARY:
case SYBDECIMAL:
case SYBNUMERIC:
case SYBBITN:
{
return false;
}
default:
{
throw new TdsException("Unrecognized column type 0x"
+ Integer.toHexString(nativeColumnType));
}
}
}
private Object readFloatN(int len)
throws TdsException, java.io.IOException
{
Object tmp;
switch (len)
{
case 8:
{
long l = comm.getTdsInt64();
tmp = new Double(Double.longBitsToDouble(l));
break;
}
case 4:
{
int i = comm.getTdsInt();
tmp = new Float(Float.intBitsToFloat(i));
break;
}
case 0:
{
tmp = null;
break;
}
default:
{
throw new TdsNotImplemented("Don't now how to handle "
+ "float with size of "
+ len
+ "(0x"
+ Integer.toHexString(len & 0xff)
+ ")");
}
}
return tmp;
}
private Object getMoneyValue(
int type)
throws java.io.IOException, TdsException
{
int len;
Object result;
if (type == SYBMONEYN)
{
len = comm.getByte();
}
else
{
len = lookupColumnSize((byte)type);
}
if (len == 0)
{
result = null;
}
else
{
BigInteger x = null;
if (len == 4)
{
x = BigInteger.valueOf(comm.getTdsInt());
}
else if (len == 8)
{
byte b4 = comm.getByte();
byte b5 = comm.getByte();
byte b6 = comm.getByte();
byte b7 = comm.getByte();
byte b0 = comm.getByte();
byte b1 = comm.getByte();
byte b2 = comm.getByte();
byte b3 = comm.getByte();
long l =
(long)(b0&0xff) + ((long)(b1&0xff)<<8) +
((long)(b2&0xff)<<16) + ((long)(b3&0xff)<<24) +
((long)(b4&0xff)<<32) + ((long)(b5&0xff)<<40) +
((long)(b6&0xff)<<48) + ((long)(b7&0xff)<<56);
x = BigInteger.valueOf(l);
}
else
{
throw new TdsConfused("Don't know what to do with len of "
+ len);
}
x = x.divide(BigInteger.valueOf(100));
result = new BigDecimal(x, 2);
}
return result;
} // getMoneyValue
/**
* Extracts decimal value from the server's results packet. Takes
* advantage of Java's superb handling of large numbers, which does
* all the heavy lifting for us. Format is:
* <UL>
* <LI>Length byte <code>len</code>; count includes sign byte.</LI>
* <LI>Sign byte (0=negative; 1=positive).</LI>
* <LI>Magnitude bytes (array of <code>len</code> - 1 bytes,
* in little-endian order.</LI>
* </UL>
*
* @param scale number of decimal digits after the decimal
* point.
* @return <code>BigDecimal</code> for extracted value
* (or (<code>null</code> if appropriate).
*/
private Object getDecimalValue(int scale)
throws TdsException, java.io.IOException, NumberFormatException
{
int len = comm.getByte() & 0xff;
if (--len < 1)
return null;
// RMK 2000-06-10. Deduced from some testing/packet sniffing.
byte[] bytes = new byte[len];
int signum = comm.getByte() == 0 ? -1 : 1;
while (len > 0)
bytes[--len] = comm.getByte();
BigInteger bigInt = new BigInteger(signum, bytes);
return new BigDecimal(bigInt, scale);
}
private Object getDatetimeValue(
int type)
throws java.io.IOException, TdsException
{
// Some useful constants
final long SECONDS_PER_DAY = 24L * 60L * 60L;
final long DAYS_BETWEEN_1900_AND_1970 = 25567L;
int len;
Object result;
if (type == SYBDATETIMN)
{
len = comm.getByte();
}
else if (type == SYBDATETIME4)
{
len = 4;
}
else
{
len = 8; // XXX shouldn't this be an error?
}
switch (len)
{
case 0:
{
result = null;
break;
}
case 8:
{
// It appears that a datetime is made of of 2 32bit ints
// The first one is the number of days since 1900
// The second integer is the number of seconds*300
// The reason the calculations below are sliced up into
// such small baby steps is to avoid a bug in JDK1.2.2's
// runtime, which got confused by the original complexity.
long tdsDays = (long)comm.getTdsInt();
long tdsTime = (long)comm.getTdsInt();
long sqlDays = tdsDays - DAYS_BETWEEN_1900_AND_1970;
long seconds = sqlDays * SECONDS_PER_DAY + tdsTime / 300L;
long micros = ((tdsTime % 300L) * 1000000L) / 300L;
long millis = seconds * 1000L + micros / 1000L - zoneOffset;
// Round up if appropriate.
if (micros % 1000L >= 500L)
millis++;
result = new Timestamp(millis - getDstOffset(millis));
break;
}
case 4:
{
// Accroding to Transact SQL Reference
// a smalldatetime is two small integers.
// The first is the number of days past January 1, 1900,
// the second smallint is the number of minutes past
// midnight.
long tdsDays = (long)comm.getTdsShort();
long minutes = (long)comm.getTdsShort();
long sqlDays = tdsDays - DAYS_BETWEEN_1900_AND_1970;
long seconds = sqlDays * SECONDS_PER_DAY + minutes * 60L;
long millis = seconds * 1000L - zoneOffset;
result = new Timestamp(millis - getDstOffset(millis));
break;
}
default:
{
result = null;
throw new TdsNotImplemented("Don't now how to handle "
+ "date with size of "
+ len);
}
}
return result;
} // getDatetimeValue()
/**
* Determines the number of milliseconds needed to adjust for daylight
* savings time for a given date/time value. Note that there is a problem
* with the way SQL Server sends a DATETIME value, since it is constructed
* to represent the local time for the server. This means that each fall
* there is a window of approximately one hour during which a single value
* can represent two different times.
*/
private long getDstOffset(long time) {
Calendar cal = Calendar.getInstance();
cal.setTime(new java.util.Date(time));
return cal.get(Calendar.DST_OFFSET);
}
private Object getIntValue(int type)
throws java.io.IOException, TdsException
{
Object result;
int len;
switch (type)
{
case SYBINTN:
{
len = comm.getByte();
break;
}
case SYBINT4:
{
len = 4;
break;
}
case SYBINT2:
{
len = 2;
break;
}
case SYBINT1:
{
len = 1;
break;
}
default:
{
result = null;
throw new TdsNotImplemented(
"can't handle integer of type "
+ Integer.toHexString(type));
}
}
switch (len)
{
case 4: {result = new Long(comm.getTdsInt()); break;}
case 2: {result = new Long(comm.getTdsShort()); break;}
case 1:
{
int tmp = toUInt(comm.getByte()); // XXX Are we sure this should be unsigned?
result = new Long(tmp);
break;
}
case 0:
{
result = null;
break;
}
default:
{
result = null;
throw new TdsConfused("Bad SYBINTN length of " +
len);
}
}
return result;
} // getIntValue()
private Object getCharValue(boolean wideChars)
throws TdsException, java.io.IOException
{
Object result;
int len = tdsVer == Tds.TDS70 ? comm.getTdsShort() : comm.getByte() & 0xFF;
if (len == 0 || tdsVer == Tds.TDS70 && len == 0xFFFF)
{
result = null;
}
else if (len > 0)
{
if (wideChars)
result = comm.getString(len / 2);
else
result = encoder.getString(comm.getBytes(len));
if (result.equals(" "))
{
// In SQL trailing spaces are stripped from strings
// MS SQLServer denotes a zero length string
// as a single space.
result = "";
}
}
else
{
throw new TdsConfused("String with length<0");
}
return result;
} // getCharValue()
private Object getTextValue(boolean wideChars)
throws TdsException, java.io.IOException
{
String result;
byte hasValue = comm.getByte();
if (hasValue==0)
{
result = null;
}
else
{
// XXX Have no idea what these 24 bytes are
// 2000-06-06 RMK They are the TEXTPTR (16 bytes) and the TIMESTAMP.
comm.skip(24);
int len = comm.getTdsInt();
// RMK 2000-06-11
// The logic immediately below does not agree with test t0031,
// so I'm commenting it out. On the other hand, it's a bit
// puzzling that a column defined as TEXT NOT NULL needs the
// hasValue byte read just above, but apparently it does.
//if (len == 0)
//{
// result = null;
//}
//else
if (len >= 0)
{
if (wideChars) {
result = comm.getString(len / 2);
} else {
result
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -