X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FNpgsql%2FNpgsql%2FNpgsqlDataReader.cs;h=1594d87f22f0030aabb8ec53ba389e529a1aecd3;hb=c39145af2464b19374fac41b252e07480ae1a197;hp=5b6e321472ace051d972b1e5f23f1a8468ff6d4c;hpb=c0ea39b2d6a67619e0064247063dc4771611e74b;p=mono.git diff --git a/mcs/class/Npgsql/Npgsql/NpgsqlDataReader.cs b/mcs/class/Npgsql/Npgsql/NpgsqlDataReader.cs index 5b6e321472a..1594d87f22f 100755 --- a/mcs/class/Npgsql/Npgsql/NpgsqlDataReader.cs +++ b/mcs/class/Npgsql/Npgsql/NpgsqlDataReader.cs @@ -1,507 +1,721 @@ - -// Npgsql.NpgsqlDataReader.cs -// -// Author: -// Francisco Jr. (fxjrlists@yahoo.com.br) -// -// Copyright (C) 2002 The Npgsql Development Team -// - -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -using System; -using System.Data; -using System.Collections; - - -namespace Npgsql -{ - public class NpgsqlDataReader : IDataReader, IEnumerable - { - private NpgsqlConnection _connection; - private ArrayList _resultsets; - private ArrayList _responses; - private Int32 _rowIndex; - private Int32 _resultsetIndex; - private NpgsqlResultSet _currentResultset; - private DataTable _currentResultsetSchema; - - - // Logging related values - private static readonly String CLASSNAME = "NpgsqlDataReader"; - - internal NpgsqlDataReader( ArrayList resultsets, ArrayList responses, NpgsqlConnection connection) - { - _resultsets = resultsets; - _responses = responses; - _connection = connection; - _rowIndex = -1; - _resultsetIndex = 0; - - _currentResultset = (NpgsqlResultSet)_resultsets[_resultsetIndex]; - - - - } - - private Boolean CanRead() - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".CanRead() ", LogLevel.Debug); - /*if (_currentResultset == null) - return false;*/ - return (_currentResultset != null); - - } - - - public void Dispose() - { - - } - - public Int32 Depth - { - get - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_Depth() ", LogLevel.Debug); - return 0; - } - } - - public Boolean IsClosed - { - get - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_IsClosed()", LogLevel.Debug); - return false; - } - } - - public Int32 RecordsAffected - { - get - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_RecordsAffected()", LogLevel.Debug); - - /*if (_currentResultset == null) - return 0; //[FIXME] Get the actual number of rows deleted, updated or inserted. - return -1; - */ - - if (CanRead()) - return -1; - - String[] ret_string_tokens = ((String)_responses[_resultsetIndex]).Split(null); // whitespace separator. - - return Int32.Parse(ret_string_tokens[ret_string_tokens.Length - 1]); - } - - } - - public void Close() - { - - } - - public Boolean NextResult() - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".NextResult()", LogLevel.Debug); - //throw new NotImplementedException(); - - //[FIXME] Should the currentResultset not be modified - // in case there aren't any more resultsets? - // SqlClient modify to a invalid resultset and throws exceptions - // when trying to access any data. - - - if((_resultsetIndex + 1) < _resultsets.Count) - { - _resultsetIndex++; - _rowIndex = -1; - _currentResultset = (NpgsqlResultSet)_resultsets[_resultsetIndex]; - return true; - } - else - return false; - - } - - public Boolean Read() - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".Read()", LogLevel.Debug); - - if (!CanRead()) - return false; - - _rowIndex++; - return (_rowIndex < _currentResultset.Count); - } - - public DataTable GetSchemaTable() - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetSchemaTable()", LogLevel.Debug); - //throw new NotImplementedException(); - - if (!CanRead()) - return null; //[FIXME] Should we return null or throw an exception?? - - if(_currentResultsetSchema == null) - _currentResultsetSchema = GetResultsetSchema(); - - return _currentResultsetSchema; - - } - - - public Int32 FieldCount - { - get - { - - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".get_FieldCount()", LogLevel.Debug); - //return ((_currentResultset == null) ? 0 : _currentResultset.RowDescription.NumFields); - if (CanRead()) - return _currentResultset.RowDescription.NumFields; - else - return -1; - - } - - } - - public String GetName(Int32 i) - { - //throw new NotImplementedException(); - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetName(Int32)", LogLevel.Debug); - - if (CanRead()) - return _currentResultset.RowDescription[i].name; - else - return String.Empty; - } - - public String GetDataTypeName(Int32 i) - { - // FIXME: have a type name instead of the oid - return (_currentResultset.RowDescription[i].type_oid).ToString(); - } - - public Type GetFieldType(Int32 i) - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetFieldType(Int32)", LogLevel.Debug); - //[FIXME] hack - - return Type.GetType(PGUtil.GetSystemTypeFromDbType(_currentResultset.RowDescription[i].type_oid)); - } - - public Object GetValue(Int32 i) - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetValue(Int32)", LogLevel.Debug); - if (i < 0 || _rowIndex < 0) - throw new InvalidOperationException("Cannot read data."); - return ((NpgsqlAsciiRow)_currentResultset[_rowIndex])[i]; - } - - public Int32 GetValues(Object[] values) - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetValues(Object[])", LogLevel.Debug); - - // Only the number of elements in the array are filled. - // It's also possible to pass an array with more that FieldCount elements. - Int32 maxColumnIndex = (values.Length < FieldCount) ? values.Length : FieldCount; - - for (Int32 i = 0; i < maxColumnIndex; i++) - values[i] = GetValue(i); - - return maxColumnIndex; - - } - - public Int32 GetOrdinal(String name) - { - return _currentResultset.RowDescription.FieldIndex(name); - } - - public Object this [ Int32 i ] - { - get - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".this[Int32]", LogLevel.Debug); - return GetValue(i); - } - } - - public Object this [ String name ] - { - get - { - //throw new NotImplementedException(); - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".this[String]", LogLevel.Debug); - return GetValue(_currentResultset.RowDescription.FieldIndex(name)); - } - } - - public Boolean GetBoolean(Int32 i) - { - // Should this be done using the GetValue directly and not by converting to String - // and parsing from there? - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetBoolean(Int32)", LogLevel.Debug); - - switch ((String) this[i]) - { - case "t": - return true; - - case "f": - return false; - - default: - throw new System.InvalidCastException(); - - } - - } - - public Byte GetByte(Int32 i) - { - throw new NotImplementedException(); - } - - public Int64 GetBytes(Int32 i, Int64 fieldOffset, Byte[] buffer, Int32 bufferoffset, Int32 length) - { - throw new NotImplementedException(); - } - - public Char GetChar(Int32 i) - { - throw new NotImplementedException(); - } - - public Int64 GetChars(Int32 i, Int64 fieldoffset, Char[] buffer, Int32 bufferoffset, Int32 length) - { - String str; - - str = GetString(i); - if (buffer == null) - return str.Length; - - str.ToCharArray(bufferoffset, length).CopyTo(buffer, 0); - return buffer.GetLength(0); - } - - public Guid GetGuid(Int32 i) - { - throw new NotImplementedException(); - } - - public Int16 GetInt16(Int32 i) - { - // Should this be done using the GetValue directly and not by converting to String - // and parsing from there? - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt16(Int32)", LogLevel.Debug); - try - { - return Int16.Parse((String) this[i]); - } catch (System.FormatException) - { - throw new System.InvalidCastException(); - } - - - } - - public Int32 GetInt32(Int32 i) - { - // Should this be done using the GetValue directly and not by converting to String - // and parsing from there? - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt32(Int32)", LogLevel.Debug); - try - { - return Int32.Parse((String) this[i]); - } catch (System.FormatException) - { - throw new System.InvalidCastException(); - } - - - } - - public Int64 GetInt64(Int32 i) - { - // Should this be done using the GetValue directly and not by converting to String - // and parsing from there? - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt64(Int32)", LogLevel.Debug); - try - { - return Int64.Parse((String) this[i]); - } catch (System.FormatException) - { - throw new System.InvalidCastException(); - } - } - - public Single GetFloat(Int32 i) - { - // Should this be done using the GetValue directly and not by converting to String - // and parsing from there? - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetFloat(Int32)", LogLevel.Debug); - try - { - return Single.Parse((String) this[i]); - } catch (System.FormatException) - { - throw new System.InvalidCastException(); - } - } - - public Double GetDouble(Int32 i) - { - // Should this be done using the GetValue directly and not by converting to String - // and parsing from there? - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetDouble(Int32)", LogLevel.Debug); - try - { - return Double.Parse((String) this[i]); - } catch (System.FormatException) - { - throw new System.InvalidCastException(); - } - } - - public String GetString(Int32 i) - { - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetString(Int32)", LogLevel.Debug); - return (String) GetValue(i); - } - - public Decimal GetDecimal(Int32 i) - { - // Should this be done using the GetValue directly and not by converting to String - // and parsing from there? - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetDecimal(Int32)", LogLevel.Debug); - try - { - return Decimal.Parse((String) this[i]); - } catch (System.FormatException) - { - throw new System.InvalidCastException(); - } - } - - public DateTime GetDateTime(Int32 i) - { - // Should this be done using the GetValue directly and not by converting to String - // and parsing from there? - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetInt32(Int32)", LogLevel.Debug); - try { - // FIXME: here until DateTime works - string sValue = (string) this[i]; - Console.WriteLine("GetDateTime: " + sValue); - - return DateTime.Now; - } catch (System.FormatException) { - throw new System.InvalidCastException(); - } - } - - public IDataReader GetData(Int32 i) - { - throw new NotImplementedException(); - } - - public Boolean IsDBNull(Int32 i) - { - //throw new NotImplementedException(); - - return ((NpgsqlAsciiRow)_currentResultset[_rowIndex]).IsNull(i); - } - - private DataTable GetResultsetSchema() - { - DataTable result = null; - NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".GetResultsetSchema()", LogLevel.Debug); - // [FIXME] For now, just support fields name. - - NpgsqlRowDescription rd = _currentResultset.RowDescription; - Int16 numFields = rd.NumFields; - if(numFields > 0) { - result = new DataTable("SchemaTable"); - - result.Columns.Add ("ColumnName", typeof (string)); - result.Columns.Add ("ColumnOrdinal", typeof (int)); - result.Columns.Add ("ColumnSize", typeof (int)); - result.Columns.Add ("NumericPrecision", typeof (int)); - result.Columns.Add ("NumericScale", typeof (int)); - result.Columns.Add ("IsUnique", typeof (bool)); - result.Columns.Add ("IsKey", typeof (bool)); - DataColumn dc = result.Columns["IsKey"]; - dc.AllowDBNull = true; // IsKey can have a DBNull - result.Columns.Add ("BaseCatalogName", typeof (string)); - result.Columns.Add ("BaseColumnName", typeof (string)); - result.Columns.Add ("BaseSchemaName", typeof (string)); - result.Columns.Add ("BaseTableName", typeof (string)); - result.Columns.Add ("DataType", typeof(Type)); - result.Columns.Add ("AllowDBNull", typeof (bool)); - result.Columns.Add ("ProviderType", typeof (int)); - result.Columns.Add ("IsAliased", typeof (bool)); - result.Columns.Add ("IsExpression", typeof (bool)); - result.Columns.Add ("IsIdentity", typeof (bool)); - result.Columns.Add ("IsAutoIncrement", typeof (bool)); - result.Columns.Add ("IsRowVersion", typeof (bool)); - result.Columns.Add ("IsHidden", typeof (bool)); - result.Columns.Add ("IsLong", typeof (bool)); - result.Columns.Add ("IsReadOnly", typeof (bool)); - - DataRow row; - - for (Int16 i = 0; i < numFields; i++) { - row = result.NewRow(); - - row["ColumnName"] = GetName(i); - row["ColumnOrdinal"] = i + 1; - row["ColumnSize"] = (int) rd[i].type_size; - row["NumericPrecision"] = 0; - row["NumericScale"] = 0; - row["IsUnique"] = false; - row["IsKey"] = DBNull.Value; - row["BaseCatalogName"] = ""; - row["BaseColumnName"] = GetName(i); - row["BaseSchemaName"] = ""; - row["BaseTableName"] = ""; - row["DataType"] = GetFieldType(i); - row["AllowDBNull"] = false; - row["ProviderType"] = (int) rd[i].type_oid; - row["IsAliased"] = false; - row["IsExpression"] = false; - row["IsIdentity"] = false; - row["IsAutoIncrement"] = false; - row["IsRowVersion"] = false; - row["IsHidden"] = false; - row["IsLong"] = false; - row["IsReadOnly"] = false; - - result.Rows.Add(row); - } - } - - return result; - - } - - IEnumerator IEnumerable.GetEnumerator () { - return new System.Data.Common.DbEnumerator (this); - } - } -} + +// Npgsql.NpgsqlDataReader.cs +// +// Author: +// Francisco Jr. (fxjrlists@yahoo.com.br) +// +// Copyright (C) 2002 The Npgsql Development Team +// npgsql-general@gborg.postgresql.org +// http://gborg.postgresql.org/project/npgsql/projdisplay.php +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Collections; + +using NpgsqlTypes; + +namespace Npgsql +{ + /// + /// Provides a means of reading a forward-only stream of rows from a PostgreSQL backend. This class cannot be inherited. + /// + public sealed class NpgsqlDataReader : IDataReader, IEnumerable + { + private NpgsqlConnection _connection; + private ArrayList _resultsets; + private ArrayList _responses; + private Int32 _rowIndex; + private Int32 _resultsetIndex; + private NpgsqlResultSet _currentResultset; + private DataTable _currentResultsetSchema; + private CommandBehavior _behavior; + private Boolean _isClosed; + + + // Logging related values + private static readonly String CLASSNAME = "NpgsqlDataReader"; + + internal NpgsqlDataReader( ArrayList resultsets, ArrayList responses, NpgsqlConnection connection, CommandBehavior behavior) + { + _resultsets = resultsets; + _responses = responses; + _connection = connection; + _rowIndex = -1; + _resultsetIndex = 0; + + if (_resultsets.Count > 0) + _currentResultset = (NpgsqlResultSet)_resultsets[_resultsetIndex]; + + _behavior = behavior; + _isClosed = false; + } + + private Boolean HaveResultSet() + { + return (_currentResultset != null); + } + + private Boolean HaveRow() + { + return (HaveResultSet() && _rowIndex >= 0 && _rowIndex < _currentResultset.Count); + } + + private void CheckHaveResultSet() + { + if (! HaveResultSet()) + { + throw new InvalidOperationException("Cannot read data. No result set."); + } + } + + private void CheckHaveRow() + { + CheckHaveResultSet(); + + if (_rowIndex < 0) + { + throw new InvalidOperationException("DataReader positioned before beginning of result set. Did you call Read()?"); + } + else if (_rowIndex >= _currentResultset.Count) + { + throw new InvalidOperationException("DataReader positioned beyond end of result set."); + } + } + + + /// + /// Releases the resources used by the NpgsqlCommand. + /// + public void Dispose() + { + Dispose(true); + } + + /// + /// Releases the resources used by the NpgsqlCommand. + /// + protected void Dispose (bool disposing) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Dispose"); + if (disposing) + { + this.Close(); + } + } + + /// + /// Gets a value indicating the depth of nesting for the current row. Always returns zero. + /// + public Int32 Depth + { + get + { + NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "Depth"); + return 0; + } + } + + /// + /// Gets a value indicating whether the data reader is closed. + /// + public Boolean IsClosed + { + get + { + NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "IsClosed"); + return _isClosed; + } + } + + /// + /// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. + /// + public Int32 RecordsAffected + { + get + { + NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "RecordsAffected"); + + if (HaveResultSet()) + { + return -1; + } + + String[] _returnStringTokens = ((String)_responses[_resultsetIndex]).Split(null); // whitespace separator. + + try + { + return Int32.Parse(_returnStringTokens[_returnStringTokens.Length - 1]); + } + catch (FormatException) + { + return -1; + } + } + } + + /// + /// Indicates if NpgsqlDatareader has rows to be read. + /// + + public Boolean HasRows + { + get + { + return _currentResultset.Count > 0; + } + + } + + /// + /// Closes the data reader object. + /// + public void Close() + { + if ((_behavior & CommandBehavior.CloseConnection) == CommandBehavior.CloseConnection) + { + _connection.Close(); + + } + + _isClosed = true; + } + + /// + /// Advances the data reader to the next result, when multiple result sets were returned by the PostgreSQL backend. + /// + /// True if the reader was advanced, otherwise false. + public Boolean NextResult() + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "NextResult"); + + if((_resultsetIndex + 1) < _resultsets.Count) + { + _resultsetIndex++; + _rowIndex = -1; + _currentResultset = (NpgsqlResultSet)_resultsets[_resultsetIndex]; + return true; + } + else + return false; + + } + + /// + /// Advances the data reader to the next row. + /// + /// True if the reader was advanced, otherwise false. + public Boolean Read() + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Read"); + + CheckHaveResultSet(); + + if (_rowIndex < _currentResultset.Count) + { + _rowIndex++; + return (_rowIndex < _currentResultset.Count); + } + else + { + return false; + } + } + + /// + /// Returns a System.Data.DataTable that describes the column metadata of the DataReader. + /// + public DataTable GetSchemaTable() + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetSchemaTable"); + + if(_currentResultsetSchema == null) + _currentResultsetSchema = GetResultsetSchema(); + + return _currentResultsetSchema; + } + + /// + /// Gets the number of columns in the current row. + /// + public Int32 FieldCount + { + get + { + + NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "FieldCount"); + + if (! HaveResultSet()) //Executed a non return rows query. + return -1; + else + return _currentResultset.RowDescription.NumFields; + + + } + + } + + /// + /// Return the column name of the column at index . + /// + public String GetName(Int32 Index) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetName"); + + CheckHaveResultSet(); + + return _currentResultset.RowDescription[Index].name; + } + + /// + /// Return the data type OID of the column at index . + /// + public String GetDataTypeOID(Int32 Index) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetDataTypeName"); + + CheckHaveResultSet(); + + NpgsqlBackendTypeInfo TI = GetTypeInfo(Index); + + return _currentResultset.RowDescription[Index].type_oid.ToString(); + } + + /// + /// Return the data type name of the column at index . + /// + public String GetDataTypeName(Int32 Index) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetDataTypeName"); + + CheckHaveResultSet(); + + NpgsqlBackendTypeInfo TI = GetTypeInfo(Index); + + if (TI == null) + { + return _currentResultset.RowDescription[Index].type_oid.ToString(); + } + else + { + return TI.Name; + } + } + + /// + /// Return the data type of the column at index . + /// + public Type GetFieldType(Int32 Index) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetFieldType"); + + CheckHaveResultSet(); + + NpgsqlBackendTypeInfo TI = GetTypeInfo(Index); + + if (TI == null) + { + return typeof(String); //Default type is string. + } + else + { + return TI.Type; + } + } + + /// + /// Return the data DbType of the column at index . + /// + public DbType GetFieldDbType(Int32 Index) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetFieldType"); + + CheckHaveResultSet(); + + NpgsqlBackendTypeInfo TI = GetTypeInfo(Index); + + if (TI == null) + { + return DbType.String; + } + else + { + //return TI.DBType; + return DbType.String; + } + } + + /// + /// Return the data NpgsqlDbType of the column at index . + /// + public NpgsqlDbType GetFieldNpgsqlDbType(Int32 Index) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetFieldType"); + + CheckHaveResultSet(); + + NpgsqlBackendTypeInfo TI = GetTypeInfo(Index); + + if (TI == null) + { + return NpgsqlDbType.Text; + } + else + { + return TI.NpgsqlDbType; + + } + } + + + /// + /// Return the value of the column at index . + /// + public Object GetValue(Int32 Index) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetValue"); + + if (Index < 0 || Index >= _currentResultset.RowDescription.NumFields) + { + throw new IndexOutOfRangeException("Column index out of range"); + } + + CheckHaveRow(); + + return ((NpgsqlAsciiRow)_currentResultset[_rowIndex])[Index]; + } + + /// + /// Copy values from each column in the current row into . + /// + /// The number of column values copied. + public Int32 GetValues(Object[] Values) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetValues"); + + CheckHaveRow(); + + // Only the number of elements in the array are filled. + // It's also possible to pass an array with more that FieldCount elements. + Int32 maxColumnIndex = (Values.Length < FieldCount) ? Values.Length : FieldCount; + + for (Int32 i = 0; i < maxColumnIndex; i++) + { + Values[i] = GetValue(i); + } + + return maxColumnIndex; + + } + + /// + /// Return the column name of the column named . + /// + public Int32 GetOrdinal(String Name) + { + CheckHaveResultSet(); + return _currentResultset.RowDescription.FieldIndex(Name); + } + + /// + /// Gets the value of a column in its native format. + /// + public Object this [ Int32 i ] + { + get + { + NpgsqlEventLog.LogIndexerGet(LogLevel.Debug, CLASSNAME, i); + return GetValue(i); + } + } + + /// + /// Gets the value of a column in its native format. + /// + public Object this [ String name ] + { + get + { + NpgsqlEventLog.LogIndexerGet(LogLevel.Debug, CLASSNAME, name); + return GetValue(_currentResultset.RowDescription.FieldIndex(name)); + } + } + + /// + /// Gets the value of a column as Boolean. + /// + public Boolean GetBoolean(Int32 i) + { + // Should this be done using the GetValue directly and not by converting to String + // and parsing from there? + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetBoolean"); + + return (Boolean) GetValue(i); + } + + /// + /// Gets the value of a column as Byte. Not implemented. + /// + public Byte GetByte(Int32 i) + { + throw new NotImplementedException(); + } + + /// + /// Gets raw data from a column. + /// + public Int64 GetBytes(Int32 i, Int64 fieldOffset, Byte[] buffer, Int32 bufferoffset, Int32 length) + { + + Byte[] result; + + result = (Byte[]) GetValue(i); + + if (buffer == null) + return result.Length; + + + // We just support read all the field for while. So, any fieldOffset value other than 0 will not read + // anything and return 0. + + if (fieldOffset != 0) + return 0; + + // [TODO] Implement blob support. + + result.CopyTo(buffer, 0); + + + return result.Length; + + } + + /// + /// Gets the value of a column as Char. Not implemented. + /// + public Char GetChar(Int32 i) + { + throw new NotImplementedException(); + } + + /// + /// Gets raw data from a column. + /// + public Int64 GetChars(Int32 i, Int64 fieldoffset, Char[] buffer, Int32 bufferoffset, Int32 length) + { + String str; + + str = GetString(i); + if (buffer == null) + return str.Length; + + str.ToCharArray(bufferoffset, length).CopyTo(buffer, 0); + return buffer.GetLength(0); + } + + /// + /// Gets the value of a column converted to a Guid. Not implemented. + /// + public Guid GetGuid(Int32 i) + { + throw new NotImplementedException(); + } + + /// + /// Gets the value of a column as Int16. + /// + public Int16 GetInt16(Int32 i) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetInt16"); + + return (Int16) GetValue(i); + } + + /// + /// Gets the value of a column as Int32. + /// + public Int32 GetInt32(Int32 i) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetInt32"); + + return (Int32) GetValue(i); + } + + /// + /// Gets the value of a column as Int64. + /// + public Int64 GetInt64(Int32 i) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetInt64"); + + return (Int64) GetValue(i); + } + + /// + /// Gets the value of a column as Single. + /// + public Single GetFloat(Int32 i) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetFloat"); + + return (Single) GetValue(i); + } + + /// + /// Gets the value of a column as Double. + /// + public Double GetDouble(Int32 i) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetDouble"); + + return (Double) GetValue(i); + } + + /// + /// Gets the value of a column as String. + /// + public String GetString(Int32 i) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetString"); + + return (String) GetValue(i); + } + + /// + /// Gets the value of a column as Decimal. + /// + public Decimal GetDecimal(Int32 i) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetDecimal"); + + return (Decimal) GetValue(i); + } + + /// + /// Gets the value of a column as DateTime. + /// + public DateTime GetDateTime(Int32 i) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetDateTime"); + + return (DateTime) GetValue(i); + } + + /// + /// Not implemented. + /// + public IDataReader GetData(Int32 i) + { + throw new NotImplementedException(); + } + + /// + /// Report whether the value in a column is DBNull. + /// + public Boolean IsDBNull(Int32 i) + { + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "IsDBNull"); + + return (GetValue(i) == DBNull.Value); + } + + internal NpgsqlBackendTypeInfo GetTypeInfo(Int32 FieldIndex) + { + return _currentResultset.RowDescription[FieldIndex].type_info; + } + + private DataTable GetResultsetSchema() + { + + NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "GetResultsetSchema"); + DataTable result = null; + + NpgsqlRowDescription rd = _currentResultset.RowDescription; + Int16 numFields = rd.NumFields; + if(numFields > 0) + { + result = new DataTable("SchemaTable"); + + result.Columns.Add ("ColumnName", typeof (string)); + result.Columns.Add ("ColumnOrdinal", typeof (int)); + result.Columns.Add ("ColumnSize", typeof (int)); + result.Columns.Add ("NumericPrecision", typeof (int)); + result.Columns.Add ("NumericScale", typeof (int)); + result.Columns.Add ("IsUnique", typeof (bool)); + result.Columns.Add ("IsKey", typeof (bool)); + DataColumn dc = result.Columns["IsKey"]; + dc.AllowDBNull = true; // IsKey can have a DBNull + result.Columns.Add ("BaseCatalogName", typeof (string)); + result.Columns.Add ("BaseColumnName", typeof (string)); + result.Columns.Add ("BaseSchemaName", typeof (string)); + result.Columns.Add ("BaseTableName", typeof (string)); + result.Columns.Add ("DataType", typeof(Type)); + result.Columns.Add ("AllowDBNull", typeof (bool)); + result.Columns.Add ("ProviderType", typeof (int)); + result.Columns.Add ("IsAliased", typeof (bool)); + result.Columns.Add ("IsExpression", typeof (bool)); + result.Columns.Add ("IsIdentity", typeof (bool)); + result.Columns.Add ("IsAutoIncrement", typeof (bool)); + result.Columns.Add ("IsRowVersion", typeof (bool)); + result.Columns.Add ("IsHidden", typeof (bool)); + result.Columns.Add ("IsLong", typeof (bool)); + result.Columns.Add ("IsReadOnly", typeof (bool)); + + DataRow row; + + for (Int16 i = 0; i < numFields; i++) + { + row = result.NewRow(); + + row["ColumnName"] = GetName(i); + row["ColumnOrdinal"] = i + 1; + row["ColumnSize"] = (int) rd[i].type_size; + row["NumericPrecision"] = 0; + row["NumericScale"] = 0; + row["IsUnique"] = false; + row["IsKey"] = DBNull.Value; + row["BaseCatalogName"] = ""; + row["BaseColumnName"] = GetName(i); + row["BaseSchemaName"] = ""; + row["BaseTableName"] = ""; + row["DataType"] = GetFieldType(i); + row["AllowDBNull"] = false; + row["ProviderType"] = (int) rd[i].type_oid; + row["IsAliased"] = false; + row["IsExpression"] = false; + row["IsIdentity"] = false; + row["IsAutoIncrement"] = false; + row["IsRowVersion"] = false; + row["IsHidden"] = false; + row["IsLong"] = false; + row["IsReadOnly"] = false; + + result.Rows.Add(row); + } + } + + return result; + + } + + IEnumerator IEnumerable.GetEnumerator () + { + return new System.Data.Common.DbEnumerator (this); + } + } +}