**** Merged from MCS ****
[mono-project.git] / mcs / class / ByteFX.Data / mysqlclient / Field.cs
blob70aaa93c885585aceefe87bbee8132903db9b667
1 // ByteFX.Data data access components for .Net
2 // Copyright (C) 2002-2003 ByteFX, Inc.
3 //
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.
8 //
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.
13 //
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
18 using System;
19 using System.Data;
20 using System.Data.SqlTypes;
21 using System.Globalization;
22 using System.Text;
23 using ByteFX.Data.Common;
25 namespace ByteFX.Data.MySqlClient
27 internal enum ColumnFlags : int
29 NOT_NULL = 1,
30 PRIMARY_KEY = 2,
31 UNIQUE_KEY = 4,
32 MULTIPLE_KEY = 8,
33 BLOB = 16,
34 UNSIGNED = 32,
35 ZERO_FILL = 64,
36 BINARY = 128,
37 ENUM = 256,
38 AUTO_INCREMENT = 512,
39 TIMESTAMP = 1024,
40 SET = 2048,
41 NUMBER = 32768
44 /// <summary>
45 /// Summary description for Field.
46 /// </summary>
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 = ".";
69 public byte[] Buffer
71 get { return buffer; }
74 public long BufferIndex
76 get { return bufIndex; }
79 public long BufferLength
81 get { return bufLength; }
84 /// <summary>
85 /// CopyBuffer makes a copy of the byte buffer given to us while
86 /// the rowset was being read
87 /// </summary>
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++ ];
94 bufIndex = 0;
95 buffer = newbuf;
96 value = newbuf;
99 /// <summary>
100 /// GetValue returns an object that represents the value of this field.
101 /// </summary>
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))
108 CopyBuffer();
109 return value;
112 public MySqlDbType Type
114 get { return colType; }
115 set { colType = value; }
118 public int NumericPrecision
120 get
122 if (colType == MySqlDbType.Decimal)
123 return colLen;
124 return -1;
129 public int NumericScale
131 get
133 if (colType == MySqlDbType.Decimal)
134 return colDecimals;
135 return -1;
137 set
139 colDecimals = value;
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;
174 public bool IsBlob()
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 )
191 if (len == -1)
193 value = DBNull.Value;
194 buffer = null;
195 return;
198 buffer = buf;
199 bufIndex = index;
200 bufLength = len;
202 // if it is a blob and binary, then GetBytes is the way to go
203 if ( IsBlob() && IsBinary() )
205 dbType = DbType.Binary;
206 value = buffer;
207 return;
210 string sValue = encoding.GetString( buf, (int)index, (int)len );
212 switch(colType)
214 case MySqlDbType.Byte:
215 if (IsUnsigned())
216 value = Byte.Parse( sValue );
217 else
218 value = SByte.Parse( sValue );
219 break;
221 case MySqlDbType.Short:
222 if (IsUnsigned())
223 value = UInt16.Parse( sValue );
224 else
225 value = Int16.Parse( sValue );
226 break;
228 case MySqlDbType.Int :
229 case MySqlDbType.Int24:
230 if (IsUnsigned())
231 value = UInt32.Parse( sValue );
232 else
233 value = Int32.Parse( sValue );
234 break;
236 case MySqlDbType.BigInt:
237 if (IsUnsigned())
238 value = UInt64.Parse( sValue );
239 else
240 value = Int64.Parse( sValue );
241 break;
243 case MySqlDbType.Decimal:
244 value = Decimal.Parse( sValue , numberFormat );
245 break;
247 case MySqlDbType.Float:
248 value = Convert.ToSingle( sValue, numberFormat );
249 break;
251 case MySqlDbType.Double:
252 value = Convert.ToDouble( sValue, numberFormat );
253 break;
255 case MySqlDbType.Year:
256 value = Int32.Parse( sValue );
257 break;
259 case MySqlDbType.Date:
260 ParseDateValue( "0000-00-00", "yyyy-MM-dd", sValue );
261 break;
263 case MySqlDbType.Datetime:
264 ParseDateValue( "0000-00-00 00:00:00", "yyyy-MM-dd HH:mm:ss", sValue );
265 break;
267 case MySqlDbType.Time:
268 if (sValue.Equals("00:00:00"))
269 value = DBNull.Value;
270 else
271 value = TimeSpan.Parse(sValue);
272 break;
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 );
279 return;
282 string pattern;
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;
292 case 14:
293 default: pattern = "yyyyMMddHHmmss"; break;
296 if (ColumnLength > 2 && sValue.Equals( null_value.Substring(0, ColumnLength)))
297 value = DBNull.Value;
298 else
299 value = DateTime.ParseExact( sValue, pattern, new System.Globalization.DateTimeFormatInfo());
300 break;
302 case MySqlDbType.String:
303 case MySqlDbType.VarChar:
304 case MySqlDbType.Blob:
305 case MySqlDbType.TinyBlob:
306 case MySqlDbType.LongBlob:
307 case MySqlDbType.MediumBlob:
308 value = sValue;
309 break;
311 default:
312 throw new NotSupportedException();
316 protected void ParseDateValue( string nullpattern, string pattern, string data )
318 if ( data.Equals (nullpattern) )
319 value = DBNull.Value;
320 else
321 value = DateTime.ParseExact( data, pattern, new System.Globalization.DateTimeFormatInfo());
324 public string GetFieldTypeName()
326 switch (colType)
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()
358 switch (colType)
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);
389 else
390 return typeof(System.String);
392 case MySqlDbType.Year:
393 return typeof(System.Int32);
395 default:
396 case MySqlDbType.Null: return typeof(System.DBNull);
400 public DbType GetDbType()
402 switch (colType)
404 case MySqlDbType.Decimal: return DbType.Decimal;
405 case MySqlDbType.Byte: return DbType.Byte;
406 case MySqlDbType.Short:
407 if (IsUnsigned())
408 return DbType.UInt16;
409 else
410 return DbType.Int16;
412 case MySqlDbType.Int:
413 if (IsUnsigned())
414 return DbType.UInt32;
415 else
416 return DbType.Int32;
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:
423 if (IsUnsigned())
424 return DbType.UInt64;
425 else
426 return DbType.Int64;
428 case MySqlDbType.Int24:
429 if (IsUnsigned())
430 return DbType.UInt32;
431 else
432 return DbType.Int32;
433 case MySqlDbType.Date:
434 case MySqlDbType.Year:
435 case MySqlDbType.Newdate:
436 return DbType.Date;
438 case MySqlDbType.Time:
439 return DbType.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");