//
-// System.Data.SqlClient.SqlDataReader.cs
+// Mono.Data.PostgreSqlClient.PgSqlDataReader.cs
//
// Author:
// Rodrigo Moya (rodrigo@ximian.com)
// Gonzalo Paniagua Javier <gonzalo@gnome-db.org>
//
+//
+// 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.
+//
+
// *** uncomment #define to get debug messages, comment for production ***
//#define DEBUG_SqlDataReader
using System.Collections;
using System.ComponentModel;
using System.Data;
+using System.Data.Common;
-namespace System.Data.SqlClient {
+namespace Mono.Data.PostgreSqlClient {
/// <summary>
/// Provides a means of reading one or more forward-only streams
/// of result sets obtained by executing a command
/// at a SQL database.
/// </summary>
- //public sealed class SqlDataReader : MarshalByRefObject,
- // IEnumerable, IDataReader, IDisposable, IDataRecord
- public sealed class SqlDataReader : IEnumerable,
- IDataReader, IDataRecord {
+ public sealed class PgSqlDataReader : MarshalByRefObject,
+ IEnumerable, IDataReader, IDisposable, IDataRecord {
+
#region Fields
- private SqlCommand cmd;
- private DataTable table;
+ private PgSqlCommand cmd;
+ private DataTable table = null;
// columns in a row
private object[] fields; // data value in a .NET type
private int rows;
private int cols;
+ private int recordsAffected = -1; // TODO: get this value
+
private int currentRow = -1; // no Read() has been done yet
+ private bool disposed = false;
+
#endregion // Fields
#region Constructors
- internal SqlDataReader (SqlCommand sqlCmd,
- DataTable dataTableSchema, IntPtr pg_result,
- int rowCount, int fieldCount, string[] pgtypes) {
+ internal PgSqlDataReader (PgSqlCommand sqlCmd) {
cmd = sqlCmd;
- table = dataTableSchema;
- pgResult = pg_result;
- rows = rowCount;
- cols = fieldCount;
- types = pgtypes;
open = true;
+ cmd.OpenReader(this);
}
#endregion
[MonoTODO]
public void Close() {
- // close result set
- PostgresLibrary.PQclear (pgResult);
open = false;
- // TODO: change busy state on SqlConnection to not busy
+
+ // free PgSqlDataReader resources in PgSqlCommand
+ // and allow PgSqlConnection to be used again
+ cmd.CloseReader();
+
+ // TODO: get parameters from result
+
+ Dispose (true);
}
[MonoTODO]
[MonoTODO]
public bool NextResult() {
- throw new NotImplementedException ();
+ PgSqlResult res;
+ currentRow = -1;
+ bool resultReturned;
+
+ // reset
+ table = null;
+ pgResult = IntPtr.Zero;
+ rows = 0;
+ cols = 0;
+ types = null;
+ recordsAffected = -1;
+
+ res = cmd.NextResult();
+ resultReturned = res.ResultReturned;
+
+ if(resultReturned == true) {
+ table = res.Table;
+ pgResult = res.PgResult;
+ rows = res.RowCount;
+ cols = res.FieldCount;
+ types = res.PgTypes;
+ recordsAffected = res.RecordsAffected;
+ }
+
+ res = null;
+ return resultReturned;
}
[MonoTODO]
public bool Read() {
+
string dataValue;
int c = 0;
- //Console.WriteLine("if current row: " + currentRow + " rows: " + rows);
if(currentRow < rows - 1) {
- //Console.WriteLine("currentRow++: ");
currentRow++;
-
- //Console.WriteLine("re-init row --- cols: " + cols);
-
+
// re-init row
fields = new object[cols];
//dbTypes = new DbType[cols];
[MonoTODO]
public Type GetFieldType(int i) {
- return table.Columns[i].DataType;
+ DataRow row = table.Rows[i];
+ return Type.GetType((string)row["DataType"]);
}
[MonoTODO]
[MonoTODO]
public string GetName(int i) {
- return table.Columns[i].ColumnName;
+
+ DataRow row = table.Rows[i];
+ return (string) row["ColumnName"];
}
[MonoTODO]
public int GetOrdinal(string name) {
+
int i;
- for(i = 0; i < cols; i ++) {
- if(table.Columns[i].ColumnName.Equals(name)) {
- return i;
- }
+ DataRow row;
+ for(i = 0; i < table.Rows.Count; i++) {
+ row = table.Rows[i];
+ if(((string) row["ColumnName"]).Equals(name))
+ return i;
}
-
- for(i = 0; i < cols; i++) {
+
+ for(i = 0; i < table.Rows.Count; i++) {
string ta;
string n;
-
- ta = table.Columns[i].ColumnName.ToUpper();
+
+ row = table.Rows[i];
+ ta = ((string) row["ColumnName"]).ToUpper();
n = name.ToUpper();
if(ta.Equals(n)) {
}
[MonoTODO]
- public IEnumerator GetEnumerator() {
- throw new NotImplementedException ();
+ IEnumerator IEnumerable.GetEnumerator () {
+ return new DbEnumerator (this);
}
#endregion // Public Methods
#region Destructors
- [MonoTODO]
- public void Dispose () {
+ private void Dispose(bool disposing) {
+ if(!this.disposed) {
+ if(disposing) {
+ // release any managed resources
+ cmd = null;
+ table = null;
+ fields = null;
+ types = null;
+ isNull = null;
+ actualLength = null;
+ dbTypes = null;
+ }
+ // release any unmanaged resources
+
+ // clear unmanaged PostgreSQL result set
+ if (pgResult != IntPtr.Zero) {
+ PostgresLibrary.PQclear (pgResult);
+ pgResult = IntPtr.Zero;
+ }
+
+ // close any handles
+ this.disposed = true;
+ }
}
- [MonoTODO]
- ~SqlDataReader() {
+ void IDisposable.Dispose() {
+ Dispose(true);
+ }
+
+ ~PgSqlDataReader() {
+ Dispose(false);
}
#endregion // Destructors
public int Depth {
[MonoTODO]
get {
- throw new NotImplementedException ();
+ return 0; // always return zero, unless
+ // this provider will allow
+ // nesting of a row
}
}
public int RecordsAffected {
[MonoTODO]
get {
- throw new NotImplementedException ();
+ return recordsAffected;
}
}
[MonoTODO]
get {
int i;
- for(i = 0; i < cols; i ++) {
- if(table.Columns[i].ColumnName.Equals(name)) {
- return fields[i];
- }
+ DataRow row;
+ for(i = 0; i < table.Rows.Count; i++) {
+ row = table.Rows[i];
+ if(row["ColumnName"].Equals(name))
+ return fields[i];
}
-
- for(i = 0; i < cols; i++) {
+
+ for(i = 0; i < table.Rows.Count; i++) {
string ta;
string n;
-
- ta = table.Columns[i].ColumnName.ToUpper();
+
+ row = table.Rows[i];
+ ta = ((string) row["ColumnName"]).ToUpper();
n = name.ToUpper();
if(ta.Equals(n)) {