1 // ByteFX.Data data access components for .Net
2 // Copyright (C) 2002-2003 ByteFX, Inc.
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
9 // This library 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 GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 using System
.Data
.SqlTypes
;
21 using System
.Globalization
;
23 using ByteFX
.Data
.Common
;
25 namespace ByteFX
.Data
.MySqlClient
27 internal enum ColumnFlags
: int
45 /// Summary description for Field.
47 internal class MySqlField
: Common
.Field
49 protected MySqlDbType colType
;
50 protected ColumnFlags colFlags
;
51 protected int colDecimals
;
52 protected Encoding encoding
;
53 private static NumberFormatInfo numberFormat
= null;
55 protected byte[] buffer
;
56 protected long bufIndex
;
57 protected long bufLength
;
59 public MySqlField(Encoding encoding
)
61 this.encoding
= encoding
;
62 if (numberFormat
== null)
64 numberFormat
= (NumberFormatInfo
)NumberFormatInfo
.InvariantInfo
.Clone();
65 numberFormat
.NumberDecimalSeparator
= ".";
71 get { return buffer; }
74 public long BufferIndex
76 get { return bufIndex; }
79 public long BufferLength
81 get { return bufLength; }
85 /// CopyBuffer makes a copy of the byte buffer given to us while
86 /// the rowset was being read
88 private void CopyBuffer()
90 byte[] newbuf
= new byte[ bufLength
];
91 long oldIndex
= bufIndex
;
92 for (long i
=0; i
< bufLength
; i
++)
93 newbuf
[i
] = buffer
[ oldIndex
++ ];
100 /// GetValue returns an object that represents the value of this field.
102 /// <returns></returns>
103 public object GetValue()
105 // if our value is a byte buffer and we are using only
106 // a part of that buffer, then we need to make a copy
107 if (value is byte[] && (bufIndex
> 0 || bufLength
< buffer
.Length
))
112 public MySqlDbType Type
114 get { return colType; }
115 set { colType = value; }
118 public int NumericPrecision
122 if (colType
== MySqlDbType
.Decimal
)
129 public int NumericScale
133 if (colType
== MySqlDbType
.Decimal
)
143 public ColumnFlags Flags
145 get { return colFlags; }
146 set { colFlags = value; }
149 public bool IsAutoIncrement()
151 return (colFlags
& ColumnFlags
.AUTO_INCREMENT
) > 0;
154 public bool IsNumeric()
156 return (colFlags
& ColumnFlags
.NUMBER
) > 0;
159 public bool AllowsNull()
161 return (colFlags
& ColumnFlags
.NOT_NULL
) == 0;
164 public bool IsUnique()
166 return (colFlags
& ColumnFlags
.UNIQUE_KEY
) > 0;
169 public bool IsPrimaryKey()
171 return (colFlags
& ColumnFlags
.PRIMARY_KEY
) > 0;
176 return (colFlags
& ColumnFlags
.BLOB
) > 0;
179 public bool IsBinary()
181 return (colFlags
& ColumnFlags
.BINARY
) > 0;
184 public bool IsUnsigned()
186 return (colFlags
& ColumnFlags
.UNSIGNED
) > 0;
189 public void SetValueData( byte[] buf
, long index
, long len
, DBVersion version
)
193 value = DBNull
.Value
;
202 // if it is a blob and binary, then GetBytes is the way to go
203 if ( IsBlob() && IsBinary() )
205 dbType
= DbType
.Binary
;
210 string sValue
= encoding
.GetString( buf
, (int)index
, (int)len
);
214 case MySqlDbType
.Byte
:
216 value = Byte
.Parse( sValue
);
218 value = SByte
.Parse( sValue
);
221 case MySqlDbType
.Short
:
223 value = UInt16
.Parse( sValue
);
225 value = Int16
.Parse( sValue
);
228 case MySqlDbType
.Int
:
229 case MySqlDbType
.Int24
:
231 value = UInt32
.Parse( sValue
);
233 value = Int32
.Parse( sValue
);
236 case MySqlDbType
.BigInt
:
238 value = UInt64
.Parse( sValue
);
240 value = Int64
.Parse( sValue
);
243 case MySqlDbType
.Decimal
:
244 value = Decimal
.Parse( sValue
, numberFormat
);
247 case MySqlDbType
.Float
:
248 value = Convert
.ToSingle( sValue
, numberFormat
);
251 case MySqlDbType
.Double
:
252 value = Convert
.ToDouble( sValue
, numberFormat
);
255 case MySqlDbType
.Year
:
256 value = Int32
.Parse( sValue
);
259 case MySqlDbType
.Date
:
260 ParseDateValue( "0000-00-00", "yyyy-MM-dd", sValue
);
263 case MySqlDbType
.Datetime
:
264 ParseDateValue( "0000-00-00 00:00:00", "yyyy-MM-dd HH:mm:ss", sValue
);
267 case MySqlDbType
.Time
:
268 if (sValue
.Equals("00:00:00"))
269 value = DBNull
.Value
;
271 value = TimeSpan
.Parse(sValue
);
274 case MySqlDbType
.Timestamp
:
275 // MySql 4.1.0 and later use DateTime format for timestamp
276 if (version
.isAtLeast(4,1,0))
278 ParseDateValue( "0000-00-00 00:00:00", "yyyy-MM-dd HH:mm:ss", sValue
);
283 string null_value
= "00000000000000";
284 switch (ColumnLength
)
286 case 2: pattern
= "yy"; break;
287 case 4: pattern
= "yyMM"; break;
288 case 6: pattern
= "yyMMdd"; break;
289 case 8: pattern
= "yyyyMMdd"; break;
290 case 10: pattern
= "yyMMddHHmm"; break;
291 case 12: pattern
= "yyMMddHHmmss"; break;
293 default: pattern
= "yyyyMMddHHmmss"; break;
296 if (ColumnLength
> 2 && sValue
.Equals( null_value
.Substring(0, ColumnLength
)))
297 value = DBNull
.Value
;
299 value = DateTime
.ParseExact( sValue
, pattern
, new System
.Globalization
.DateTimeFormatInfo());
302 case MySqlDbType
.String
:
303 case MySqlDbType
.VarChar
:
304 case MySqlDbType
.Blob
:
305 case MySqlDbType
.TinyBlob
:
306 case MySqlDbType
.LongBlob
:
307 case MySqlDbType
.MediumBlob
:
312 throw new NotSupportedException();
316 protected void ParseDateValue( string nullpattern
, string pattern
, string data
)
318 if ( data
.Equals (nullpattern
) )
319 value = DBNull
.Value
;
321 value = DateTime
.ParseExact( data
, pattern
, new System
.Globalization
.DateTimeFormatInfo());
324 public string GetFieldTypeName()
328 case MySqlDbType
.Decimal
: return "DECIMAL";
329 case MySqlDbType
.Byte
: return "TINY";
330 case MySqlDbType
.Short
: return "SHORT";
331 case MySqlDbType
.Int
: return "INTEGER";
332 case MySqlDbType
.Float
: return "FLOAT";
333 case MySqlDbType
.Double
: return "DOUBLE";
334 case MySqlDbType
.Null
: return "NULL";
335 case MySqlDbType
.Timestamp
: return "TIMESTAMP";
336 case MySqlDbType
.BigInt
: return "BIGINT";
337 case MySqlDbType
.Int24
: return "INT24";
338 case MySqlDbType
.Date
: return "DATE";
339 case MySqlDbType
.Time
: return "TIME";
340 case MySqlDbType
.Datetime
: return "DATETIME";
341 case MySqlDbType
.Year
: return "YEAR";
342 case MySqlDbType
.Newdate
: return "NEWDATE";
343 case MySqlDbType
.Enum
: return "ENUM";
344 case MySqlDbType
.Set
: return "SET";
345 case MySqlDbType
.TinyBlob
: return "TINY_BLOB";
346 case MySqlDbType
.MediumBlob
: return "MEDIUM_BLOB";
347 case MySqlDbType
.LongBlob
: return "LONG_BLOB";
348 case MySqlDbType
.Blob
: return "BLOB";
349 case MySqlDbType
.VarChar
: return "VAR_STRING";
350 case MySqlDbType
.String
: return "STRING";
352 return "Unknown typeid";
356 public Type
GetFieldType()
360 case MySqlDbType
.Byte
: return IsUnsigned() ? typeof(System
.Byte
) : typeof(System
.SByte
);
362 case MySqlDbType
.Short
: return IsUnsigned() ? typeof(System
.UInt16
) : typeof(System
.Int16
);
364 case MySqlDbType
.Int
:
365 case MySqlDbType
.Int24
: return IsUnsigned() ? typeof(System
.UInt32
) : typeof(System
.Int32
);
367 case MySqlDbType
.BigInt
: return IsUnsigned() ? typeof(System
.UInt64
) : typeof(System
.Int64
);
369 case MySqlDbType
.Float
: return typeof(System
.Single
);
370 case MySqlDbType
.Double
: return typeof(System
.Double
);
372 case MySqlDbType
.Time
: return typeof(System
.TimeSpan
);
374 case MySqlDbType
.Date
:
375 case MySqlDbType
.Datetime
:
376 case MySqlDbType
.Timestamp
: return typeof(System
.DateTime
);
378 case MySqlDbType
.Decimal
: return typeof(System
.Decimal
);
380 case MySqlDbType
.VarChar
:
381 case MySqlDbType
.String
: return typeof(System
.String
);
383 case MySqlDbType
.TinyBlob
:
384 case MySqlDbType
.MediumBlob
:
385 case MySqlDbType
.LongBlob
:
386 case MySqlDbType
.Blob
:
387 if ((colFlags
& ColumnFlags
.BINARY
) != 0)
388 return typeof(System
.Array
);
390 return typeof(System
.String
);
392 case MySqlDbType
.Year
:
393 return typeof(System
.Int32
);
396 case MySqlDbType
.Null
: return typeof(System
.DBNull
);
400 public DbType
GetDbType()
404 case MySqlDbType
.Decimal
: return DbType
.Decimal
;
405 case MySqlDbType
.Byte
: return DbType
.Byte
;
406 case MySqlDbType
.Short
:
408 return DbType
.UInt16
;
412 case MySqlDbType
.Int
:
414 return DbType
.UInt32
;
418 case MySqlDbType
.Float
: return DbType
.Single
;
419 case MySqlDbType
.Double
: return DbType
.Double
;
420 case MySqlDbType
.Null
: return DbType
.Object
;
422 case MySqlDbType
.BigInt
:
424 return DbType
.UInt64
;
428 case MySqlDbType
.Int24
:
430 return DbType
.UInt32
;
433 case MySqlDbType
.Date
:
434 case MySqlDbType
.Year
:
435 case MySqlDbType
.Newdate
:
438 case MySqlDbType
.Time
:
440 case MySqlDbType
.Datetime
:
441 case MySqlDbType
.Timestamp
:
442 return DbType
.DateTime
;
444 case MySqlDbType
.Enum
: return DbType
.UInt32
;
445 case MySqlDbType
.Set
: return DbType
.Object
;
447 case MySqlDbType
.TinyBlob
:
448 case MySqlDbType
.MediumBlob
:
449 case MySqlDbType
.LongBlob
:
450 case MySqlDbType
.Blob
:
451 if (IsBinary()) return DbType
.Binary
;
452 return DbType
.String
;
453 case MySqlDbType
.VarChar
:
454 return DbType
.String
;
455 case MySqlDbType
.String
:
456 return DbType
.StringFixedLength
;
458 throw new Exception("unknown MySqlDbType");