📄 tdsdata.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.math.BigInteger;
import java.math.BigDecimal;
import java.sql.SQLException;
import net.sourceforge.jtds.util.BlobBuffer;
/**
* Implement TDS data types and related I/O logic.
* <p>
* Implementation notes:
* <bl>
* <li>This class encapsulates all the knowledge about reading and writing
* TDS data descriptors and related application data.
* <li>There are four key methods supplied here:
* <ol>
* <li>readType() - Reads the column and parameter meta data.
* <li>readData() - Reads actual data values.
* <li>writeParam() - Write parameter descriptors and data.
* <li>getNativeType() - knows how to map JDBC data types to the equivalent TDS type.
* </ol>
* </bl>
*
* @author Mike Hutchinson
* @author Alin Sinpalean
* @author freeTDS project
* @version $Id: TdsData.java,v 1.51 2005/06/03 12:29:09 alin_sinpalean Exp $
*/
public class TdsData {
/**
* This class implements a descriptor for TDS data types;
*
* @author Mike Hutchinson.
*/
private static class TypeInfo {
/** The SQL type name. */
public final String sqlType;
/**
* The size of this type or < 0 for variable sizes.
* <p> Special values as follows:
* <ol>
* <li> -5 sql_variant type.
* <li> -4 text, image or ntext types.
* <li> -2 SQL Server 7+ long char and var binary types.
* <li> -1 varchar, varbinary, null types.
* </ol>
*/
public final int size;
/**
* The precision of the type.
* <p>If this is -1 precision must be calculated from buffer size
* eg for varchar fields.
*/
public final int precision;
/**
* The display size of the type.
* <p>-1 If the display size must be calculated from the buffer size.
*/
public final int displaySize;
/** true if type is a signed numeric. */
public final boolean isSigned;
/** true if type requires TDS80 collation. */
public final boolean isCollation;
/** The java.sql.Types constant for this data type. */
public final int jdbcType;
/**
* Construct a new TDS data type descriptor.
*
* @param sqlType SQL type name.
* @param size Byte size for this type or < 0 for variable length types.
* @param precision Decimal precision or -1
* @param displaySize Printout size for this type or special values -1,-2.
* @param isSigned True if signed numeric type.
* @param isCollation True if type has TDS 8 collation information.
* @param jdbcType The java.sql.Type constant for this type.
*/
TypeInfo(String sqlType, int size, int precision, int displaySize,
boolean isSigned, boolean isCollation, int jdbcType) {
this.sqlType = sqlType;
this.size = size;
this.precision = precision;
this.displaySize = displaySize;
this.isSigned = isSigned;
this.isCollation = isCollation;
this.jdbcType = jdbcType;
}
}
/*
* Constants for TDS data types
*/
private static final int SYBCHAR = 47; // 0x2F
private static final int SYBVARCHAR = 39; // 0x27
private static final int SYBINTN = 38; // 0x26
private static final int SYBINT1 = 48; // 0x30
private static final int SYBDATE = 49; // 0x31 Sybase 12
private static final int SYBTIME = 51; // 0x33 Sybase 12
private static final int SYBINT2 = 52; // 0x34
private static final int SYBINT4 = 56; // 0x38
private static final int SYBINT8 = 127;// 0x7F
private static final int SYBFLT8 = 62; // 0x3E
private static final int SYBDATETIME = 61; // 0x3D
private static final int SYBBIT = 50; // 0x32
private static final int SYBTEXT = 35; // 0x23
private static final int SYBNTEXT = 99; // 0x63
private static final int SYBIMAGE = 34; // 0x22
private static final int SYBMONEY4 = 122;// 0x7A
private static final int SYBMONEY = 60; // 0x3C
private static final int SYBDATETIME4 = 58; // 0x3A
private static final int SYBREAL = 59; // 0x3B
private static final int SYBBINARY = 45; // 0x2D
private static final int SYBVOID = 31; // 0x1F
private static final int SYBVARBINARY = 37; // 0x25
private static final int SYBNVARCHAR = 103;// 0x67
private static final int SYBBITN = 104;// 0x68
private static final int SYBNUMERIC = 108;// 0x6C
private static final int SYBDECIMAL = 106;// 0x6A
private static final int SYBFLTN = 109;// 0x6D
private static final int SYBMONEYN = 110;// 0x6E
private static final int SYBDATETIMN = 111;// 0x6F
private static final int SYBDATEN = 123;// 0x7B SYBASE 12
private static final int SYBTIMEN = 147;// 0x93 SYBASE 12
private static final int XSYBCHAR = 175;// 0xAF
private static final int XSYBVARCHAR = 167;// 0xA7
private static final int XSYBNVARCHAR = 231;// 0xE7
private static final int XSYBNCHAR = 239;// 0xEF
private static final int XSYBVARBINARY = 165;// 0xA5
private static final int XSYBBINARY = 173;// 0xAD
private static final int SYBLONGBINARY = 225;// 0xE1 SYBASE 12
private static final int SYBSINT1 = 64; // 0x40
private static final int SYBUINT2 = 65; // 0x41
private static final int SYBUINT4 = 66; // 0x42
private static final int SYBUINT8 = 67; // 0x43
private static final int SYBUNIQUE = 36; // 0x24
private static final int SYBVARIANT = 98; // 0x62
/*
* Special case for Sybase 12.5+
* This long data type is used to send text and image
* data as statement parameters as a replacement for
* writetext.
* As far as I can tell this data type is only sent not
* received.
*/
static final int SYBLONGDATA = 36; // 0x24 SYBASE 12
/*
* Constants for Sybase User Defined data types used to
* qualify the new longchar and longbinary types.
*/
private static final int UDT_CHAR = 1; // 0x01
private static final int UDT_VARCHAR = 2; // 0x02
private static final int UDT_BINARY = 3; // 0x03
private static final int UDT_VARBINARY = 4; // 0x04
private static final int UDT_NCHAR = 18; // 0x03
private static final int UDT_NVARCHAR = 19; // 0x03
private static final int UDT_UNICHAR = 34; // 0x22
private static final int UDT_UNIVARCHAR = 35; // 0x23
// Common to Sybase and SQL Server
private static final int UDT_TIMESTAMP = 80; // 0x50
private static final int UDT_SYSNAME = 18; // 0x12
// SQL Server 7+
private static final int UDT_NEWSYSNAME =256; // 0x100
/*
* Constants for variable length data types
*/
private static final int VAR_MAX = 255;
private static final int SYB_LONGVAR_MAX = 16384;
private static final int MS_LONGVAR_MAX = 8000;
private static final int SYB_CHUNK_SIZE = 8192;
/**
* Array of TDS data type descriptors.
*/
private final static TypeInfo types[] = new TypeInfo[256];
/**
* Static block to initialise TDS data type descriptors.
*/
static {// SQL Type Size Prec DS signed TDS8 Col java Type
types[SYBCHAR] = new TypeInfo("char", -1, -1, 1, false, false, java.sql.Types.CHAR);
types[SYBVARCHAR] = new TypeInfo("varchar", -1, -1, 1, false, false, java.sql.Types.VARCHAR);
types[SYBINTN] = new TypeInfo("int", -1, 10, 11, true, false, java.sql.Types.INTEGER);
types[SYBINT1] = new TypeInfo("tinyint", 1, 3, 4, false, false, java.sql.Types.TINYINT);
types[SYBINT2] = new TypeInfo("smallint", 2, 5, 6, true, false, java.sql.Types.SMALLINT);
types[SYBINT4] = new TypeInfo("int", 4, 10, 11, true, false, java.sql.Types.INTEGER);
types[SYBINT8] = new TypeInfo("bigint", 8, 19, 20, true, false, java.sql.Types.BIGINT);
types[SYBFLT8] = new TypeInfo("float", 8, 15, 24, true, false, java.sql.Types.DOUBLE);
types[SYBDATETIME] = new TypeInfo("datetime", 8, 23, 23, false, false, java.sql.Types.TIMESTAMP);
types[SYBBIT] = new TypeInfo("bit", 1, 1, 1, false, false, java.sql.Types.BIT);
types[SYBTEXT] = new TypeInfo("text", -4, -1, -1, false, true, java.sql.Types.CLOB);
types[SYBNTEXT] = new TypeInfo("ntext", -4, -1, -1, false, true, java.sql.Types.CLOB);
types[SYBIMAGE] = new TypeInfo("image", -4, -1, -1, false, false, java.sql.Types.BLOB);
types[SYBMONEY4] = new TypeInfo("smallmoney", 4, 10, 12, true, false, java.sql.Types.DECIMAL);
types[SYBMONEY] = new TypeInfo("money", 8, 19, 21, true, false, java.sql.Types.DECIMAL);
types[SYBDATETIME4] = new TypeInfo("smalldatetime", 4, 16, 19, false, false, java.sql.Types.TIMESTAMP);
types[SYBREAL] = new TypeInfo("real", 4, 7, 14, true, false, java.sql.Types.REAL);
types[SYBBINARY] = new TypeInfo("binary", -1, -1, 2, false, false, java.sql.Types.BINARY);
types[SYBVOID] = new TypeInfo("void", -1, 1, 1, false, false, 0);
types[SYBVARBINARY] = new TypeInfo("varbinary", -1, -1, -1, false, false, java.sql.Types.VARBINARY);
types[SYBNVARCHAR] = new TypeInfo("nvarchar", -1, -1, -1, false, false, java.sql.Types.VARCHAR);
types[SYBBITN] = new TypeInfo("bit", -1, 1, 1, false, false, java.sql.Types.BIT);
types[SYBNUMERIC] = new TypeInfo("numeric", -1, -1, -1, true, false, java.sql.Types.NUMERIC);
types[SYBDECIMAL] = new TypeInfo("decimal", -1, -1, -1, true, false, java.sql.Types.DECIMAL);
types[SYBFLTN] = new TypeInfo("float", -1, 15, 24, true, false, java.sql.Types.DOUBLE);
types[SYBMONEYN] = new TypeInfo("money", -1, 19, 21, true, false, java.sql.Types.DECIMAL);
types[SYBDATETIMN] = new TypeInfo("datetime", -1, 23, 23, false, false, java.sql.Types.TIMESTAMP);
types[SYBDATE] = new TypeInfo("date", 4, 10, 10, false, false, java.sql.Types.DATE);
types[SYBTIME] = new TypeInfo("time", 4, 8, 8, false, false, java.sql.Types.TIME);
types[SYBDATEN] = new TypeInfo("date", -1, 10, 10, false, false, java.sql.Types.DATE);
types[SYBTIMEN] = new TypeInfo("time", -1, 8, 8, false, false, java.sql.Types.TIME);
types[XSYBCHAR] = new TypeInfo("char", -2, -1, -1, false, true, java.sql.Types.CHAR);
types[XSYBVARCHAR] = new TypeInfo("varchar", -2, -1, -1, false, true, java.sql.Types.VARCHAR);
types[XSYBNVARCHAR] = new TypeInfo("nvarchar", -2, -1, -1, false, true, java.sql.Types.VARCHAR);
types[XSYBNCHAR] = new TypeInfo("nchar", -2, -1, -1, false, true, java.sql.Types.CHAR);
types[XSYBVARBINARY]= new TypeInfo("varbinary", -2, -1, -1, false, false, java.sql.Types.VARBINARY);
types[XSYBBINARY] = new TypeInfo("binary", -2, -1, -1, false, false, java.sql.Types.BINARY);
types[SYBLONGBINARY]= new TypeInfo("varbinary", -5, -1, 2, false, false, java.sql.Types.BINARY);
types[SYBSINT1] = new TypeInfo("tinyint", 1, 2, 3, false, false, java.sql.Types.TINYINT);
types[SYBUINT2] = new TypeInfo("smallint", 2, 5, 6, false, false, java.sql.Types.SMALLINT);
types[SYBUINT4] = new TypeInfo("int", 4, 10, 11, false, false, java.sql.Types.INTEGER);
types[SYBUINT8] = new TypeInfo("bigint", 8, 20, 20, false, false, java.sql.Types.BIGINT);
types[SYBUNIQUE] = new TypeInfo("uniqueidentifier",-1,36,36, false, false, java.sql.Types.CHAR);
types[SYBVARIANT] = new TypeInfo("sql_variant", -5, 0, 8000, false, false, java.sql.Types.VARCHAR);
}
/** Default Decimal Scale. */
static final int DEFAULT_SCALE = 10;
/**
* TDS 8 supplies collation information for character data types.
*
* @param in the server response stream
* @param ci the column descriptor
* @return the number of bytes read from the stream as an <code>int</code>
*/
static int getCollation(ResponseStream in, ColInfo ci) throws IOException {
if (TdsData.isCollation(ci)) {
// Read TDS8 collation info
ci.collation = new byte[5];
in.read(ci.collation);
return 5;
}
return 0;
}
/**
* Set the <code>charsetInfo</code> field of <code>ci</code> according to
* the value of its <code>collation</code> field.
* <p>
* The <code>Connection</code> is used to find out whether a specific
* charset was requested. In this case, the column charset will be ignored.
*
* @param ci the <code>ColInfo</code> instance to update
* @param connection a <code>Connection</code> instance to check whether it
* has a fixed charset or not
* @throws SQLException if a <code>CharsetInfo</code> is not found for this
* particular column collation
*/
static void setColumnCharset(ColInfo ci, ConnectionJDBC2 connection)
throws SQLException {
if (connection.isCharsetSpecified()) {
// If a charset was requested on connection creation, ignore the
// column collation and use default
ci.charsetInfo = connection.getCharsetInfo();
} else if (ci.collation != null) {
// TDS version will be 8.0 or higher in this case and connection
// collation will be non-null
byte[] collation = ci.collation;
byte[] defaultCollation = connection.getCollation();
int i;
for (i = 0; i < 5; ++i) {
if (collation[i] != defaultCollation[i]) {
break;
}
}
if (i == 5) {
ci.charsetInfo = connection.getCharsetInfo();
} else {
ci.charsetInfo = CharsetInfo.getCharset(collation);
}
}
}
/**
* Read the TDS datastream and populate the ColInfo parameter with
* data type and related information.
* <p>The type infomation conforms to one of the following formats:
* <ol>
* <li> [int1 type] - eg SYBINT4.
* <li> [int1 type] [int1 buffersize] - eg VARCHAR < 256
* <li> [int1 type] [int2 buffersize] - eg VARCHAR > 255.
* <li> [int1 type] [int4 buffersize] [int1 tabnamelen] [int1*n tabname] - eg text.
* <li> [int1 type] [int4 buffersize] - eg sql_variant.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -