AbstractDataReader.cs :  » 2.6.4-mono-.net-core » System.Data » System » Data » ProviderBase » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Data 
System.Data » System » Data » ProviderBase » AbstractDataReader.cs
//
// System.Data.Common.AbstractDataReader
//
// Authors:
//  Konstantin Triger <kostat@mainsoft.com>
//  Boris Kirzner <borisk@mainsoft.com>
//  
// (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
//

//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//


using System;
using System.Data;
using System.Collections;
using System.Data.Common;

using java.io;
using java.sql;

namespace System.Data.ProviderBase{
  public abstract class AbstractDataReader : DbDataReader, ISafeDataRecord {

    #region Fields

    private ResultSetMetaData _resultsMetaData;
    protected AbstractDbCommand _command;
    private DataTable _schemaTable;
    private ReaderState _readerState = ReaderState.Uninitialized;

    private IReaderCacheContainer[] _readerCache;
    private int _currentCacheFilledPosition; 
    private Stack _resultSetStack = new Stack();
    private bool _isClosed = false;

    [Flags]
    private enum ReaderState { Uninitialized = 0, Empty = 1, HasRows = 2, FirstRed = 4, Eof = 8, Fetching = 16 };

    protected internal enum SCHEMA_TABLE { ColumnName,
      ColumnOrdinal,
      ColumnSize,
      NumericPrecision,
      NumericScale,
      IsUnique,
      IsKey,
      BaseServerName,
      BaseCatalogName,
      BaseColumnName,
      BaseSchemaName,
      BaseTableName,
      DataType,
      AllowDBNull,
      ProviderType,
      IsAliased,
      IsExpression,
      IsIdentity,
      IsAutoIncrement,
      IsRowVersion,
      IsHidden,
      IsLong,
      IsReadOnly};

    #endregion // Fields

    #region Constructors
    
    protected AbstractDataReader(AbstractDbCommand command) {
      _command = command;
      if (_command.Connection != null) {
        ((AbstractDBConnection)_command.Connection).AddReference(this);
      }
    }

    #endregion // Constructors

    #region Properties

    public override int Depth {
      get { return 0; }
    }

    public override bool HasRows {
      get {
        if (IsClosed) {
          throw new InvalidOperationException("Invalid attempt to HasRows when reader is closed.");
        }

        try {
          if(null == Results)
            return false;
        }
        catch(SystemException) {
          //suppress
          return false;
        }

        return (_readerState & ReaderState.HasRows) != 0;
      }
    }

    public override int RecordsAffected
    {
      // MSDN : The RecordsAffected property is not set 
      // until all rows are read and you close the reader.
      get { 
        return _command.RecordsAffected; 
      }
    }

    public override int FieldCount
    {
      get {
        if (ResultsMetaData == null)
          return 0;

        try {
          return ResultsMetaData.getColumnCount();
        }
        catch (SQLException exp) {
          throw CreateException(exp);
        }

      }
    }

    protected internal CommandBehavior Behavior
    {
      get {
        return _command.Behavior;
      }
    }

    public override Object this[String columnName]
    {
      get {
        try {
          int columnIndex = Results.findColumn(columnName) - 1;
          return this[columnIndex];
        }
        catch (SQLException exp) {
          throw new IndexOutOfRangeException(exp.Message, exp);
        }        
      }
    }

    public override Object this[int columnIndex]
    {
      get { return GetValue(columnIndex); }
    }

    protected ResultSet Results
    {
      get {
        if (_readerState == ReaderState.Uninitialized) {

          if (_resultSetStack.Count == 0) {
            ResultSet resultSet =  _command.CurrentResultSet;
            if (resultSet == null)
              return null;

            _resultSetStack.Push(resultSet);
          }

          _readerState = ReaderState.Fetching;
          for (;;) {
            try {
              Configuration.BooleanSetting prefetchSchema = Configuration.Switches.PrefetchSchema;

              if (prefetchSchema == Configuration.BooleanSetting.NotSet) {
                AbstractDBConnection conn = (AbstractDBConnection)((ICloneable)_command.Connection);
                string driverName = conn.JdbcConnection.getMetaData().getDriverName();
                if (driverName.IndexOf("DB2", StringComparison.Ordinal) >= 0)
                  prefetchSchema = Configuration.BooleanSetting.True;
              }

              if (prefetchSchema == Configuration.BooleanSetting.True)
                GetSchemaTable();

              ResultSet resultSet = (ResultSet)_resultSetStack.Peek();
              if (resultSet.next()) {
                _readerState = (ReaderState.HasRows | ReaderState.FirstRed);
                ResultSetMetaData rsMetaData = ResultsMetaData;
                DbConvert.JavaSqlTypes javaSqlType = (DbConvert.JavaSqlTypes)rsMetaData.getColumnType(1);
                if (javaSqlType == DbConvert.JavaSqlTypes.OTHER) {
                  object value = GetValue(0);
                  if (value != null && value is ResultSet) {
                    _resultsMetaData = null;
                    _readerCache = null;
                    SchemaTable = null;
                    _readerState = ReaderState.Fetching;
                    _resultSetStack.Push(value);
                    continue;
                  }
                }
              }
              else
                _readerState = ReaderState.Empty;

              break;
            }
            catch(SQLException e) {
              throw CreateException(e);
            }
          }
        }

        return (_resultSetStack.Count > 0) ? (ResultSet)_resultSetStack.Peek() : null;
      }
    }

