2 * Firebird ADO.NET Data provider for .NET and Mono
4 * The contents of this file are subject to the Initial
5 * Developer's Public License Version 1.0 (the "License");
6 * you may not use this file except in compliance with the
7 * License. You may obtain a copy of the License at
8 * http://www.firebirdsql.org/index.php?op=doc&id=idpl
10 * Software distributed under the License is distributed on
11 * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
12 * express or implied. See the License for the specific
13 * language governing rights and limitations under the License.
15 * Copyright (c) 2002, 2005 Carlos Guzman Alvarez
16 * All Rights Reserved.
22 namespace FirebirdSql.Data.Common
24 internal sealed class DbField
28 private short dataType;
29 private short numericScale;
30 private short subType;
32 private short nullFlag;
34 private string relation;
37 private int charCount;
38 private DbValue dbValue;
39 private Charset charset;
40 private ArrayBase arrayHandle;
46 public DbDataType DbDataType
48 get { return this.GetDbDataType(); }
53 get { return this.dataType & ~1; }
58 get { return this.dataType; }
59 set { this.dataType = value; }
62 public short NumericScale
64 get { return this.numericScale; }
65 set { this.numericScale = value; }
70 get { return this.subType; }
74 if (this.IsCharacter())
76 // Bits 0-7 of sqlsubtype is charset_id (127 is a special value -
77 // current attachment charset).
78 // Bits 8-17 hold collation_id for this value.
79 byte[] cs = BitConverter.GetBytes(value);
81 int index = Charset.SupportedCharsets.IndexOf(cs[0]);
84 this.charset = Charset.SupportedCharsets[index];
88 this.charset = Charset.SupportedCharsets[0];
96 get { return this.length; }
100 if (this.IsCharacter())
102 this.charCount = this.length / this.charset.BytesPerCharacter;
107 public short NullFlag
109 get { return this.nullFlag; }
110 set { this.nullFlag = value; }
115 get { return this.name; }
116 set { this.name = value.Trim(); }
119 public string Relation
121 get { return this.relation; }
122 set { this.relation = value.Trim(); }
127 get { return this.owner; }
128 set { this.owner = value.Trim(); }
133 get { return this.alias; }
134 set { this.alias = value.Trim(); }
137 public Charset Charset
139 get { return this.charset; }
144 get { return this.charCount; }
147 public ArrayBase ArrayHandle
153 return this.arrayHandle;
157 throw new IscException("Field is not an array type");
165 this.arrayHandle = value;
169 throw new IscException("Field is not an array type");
174 public DbValue DbValue
176 get { return this.dbValue; }
181 get { return this.dbValue.Value; }
182 set { this.dbValue.Value = value; }
192 this.name = String.Empty;
193 this.relation = String.Empty;
194 this.owner = String.Empty;
195 this.alias = String.Empty;
196 this.dbValue = new DbValue(this, DBNull.Value);
203 public bool IsNumeric()
205 if (this.dataType == 0)
210 switch (this.DbDataType)
212 case DbDataType.SmallInt:
213 case DbDataType.Integer:
214 case DbDataType.BigInt:
215 case DbDataType.Numeric:
216 case DbDataType.Decimal:
217 case DbDataType.Float:
218 case DbDataType.Double:
226 public bool IsDecimal()
228 if (this.dataType == 0)
233 switch (this.DbDataType)
235 case DbDataType.Numeric:
236 case DbDataType.Decimal:
246 if (this.dataType == 0)
251 switch (this.DbDataType)
253 case DbDataType.Binary:
254 case DbDataType.Text:
262 public bool IsCharacter()
264 if (this.dataType == 0)
269 switch (this.DbDataType)
271 case DbDataType.Char:
272 case DbDataType.VarChar:
273 case DbDataType.Text:
281 public bool IsArray()
283 if (this.dataType == 0)
288 switch (this.DbDataType)
290 case DbDataType.Array:
298 public bool IsAliased()
300 return (this.Name != this.Alias) ? true : false;
303 public bool IsExpression()
305 return this.Name.Length == 0 ? true : false;
312 return System.Int32.MaxValue;
316 if (this.IsCharacter())
318 return this.CharCount;
327 public bool AllowDBNull()
329 return ((this.DataType & 1) == 1);
332 public void SetValue(byte[] buffer)
334 if (buffer == null || this.NullFlag == -1)
336 this.Value = System.DBNull.Value;
340 switch (this.SqlType)
342 case IscCodes.SQL_TEXT:
343 case IscCodes.SQL_VARYING:
344 if (this.DbDataType == DbDataType.Guid)
346 this.Value = new Guid(buffer);
350 string s = this.Charset.GetString(buffer, 0, buffer.Length);
352 if ((this.Length % this.Charset.BytesPerCharacter) == 0 &&
353 s.Length > this.CharCount)
355 s = s.Substring(0, this.CharCount);
362 case IscCodes.SQL_SHORT:
363 if (this.numericScale < 0)
365 this.Value = TypeDecoder.DecodeDecimal(
366 BitConverter.ToInt16(buffer, 0),
372 this.Value = BitConverter.ToInt16(buffer, 0);
376 case IscCodes.SQL_LONG:
377 if (this.NumericScale < 0)
379 this.Value = TypeDecoder.DecodeDecimal(
380 BitConverter.ToInt32(buffer, 0),
386 this.Value = BitConverter.ToInt32(buffer, 0);
390 case IscCodes.SQL_FLOAT:
391 this.Value = BitConverter.ToSingle(buffer, 0);
394 case IscCodes.SQL_DOUBLE:
395 case IscCodes.SQL_D_FLOAT:
396 this.Value = BitConverter.ToDouble(buffer, 0);
399 case IscCodes.SQL_QUAD:
400 case IscCodes.SQL_INT64:
401 case IscCodes.SQL_BLOB:
402 case IscCodes.SQL_ARRAY:
403 if (this.NumericScale < 0)
405 this.Value = TypeDecoder.DecodeDecimal(
406 BitConverter.ToInt64(buffer, 0),
412 this.Value = BitConverter.ToInt64(buffer, 0);
416 case IscCodes.SQL_TIMESTAMP:
417 DateTime date = TypeDecoder.DecodeDate(
418 BitConverter.ToInt32(buffer, 0));
420 DateTime time = TypeDecoder.DecodeTime(
421 BitConverter.ToInt32(buffer, 4));
423 this.Value = new System.DateTime(
424 date.Year, date.Month, date.Day,
425 time.Hour, time.Minute, time.Second, time.Millisecond);
428 case IscCodes.SQL_TYPE_TIME:
429 this.Value = TypeDecoder.DecodeTime(BitConverter.ToInt32(buffer, 0));
432 case IscCodes.SQL_TYPE_DATE:
433 this.Value = TypeDecoder.DecodeDate(BitConverter.ToInt32(buffer, 0));
437 throw new NotSupportedException("Unknown data type");
442 public void FixNull()
444 if (this.NullFlag == -1 && this.dbValue.IsDBNull())
446 switch (this.DbDataType)
448 case DbDataType.Char:
449 case DbDataType.VarChar:
450 this.Value = String.Empty;
453 case DbDataType.Guid:
454 this.Value = Guid.Empty;
457 case DbDataType.SmallInt:
458 this.Value = (short)0;
461 case DbDataType.Integer:
465 case DbDataType.BigInt:
466 case DbDataType.Binary:
467 case DbDataType.Array:
468 case DbDataType.Text:
469 this.Value = (long)0;
472 case DbDataType.Numeric:
473 case DbDataType.Decimal:
474 this.Value = (decimal)0;
477 case DbDataType.Float:
478 this.Value = (float)0;
481 case DbDataType.Double:
482 this.Value = (double)0;
485 case DbDataType.Date:
486 case DbDataType.Time:
487 case DbDataType.TimeStamp:
488 this.Value = new System.DateTime(0 * 10000L + 621355968000000000);
492 throw new IscException("Unknown sql data type: " + this.DataType);
497 public Type GetSystemType()
499 switch (this.DbDataType)
501 case DbDataType.Char:
502 case DbDataType.VarChar:
503 case DbDataType.Text:
504 return Type.GetType("System.String");
506 case DbDataType.SmallInt:
507 return Type.GetType("System.Int16");
509 case DbDataType.Integer:
510 return Type.GetType("System.Int32");
512 case DbDataType.BigInt:
513 return Type.GetType("System.Int64");
515 case DbDataType.Numeric:
516 case DbDataType.Decimal:
517 return Type.GetType("System.Decimal");
519 case DbDataType.Float:
520 return Type.GetType("System.Single");
522 case DbDataType.Guid:
523 return Type.GetType("System.Guid");
525 case DbDataType.Double:
526 return Type.GetType("System.Double");
528 case DbDataType.Date:
529 case DbDataType.Time:
530 case DbDataType.TimeStamp:
531 return Type.GetType("System.DateTime");
533 case DbDataType.Binary:
534 return typeof(byte[]);
536 case DbDataType.Array:
537 return Type.GetType("System.Array");
540 throw new SystemException("Invalid data type");
546 #region Private Methods
548 private DbDataType GetDbDataType()
550 // Special case for Guid handling
551 if (this.SqlType == IscCodes.SQL_TEXT && this.Length == 16 &&
552 (this.Charset != null && this.Charset.Name == "OCTETS"))
554 return DbDataType.Guid;
557 switch (this.SqlType)
559 case IscCodes.SQL_TEXT:
560 return DbDataType.Char;
562 case IscCodes.SQL_VARYING:
563 return DbDataType.VarChar;
565 case IscCodes.SQL_SHORT:
566 if (this.subType == 2)
568 return DbDataType.Decimal;
570 else if (subType == 1)
572 return DbDataType.Numeric;
576 return DbDataType.SmallInt;
579 case IscCodes.SQL_LONG:
580 if (this.subType == 2)
582 return DbDataType.Decimal;
584 else if (subType == 1)
586 return DbDataType.Numeric;
590 return DbDataType.Integer;
593 case IscCodes.SQL_QUAD:
594 case IscCodes.SQL_INT64:
595 if (this.subType == 2)
597 return DbDataType.Decimal;
599 else if (subType == 1)
601 return DbDataType.Numeric;
605 return DbDataType.BigInt;
608 case IscCodes.SQL_FLOAT:
609 return DbDataType.Float;
611 case IscCodes.SQL_DOUBLE:
612 case IscCodes.SQL_D_FLOAT:
613 if (this.subType == 2)
615 return DbDataType.Decimal;
617 else if (subType == 1)
619 return DbDataType.Numeric;
623 return DbDataType.Double;
626 case IscCodes.SQL_BLOB:
627 if (this.subType == 1)
629 return DbDataType.Text;
633 return DbDataType.Binary;
636 case IscCodes.SQL_TIMESTAMP:
637 return DbDataType.TimeStamp;
639 case IscCodes.SQL_TYPE_TIME:
640 return DbDataType.Time;
642 case IscCodes.SQL_TYPE_DATE:
643 return DbDataType.Date;
645 case IscCodes.SQL_ARRAY:
646 return DbDataType.Array;
649 throw new SystemException("Invalid data type");