DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
DeveelDbDataReader.cs
Go to the documentation of this file.
1 //
2 // Copyright 2010-2015 Deveel
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 using System;
18 using System.Collections;
19 using System.Data;
20 using System.Data.Common;
21 using System.Globalization;
22 
23 using Deveel.Data.Protocol;
24 using Deveel.Data.Sql.Objects;
25 using Deveel.Data.Types;
26 
27 using SysDataTable = System.Data.DataTable;
28 using SysDataRow = System.Data.DataRow;
29 
30 namespace Deveel.Data.Client {
31  public sealed class DeveelDbDataReader : DbDataReader {
32  private readonly DeveelDbCommand command;
33  private readonly CommandBehavior behavior;
34 
35  private bool wasRead;
36 
37  internal DeveelDbDataReader(DeveelDbCommand command, CommandBehavior behavior) {
38  this.command = command;
39  this.behavior = behavior;
40  }
41 
42  private bool CloseConnection {
43  get { return (behavior & CommandBehavior.CloseConnection) != 0; }
44  }
45 
46  private bool IsSequential {
47  get { return (behavior & CommandBehavior.SequentialAccess) != 0; }
48  }
49 
50  private T GetFinalValue<T>(int ordinal) where T : IConvertible {
51  var value = GetRuntimeValue(ordinal);
52  if (value == null || value == DBNull.Value)
53  return default(T);
54 
55  if (value is T)
56  return (T)value;
57 
58  if (!(value is IConvertible))
59  throw new InvalidCastException(String.Format("Cannot convert '{0}' to type '{1}'.", GetName(ordinal), typeof(T)));
60 
61  // TODO: Get the culture from the column and use it to convert ...
62  return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);
63  }
64 
65  private object GetRuntimeValue(int ordinal) {
66  if ((behavior & CommandBehavior.SchemaOnly) != 0)
67  return null;
68 
69  var value = command.CurrentResult.GetRuntimeValue(ordinal);
70  if (value == null || value == DBNull.Value)
71  return DBNull.Value;
72 
73  return value;
74  }
75 
76  private ISqlObject GetRawValue(int ordinal) {
77  if ((behavior & CommandBehavior.SchemaOnly) != 0)
78  return null;
79 
80  return command.CurrentResult.GetRawColumn(ordinal);
81  }
82 
83 
84  private QueryResultColumn GetColumn(int offset) {
85  return command.CurrentResult.GetColumn(offset);
86  }
87 
88  private int FindColumnIndex(string name) {
89  return command.CurrentResult.FindColumnIndex(name);
90  }
91 
92  public override void Close() {
93  try {
94  command.CurrentResult.Close();
95 
96  if (CloseConnection)
97  command.Connection.Close();
98  } catch (Exception ex) {
99  throw new DeveelDbException("An error occurred while closing the reader", ex);
100  } finally {
101  if (!CloseConnection)
102  command.Connection.EndState();
103  }
104  }
105 
106  protected override void Dispose(bool disposing) {
107  if (disposing) {
108  Close();
109  }
110 
111  base.Dispose(disposing);
112  }
113 
114  public override DataTable GetSchemaTable() {
115  if (FieldCount == 0)
116  return null;
117 
118  var table = new SysDataTable("ColumnsInfo");
119 
120  table.Columns.Add("Schema", typeof (string));
121  table.Columns.Add("Table", typeof (string));
122  table.Columns.Add("Name", typeof (string));
123  table.Columns.Add("FullName", typeof (string));
124  table.Columns.Add("SqlType", typeof (int));
125  table.Columns.Add("DbType", typeof (string));
126  table.Columns.Add("Type", typeof (string));
127  table.Columns.Add("Size", typeof (int));
128  table.Columns.Add("Scale", typeof (int));
129  table.Columns.Add("IsUnique", typeof (bool));
130  table.Columns.Add("IsNotNull", typeof (bool));
131  table.Columns.Add("IsSizeable", typeof (bool));
132  table.Columns.Add("IsNumeric", typeof (bool));
133  table.Columns.Add("UniqueGroup", typeof (int));
134 
135  for (int i = 0; i < FieldCount; i++) {
136  var row = table.NewRow();
137 
138  var column = GetColumn(i);
139 
140  string fullColumnName = column.Name;
141 
142  string schemaName = null;
143  string tableName = null;
144  string columnName = column.Name;
145  if (columnName.StartsWith("@f")) {
146  // this is a field, so take the table and schema of the field...
147  columnName = columnName.Substring(2, columnName.Length - 2);
148  fullColumnName = columnName;
149 
150  int index = columnName.IndexOf('.');
151  schemaName = columnName.Substring(0, index);
152  columnName = columnName.Substring(index + 1);
153 
154  index = columnName.IndexOf('.');
155  tableName = columnName.Substring(0, index);
156  columnName = columnName.Substring(index + 1);
157  } else if (columnName.StartsWith("@a")) {
158  // this is an alias: strip out the leading indicator...
159  columnName = columnName.Substring(2, columnName.Length - 2);
160  fullColumnName = columnName;
161  }
162 
163  row["Schema"] = schemaName;
164  row["Table"] = tableName;
165  row["Name"] = columnName;
166  row["FullName"] = fullColumnName;
167  row["SqlType"] = (int) column.Type.TypeCode;
168  row["DbType"] = column.Type.Name;
169  row["Size"] = column.Size;
170  row["Scale"] = column.Scale;
171  row["IsUnique"] = column.IsUnique;
172  row["IsQuantifiable"] = column.Type is ISizeableType;
173  row["IsNumeric"] = column.IsNumericType;
174  row["IsNotNull"] = column.IsNotNull;
175  row["UniqueGroup"] = column.UniqueGroup;
176 
177  table.Rows.Add(row);
178  }
179 
180  return table;
181  }
182 
183  public override bool NextResult() {
184  return command.NextResult();
185  }
186 
187  public override bool Read() {
188  if (wasRead && ((behavior & CommandBehavior.SingleRow)) != 0)
189  return false;
190 
191  if (command.CurrentResult.Next()) {
192  wasRead = true;
193  return true;
194  }
195 
196  return false;
197  }
198 
199  public override int Depth {
200  get { return 0; }
201  }
202 
203  public override bool IsClosed {
204  get { return command.CurrentResult.Closed; }
205  }
206 
207  public override int RecordsAffected {
208  get {
209  if (command.CurrentResult == null ||
210  !command.CurrentResult.IsUpdate)
211  return -1;
212 
213  return command.CurrentResult.AffectedRows;
214  }
215  }
216 
217  public override bool GetBoolean(int ordinal) {
218  return GetFinalValue<bool>(ordinal);
219  }
220 
221  public override byte GetByte(int ordinal) {
222  return GetFinalValue<byte>(ordinal);
223  }
224 
225  public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) {
226  throw new NotImplementedException();
227  }
228 
229  public override char GetChar(int ordinal) {
230  return GetFinalValue<char>(ordinal);
231  }
232 
233  public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) {
234  throw new NotImplementedException();
235  }
236 
237  public override Guid GetGuid(int ordinal) {
238  throw new NotImplementedException();
239  }
240 
241  public override short GetInt16(int ordinal) {
242  return GetFinalValue<short>(ordinal);
243  }
244 
245  public override int GetInt32(int ordinal) {
246  return GetFinalValue<int>(ordinal);
247  }
248 
249  public override long GetInt64(int ordinal) {
250  return GetFinalValue<long>(ordinal);
251  }
252 
253  public override DateTime GetDateTime(int ordinal) {
254  throw new NotImplementedException();
255  }
256 
257  public override string GetString(int ordinal) {
258  return GetFinalValue<string>(ordinal);
259  }
260 
261  public override object GetValue(int ordinal) {
262  return GetRuntimeValue(ordinal);
263  }
264 
265  public override int GetValues(object[] values) {
266  var colCount = System.Math.Min(FieldCount, values.Length);
267  for (int i = 0; i < colCount; i++) {
268  values[i] = GetValue(i);
269  }
270 
271  return colCount;
272  }
273 
274  public override bool IsDBNull(int ordinal) {
275  return GetRuntimeValue(ordinal) == DBNull.Value;
276  }
277 
278  public override int FieldCount {
279  get { return command.CurrentResult.ColumnCount; }
280  }
281 
282  public override object this[int ordinal] {
283  get { return GetValue(ordinal); }
284  }
285 
286  public override object this[string name] {
287  get { return GetValue(GetOrdinal(name)); }
288  }
289 
290  public override bool HasRows {
291  get { return command.CurrentResult.RowCount > 0; }
292  }
293 
294  public override decimal GetDecimal(int ordinal) {
295  throw new NotImplementedException();
296  }
297 
298  public override double GetDouble(int ordinal) {
299  return GetFinalValue<double>(ordinal);
300  }
301 
302  public override float GetFloat(int ordinal) {
303  return GetFinalValue<float>(ordinal);
304  }
305 
306  public override string GetName(int ordinal) {
307  string columnName = command.CurrentResult.GetColumn(ordinal).Name;
308  if (String.IsNullOrEmpty(columnName))
309  return String.Empty;
310  if (columnName.Length <= 2)
311  return columnName;
312 
313  if (columnName[0] == '@') {
314  if (columnName == "@aresult")
315  return String.Empty;
316 
317  columnName = columnName.Substring(2);
318  }
319 
320  return columnName;
321  }
322 
323  public override int GetOrdinal(string name) {
324  return FindColumnIndex(name);
325  }
326 
327  public override string GetDataTypeName(int ordinal) {
328  var column = command.CurrentResult.GetColumn(ordinal);
329  if (column == null)
330  return null;
331 
332  return column.Type.ToString().ToUpperInvariant();
333  }
334 
335  public override Type GetFieldType(int ordinal) {
336  throw new NotImplementedException();
337  }
338 
339  public override Type GetProviderSpecificFieldType(int ordinal) {
340  var column = command.CurrentResult.GetColumn(ordinal);
341  if (column == null)
342  return null;
343 
344  return column.ValueType;
345  }
346 
347  public override object GetProviderSpecificValue(int ordinal) {
348  return GetRawValue(ordinal);
349  }
350 
351  public override IEnumerator GetEnumerator() {
352  return new DbEnumerator(this);
353  }
354  }
355 }
A long string in the system.
override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)
override object GetProviderSpecificValue(int ordinal)
override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length)
override void Dispose(bool disposing)
override DateTime GetDateTime(int ordinal)
override double GetDouble(int ordinal)
override string GetName(int ordinal)
override decimal GetDecimal(int ordinal)
Defines the contract for a valid SQL Object
Definition: ISqlObject.cs:23
DeveelDbDataReader(DeveelDbCommand command, CommandBehavior behavior)
override bool GetBoolean(int ordinal)
override Type GetFieldType(int ordinal)
override string GetString(int ordinal)
override object GetValue(int ordinal)
QueryResultColumn GetColumn(int offset)
override short GetInt16(int ordinal)
override int GetValues(object[] values)
override float GetFloat(int ordinal)
override Type GetProviderSpecificFieldType(int ordinal)
override string GetDataTypeName(int ordinal)
System.Data.DataTable SysDataTable