    protected ResultSetMetaData ResultsMetaData
    {
      get {
        ResultSet results = Results;
        if (results == null) {
          return null;
        }
        if(_resultsMetaData == null) {
          _resultsMetaData = results.getMetaData();
        }
        return _resultsMetaData;
      }      
    }

    protected DataTable SchemaTable
    {
      get {
        if (_schemaTable == null) {
          _schemaTable = ConstructSchemaTable();
        }
        return _schemaTable;
      }

      set {_schemaTable = value; }
    }

    internal protected IReaderCacheContainer[] ReaderCache
    {
      get {
        if (_readerCache == null) {
          _readerCache = CreateReaderCache();
          _currentCacheFilledPosition = -1;
        }
        return _readerCache;
      }
    }

    public override bool IsClosed {
      get { return _isClosed; }
    }

    #endregion // Properties

    #region Methods

    protected abstract int GetProviderType(int jdbcType);

    protected abstract SystemException CreateException(string message, SQLException e);

    protected abstract SystemException CreateException(IOException e);

    protected SystemException CreateException(SQLException e)
    {
      return CreateException(e.Message,e);  
    }

    private bool CloseCurrentResultSet() {
      if (_resultSetStack.Count > 0) {
        try{
          _resultsMetaData = null;
          _readerCache = null;
          _readerState = ReaderState.Uninitialized;
          ResultSet rs = (ResultSet)_resultSetStack.Pop();
          rs.close();
          return true;
        }
        catch (SQLException exp) {
          throw CreateException(exp);
        }
      }

      return false;
    }

    // FIXME : add Close(bool readAllRecords) and pass this bool to skip looping over NextResult(), override AbstractDbCommand.ExecuteScalar
    public override void Close()
    {
      if (IsClosed)
        return;

      try {
        CloseCurrentResultSet();
        _command.OnReaderClosed(this);
      }
      finally {
        CloseInternal();
      }
    }

    internal void CloseInternal()
    {
      _resultsMetaData = null;
      _readerCache = null;
      _isClosed = true;
    }

    public override IEnumerator GetEnumerator ()
    {
      bool closeReader = (Behavior & CommandBehavior.CloseConnection) != 0;
      return new DbEnumerator (this , closeReader);
    }

    public override bool NextResult()
    {
      CloseCurrentResultSet();

      if ((_command.Behavior & CommandBehavior.SingleResult) != 0) {
        while (CloseCurrentResultSet());
        while (_command.NextResultSet());
        return false;
      }

      try {
        while (_resultSetStack.Count > 0) {
          ResultSet rs = (ResultSet)_resultSetStack.Peek();

          if(!rs.next()) {
            CloseCurrentResultSet();
            continue;
          }

          // must be a ResultSet
          object childRs = rs.getObject(1);
          if (childRs != null) {
            SchemaTable = null;
            _resultSetStack.Push(childRs);
            return true;
          }
        }
      }
      catch (SQLException exp) {
        throw CreateException(exp);
      }
        
      if (_command.NextResultSet()) {
        SchemaTable = null;  
        return true;
      }
      return false;
    }

    public override bool Read()
    {
      if(null == Results ||
        (_readerState & (ReaderState.HasRows | ReaderState.Eof)) != ReaderState.HasRows)
        return false;

      bool firstRead = false;

      try {
        if ((_readerState & ReaderState.FirstRed) != 0) {
          firstRead = true;
          _readerState &= ~ReaderState.FirstRed;
          return true;
        }
        else {
          bool next = Results.next();

          if (!next)
            _readerState |= ReaderState.Eof;

          return next;
        }
      }      
      catch (SQLException exp) {
        // suppress exception as .Net does
        return false;
      }
      finally {
        // in case of first read we could sampled the first value
        // to see whether there is a resultset, so _currentCacheFilledPosition
        // might be already inited
        if (!firstRead)
          _currentCacheFilledPosition = -1;
      }
    }

