[MonoTODO]
SqlDataReader ExecuteReader ()
{
- throw new NotImplementedException ();
+ return ExecuteReader(CommandBehavior.Default);
}
[MonoTODO]
[MonoTODO]
public SqlDataReader ExecuteReader (CommandBehavior behavior)
{
- throw new NotImplementedException ();
+ // FIXME: currently only works for a
+ // single result set
+ // ExecuteReader can be used
+ // for multiple result sets
+ SqlDataReader dataReader = null;
+
+ IntPtr pgResult; // PGresult
+ ExecStatusType execStatus;
+
+ if(conn.State != ConnectionState.Open)
+ throw new InvalidOperationException(
+ "ConnnectionState is not Open");
+
+ // FIXME: PQexec blocks
+ // while PQsendQuery is non-blocking
+ // which is better to use?
+ // int PQsendQuery(PGconn *conn,
+ // const char *query);
+
+ // execute SQL command
+ // uses internal property to get the PGConn IntPtr
+ pgResult = PostgresLibrary.
+ PQexec (conn.PostgresConnection, sql);
+
+ execStatus = PostgresLibrary.
+ PQresultStatus (pgResult);
+
+ if(execStatus == ExecStatusType.PGRES_TUPLES_OK) {
+ DataTable dt = null;
+ int rows, cols;
+ int[] oids;
+
+ // FIXME: maybe i should move the
+ // BuildTableSchema code
+ // to the SqlDataReader?
+ dt = BuildTableSchema(pgResult,
+ out rows, out cols, out oids);
+ dataReader = new SqlDataReader(this, dt, pgResult,
+ rows, cols, oids);
+ }
+ else {
+ String errorMessage;
+
+ errorMessage = PostgresLibrary.
+ PQresStatus(execStatus);
+
+ errorMessage += " " + PostgresLibrary.\r
+ PQresultErrorMessage(pgResult);\r
+ \r
+ throw new SqlException(0, 0,
+ errorMessage, 0, "",
+ conn.DataSource, "SqlCommand", 0);\r
+ }
+
+ return dataReader;
+ }
+
+ internal DataTable BuildTableSchema (IntPtr pgResult,
+ out int nRows,
+ out int nFields,
+ out int[] oids) {
+
+ int nCol;
+
+ DataTable dt = new DataTable();
+
+ nRows = PostgresLibrary.
+ PQntuples(pgResult);
+
+ nFields = PostgresLibrary.
+ PQnfields(pgResult);
+
+ oids = new int[nFields];
+
+ for(nCol = 0; nCol < nFields; nCol++) {
+ // get column name
+ String fieldName;
+ fieldName = PostgresLibrary.
+ PQfname(pgResult, nCol);
+
+ // get PostgreSQL data type (OID)
+ oids[nCol] = PostgresLibrary.
+ PQftype(pgResult, nCol);
+
+ int definedSize;
+ // get defined size of column
+ definedSize = PostgresLibrary.
+ PQfsize(pgResult, nCol);
+
+ // build the data column and add it the table
+ DataColumn dc = new DataColumn(fieldName);
+ dc.DataType = PostgresHelper.OidToType(oids[nCol]);
+ dc.MaxLength = definedSize;
+ dc.SetTable(dt);
+
+ dt.Columns.Add(dc);
+ }
+ return dt;
}
[MonoTODO]
nRow, nCol);
obj = PostgresHelper.
- OidTypeToSystem (oid, value);
+ ConvertPgTypeToSystem (oid, value);
}
// close result set
// support SSL. Set to 0 (default) to
// negotiate with server.
- ConnectionState conState = ConnectionState.Closed;
-
+ private ConnectionState conState = ConnectionState.Closed;
+ private bool dataReaderOpen = false;
+ // FIXME: if true, throw an exception if SqlConnection
+ // is used used for anything other than reading
+ // data using SqlDataReader
+
#endregion // Fields
#region Constructors
{
#region Fields
- private DataTable table = null;
+ private SqlCommand cmd;
+ private DataTable table;
+
+ private object[] fields;
+ private int[] oid; // PostgreSQL Type
+
+ private bool open = false;
+ IntPtr pgResult; // PGresult
+ private int rows;
+ private int cols;
+
+ private int currentRow = -1; // no Read() has been done yet
#endregion // Fields
+ #region Constructors
+
+ internal SqlDataReader (SqlCommand sqlCmd,
+ DataTable dataTableSchema, IntPtr pg_result,
+ int rowCount, int fieldCount, int[] oids) {
+
+ cmd = sqlCmd;
+ table = dataTableSchema;
+ pgResult = pg_result;
+ rows = rowCount;
+ cols = fieldCount;
+ oid = oids;
+ }
+
+ #endregion
+
#region Public Methods
[MonoTODO]
public void Close()
{
- throw new NotImplementedException ();
+ // close result set
+ PostgresLibrary.PQclear (pgResult);
+
+ // TODO: change busy state on SqlConnection to not busy
}
[MonoTODO]
public DataTable GetSchemaTable()
{
- throw new NotImplementedException ();
+ return table;
}
[MonoTODO]
[MonoTODO]
public bool Read()
{
- throw new NotImplementedException ();
+ string value;
+ fields = new object[cols]; // re-init row
+
+ if(currentRow < rows - 1) {
+ currentRow++;
+ int c;
+ for(c = 0; c < cols; c++) {
+
+ // get data value
+ value = PostgresLibrary.
+ PQgetvalue(
+ pgResult,
+ currentRow, c);
+
+ int columnIsNull;
+ // is column NULL?
+ columnIsNull = PostgresLibrary.
+ PQgetisnull(pgResult,
+ currentRow, c);
+
+ int actualLength;
+ // get Actual Length
+ actualLength = PostgresLibrary.
+ PQgetlength(pgResult,
+ currentRow, c);
+
+ fields[c] = PostgresHelper.
+ ConvertPgTypeToSystem (oid[c], value);
+ }
+ return true;
+ }
+ return false; // EOF
}
[MonoTODO]
[MonoTODO]
public short GetInt16(int i)
{
- throw new NotImplementedException ();
+ return (short) fields[i];
}
[MonoTODO]
public int GetInt32(int i)
{
- throw new NotImplementedException ();
+ return (int) fields[i];
}
[MonoTODO]
public long GetInt64(int i)
{
- throw new NotImplementedException ();
+ return (long) fields[i];
}
[MonoTODO]
public string GetName(int i)
{
- throw new NotImplementedException ();
+ return table.Columns[i].ColumnName;
}
[MonoTODO]
[MonoTODO]
public string GetString(int i)
{
- throw new NotImplementedException ();
+ return (string) fields[i];
}
[MonoTODO]
public object GetValue(int i)
{
- throw new NotImplementedException ();
+ return fields[i];
}
[MonoTODO]
public int FieldCount {
[MonoTODO]
get {
- throw new NotImplementedException ();
+ return cols;
}
}
public object this[string name] {
[MonoTODO]
get {
- throw new NotImplementedException ();
+ int i;
+ for(i = 0; i < cols; i ++) {
+ if(table.Columns[i].ColumnName.Equals(name)) {
+ return fields[i];
+ }
+
+ }
+
+ if(i == cols) {
+ for(i = 0; i < cols; i++) {
+ string ta;
+ string n;
+
+ ta = table.Columns[i].ColumnName.ToUpper();
+ n = name.ToUpper();
+
+ if(ta.Equals(n)) {
+ return fields[i];
+ }
+ }
+ }
+ throw new MissingFieldException("Missing field: " + name);
}
}
[MonoTODO]
get
{
- throw new NotImplementedException ();
+ return fields[i];
}
}
sealed internal class PostgresHelper {
- public static object OidTypeToSystem (int oid, String value) {
+ /// <summary>\r
+ /// Convert a PostgreSQL Type to a .NET System type.\r
+ /// </summary>\r
+ /// <param name="oid"></param>\r
+ /// <param name="value"></param>\r
+ /// <returns></returns>
+ public static object ConvertPgTypeToSystem (int oid, String value) {
object obj = null;
// FIXME: more types need
// to .NET System.<type>
switch(oid) {
- case 1023: // varchar
+ case 1043: // varchar
case 25: // text
case 18: // char
- obj = (object) value; // String
+ obj = (object) String.Copy(value);
break;
case 16: // bool
obj = (object) Boolean.Parse(value);
case 20: // int8\r
obj = (object) Int64.Parse(value);\r
break;\r
+ default:\r
+ throw new NotImplementedException(\r
+ "PGNI1: PostgreSQL oid data type " + oid +\r
+ " not mapped to .NET System data type.");\r
}
return obj;
}
+
+ /// <summary>\r
+ /// Convert the PostgreSQL Type oid to the .NET System.Type.\r
+ /// </summary>\r
+ /// <param name="oid"></param>\r
+ /// <returns></returns>
+ public static Type OidToType (int oid) {
+ // FIXME: more types need
+ // to be mapped
+ // from PostgreSQL oid type
+ // to .NET System.<type>
+ Type typ = null;
+
+ switch(oid) {
+ case 1043: // varchar
+ case 25: // text
+ case 18: // char
+ typ = typeof(String);
+ break;
+ case 16: // bool
+ typ = typeof(Boolean);
+ break;
+ case 21: // int2\r
+ typ = typeof(Int16);\r
+ break;\r
+ case 23: // int4\r
+ typ = typeof(Int32);\r
+ break;\r
+ case 20: // int8\r
+ typ = typeof(Int64);\r
+ break;\r
+ default:\r
+ throw new NotImplementedException(\r
+ "PGNI2: PostgreSQL oid type " + oid +\r
+ " not mapped to .NET System Type.");\r
+ }
+ return typ;
+ }
}
sealed internal class PostgresLibrary
[MonoTODO]
SqlDataReader ExecuteReader ()
{
- throw new NotImplementedException ();
+ return ExecuteReader(CommandBehavior.Default);
}
[MonoTODO]
[MonoTODO]
public SqlDataReader ExecuteReader (CommandBehavior behavior)
{
- throw new NotImplementedException ();
+ // FIXME: currently only works for a
+ // single result set
+ // ExecuteReader can be used
+ // for multiple result sets
+ SqlDataReader dataReader = null;
+
+ IntPtr pgResult; // PGresult
+ ExecStatusType execStatus;
+
+ if(conn.State != ConnectionState.Open)
+ throw new InvalidOperationException(
+ "ConnnectionState is not Open");
+
+ // FIXME: PQexec blocks
+ // while PQsendQuery is non-blocking
+ // which is better to use?
+ // int PQsendQuery(PGconn *conn,
+ // const char *query);
+
+ // execute SQL command
+ // uses internal property to get the PGConn IntPtr
+ pgResult = PostgresLibrary.
+ PQexec (conn.PostgresConnection, sql);
+
+ execStatus = PostgresLibrary.
+ PQresultStatus (pgResult);
+
+ if(execStatus == ExecStatusType.PGRES_TUPLES_OK) {
+ DataTable dt = null;
+ int rows, cols;
+ int[] oids;
+
+ // FIXME: maybe i should move the
+ // BuildTableSchema code
+ // to the SqlDataReader?
+ dt = BuildTableSchema(pgResult,
+ out rows, out cols, out oids);
+ dataReader = new SqlDataReader(this, dt, pgResult,
+ rows, cols, oids);
+ }
+ else {
+ String errorMessage;
+
+ errorMessage = PostgresLibrary.
+ PQresStatus(execStatus);
+
+ errorMessage += " " + PostgresLibrary.\r
+ PQresultErrorMessage(pgResult);\r
+ \r
+ throw new SqlException(0, 0,
+ errorMessage, 0, "",
+ conn.DataSource, "SqlCommand", 0);\r
+ }
+
+ return dataReader;
+ }
+
+ internal DataTable BuildTableSchema (IntPtr pgResult,
+ out int nRows,
+ out int nFields,
+ out int[] oids) {
+
+ int nCol;
+
+ DataTable dt = new DataTable();
+
+ nRows = PostgresLibrary.
+ PQntuples(pgResult);
+
+ nFields = PostgresLibrary.
+ PQnfields(pgResult);
+
+ oids = new int[nFields];
+
+ for(nCol = 0; nCol < nFields; nCol++) {
+ // get column name
+ String fieldName;
+ fieldName = PostgresLibrary.
+ PQfname(pgResult, nCol);
+
+ // get PostgreSQL data type (OID)
+ oids[nCol] = PostgresLibrary.
+ PQftype(pgResult, nCol);
+
+ int definedSize;
+ // get defined size of column
+ definedSize = PostgresLibrary.
+ PQfsize(pgResult, nCol);
+
+ // build the data column and add it the table
+ DataColumn dc = new DataColumn(fieldName);
+ dc.DataType = PostgresHelper.OidToType(oids[nCol]);
+ dc.MaxLength = definedSize;
+ dc.SetTable(dt);
+
+ dt.Columns.Add(dc);
+ }
+ return dt;
}
[MonoTODO]
nRow, nCol);
obj = PostgresHelper.
- OidTypeToSystem (oid, value);
+ ConvertPgTypeToSystem (oid, value);
}
// close result set
// support SSL. Set to 0 (default) to
// negotiate with server.
- ConnectionState conState = ConnectionState.Closed;
-
+ private ConnectionState conState = ConnectionState.Closed;
+ private bool dataReaderOpen = false;
+ // FIXME: if true, throw an exception if SqlConnection
+ // is used used for anything other than reading
+ // data using SqlDataReader
+
#endregion // Fields
#region Constructors
{
#region Fields
- private DataTable table = null;
+ private SqlCommand cmd;
+ private DataTable table;
+
+ private object[] fields;
+ private int[] oid; // PostgreSQL Type
+
+ private bool open = false;
+ IntPtr pgResult; // PGresult
+ private int rows;
+ private int cols;
+
+ private int currentRow = -1; // no Read() has been done yet
#endregion // Fields
+ #region Constructors
+
+ internal SqlDataReader (SqlCommand sqlCmd,
+ DataTable dataTableSchema, IntPtr pg_result,
+ int rowCount, int fieldCount, int[] oids) {
+
+ cmd = sqlCmd;
+ table = dataTableSchema;
+ pgResult = pg_result;
+ rows = rowCount;
+ cols = fieldCount;
+ oid = oids;
+ }
+
+ #endregion
+
#region Public Methods
[MonoTODO]
public void Close()
{
- throw new NotImplementedException ();
+ // close result set
+ PostgresLibrary.PQclear (pgResult);
+
+ // TODO: change busy state on SqlConnection to not busy
}
[MonoTODO]
public DataTable GetSchemaTable()
{
- throw new NotImplementedException ();
+ return table;
}
[MonoTODO]
[MonoTODO]
public bool Read()
{
- throw new NotImplementedException ();
+ string value;
+ fields = new object[cols]; // re-init row
+
+ if(currentRow < rows - 1) {
+ currentRow++;
+ int c;
+ for(c = 0; c < cols; c++) {
+
+ // get data value
+ value = PostgresLibrary.
+ PQgetvalue(
+ pgResult,
+ currentRow, c);
+
+ int columnIsNull;
+ // is column NULL?
+ columnIsNull = PostgresLibrary.
+ PQgetisnull(pgResult,
+ currentRow, c);
+
+ int actualLength;
+ // get Actual Length
+ actualLength = PostgresLibrary.
+ PQgetlength(pgResult,
+ currentRow, c);
+
+ fields[c] = PostgresHelper.
+ ConvertPgTypeToSystem (oid[c], value);
+ }
+ return true;
+ }
+ return false; // EOF
}
[MonoTODO]
[MonoTODO]
public short GetInt16(int i)
{
- throw new NotImplementedException ();
+ return (short) fields[i];
}
[MonoTODO]
public int GetInt32(int i)
{
- throw new NotImplementedException ();
+ return (int) fields[i];
}
[MonoTODO]
public long GetInt64(int i)
{
- throw new NotImplementedException ();
+ return (long) fields[i];
}
[MonoTODO]
public string GetName(int i)
{
- throw new NotImplementedException ();
+ return table.Columns[i].ColumnName;
}
[MonoTODO]
[MonoTODO]
public string GetString(int i)
{
- throw new NotImplementedException ();
+ return (string) fields[i];
}
[MonoTODO]
public object GetValue(int i)
{
- throw new NotImplementedException ();
+ return fields[i];
}
[MonoTODO]
public int FieldCount {
[MonoTODO]
get {
- throw new NotImplementedException ();
+ return cols;
}
}
public object this[string name] {
[MonoTODO]
get {
- throw new NotImplementedException ();
+ int i;
+ for(i = 0; i < cols; i ++) {
+ if(table.Columns[i].ColumnName.Equals(name)) {
+ return fields[i];
+ }
+
+ }
+
+ if(i == cols) {
+ for(i = 0; i < cols; i++) {
+ string ta;
+ string n;
+
+ ta = table.Columns[i].ColumnName.ToUpper();
+ n = name.ToUpper();
+
+ if(ta.Equals(n)) {
+ return fields[i];
+ }
+ }
+ }
+ throw new MissingFieldException("Missing field: " + name);
}
}
[MonoTODO]
get
{
- throw new NotImplementedException ();
+ return fields[i];
}
}
sealed internal class PostgresHelper {
- public static object OidTypeToSystem (int oid, String value) {
+ /// <summary>\r
+ /// Convert a PostgreSQL Type to a .NET System type.\r
+ /// </summary>\r
+ /// <param name="oid"></param>\r
+ /// <param name="value"></param>\r
+ /// <returns></returns>
+ public static object ConvertPgTypeToSystem (int oid, String value) {
object obj = null;
// FIXME: more types need
// to .NET System.<type>
switch(oid) {
- case 1023: // varchar
+ case 1043: // varchar
case 25: // text
case 18: // char
- obj = (object) value; // String
+ obj = (object) String.Copy(value);
break;
case 16: // bool
obj = (object) Boolean.Parse(value);
case 20: // int8\r
obj = (object) Int64.Parse(value);\r
break;\r
+ default:\r
+ throw new NotImplementedException(\r
+ "PGNI1: PostgreSQL oid data type " + oid +\r
+ " not mapped to .NET System data type.");\r
}
return obj;
}
+
+ /// <summary>\r
+ /// Convert the PostgreSQL Type oid to the .NET System.Type.\r
+ /// </summary>\r
+ /// <param name="oid"></param>\r
+ /// <returns></returns>
+ public static Type OidToType (int oid) {
+ // FIXME: more types need
+ // to be mapped
+ // from PostgreSQL oid type
+ // to .NET System.<type>
+ Type typ = null;
+
+ switch(oid) {
+ case 1043: // varchar
+ case 25: // text
+ case 18: // char
+ typ = typeof(String);
+ break;
+ case 16: // bool
+ typ = typeof(Boolean);
+ break;
+ case 21: // int2\r
+ typ = typeof(Int16);\r
+ break;\r
+ case 23: // int4\r
+ typ = typeof(Int32);\r
+ break;\r
+ case 20: // int8\r
+ typ = typeof(Int64);\r
+ break;\r
+ default:\r
+ throw new NotImplementedException(\r
+ "PGNI2: PostgreSQL oid type " + oid +\r
+ " not mapped to .NET System Type.");\r
+ }
+ return typ;
+ }
}
sealed internal class PostgresLibrary
+2002-05-03 Daniel Morgan <danmorg@sc.rr.com>
+
+ * Test/TestExecuteScalar.cs: added test for
+ method ExecuteScalar in class SqlCommand.
+
+ * System.Data/DataColumnCollection.cs - it should
+ inherit properties from base InternalDataCollectionBase
+ and use them instead of overriding them, such as, List.
+
+ * System.Data/DataColumn.cs
+ * System.Data/DataTable.cs: tweaks to retrieve
+ meta data from the database
+
+ * System.Data.SqlClient/PostgresLibrary.cs -
+ added method OidToType to convert PostgreSQL oid type
+ to System.Type. Renamed method OidTypeToSystem
+ to ConvertPgTypeToSystem for converting the data value
+ from a PostgreSQL type to a .NET System type.
+
+ * System.Data.SqlClient/SqlCommand.cs: implemented
+ method ExecuteReader which returns a SqlDataReader
+ for a light forward only read only result set.
+ It works on types int4 ==> Int32 and
+ varchar ==> String. Other types
+ will come later.
+
+ * System.Data.SqlClient/SqlConnection.cs: added comment
+
+ * System.Data.SqlClient/SqlDataReader.cs: implemented
+ class. It works, but still lots to do.
+
+ * Test/ReadPostgresData.cs: stuff
+
+ * Test/TestSqlDataReader.cs: updated test for SqlDataReader
+ to display meta data and the data
+
2002-05-03 Duncan Mak <duncan@ximian.com>
* TODO: Took out all the Exceptions. They should be all done now.
sealed internal class PostgresHelper {
- public static object OidTypeToSystem (int oid, String value) {
+ /// <summary>\r
+ /// Convert a PostgreSQL Type to a .NET System type.\r
+ /// </summary>\r
+ /// <param name="oid"></param>\r
+ /// <param name="value"></param>\r
+ /// <returns></returns>
+ public static object ConvertPgTypeToSystem (int oid, String value) {
object obj = null;
// FIXME: more types need
// to .NET System.<type>
switch(oid) {
- case 1023: // varchar
+ case 1043: // varchar
case 25: // text
case 18: // char
- obj = (object) value; // String
+ obj = (object) String.Copy(value);
break;
case 16: // bool
obj = (object) Boolean.Parse(value);
case 20: // int8\r
obj = (object) Int64.Parse(value);\r
break;\r
+ default:\r
+ throw new NotImplementedException(\r
+ "PGNI1: PostgreSQL oid data type " + oid +\r
+ " not mapped to .NET System data type.");\r
}
return obj;
}
+
+ /// <summary>\r
+ /// Convert the PostgreSQL Type oid to the .NET System.Type.\r
+ /// </summary>\r
+ /// <param name="oid"></param>\r
+ /// <returns></returns>
+ public static Type OidToType (int oid) {
+ // FIXME: more types need
+ // to be mapped
+ // from PostgreSQL oid type
+ // to .NET System.<type>
+ Type typ = null;
+
+ switch(oid) {
+ case 1043: // varchar
+ case 25: // text
+ case 18: // char
+ typ = typeof(String);
+ break;
+ case 16: // bool
+ typ = typeof(Boolean);
+ break;
+ case 21: // int2\r
+ typ = typeof(Int16);\r
+ break;\r
+ case 23: // int4\r
+ typ = typeof(Int32);\r
+ break;\r
+ case 20: // int8\r
+ typ = typeof(Int64);\r
+ break;\r
+ default:\r
+ throw new NotImplementedException(\r
+ "PGNI2: PostgreSQL oid type " + oid +\r
+ " not mapped to .NET System Type.");\r
+ }
+ return typ;
+ }
}
sealed internal class PostgresLibrary
[MonoTODO]
SqlDataReader ExecuteReader ()
{
- throw new NotImplementedException ();
+ return ExecuteReader(CommandBehavior.Default);
}
[MonoTODO]
[MonoTODO]
public SqlDataReader ExecuteReader (CommandBehavior behavior)
{
- throw new NotImplementedException ();
+ // FIXME: currently only works for a
+ // single result set
+ // ExecuteReader can be used
+ // for multiple result sets
+ SqlDataReader dataReader = null;
+
+ IntPtr pgResult; // PGresult
+ ExecStatusType execStatus;
+
+ if(conn.State != ConnectionState.Open)
+ throw new InvalidOperationException(
+ "ConnnectionState is not Open");
+
+ // FIXME: PQexec blocks
+ // while PQsendQuery is non-blocking
+ // which is better to use?
+ // int PQsendQuery(PGconn *conn,
+ // const char *query);
+
+ // execute SQL command
+ // uses internal property to get the PGConn IntPtr
+ pgResult = PostgresLibrary.
+ PQexec (conn.PostgresConnection, sql);
+
+ execStatus = PostgresLibrary.
+ PQresultStatus (pgResult);
+
+ if(execStatus == ExecStatusType.PGRES_TUPLES_OK) {
+ DataTable dt = null;
+ int rows, cols;
+ int[] oids;
+
+ // FIXME: maybe i should move the
+ // BuildTableSchema code
+ // to the SqlDataReader?
+ dt = BuildTableSchema(pgResult,
+ out rows, out cols, out oids);
+ dataReader = new SqlDataReader(this, dt, pgResult,
+ rows, cols, oids);
+ }
+ else {
+ String errorMessage;
+
+ errorMessage = PostgresLibrary.
+ PQresStatus(execStatus);
+
+ errorMessage += " " + PostgresLibrary.\r
+ PQresultErrorMessage(pgResult);\r
+ \r
+ throw new SqlException(0, 0,
+ errorMessage, 0, "",
+ conn.DataSource, "SqlCommand", 0);\r
+ }
+
+ return dataReader;
+ }
+
+ internal DataTable BuildTableSchema (IntPtr pgResult,
+ out int nRows,
+ out int nFields,
+ out int[] oids) {
+
+ int nCol;
+
+ DataTable dt = new DataTable();
+
+ nRows = PostgresLibrary.
+ PQntuples(pgResult);
+
+ nFields = PostgresLibrary.
+ PQnfields(pgResult);
+
+ oids = new int[nFields];
+
+ for(nCol = 0; nCol < nFields; nCol++) {
+ // get column name
+ String fieldName;
+ fieldName = PostgresLibrary.
+ PQfname(pgResult, nCol);
+
+ // get PostgreSQL data type (OID)
+ oids[nCol] = PostgresLibrary.
+ PQftype(pgResult, nCol);
+
+ int definedSize;
+ // get defined size of column
+ definedSize = PostgresLibrary.
+ PQfsize(pgResult, nCol);
+
+ // build the data column and add it the table
+ DataColumn dc = new DataColumn(fieldName);
+ dc.DataType = PostgresHelper.OidToType(oids[nCol]);
+ dc.MaxLength = definedSize;
+ dc.SetTable(dt);
+
+ dt.Columns.Add(dc);
+ }
+ return dt;
}
[MonoTODO]
nRow, nCol);
obj = PostgresHelper.
- OidTypeToSystem (oid, value);
+ ConvertPgTypeToSystem (oid, value);
}
// close result set
// support SSL. Set to 0 (default) to
// negotiate with server.
- ConnectionState conState = ConnectionState.Closed;
-
+ private ConnectionState conState = ConnectionState.Closed;
+ private bool dataReaderOpen = false;
+ // FIXME: if true, throw an exception if SqlConnection
+ // is used used for anything other than reading
+ // data using SqlDataReader
+
#endregion // Fields
#region Constructors
{
#region Fields
- private DataTable table = null;
+ private SqlCommand cmd;
+ private DataTable table;
+
+ private object[] fields;
+ private int[] oid; // PostgreSQL Type
+
+ private bool open = false;
+ IntPtr pgResult; // PGresult
+ private int rows;
+ private int cols;
+
+ private int currentRow = -1; // no Read() has been done yet
#endregion // Fields
+ #region Constructors
+
+ internal SqlDataReader (SqlCommand sqlCmd,
+ DataTable dataTableSchema, IntPtr pg_result,
+ int rowCount, int fieldCount, int[] oids) {
+
+ cmd = sqlCmd;
+ table = dataTableSchema;
+ pgResult = pg_result;
+ rows = rowCount;
+ cols = fieldCount;
+ oid = oids;
+ }
+
+ #endregion
+
#region Public Methods
[MonoTODO]
public void Close()
{
- throw new NotImplementedException ();
+ // close result set
+ PostgresLibrary.PQclear (pgResult);
+
+ // TODO: change busy state on SqlConnection to not busy
}
[MonoTODO]
public DataTable GetSchemaTable()
{
- throw new NotImplementedException ();
+ return table;
}
[MonoTODO]
[MonoTODO]
public bool Read()
{
- throw new NotImplementedException ();
+ string value;
+ fields = new object[cols]; // re-init row
+
+ if(currentRow < rows - 1) {
+ currentRow++;
+ int c;
+ for(c = 0; c < cols; c++) {
+
+ // get data value
+ value = PostgresLibrary.
+ PQgetvalue(
+ pgResult,
+ currentRow, c);
+
+ int columnIsNull;
+ // is column NULL?
+ columnIsNull = PostgresLibrary.
+ PQgetisnull(pgResult,
+ currentRow, c);
+
+ int actualLength;
+ // get Actual Length
+ actualLength = PostgresLibrary.
+ PQgetlength(pgResult,
+ currentRow, c);
+
+ fields[c] = PostgresHelper.
+ ConvertPgTypeToSystem (oid[c], value);
+ }
+ return true;
+ }
+ return false; // EOF
}
[MonoTODO]
[MonoTODO]
public short GetInt16(int i)
{
- throw new NotImplementedException ();
+ return (short) fields[i];
}
[MonoTODO]
public int GetInt32(int i)
{
- throw new NotImplementedException ();
+ return (int) fields[i];
}
[MonoTODO]
public long GetInt64(int i)
{
- throw new NotImplementedException ();
+ return (long) fields[i];
}
[MonoTODO]
public string GetName(int i)
{
- throw new NotImplementedException ();
+ return table.Columns[i].ColumnName;
}
[MonoTODO]
[MonoTODO]
public string GetString(int i)
{
- throw new NotImplementedException ();
+ return (string) fields[i];
}
[MonoTODO]
public object GetValue(int i)
{
- throw new NotImplementedException ();
+ return fields[i];
}
[MonoTODO]
public int FieldCount {
[MonoTODO]
get {
- throw new NotImplementedException ();
+ return cols;
}
}
public object this[string name] {
[MonoTODO]
get {
- throw new NotImplementedException ();
+ int i;
+ for(i = 0; i < cols; i ++) {
+ if(table.Columns[i].ColumnName.Equals(name)) {
+ return fields[i];
+ }
+
+ }
+
+ if(i == cols) {
+ for(i = 0; i < cols; i++) {
+ string ta;
+ string n;
+
+ ta = table.Columns[i].ColumnName.ToUpper();
+ n = name.ToUpper();
+
+ if(ta.Equals(n)) {
+ return fields[i];
+ }
+ }
+ }
+ throw new MissingFieldException("Missing field: " + name);
}
}
[MonoTODO]
get
{
- throw new NotImplementedException ();
+ return fields[i];
}
}
public DataColumn(string columnName): this()
{
ColumnName = columnName;
- Caption = columnName;
}
public DataColumn(string columnName, Type dataType): this(columnName)
/// </summary>
public class DataColumnCollection : InternalDataCollectionBase
{
-
- protected new ArrayList list = null;
-
// The defaultNameIndex is used to create a default name for a column if one wasn't given.
private int defaultNameIndex;
// Internal Constructor. This Class can only be created from other classes in this assembly.
internal DataColumnCollection(DataTable table):base()
{
- list = new ArrayList();
defaultNameIndex = 1;
parentTable = table;
}
{
get
{
- return (DataColumn)list[index];
+ return (DataColumn) base.List[index];
}
}
{
get
{
- foreach (DataColumn column in list)
+ foreach (DataColumn column in base.List)
{
if (column.ColumnName == name)
{
{
get
{
- return list;
+ return base.List;
}
}
{
DataColumn column = new DataColumn("Column" + defaultNameIndex.ToString());
CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
- list.Add(column);
+ base.List.Add(column);
OnCollectionChanged(e);
defaultNameIndex++;
return column;
else
{
CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
- list.Add(column);
+ base.List.Add(column);
OnCollectionChanged(e);
return;
}
DataColumn column = new DataColumn(columnName);
CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
- list.Add(column);
+ base.List.Add(column);
OnCollectionChanged(e);
return column;
}
{
DataColumn column = new DataColumn(columnName, type);
CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
- list.Add(column);
+ base.List.Add(column);
OnCollectionChanged(e);
return column;
}
{
DataColumn column = new DataColumn(columnName, type, expression);
CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
- list.Add(column);
+ base.List.Add(column);
OnCollectionChanged(e);
return column;
}
//Check if another column's expression depends on this column.
- foreach (DataColumn dataColumn in list)
+ foreach (DataColumn dataColumn in List)
{
if (dataColumn.Expression.ToString().IndexOf(column.ColumnName) > 0)
{
public void Clear()
{
CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this);
- list.Clear();
+ base.List.Clear();
OnCollectionChanged(e);
return;
}
/// <returns>The index of the column specified by column if it is found; otherwise, -1.</returns>
public virtual int IndexOf(DataColumn column)
{
- return list.IndexOf(column);
+ return base.List.IndexOf(column);
}
/// <summary>
public void Remove(DataColumn column)
{
CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Remove, this);
- list.Remove(column);
+ base.List.Remove(column);
OnCollectionChanged(e);
return;
}
{
DataColumn column = this[name];
CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Remove, this);
- list.Remove(column);
+ base.List.Remove(column);
OnCollectionChanged(e);
return;
}
public void RemoveAt(int index)
{
CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Remove, this);
- list.RemoveAt(index);
+ base.List.RemoveAt(index);
OnCollectionChanged(e);
return;
}
private bool _containsListCollection;
private string _encodedTableName;
-
-
/// <summary>
/// Initializes a new instance of the DataTable class with no arguments.
/// </summary>
/// </summary>
public DataRow NewRow()
{
- DataRow dataRow = null;
+ DataRow dataRow = new DataRow();
+ dataRow.SetTable(this);
return dataRow;
}
object obj = null;
switch(oid) {
- case 1023: // varchar
+ case 1043: // varchar
Console.WriteLine("oid 1023 varchar ==> String found");
obj = (object) String.Copy(value); // String
break;
return obj;
}
+
+ public static Type OidToType (int oid) {
+ Type typ = null;
+
+ switch(oid) {
+ case 1043: // varchar
+ case 25: // text
+ case 18: // char
+ typ = typeof(String);
+ break;
+ case 16: // bool
+ typ = typeof(Boolean);
+ break;
+ case 21: // int2\r
+ typ = typeof(Int16);\r
+ break;\r
+ case 23: // int4\r
+ typ = typeof(Int32);\r
+ break;\r
+ case 20: // int8\r
+ typ = typeof(Int64);\r
+ break;\r
+ default:\r
+ throw new NotImplementedException(\r
+ "PGNI2: PostgreSQL oid type " + oid +\r
+ " not mapped to .NET System Type.");\r
+ }
+ return typ;
+ }
+
}
sealed public class PostgresLibrary {
PGRES_FATAL_ERROR
}
+
[DllImport("pq")]
public static extern string PQerrorMessage (IntPtr conn);
// char *PQerrorMessage(const PGconn *conn);
Test();
TestExecuteScalar();
+
+ Type t;
+ int oid;
+
+ oid = 1043;
+ t = PostgresHelper.OidToType(oid); // varchar ==> String
+ Console.WriteLine("OidToType varchar oid: " + oid +
+ " ==> t: " + t.ToString());
+
+ oid = 23;
+ t = PostgresHelper.OidToType(oid); // int4 ==> Int32
+ Console.WriteLine("OidToType int4 oid: " + oid +
+ " ==> t: " + t.ToString());
+
}
}
}
--- /dev/null
+//\r
+// Test/ExecuteScalar.cs\r
+//\r
+// Test the ExecuteScalar method in the \r
+// System.Data.SqlClient.SqlCommand class\r
+//\r
+// ExecuteScalar is meant to be lightweight\r
+// compared to ExecuteReader and only\r
+// returns one column and one row as one object.\r
+//\r
+// It is meant for SELECT SQL statements that\r
+// use an aggregate/group by function, such as,\r
+// count(), sum(), avg(), min(), max(), etc...\r
+// \r
+// The object that is returned you do an\r
+// explicit cast. For instance, to retrieve a\r
+// Count of rows in a PostgreSQL table, you\r
+// would use "SELECT COUNT(*) FROM SOMETABLE"\r
+// which returns a number of oid type 20 which is \r
+// a PostgreSQL int8 which maps to \r
+// the .NET type System.Int64. You\r
+// have to explicitly convert this returned object\r
+// to the type you are expecting, such as, an Int64\r
+// is returned for a COUNT().\r
+// would be:\r
+// Int64 myCount = (Int64) cmd.ExecuteScalar(selectStatement);\r
+//\r
+// Author:\r
+// Daniel Morgan <danmorg@sc.rr.com>\r
+//\r
+// (C) 2002 Daniel Morgan\r
+//\r
+\r
+using System;\r
+using System.Data;\r
+using System.Data.SqlClient;\r
+\r
+namespace TestSystemDataSqlClient\r
+{\r
+ class TestSqlDataReader\r
+ {\r
+\r
+ static void Test() { \r
+ SqlConnection con = null;\r
+ SqlCommand cmd = null;\r
+ \r
+ String connectionString = null;\r
+ String sql = null;\r
+\r
+ connectionString =
+ "host=localhost;" +
+ "dbname=test;" +
+ "user=danmorg;" +
+ "password=viewsonic";
+ \r
+ try {\r
+ con = new SqlConnection(connectionString);\r
+ con.Open();\r
+\r
+ sql = "select count(*) " + \r
+ "from sometable";\r
+ cmd = new SqlCommand(sql,con);\r
+ Console.WriteLine("Executing...");\r
+ Int64 rowCount = (Int64) cmd.ExecuteScalar();\r
+ Console.WriteLine("Row Count: " + rowCount);\r
+\r
+ sql = "select max(tdesc) " + \r
+ "from sometable";\r
+ cmd = new SqlCommand(sql,con);\r
+ Console.WriteLine("Executing...");\r
+ String maxValue = (string) cmd.ExecuteScalar();\r
+ Console.WriteLine("Max Value: " + maxValue);\r
+\r
+ }\r
+ catch(Exception e) {\r
+ Console.WriteLine(e.ToString());\r
+ }\r
+ finally {\r
+ if(con != null)
+ if(con.State == ConnectionState.Open)
+ con.Close();\r
+ }\r
+ }\r
+\r
+ [STAThread]\r
+ static void Main(string[] args)\r
+ {\r
+ Test();\r
+ }\r
+\r
+ }\r
+}\r
"user=danmorg;" +
"password=viewsonic";
\r
- sql = "select tid, tdesc " + \r
+ sql = "select tid, tdesc, aint4 " + \r
"from sometable";\r
\r
con = new SqlConnection(connectionString);\r
\r
cmd = new SqlCommand(sql, con);\r
rdr = cmd.ExecuteReader();\r
+\r
+ // get the DataTable that holds\r
+ // the schema\r
+ DataTable dt = rdr.GetSchemaTable();\r
\r
- // rdr.GetInt32(0) \r
- // rdr.GetString(1)\r
+ // number of columns in the table\r
+ Console.WriteLine("dt.Columns.Count: " +\r
+ dt.Columns.Count);\r
+\r
+ // display the schema\r
+ for(int c = 0; c < dt.Columns.Count; c++) {\r
+ Console.WriteLine("* Column Name: " + \r
+ dt.Columns[c].ColumnName);\r
+ Console.WriteLine(" MaxLength: " +\r
+ dt.Columns[c].MaxLength);\r
+ Console.WriteLine(" Type: " +\r
+ dt.Columns[c].DataType);\r
+ }\r
+\r
+ // Read and display the rows\r
while(rdr.Read()) {\r
- Console.WriteLine(\r
- rdr["fname"].ToString() + \r
- ", " + \r
- rdr["lname"].ToString());\r
+ Console.WriteLine("Row: " +\r
+ rdr["tid"].ToString() + ", " + \r
+ rdr["tdesc"].ToString() + ", " + \r
+ rdr["aint4"].ToString()\r
+ );\r
+\r
+ Console.WriteLine("1:" + rdr.GetString(0));\r
+ Console.WriteLine("1:" + rdr.GetString(1));\r
+ Console.WriteLine("2:" + rdr.GetInt32(2));\r
}\r
+ \r
rdr.Close();\r
con.Close();\r
}\r