1 //---------------------------------------------------------------------
2 // <copyright file="FunctionDetailsReader.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
10 using System.Collections.Generic;
12 using System.Data.Common;
13 using System.Data.EntityClient;
14 using System.Diagnostics;
15 using System.Data.Metadata.Edm;
17 namespace System.Data.Entity.Design.SsdlGenerator
20 /// The purpose of this class is to give us strongly typed access to the results of the reader.
21 /// NOTE: this class will dispose of the command when the reader is disposed.
23 internal abstract class FunctionDetailsReader : IDisposable
25 private DbDataReader _reader;
26 private EntityCommand _command;
27 private EntityConnection _connection;
28 private object[] _currentRow;
30 public static FunctionDetailsReader Create(EntityConnection connection, IEnumerable<EntityStoreSchemaFilterEntry> filters, Version storeSchemaModelVersion)
32 Debug.Assert(connection != null, "the parameter connection is null");
33 Debug.Assert(connection.State == ConnectionState.Open, "the connection is not Open");
35 if (storeSchemaModelVersion >= EntityFrameworkVersions.Version3)
37 return new FunctionDetailsReaderV3(connection, filters);
41 return new FunctionDetailsReaderV1(connection, filters);
45 protected void InitializeReader(EntityConnection connection, IEnumerable<EntityStoreSchemaFilterEntry> filters)
47 _connection = connection;
49 _command = EntityStoreSchemaGeneratorDatabaseSchemaLoader.CreateFilteredCommand(
52 FunctionOrderByClause,
53 EntityStoreSchemaFilterObjectTypes.Function,
54 new List<EntityStoreSchemaFilterEntry>(filters),
55 new string[] { FunctionDetailAlias });
56 _reader = _command.ExecuteReader(CommandBehavior.SequentialAccess);
61 Debug.Assert(_reader != null, "don't Read() when it is created from a memento");
62 bool haveRow = _reader.Read();
65 if (_currentRow == null)
67 _currentRow = new object[ColumnCount];
69 _reader.GetValues(_currentRow);
80 // Technically, calling GC.SuppressFinalize is not required because the class does not
81 // have a finalizer, but it does no harm, protects against the case where a finalizer is added
82 // in the future, and prevents an FxCop warning.
83 GC.SuppressFinalize(this);
84 Debug.Assert(_reader != null, "don't Dispose() when it is created from a memento");
89 internal abstract int ColumnCount { get; }
91 public abstract string Catalog { get; }
93 public abstract string Schema { get; }
95 public abstract string ProcedureName { get; }
97 public abstract string ReturnType { get; }
99 public abstract bool IsIsAggregate { get; }
101 public abstract bool IsBuiltIn { get; }
103 public abstract bool IsComposable { get; }
105 public abstract bool IsNiladic { get; }
107 public abstract bool IsTvf { get; }
109 public abstract string ParameterName { get; }
111 public abstract bool IsParameterNameNull { get; }
113 public abstract string ParameterType { get; }
115 public abstract bool IsParameterTypeNull { get; }
117 public abstract string ProcParameterMode { get; }
119 public abstract bool IsParameterModeNull { get; }
121 public bool TryGetParameterMode(out ParameterMode mode)
123 if (IsParameterModeNull)
125 mode = (ParameterMode)(-1);
129 switch (ProcParameterMode)
132 mode = ParameterMode.In;
135 mode = ParameterMode.Out;
138 mode = ParameterMode.InOut;
141 mode = (ParameterMode)(-1);
146 internal EntityStoreSchemaGenerator.DbObjectKey CreateDbObjectKey()
148 Debug.Assert(_currentRow != null, "don't call this method when you not reading");
149 return new EntityStoreSchemaGenerator.DbObjectKey(this.Catalog, this.Schema, this.ProcedureName, EntityStoreSchemaGenerator.DbObjectType.Function);
152 protected static T ConvertDBNull<T>(object value)
154 return Convert.IsDBNull(value) ? default(T) : (T)value;
157 public abstract void Attach(Memento memento);
159 public abstract Memento CreateMemento();
161 private static readonly string FunctionDetailAlias = "sp";
162 protected abstract string FunctionDetailSql { get; }
163 private static readonly string FunctionOrderByClause = @"
170 internal sealed class FunctionDetailsReaderV1 : FunctionDetailsReader
172 internal FunctionDetailsReaderV1(MementoV1 memento)
174 _currentRow = memento.Values;
177 public FunctionDetailsReaderV1(EntityConnection connection, IEnumerable<EntityStoreSchemaFilterEntry> filters)
179 InitializeReader(connection, filters);
182 public override void Attach(Memento memento)
184 Debug.Assert(memento != null, "the parameter memento is null");
185 Debug.Assert(memento.Values != null, "the values in the memento are null");
186 Debug.Assert(memento is MementoV1, "the memento is for a different version");
187 Debug.Assert(_reader == null, "don't attach to a real reader");
188 _currentRow = memento.Values;
191 public override Memento CreateMemento()
193 Debug.Assert(_currentRow != null, "don't call this method when you not reading");
194 return new MementoV1((object[])_currentRow.Clone());
197 const int PROC_SCHEMA_INDEX = 0;
198 const int PROC_NAME_INDEX = 1;
199 const int PROC_RET_TYPE_INDEX = 2;
200 const int PROC_ISAGGREGATE_INDEX = 3;
201 const int PROC_ISCOMPOSABLE_INDEX = 4;
202 const int PROC_ISBUILTIN_INDEX = 5;
203 const int PROC_ISNILADIC_INDEX = 6;
204 const int PARAM_NAME_INDEX = 7;
205 const int PARAM_TYPE_INDEX = 8;
206 const int PARAM_DIRECTION_INDEX = 9;
208 internal override int ColumnCount { get { return 10; } }
210 public override string Catalog { get { return null; } }
212 public override string Schema
214 get { return ConvertDBNull<string>(_currentRow[PROC_SCHEMA_INDEX]); }
217 public override string ProcedureName
219 get { return ConvertDBNull<string>(_currentRow[PROC_NAME_INDEX]); }
222 public override string ReturnType
224 get { return ConvertDBNull<string>(_currentRow[PROC_RET_TYPE_INDEX]); }
227 public override bool IsIsAggregate
229 get { return ConvertDBNull<bool>(_currentRow[PROC_ISAGGREGATE_INDEX]); }
232 public override bool IsBuiltIn
234 get { return ConvertDBNull<bool>(_currentRow[PROC_ISBUILTIN_INDEX]); }
237 public override bool IsComposable
239 get { return ConvertDBNull<bool>(_currentRow[PROC_ISCOMPOSABLE_INDEX]); }
242 public override bool IsNiladic
244 get { return ConvertDBNull<bool>(_currentRow[PROC_ISNILADIC_INDEX]); }
247 public override bool IsTvf { get { return false; } }
249 public override string ParameterName
251 get { return (string)_currentRow[PARAM_NAME_INDEX]; }
254 public override bool IsParameterNameNull
256 get { return Convert.IsDBNull(_currentRow[PARAM_NAME_INDEX]); }
259 public override string ParameterType
261 get { return (string)_currentRow[PARAM_TYPE_INDEX]; }
264 public override bool IsParameterTypeNull
266 get { return Convert.IsDBNull(_currentRow[PARAM_TYPE_INDEX]); }
269 public override string ProcParameterMode
271 get { return (string)_currentRow[PARAM_DIRECTION_INDEX]; }
274 public override bool IsParameterModeNull
276 get { return Convert.IsDBNull(_currentRow[PARAM_DIRECTION_INDEX]); }
279 protected override string FunctionDetailSql
297 r.CatalogName as CatalogName
298 , r.SchemaName as SchemaName
300 , r.ReturnType.TypeName as ReturnTypeName
301 , r.IsAggregate as IsAggregate
302 , true as IsComposable
303 , r.IsBuiltIn as IsBuiltIn
304 , r.IsNiladic as IsNiladic
305 , p.Name as ParameterName
306 , p.ParameterType.TypeName as ParameterType
308 , p.Ordinal as Ordinal
310 OfType(SchemaInformation.Functions, Store.ScalarFunction) as r
315 r.CatalogName as CatalogName
316 , r.SchemaName as SchemaName
318 , CAST(NULL as string) as ReturnTypeName
319 , false as IsAggregate
320 , false as IsComposable
323 , p.Name as ParameterName
324 , p.ParameterType.TypeName as ParameterType
326 , p.Ordinal as Ordinal
328 SchemaInformation.Procedures as r
330 r.Parameters as p)) as sp
336 internal sealed class FunctionDetailsReaderV3 : FunctionDetailsReader
338 internal FunctionDetailsReaderV3(MementoV3 memento)
340 _currentRow = memento.Values;
343 public FunctionDetailsReaderV3(EntityConnection connection, IEnumerable<EntityStoreSchemaFilterEntry> filters)
345 InitializeReader(connection, filters);
348 public override void Attach(Memento memento)
350 Debug.Assert(memento != null, "the parameter memento is null");
351 Debug.Assert(memento.Values != null, "the values in the memento are null");
352 Debug.Assert(memento is MementoV3, "the memento is for a different version");
353 Debug.Assert(_reader == null, "don't attach to a real reader");
354 _currentRow = memento.Values;
357 public override Memento CreateMemento()
359 Debug.Assert(_currentRow != null, "don't call this method when you not reading");
360 return new MementoV3((object[])_currentRow.Clone());
363 const int PROC_CATALOG_INDEX = 0;
364 const int PROC_SCHEMA_INDEX = 1;
365 const int PROC_NAME_INDEX = 2;
366 const int PROC_RET_TYPE_INDEX = 3;
367 const int PROC_ISAGGREGATE_INDEX = 4;
368 const int PROC_ISCOMPOSABLE_INDEX = 5;
369 const int PROC_ISBUILTIN_INDEX = 6;
370 const int PROC_ISNILADIC_INDEX = 7;
371 const int PROC_ISTVF_INDEX = 8;
372 const int PARAM_NAME_INDEX = 9;
373 const int PARAM_TYPE_INDEX = 10;
374 const int PARAM_DIRECTION_INDEX = 11;
376 internal override int ColumnCount { get { return 12; } }
378 public override string Catalog
380 get { return ConvertDBNull<string>(_currentRow[PROC_CATALOG_INDEX]); }
383 public override string Schema
385 get { return ConvertDBNull<string>(_currentRow[PROC_SCHEMA_INDEX]); }
388 public override string ProcedureName
390 get { return ConvertDBNull<string>(_currentRow[PROC_NAME_INDEX]); }
393 public override string ReturnType
395 get { return ConvertDBNull<string>(_currentRow[PROC_RET_TYPE_INDEX]); }
398 public override bool IsIsAggregate
400 get { return ConvertDBNull<bool>(_currentRow[PROC_ISAGGREGATE_INDEX]); }
403 public override bool IsBuiltIn
405 get { return ConvertDBNull<bool>(_currentRow[PROC_ISBUILTIN_INDEX]); }
408 public override bool IsComposable
410 get { return ConvertDBNull<bool>(_currentRow[PROC_ISCOMPOSABLE_INDEX]); }
413 public override bool IsNiladic
415 get { return ConvertDBNull<bool>(_currentRow[PROC_ISNILADIC_INDEX]); }
418 public override bool IsTvf
420 get { return ConvertDBNull<bool>(_currentRow[PROC_ISTVF_INDEX]); }
423 public override string ParameterName
425 get { return (string)_currentRow[PARAM_NAME_INDEX]; }
428 public override bool IsParameterNameNull
430 get { return Convert.IsDBNull(_currentRow[PARAM_NAME_INDEX]); }
433 public override string ParameterType
435 get { return (string)_currentRow[PARAM_TYPE_INDEX]; }
438 public override bool IsParameterTypeNull
440 get { return Convert.IsDBNull(_currentRow[PARAM_TYPE_INDEX]); }
443 public override string ProcParameterMode
445 get { return (string)_currentRow[PARAM_DIRECTION_INDEX]; }
448 public override bool IsParameterModeNull
450 get { return Convert.IsDBNull(_currentRow[PARAM_DIRECTION_INDEX]); }
453 protected override string FunctionDetailSql
458 Function IsTvf(f Store.Function) as (f is of (Store.TableValuedFunction))
474 r.CatalogName as CatalogName
475 , r.SchemaName as SchemaName
477 , TREAT(r as Store.ScalarFunction).ReturnType.TypeName as ReturnTypeName
478 , TREAT(r as Store.ScalarFunction).IsAggregate as IsAggregate
479 , true as IsComposable
480 , r.IsBuiltIn as IsBuiltIn
481 , r.IsNiladic as IsNiladic
483 , p.Name as ParameterName
484 , p.ParameterType.TypeName as ParameterType
486 , p.Ordinal as Ordinal
488 SchemaInformation.Functions as r
493 r.CatalogName as CatalogName
494 , r.SchemaName as SchemaName
496 , CAST(NULL as string) as ReturnTypeName
497 , false as IsAggregate
498 , false as IsComposable
502 , p.Name as ParameterName
503 , p.ParameterType.TypeName as ParameterType
505 , p.Ordinal as Ordinal
507 SchemaInformation.Procedures as r
509 r.Parameters as p)) as sp
515 internal abstract class Memento
517 protected object[] _values;
519 internal object[] Values
521 get { return _values; }
524 public abstract FunctionDetailsReader CreateReader();
527 internal sealed class MementoV1 : Memento
529 internal MementoV1(object[] values)
534 public override FunctionDetailsReader CreateReader()
536 return new FunctionDetailsReaderV1(this);
540 internal sealed class MementoV3 : Memento
542 internal MementoV3(object[] values)
547 public override FunctionDetailsReader CreateReader()
549 return new FunctionDetailsReaderV3(this);