    public override bool GetBoolean(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((BooleanReaderCacheContainer)ReaderCache[columnIndex]).GetBoolean();
    }

    public bool GetBooleanSafe(int columnIndex)
    {
      if (ReaderCache[columnIndex] is BooleanReaderCacheContainer) {
        return GetBoolean(columnIndex);
      }
      else {
        return Convert.ToBoolean(GetValue(columnIndex));
      }
    }

    public override byte GetByte(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((ByteReaderCacheContainer)ReaderCache[columnIndex]).GetByte();
    }

    public byte GetByteSafe(int columnIndex)
    {
      if (ReaderCache[columnIndex] is ByteReaderCacheContainer) {
        return GetByte(columnIndex);
      }
      else {
        return Convert.ToByte(GetValue(columnIndex));
      }
    }

    public override long GetBytes(
      int columnIndex,
      long dataIndex,
      byte[] buffer,
      int bufferIndex,
      int length)
    {
      FillReaderCache(columnIndex);
      return ((BytesReaderCacheContainer)ReaderCache[columnIndex])
        .GetBytes(dataIndex, buffer, bufferIndex, length);
    }

    public virtual byte[] GetBytes(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((BytesReaderCacheContainer)ReaderCache[columnIndex]).GetBytes();
    }

    public override char GetChar(int columnIndex)
    {
      FillReaderCache(columnIndex);
      string s = ((StringReaderCacheContainer)ReaderCache[columnIndex]).GetString();
      if(s == null) {
        return '\0';
      }
      return s[0];
    }

    public char GetCharSafe(int columnIndex)
    {
      if (ReaderCache[columnIndex] is StringReaderCacheContainer) {
        return GetChar(columnIndex);
      }
      else {
        return Convert.ToChar(GetValue(columnIndex));
      }
    }

    public override long GetChars(
      int columnIndex,
      long dataIndex,
      char[] buffer,
      int bufferIndex,
      int length)
    {
      FillReaderCache(columnIndex);
      return ((CharsReaderCacheContainer)ReaderCache[columnIndex])
        .GetChars(dataIndex, buffer, bufferIndex, length);
    }

    public override string GetDataTypeName(int columnIndex)
    {
      try {
        if (ResultsMetaData == null) {
          return String.Empty;
        }
        return ResultsMetaData.getColumnTypeName(columnIndex + 1);
      }
      catch (SQLException exp) {
        throw CreateException(exp);
      }
    }

    public override DateTime GetDateTime(int columnIndex)
    {
      return GetDateTimeUnsafe(columnIndex);
    }

    DateTime GetDateTimeUnsafe(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((DateTimeReaderCacheContainer)ReaderCache[columnIndex]).GetDateTime();
    }

    public DateTime GetDateTimeSafe(int columnIndex)
    {
      if (ReaderCache[columnIndex] is DateTimeReaderCacheContainer) {
        return GetDateTimeUnsafe(columnIndex);
      }
      else {
        return Convert.ToDateTime(GetValue(columnIndex));
      }
    }

    public virtual TimeSpan GetTimeSpan(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((TimeSpanReaderCacheContainer)ReaderCache[columnIndex]).GetTimeSpan();
    }

    public override Guid GetGuid(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((GuidReaderCacheContainer)ReaderCache[columnIndex]).GetGuid();
    }

    public override decimal GetDecimal(int columnIndex)
    {
      return GetDecimalUnsafe(columnIndex);
    }

    decimal GetDecimalUnsafe(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((DecimalReaderCacheContainer)ReaderCache[columnIndex]).GetDecimal();
    }

    public decimal GetDecimalSafe(int columnIndex)
    {
      if (ReaderCache[columnIndex] is DecimalReaderCacheContainer) {
        return GetDecimalUnsafe(columnIndex);
      }
      else {
        return Convert.ToDecimal(GetValue(columnIndex));
      }
    }

    public override double GetDouble(int columnIndex)
    {
      return GetDoubleUnsafe(columnIndex);
    }

    double GetDoubleUnsafe(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((DoubleReaderCacheContainer)ReaderCache[columnIndex]).GetDouble();
    }

    public double GetDoubleSafe(int columnIndex)
    {
      if (ReaderCache[columnIndex] is DoubleReaderCacheContainer) {
        return GetDoubleUnsafe(columnIndex);
      }
      else {
        return Convert.ToDouble(GetValue(columnIndex));
      }
    }

    public override float GetFloat(int columnIndex)
    {
      return GetFloatUnsafe(columnIndex);
    }

    float GetFloatUnsafe(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((FloatReaderCacheContainer)ReaderCache[columnIndex]).GetFloat();
    }

