2
Copyright (C) 2002 MySQL AB
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
package com.mysql.jdbc;
21
import java.io.UnsupportedEncodingException;
25
* Field is a class used to describe fields in a
28
* @author Mark Matthews
29
* @version $Id: Field.java,v 1.15.2.4 2003/03/21 13:43:50 mmatthew Exp $
32
//~ Static fields/initializers ---------------------------------------------
34
private static final int AUTO_INCREMENT_FLAG = 512;
35
private static final int NO_CHARSET_INFO = -1;
37
//~ Instance fields --------------------------------------------------------
39
private Connection connection = null;
40
private String charsetName = null;
41
private String databaseName = null;
42
private String defaultValue = null;
43
private String fullName = null;
44
private String fullNameWithDatabase = null;
45
private String fullOriginalName = null;
46
private String fullOriginalNameWithDatabase = null;
47
private String name; // The Field name
48
private String originalColumnName = null;
49
private String originalTableName = null;
50
private String tableName; // The Name of the Table
51
private byte[] buffer;
52
private int charsetIndex = 0;
53
private int colDecimals;
54
private int databaseNameLength = -1;
57
private int databaseNameStart = -1;
58
private int defaultValueLength = -1;
60
// default value info - from COM_LIST_FIELDS execution
61
private int defaultValueStart = -1;
62
private int length; // Internal length of the field;
63
private int mysqlType = -1; // the MySQL type
64
private int nameLength;
65
private int nameStart;
66
private int originalColumnNameLength = -1;
68
// column name info (before aliasing)
69
private int originalColumnNameStart = -1;
70
private int originalTableNameLength = -1;
72
// table name info (before aliasing)
73
private int originalTableNameStart = -1;
74
private int precisionAdjustFactor = 0;
75
private int sqlType = -1; // the java.sql.Type
76
private int tableNameLength;
77
private int tableNameStart;
78
private short colFlag;
80
//~ Constructors -----------------------------------------------------------
83
* Constructor used by DatabaseMetaData methods.
85
Field(String tableName, String columnName, int jdbcType, int length) {
86
this.tableName = tableName;
87
this.name = columnName;
95
* Constructor used when communicating with pre 4.1 servers
97
Field(Connection conn, byte[] buffer, int nameStart, int nameLength,
98
int tableNameStart, int tableNameLength, int length, int mysqlType,
99
short colFlag, int colDecimals) {
100
this(conn, buffer, -1, -1, tableNameStart, tableNameLength, -1, -1,
101
nameStart, nameLength, -1, -1, length, mysqlType, colFlag,
102
colDecimals, -1, -1, NO_CHARSET_INFO);
106
* Constructor used when communicating with 4.1 and newer
109
Field(Connection conn, byte[] buffer, int databaseNameStart,
110
int databaseNameLength, int tableNameStart, int tableNameLength,
111
int originalTableNameStart, int originalTableNameLength, int nameStart,
112
int nameLength, int originalColumnNameStart,
113
int originalColumnNameLength, int length, int mysqlType, short colFlag,
114
int colDecimals, int defaultValueStart, int defaultValueLength,
116
this.connection = conn;
117
this.buffer = buffer;
118
this.nameStart = nameStart;
119
this.nameLength = nameLength;
120
this.tableNameStart = tableNameStart;
121
this.tableNameLength = tableNameLength;
122
this.length = length;
123
this.colFlag = colFlag;
124
this.colDecimals = colDecimals;
125
this.mysqlType = mysqlType;
128
this.databaseNameStart = databaseNameStart;
129
this.databaseNameLength = databaseNameLength;
131
this.originalTableNameStart = originalTableNameStart;
132
this.originalTableNameLength = originalTableNameLength;
134
this.originalColumnNameStart = originalColumnNameStart;
135
this.originalColumnNameLength = originalColumnNameLength;
137
this.defaultValueStart = defaultValueStart;
138
this.defaultValueLength = defaultValueLength;
140
// Map MySqlTypes to java.sql Types
141
sqlType = MysqlDefs.mysqlToJavaType(mysqlType);
143
// If we're not running 4.1 or newer, use the connection's
145
if (charsetIndex != NO_CHARSET_INFO) {
146
this.charsetIndex = charsetIndex;
147
this.charsetName = CharsetMapping.INDEX_TO_CHARSET[this.charsetIndex];
150
if (this.charsetName == null) {
151
this.charsetName = this.connection.getEncoding();
154
this.charsetName = this.connection.getEncoding();
157
boolean isBinary = isBinary();
160
// Handle TEXT type (special case), Fix proposed by Peter McKeown
162
if ((sqlType == java.sql.Types.LONGVARBINARY) && !isBinary) {
163
sqlType = java.sql.Types.LONGVARCHAR;
164
} else if ((sqlType == java.sql.Types.VARBINARY) && !isBinary) {
165
sqlType = java.sql.Types.VARCHAR;
169
// Handle odd values for 'M' for floating point/decimal numbers
172
switch (this.mysqlType) {
173
case MysqlDefs.FIELD_TYPE_DECIMAL:
174
this.precisionAdjustFactor = -1;
178
case MysqlDefs.FIELD_TYPE_DOUBLE:
179
case MysqlDefs.FIELD_TYPE_FLOAT:
180
this.precisionAdjustFactor = 1;
185
switch (this.mysqlType) {
186
case MysqlDefs.FIELD_TYPE_DOUBLE:
187
case MysqlDefs.FIELD_TYPE_FLOAT:
188
this.precisionAdjustFactor = 1;
195
//~ Methods ----------------------------------------------------------------
200
* @return DOCUMENT ME!
202
public boolean isAutoIncrement() {
203
return ((colFlag & AUTO_INCREMENT_FLAG) > 0);
209
* @return DOCUMENT ME!
211
public boolean isBinary() {
212
return ((colFlag & 128) > 0);
218
* @return DOCUMENT ME!
220
public boolean isBlob() {
221
return ((colFlag & 16) > 0);
225
* Returns the character set (if known) for this
228
* @return the character set
230
public String getCharacterSet() {
231
return this.charsetName;
237
* @param conn DOCUMENT ME!
239
public void setConnection(Connection conn) {
240
this.connection = conn;
242
this.charsetName = this.connection.getEncoding();
248
* @return DOCUMENT ME!
250
public String getDatabaseName() {
251
if ((this.databaseName == null) && (this.databaseNameStart != -1)
252
&& (this.databaseNameLength != -1)) {
253
this.databaseName = getStringFromBytes(this.databaseNameStart,
254
this.databaseNameLength);
257
return this.databaseName;
263
* @return DOCUMENT ME!
265
public String getFullName() {
266
if (fullName == null) {
267
StringBuffer fullNameBuf = new StringBuffer(getTableName().length()
268
+ 1 + getName().length());
269
fullNameBuf.append(tableName);
271
// much faster to append a char than a String
272
fullNameBuf.append('.');
273
fullNameBuf.append(name);
274
fullName = fullNameBuf.toString();
284
* @return DOCUMENT ME!
286
public String getFullOriginalName() {
289
if (this.originalColumnName == null) {
290
return null; // we don't have this information
293
if (fullName == null) {
294
StringBuffer fullOriginalNameBuf = new StringBuffer(getOriginalTableName()
296
+ 1 + getOriginalName().length());
297
fullOriginalNameBuf.append(this.originalTableName);
299
// much faster to append a char than a String
300
fullOriginalNameBuf.append('.');
301
fullOriginalNameBuf.append(this.originalColumnName);
302
this.fullOriginalName = fullOriginalNameBuf.toString();
303
fullOriginalNameBuf = null;
306
return this.fullOriginalName;
312
* @return DOCUMENT ME!
314
public int getLength() {
321
* @return DOCUMENT ME!
323
public boolean isMultipleKey() {
324
return ((colFlag & 8) > 0);
330
* @return DOCUMENT ME!
332
public int getMysqlType() {
339
* @return DOCUMENT ME!
341
public String getName() {
342
if (this.name == null) {
343
this.name = getStringFromBytes(this.nameStart, this.nameLength);
352
* @return DOCUMENT ME!
354
public String getOriginalName() {
355
if ((this.originalColumnName == null)
356
&& (this.originalColumnNameStart != -1)
357
&& (this.originalColumnNameLength != -1)) {
358
this.originalColumnName = getStringFromBytes(this.originalColumnNameStart,
359
this.originalColumnNameLength);
362
return this.originalColumnName;
368
* @return DOCUMENT ME!
370
public String getOriginalTableName() {
371
if ((this.originalTableName == null)
372
&& (this.originalTableNameStart != -1)
373
&& (this.originalTableNameLength != -1)) {
374
this.originalTableName = getStringFromBytes(this.originalTableNameStart,
375
this.originalTableNameLength);
378
return this.originalTableName;
382
* Returns amount of correction that
383
* should be applied to the precision value.
385
* Different versions of MySQL report different
388
* @return the amount to adjust precision value by.
390
public int getPrecisionAdjustFactor() {
391
return this.precisionAdjustFactor;
397
* @return DOCUMENT ME!
399
public boolean isPrimaryKey() {
400
return ((colFlag & 2) > 0);
406
* @return DOCUMENT ME!
408
public int getSQLType() {
415
* @return DOCUMENT ME!
417
public String getTable() {
418
return getTableName();
424
* @return DOCUMENT ME!
426
public String getTableName() {
427
if (tableName == null) {
428
tableName = getStringFromBytes(tableNameStart, tableNameLength);
437
* @return DOCUMENT ME!
439
public boolean isUniqueKey() {
440
return ((colFlag & 4) > 0);
446
* @return DOCUMENT ME!
448
public boolean isUnsigned() {
449
return ((colFlag & 32) > 0);
455
* @return DOCUMENT ME!
457
public boolean isZeroFill() {
458
return ((colFlag & 64) > 0);
464
* @return DOCUMENT ME!
466
public String toString() {
467
return getFullName();
474
boolean isNotNull() {
475
return ((colFlag & 1) > 0);
479
* Create a string with the correct charset encoding from the
480
* byte-buffer that contains the data for this field
482
private String getStringFromBytes(int stringStart, int stringLength) {
483
if ((stringStart == -1) || (stringLength == -1)) {
487
String stringVal = null;
489
if (connection != null) {
490
if (connection.useUnicode()) {
491
String encoding = connection.getEncoding();
493
if (encoding != null) {
494
SingleByteCharsetConverter converter = null;
497
converter = SingleByteCharsetConverter.getInstance(encoding);
498
} catch (UnsupportedEncodingException uee) {
499
// ignore, code further down handles this
502
if (converter != null) { // we have a converter
503
stringVal = converter.toString(buffer, stringStart,
506
// we have no converter, use JVM converter
507
byte[] stringBytes = new byte[stringLength];
509
int endIndex = stringStart + stringLength;
512
for (int i = stringStart; i < endIndex; i++) {
513
stringBytes[pos++] = buffer[i];
517
stringVal = new String(stringBytes, encoding);
518
} catch (UnsupportedEncodingException ue) {
519
throw new RuntimeException(
520
"Unsupported character encoding '" + encoding
525
// we have no encoding, use JVM standard charset
526
stringVal = StringUtils.toAsciiString(buffer, stringStart,
530
// we are not using unicode, so use JVM standard charset
531
stringVal = StringUtils.toAsciiString(buffer, stringStart,
535
// we don't have a connection, so punt
536
stringVal = StringUtils.toAsciiString(buffer, stringStart,