    public float GetFloatSafe(int columnIndex)
    {
      if (ReaderCache[columnIndex] is FloatReaderCacheContainer) {
        return GetFloatUnsafe(columnIndex);
      }
      else {
        return Convert.ToSingle(GetValue(columnIndex));
      }
    }

    public override short GetInt16(int columnIndex)
    {
      return GetInt16Unsafe(columnIndex);
    }

    short GetInt16Unsafe(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((Int16ReaderCacheContainer)ReaderCache[columnIndex]).GetInt16();
    }

    public short GetInt16Safe(int columnIndex)
    {
      if (ReaderCache[columnIndex] is Int16ReaderCacheContainer) {
        return GetInt16Unsafe(columnIndex);
      }
      else {
        return Convert.ToInt16(GetValue(columnIndex));
      }
    }

    public override int GetInt32(int columnIndex)
    {
      return GetInt32Unsafe(columnIndex);
    }

    int GetInt32Unsafe(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((Int32ReaderCacheContainer)ReaderCache[columnIndex]).GetInt32();
    }

    public int GetInt32Safe(int columnIndex)
    {
      if (ReaderCache[columnIndex] is Int32ReaderCacheContainer) {
        return GetInt32Unsafe(columnIndex);
      }
      else {
        return Convert.ToInt32(GetValue(columnIndex));
      }
    }

    public override long GetInt64(int columnIndex)
    {
      return GetInt64Unsafe(columnIndex);
    }

    long GetInt64Unsafe(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((Int64ReaderCacheContainer)ReaderCache[columnIndex]).GetInt64();
    }

    public long GetInt64Safe(int columnIndex)
    {
      if (ReaderCache[columnIndex] is Int64ReaderCacheContainer) {
        return GetInt64Unsafe(columnIndex);
      }
      else {
        return Convert.ToInt64(GetValue(columnIndex));
      }
    }

    public override string GetName(int columnIndex)
    {
      try {
        if (ResultsMetaData == null) {
          return String.Empty;
        }
        return ResultsMetaData.getColumnName(columnIndex + 1);
      }
      catch (SQLException exp) {
        throw new IndexOutOfRangeException(exp.Message, exp);
      }
    }

    public override int GetOrdinal(String columnName)
    {
      try {
        int retVal = Results.findColumn(columnName);
        if(retVal != -1) {
          retVal -= 1;
        }
        return  retVal;
      }
      catch (SQLException exp) {
        throw new IndexOutOfRangeException(exp.Message, exp);
      }
    }

    public override string GetString(int columnIndex)
    {
      return GetStringUnsafe(columnIndex);
    }

    string GetStringUnsafe(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ((StringReaderCacheContainer)ReaderCache[columnIndex]).GetString();
    }

    public string GetStringSafe(int columnIndex) {
      if (ReaderCache[columnIndex] is StringReaderCacheContainer) {
        return GetStringUnsafe(columnIndex);
      }
      else {
        return Convert.ToString(GetValue(columnIndex));
      }
    }

    public override object GetValue(int columnIndex)
    {
      FillReaderCache(columnIndex);
      if (ReaderCache[columnIndex].IsNull()) {
        return DBNull.Value;
      }
      return ReaderCache[columnIndex].GetValue();
    }

    public override int GetValues(Object[] values)
    {  
      int columnCount = FieldCount;
      int i = 0;
      for (; i < values.Length && i < columnCount; i++) {
        values[i] = GetValue(i);
      }
      return i;
    }

    private void FillReaderCache(int columnIndex)
    {
      try {
        IReaderCacheContainer[] readerCache = ReaderCache;
        if ((Behavior & CommandBehavior.SequentialAccess) == 0) {          
          while (_currentCacheFilledPosition < columnIndex) {
            _currentCacheFilledPosition++;
            readerCache[_currentCacheFilledPosition].Fetch(Results,_currentCacheFilledPosition, false);
          }          
        }
        else {
          readerCache[columnIndex].Fetch(Results,columnIndex, true);
        }
      }
      catch(SQLException e) {
        _currentCacheFilledPosition = -1;
        throw CreateException(e);
      }
      catch (IOException e) {
        _currentCacheFilledPosition = -1;
        throw CreateException(e);
      }
    }

    protected virtual IReaderCacheContainer CreateReaderCacheContainer(int jdbcType, int columnIndex) {
      switch ((DbConvert.JavaSqlTypes)jdbcType) {
        case DbConvert.JavaSqlTypes.ARRAY :
          return new ArrayReaderCacheContainer();
        case DbConvert.JavaSqlTypes.BIGINT :
          return new Int64ReaderCacheContainer();
        case DbConvert.JavaSqlTypes.BINARY :
        case DbConvert.JavaSqlTypes.VARBINARY :
        case DbConvert.JavaSqlTypes.LONGVARBINARY :
          return new BytesReaderCacheContainer();
        case DbConvert.JavaSqlTypes.BIT :
          return new BooleanReaderCacheContainer();
        case DbConvert.JavaSqlTypes.BLOB :
          return new BlobReaderCacheContainer();
        case DbConvert.JavaSqlTypes.VARCHAR:
        case DbConvert.JavaSqlTypes.CHAR :            
          if (String.CompareOrdinal("uniqueidentifier", ResultsMetaData.getColumnTypeName(columnIndex)) == 0) {
            return new GuidReaderCacheContainer();
          }
          else {
            return new StringReaderCacheContainer();
          }
        case DbConvert.JavaSqlTypes.CLOB :
          return new ClobReaderCacheContainer();
        case DbConvert.JavaSqlTypes.TIME :
          return new TimeSpanReaderCacheContainer();
        case DbConvert.JavaSqlTypes.DATE :
          AbstractDBConnection conn = (AbstractDBConnection)((ICloneable)_command.Connection);
          string driverName = conn.JdbcConnection.getMetaData().getDriverName();

          if (driverName.StartsWith("PostgreSQL")) {
            return new DateTimeReaderCacheContainer();
          }
          else
            goto case DbConvert.JavaSqlTypes.TIMESTAMP;
        case DbConvert.JavaSqlTypes.TIMESTAMP :        
          return new TimestampReaderCacheContainer();
        case DbConvert.JavaSqlTypes.DECIMAL :
        case DbConvert.JavaSqlTypes.NUMERIC :
          // jdbc driver for oracle identitfies both FLOAT and NUMBEr columns as 
          // java.sql.Types.NUMERIC (2), columnTypeName NUMBER, columnClassName java.math.BigDecimal 
          // therefore we relay on scale
          int scale = ResultsMetaData.getScale(columnIndex);
          if (scale == -127) {
            // Oracle db type FLOAT
            return new DoubleReaderCacheContainer();
          }
          else {
            return new DecimalReaderCacheContainer();
          }
        case DbConvert.JavaSqlTypes.DOUBLE :
        case DbConvert.JavaSqlTypes.FLOAT :
          return new DoubleReaderCacheContainer();
        case DbConvert.JavaSqlTypes.INTEGER :
          return new Int32ReaderCacheContainer();
        case DbConvert.JavaSqlTypes.LONGVARCHAR :
          return new StringReaderCacheContainer();
        case DbConvert.JavaSqlTypes.NULL :
          return new NullReaderCacheContainer();
        case DbConvert.JavaSqlTypes.REAL :
          return new FloatReaderCacheContainer();
        case DbConvert.JavaSqlTypes.REF :
          return new RefReaderCacheContainer();
        case DbConvert.JavaSqlTypes.SMALLINT :
          return new Int16ReaderCacheContainer();
        case DbConvert.JavaSqlTypes.TINYINT :
          return new ByteReaderCacheContainer();
        case DbConvert.JavaSqlTypes.DISTINCT :
        case DbConvert.JavaSqlTypes.JAVA_OBJECT :
        case DbConvert.JavaSqlTypes.OTHER :
        case DbConvert.JavaSqlTypes.STRUCT :
        default :
          return new ObjectReaderCacheContainer();
      }
    }

    private IReaderCacheContainer[] CreateReaderCache()
    {
      try {
        IReaderCacheContainer[] readerCache = new IReaderCacheContainer[FieldCount];
        for(int i=1; i <= readerCache.Length; i++)
          readerCache[i-1] = CreateReaderCacheContainer(ResultsMetaData.getColumnType(i), i);

        return readerCache;
      }
      catch(SQLException e) {
        throw CreateException(e);
      }
    }

    protected bool IsNumeric(int columnIndex)
    {
      return ReaderCache[columnIndex].IsNumeric();
    }

    public override bool IsDBNull(int columnIndex)
    {
      FillReaderCache(columnIndex);
      return ReaderCache[columnIndex].IsNull();
    }

    public override Type GetFieldType(int i)
    {
      try {
        int javaSqlType = ResultsMetaData.getColumnType(i + 1);
        return DbConvert.JavaSqlTypeToClrType(javaSqlType);
      }
      catch (SQLException exp) {
        throw new IndexOutOfRangeException(exp.Message, exp);
      }
    }

    public IDataReader GetData(int i)
    {
      throw new NotSupportedException();
    }

    protected virtual void SetSchemaType(DataRow schemaRow, ResultSetMetaData metaData, int columnIndex) {
      DbConvert.JavaSqlTypes columnType = (DbConvert.JavaSqlTypes)metaData.getColumnType(columnIndex);

      switch (columnType) {
        case DbConvert.JavaSqlTypes.ARRAY: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = typeof (java.sql.Array);
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.BIGINT: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfInt64;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.BINARY: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = true;
          break;
        }
        case DbConvert.JavaSqlTypes.BIT: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfBoolean;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.BLOB: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = true;
          break;
        }
        case DbConvert.JavaSqlTypes.VARCHAR:
        case DbConvert.JavaSqlTypes.CHAR: {
          // FIXME : specific for Microsoft SQl Server driver
          if (String.CompareOrdinal(metaData.getColumnTypeName(columnIndex), "uniqueidentifier") == 0) {
            schemaRow [(int)SCHEMA_TABLE.ProviderType] = DbType.Guid;
            schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfGuid;
            schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          }
          else
          if (String.CompareOrdinal(metaData.getColumnTypeName(columnIndex), "sql_variant") == 0) {
            schemaRow [(int)SCHEMA_TABLE.ProviderType] = DbType.Object;
            schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfObject;
            schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          }
          else {
            schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
            schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString;
            schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          }
          break;
        }
        case DbConvert.JavaSqlTypes.CLOB: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString; // instead og .java.sql.Clob
          schemaRow [(int)SCHEMA_TABLE.IsLong] = true;
          break;
        }
        case DbConvert.JavaSqlTypes.DATE: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDateTime;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
          //                else if(DbConvert.JavaSqlTypes.DISTINCT)
          //                {
          //                    schemaRow ["ProviderType = (int)GetProviderType((int)columnType);
          //                    schemaRow ["DataType = typeof (?);
          //                    schemaRow ["IsLong = false;
          //                }
        case DbConvert.JavaSqlTypes.DOUBLE: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDouble; // was typeof(float)
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.FLOAT: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDouble;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.REAL: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfFloat;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.INTEGER: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfInt32;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.JAVA_OBJECT: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfObject;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.LONGVARBINARY: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = true;
          break;
        }
        case DbConvert.JavaSqlTypes.LONGVARCHAR: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = true;
          break;
        }
        case DbConvert.JavaSqlTypes.DECIMAL:
        case DbConvert.JavaSqlTypes.NUMERIC: {
          int scale = ResultsMetaData.getScale(columnIndex);
          if (scale == -127) {
            schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
            schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDouble;
            schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          }
          else {
            schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
            schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDecimal;
            schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          }
          break;
        }
        case DbConvert.JavaSqlTypes.REF: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = typeof (java.sql.Ref);
          schemaRow [(int)SCHEMA_TABLE.IsLong] = true;
          break;
        }
        case DbConvert.JavaSqlTypes.SMALLINT: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfInt16;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.STRUCT: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = typeof (java.sql.Struct);
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.TIME: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfTimespan;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.TIMESTAMP: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDateTime;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.TINYINT: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByte;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = false;
          break;
        }
        case DbConvert.JavaSqlTypes.VARBINARY: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = GetProviderType((int)columnType);
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = true;
          break;
        }
        default: {
          schemaRow [(int)SCHEMA_TABLE.ProviderType] = DbType.Object;
          schemaRow [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfObject;
          schemaRow [(int)SCHEMA_TABLE.IsLong] = true;
          break;
        }
      }
    }

    public override DataTable GetSchemaTable()
    {
      if (SchemaTable.Rows != null && SchemaTable.Rows.Count > 0) {
        return SchemaTable;
      }
            
      ResultSetMetaData metaData;      
      if (Behavior == CommandBehavior.SchemaOnly) {
        try {
          metaData = ((PreparedStatement)_command.Statement).getMetaData();
        }
        catch(SQLException e) {
          throw CreateException("CommandBehaviour.SchemaOnly is not supported by the JDBC driver.",e);
        }
      }
      else {
        metaData = ResultsMetaData;
      }

      if (metaData == null) {
        return SchemaTable;
      }

      DatabaseMetaData dbMetaData = null;
      AbstractDBConnection clonedConnection = null;
      if ((_command.Behavior & CommandBehavior.KeyInfo) != 0) {
        clonedConnection = (AbstractDBConnection)((ICloneable)_command.Connection).Clone();

        try {
          clonedConnection.Open();
          dbMetaData = clonedConnection.JdbcConnection.getMetaData();
        }
        catch {
          //suppress
          if (clonedConnection != null) {
            clonedConnection.Close();
          }
        }      
      }
      
      try {
        int tmp;        
        for(int i = 1; i <= metaData.getColumnCount(); i++) {
          DataRow row = SchemaTable.NewRow ();
          string columnName = metaData.getColumnLabel(i);
          string baseColumnName = metaData.getColumnName(i);
  
          row [(int)SCHEMA_TABLE.ColumnName] = columnName; // maybe we should use metaData.getColumnLabel(i);
          row [(int)SCHEMA_TABLE.ColumnSize] = metaData.getColumnDisplaySize(i);
          row [(int)SCHEMA_TABLE.ColumnOrdinal]    = i - 1;
          try {
            // FIXME : workaround for Oracle JDBC driver bug
            // getPrecision on BLOB, CLOB, NCLOB throws NumberFormatException
            tmp = metaData.getPrecision(i);
          }
          catch(java.lang.NumberFormatException e) {
            // supress exception
            tmp = 255;
          }
          row [(int)SCHEMA_TABLE.NumericPrecision] = Convert.ToInt16(tmp > 255 ? 255 : tmp);
          tmp = metaData.getScale(i);
          row [(int)SCHEMA_TABLE.NumericScale] = Convert.ToInt16(tmp > 255 ? 255 : tmp);

          row [(int)SCHEMA_TABLE.BaseServerName] = DBNull.Value;
        
          string catalog = null;
          try {
            catalog = metaData.getCatalogName(i);
          }
          catch (Exception e) {
            // supress exception
          }
          if (catalog != null && catalog.Length == 0)
            catalog =  ((AbstractDBConnection)_command.Connection).JdbcConnection.getCatalog();
          row [(int)SCHEMA_TABLE.BaseCatalogName] = catalog;
          row [(int)SCHEMA_TABLE.BaseColumnName] = baseColumnName;

          string schemaName;
          string tableName;

          try {
            tableName = metaData.getTableName(i);
          }
          catch {
            tableName = null;
          }

          try {
            schemaName = metaData.getSchemaName(i);
          }
          catch {
            schemaName = null;
          }

          if (tableName != null && tableName.Length == 0)
            tableName = null;
          if (schemaName != null && schemaName.Length == 0)
            schemaName = null;

          row [(int)SCHEMA_TABLE.BaseSchemaName] = schemaName;
          row [(int)SCHEMA_TABLE.BaseTableName] = tableName;


          row [(int)SCHEMA_TABLE.AllowDBNull] = Convert.ToBoolean(metaData.isNullable(i));
        
          InitKeyInfo(row, dbMetaData, catalog, schemaName, tableName);
        
          row [(int)SCHEMA_TABLE.IsAliased] = columnName != baseColumnName;
          row [(int)SCHEMA_TABLE.IsExpression] = false;

          row [(int)SCHEMA_TABLE.IsAutoIncrement] = metaData.isAutoIncrement(i);

          row [(int)SCHEMA_TABLE.IsHidden] = false;
          row [(int)SCHEMA_TABLE.IsReadOnly] = metaData.isReadOnly(i);

          SetSchemaType(row, metaData, i);

          SchemaTable.Rows.Add (row);
        }
      }
      catch (SQLException e) {        
        throw CreateException(e);
      }
      finally {
        if (clonedConnection != null) {
          clonedConnection.Close();
        }
      }      
      return SchemaTable;
    }

    private void InitKeyInfo(DataRow row, DatabaseMetaData dbMetaData, String catalog, String schema, String table) {
      string column = (string)row [(int)SCHEMA_TABLE.BaseColumnName];

      row [(int)SCHEMA_TABLE.IsUnique] = false;
      row [(int)SCHEMA_TABLE.IsKey] = false;
      row [(int)SCHEMA_TABLE.IsIdentity] = false;
      row [(int)SCHEMA_TABLE.IsRowVersion] = false;

      if ((_command.Behavior & CommandBehavior.KeyInfo) == 0)
        return;

      if(table == null || column == null || dbMetaData == null)
        return;

      ResultSet versionCol = dbMetaData.getVersionColumns(catalog, schema, table);
      try {
        while(versionCol.next()) {
          if(versionCol.getString("COLUMN_NAME") == column) {
            if (DatabaseMetaData__Finals.versionColumnPseudo == versionCol.getShort("PSEUDO_COLUMN")) {
              row [(int)SCHEMA_TABLE.IsIdentity] = true;
              row [(int)SCHEMA_TABLE.IsRowVersion] = true;
            }
          }
        }
      }
      finally {
        versionCol.close();
      }

      ResultSet primaryKeys = dbMetaData.getPrimaryKeys(catalog,schema,table);
      bool primaryKeyExists = false;
      int columnCount = 0;
      try {
        while(primaryKeys.next()) {
          columnCount++;
          if(primaryKeys.getString("COLUMN_NAME") == column) {
            row [(int)SCHEMA_TABLE.IsKey] = true;
            primaryKeyExists = true;
          }
        }
        // column constitutes a key by itself, so it should be marked as unique 
        if ((columnCount == 1) && (((bool)row [(int)SCHEMA_TABLE.IsKey]) == true)) {
          row [(int)SCHEMA_TABLE.IsUnique] = true;
        }
      }
      finally {
        primaryKeys.close();
      }

      ResultSet indexInfoRes = dbMetaData.getIndexInfo(catalog,schema,table,true,false);
      string currentIndexName = null;
      columnCount = 0;
      bool belongsToCurrentIndex = false;
      bool atFirstIndex = true;
      bool uniqueKeyExists = false;
      try {
        while(indexInfoRes.next()) {
          if (indexInfoRes.getShort("TYPE") ==  DatabaseMetaData__Finals.tableIndexStatistic) {
            // index of type tableIndexStatistic identifies table statistics - ignore it
            continue;
          }
          
          uniqueKeyExists = true;
          string iname = indexInfoRes.getString("INDEX_NAME");
          if (currentIndexName == iname) {
            // we're within the rows of the same index 
            columnCount++;
          }
          else {
            // we jump to row of new index 
            if (belongsToCurrentIndex && columnCount == 1) {
              // there is a constraint of type UNIQUE that applies only to this column
              row [(int)SCHEMA_TABLE.IsUnique] = true;
            }

            if (currentIndexName != null) {
              atFirstIndex = false;
            }
            currentIndexName = iname;
            columnCount = 1;
            belongsToCurrentIndex = false;
          }

          if(indexInfoRes.getString("COLUMN_NAME") == column) {
            // FIXME : this will cause "spare" columns marked as IsKey. Needs future investigation.
            // only the first index we met should be marked as a key
            //if (atFirstIndex) {
              row [(int)SCHEMA_TABLE.IsKey] = true;
            //}
            belongsToCurrentIndex = true;            
          }
        }
        // the column appears in the last index, which is single-column
        if (belongsToCurrentIndex && columnCount == 1) {
          // there is a constraint of type UNIQUE that applies only to this column
          row [(int)SCHEMA_TABLE.IsUnique] = true;
        }
      }
      finally {
        indexInfoRes.close();
      }      

      if(!primaryKeyExists && !uniqueKeyExists) {
        ResultSet bestRowId = dbMetaData.getBestRowIdentifier(catalog, schema, table, DatabaseMetaData__Finals.bestRowTemporary, false);
        try {
          while(bestRowId.next()) {
            if(bestRowId.getString("COLUMN_NAME") == column)
              row [(int)SCHEMA_TABLE.IsKey] = true;
          }
        }
        finally {
          bestRowId.close();
        }
      }
    }

    protected static DataTable ConstructSchemaTable ()
    {
      Type booleanType = DbTypes.TypeOfBoolean;
      Type stringType = DbTypes.TypeOfString;
      Type intType = DbTypes.TypeOfInt32;
      Type typeType = DbTypes.TypeOfType;
      Type shortType = DbTypes.TypeOfInt16;

      DataTable schemaTable = new DataTable ("SchemaTable");
      schemaTable.Columns.Add ("ColumnName", stringType);
      schemaTable.Columns.Add ("ColumnOrdinal", intType);
      schemaTable.Columns.Add ("ColumnSize", intType);
      schemaTable.Columns.Add ("NumericPrecision", shortType);
      schemaTable.Columns.Add ("NumericScale", shortType);
      schemaTable.Columns.Add ("IsUnique", booleanType);
      schemaTable.Columns.Add ("IsKey", booleanType);
      schemaTable.Columns.Add ("BaseServerName", stringType);
      schemaTable.Columns.Add ("BaseCatalogName", stringType);
      schemaTable.Columns.Add ("BaseColumnName", stringType);
      schemaTable.Columns.Add ("BaseSchemaName", stringType);
      schemaTable.Columns.Add ("BaseTableName", stringType);
      schemaTable.Columns.Add ("DataType", typeType);
      schemaTable.Columns.Add ("AllowDBNull", booleanType);
      schemaTable.Columns.Add ("ProviderType", intType);
      schemaTable.Columns.Add ("IsAliased", booleanType);
      schemaTable.Columns.Add ("IsExpression", booleanType);
      schemaTable.Columns.Add ("IsIdentity", booleanType);
      schemaTable.Columns.Add ("IsAutoIncrement", booleanType);
      schemaTable.Columns.Add ("IsRowVersion", booleanType);
      schemaTable.Columns.Add ("IsHidden", booleanType);
      schemaTable.Columns.Add ("IsLong", booleanType);
      schemaTable.Columns.Add ("IsReadOnly", booleanType);
      return schemaTable;
    }

    #endregion // Methods
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.