| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 |
- //
- // System.Data.SqlClient.SqlCommand.cs
- //
- // Author:
- // Rodrigo Moya ([email protected])
- // Daniel Morgan ([email protected])
- //
- // (C) Ximian, Inc 2002 http://www.ximian.com/
- // (C) Daniel Morgan, 2002
- //
- // Credits:
- // SQL and concepts were used from libgda 0.8.190 (GNOME Data Access)
- // http://www.gnome-db.org/
- // with permission from the authors of the
- // PostgreSQL provider in libgda:
- // Michael Lausch <[email protected]>
- // Rodrigo Moya <[email protected]>
- // Vivien Malerba <[email protected]>
- // Gonzalo Paniagua Javier <[email protected]>
- //
- // use #define DEBUG_SqlCommand if you want to spew debug messages
- // #define DEBUG_SqlCommand
- using System;
- using System.ComponentModel;
- using System.Data;
- using System.Data.Common;
- using System.Runtime.InteropServices;
- using System.Xml;
- namespace System.Data.SqlClient {
- /// <summary>
- /// Represents a SQL statement that is executed
- /// while connected to a SQL database.
- /// </summary>
- // public sealed class SqlCommand : Component, IDbCommand, ICloneable
- public sealed class SqlCommand : IDbCommand {
- // FIXME: Console.WriteLine() is used for debugging throughout
- #region Fields
- string sql = "";
- int timeout = 30;
- // default is 30 seconds
- // for command execution
- SqlConnection conn = null;
- SqlTransaction trans = null;
- CommandType cmdType = CommandType.Text;
- bool designTime = false;
- SqlParameterCollection parmCollection = new
- SqlParameterCollection();
- #endregion // Fields
- #region Constructors
- public SqlCommand() {
- sql = "";
- }
- public SqlCommand (string cmdText) {
- sql = cmdText;
- }
- public SqlCommand (string cmdText, SqlConnection connection) {
- sql = cmdText;
- conn = connection;
- }
- public SqlCommand (string cmdText, SqlConnection connection,
- SqlTransaction transaction) {
- sql = cmdText;
- conn = connection;
- trans = transaction;
- }
- #endregion // Constructors
- #region Methods
- [MonoTODO]
- public void Cancel () {
- // FIXME: use non-blocking Exec for this
- throw new NotImplementedException ();
- }
- // FIXME: is this the correct way to return a stronger type?
- [MonoTODO]
- IDbDataParameter IDbCommand.CreateParameter () {
- return CreateParameter ();
- }
- [MonoTODO]
- public SqlParameter CreateParameter () {
- return new SqlParameter ();
- }
- public int ExecuteNonQuery () {
- IntPtr pgResult; // PGresult
- int rowsAffected = -1;
- ExecStatusType execStatus;
- String rowsAffectedString;
- 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_COMMAND_OK) {
- rowsAffectedString = PostgresLibrary.
- PQcmdTuples (pgResult);
- if(rowsAffectedString != null)
- if(rowsAffectedString.Equals("") == false)
- rowsAffected = int.Parse(rowsAffectedString);
- PostgresLibrary.PQclear (pgResult);
- }
- else {
- String errorMessage;
-
- errorMessage = PostgresLibrary.
- PQresStatus(execStatus);
- errorMessage += " " + PostgresLibrary.
- PQresultErrorMessage(pgResult);
-
- throw new SqlException(0, 0,
- errorMessage, 0, "",
- conn.DataSource, "SqlCommand", 0);
- }
-
- return rowsAffected;
- }
-
- [MonoTODO]
- IDataReader IDbCommand.ExecuteReader () {
- return ExecuteReader ();
- }
- [MonoTODO]
- public SqlDataReader ExecuteReader () {
- return ExecuteReader(CommandBehavior.Default);
- }
- [MonoTODO]
- IDataReader IDbCommand.ExecuteReader (
- CommandBehavior behavior) {
- return ExecuteReader (behavior);
- }
- [MonoTODO]
- public SqlDataReader ExecuteReader (CommandBehavior behavior) {
- // 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;
- string[] types;
-
- // FIXME: maybe i should move the
- // BuildTableSchema code
- // to the SqlDataReader?
- dt = BuildTableSchema(pgResult,
- out rows, out cols, out types);
- dataReader = new SqlDataReader(this, dt, pgResult,
- rows, cols, types);
- }
- else {
- String errorMessage;
-
- errorMessage = PostgresLibrary.
- PQresStatus(execStatus);
- errorMessage += " " + PostgresLibrary.
- PQresultErrorMessage(pgResult);
-
- throw new SqlException(0, 0,
- errorMessage, 0, "",
- conn.DataSource, "SqlCommand", 0);
- }
-
- return dataReader;
- }
- internal DataTable BuildTableSchema (IntPtr pgResult,
- out int nRows,
- out int nFields,
- out string[] types) {
- int nCol;
-
- DataTable dt = new DataTable();
- nRows = PostgresLibrary.
- PQntuples(pgResult);
- nFields = PostgresLibrary.
- PQnfields(pgResult);
-
- int oid;
- types = new string[nFields];
- for(nCol = 0; nCol < nFields; nCol++) {
-
- DbType dbType;
- // get column name
- String fieldName;
- fieldName = PostgresLibrary.
- PQfname(pgResult, nCol);
- // get PostgreSQL data type (OID)
- oid = PostgresLibrary.
- PQftype(pgResult, nCol);
- types[nCol] = PostgresHelper.
- OidToTypname (oid, conn.Types);
-
- 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);
- dbType = PostgresHelper.
- TypnameToSqlDbType(types[nCol]);
- dc.DataType = PostgresHelper.
- DbTypeToSystemType(dbType);
- dc.MaxLength = definedSize;
- dc.SetTable(dt);
-
- dt.Columns.Add(dc);
- }
- return dt;
- }
- [MonoTODO]
- public object ExecuteScalar () {
- IntPtr pgResult; // PGresult
- ExecStatusType execStatus;
- object obj = null; // return
- int nRow = 0; // first row
- int nCol = 0; // first column
- String value;
- int nRows;
- int nFields;
- 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) {
- nRows = PostgresLibrary.
- PQntuples(pgResult);
- nFields = PostgresLibrary.
- PQnfields(pgResult);
- if(nRows > 0 && nFields > 0) {
- // get column name
- //String fieldName;
- //fieldName = PostgresLibrary.
- // PQfname(pgResult, nCol);
- int oid;
- string sType;
- DbType dbType;
- // get PostgreSQL data type (OID)
- oid = PostgresLibrary.
- PQftype(pgResult, nCol);
- sType = PostgresHelper.
- OidToTypname (oid, conn.Types);
- dbType = PostgresHelper.
- TypnameToSqlDbType(sType);
- int definedSize;
- // get defined size of column
- definedSize = PostgresLibrary.
- PQfsize(pgResult, nCol);
- // get data value
- value = PostgresLibrary.
- PQgetvalue(
- pgResult,
- nRow, nCol);
- int columnIsNull;
- // is column NULL?
- columnIsNull = PostgresLibrary.
- PQgetisnull(pgResult,
- nRow, nCol);
- int actualLength;
- // get Actual Length
- actualLength = PostgresLibrary.
- PQgetlength(pgResult,
- nRow, nCol);
-
- obj = PostgresHelper.
- ConvertDbTypeToSystem (
- dbType,
- value);
- }
- // close result set
- PostgresLibrary.PQclear (pgResult);
- }
- else {
- String errorMessage;
-
- errorMessage = PostgresLibrary.
- PQresStatus(execStatus);
- errorMessage += " " + PostgresLibrary.
- PQresultErrorMessage(pgResult);
-
- throw new SqlException(0, 0,
- errorMessage, 0, "",
- conn.DataSource, "SqlCommand", 0);
- }
-
- return obj;
- }
- [MonoTODO]
- public XmlReader ExecuteXmlReader () {
- throw new NotImplementedException ();
- }
- [MonoTODO]
- public void Prepare () {
- // FIXME: parameters have to be implemented for this
- throw new NotImplementedException ();
- }
- [MonoTODO]
- public SqlCommand Clone () {
- throw new NotImplementedException ();
- }
- #endregion // Methods
- #region Properties
- public string CommandText {
- get {
- return sql;
- }
- set {
- sql = value;
- }
- }
- public int CommandTimeout {
- get {
- return timeout;
- }
-
- set {
- // FIXME: if value < 0, throw
- // ArgumentException
- // if (value < 0)
- // throw ArgumentException;
- timeout = value;
- }
- }
- public CommandType CommandType {
- get {
- return cmdType;
- }
- set {
- cmdType = value;
- }
- }
- // FIXME: for property Connection, is this the correct
- // way to handle a return of a stronger type?
- IDbConnection IDbCommand.Connection {
- get {
- return Connection;
- }
- set {
- // FIXME: throw an InvalidOperationException
- // if the change was during a
- // transaction in progress
- // csc
- Connection = (SqlConnection) value;
- // mcs
- // Connection = value;
-
- // FIXME: set Transaction property to null
- }
- }
-
- public SqlConnection Connection {
- get {
- // conn defaults to null
- return conn;
- }
- set {
- // FIXME: throw an InvalidOperationException
- // if the change was during
- // a transaction in progress
- conn = value;
- // FIXME: set Transaction property to null
- }
- }
- public bool DesignTimeVisible {
- get {
- return designTime;
- }
-
- set{
- designTime = value;
- }
- }
- // FIXME; for property Parameters, is this the correct
- // way to handle a stronger return type?
- IDataParameterCollection IDbCommand.Parameters {
- get {
- return Parameters;
- }
- }
- SqlParameterCollection Parameters {
- get {
- return parmCollection;
- }
- }
- // FIXME: for property Transaction, is this the correct
- // way to handle a return of a stronger type?
- IDbTransaction IDbCommand.Transaction {
- get {
- return Transaction;
- }
- set {
- // FIXME: error handling - do not allow
- // setting of transaction if transaction
- // has already begun
- // csc
- Transaction = (SqlTransaction) value;
- // mcs
- // Transaction = value;
- }
- }
- public SqlTransaction Transaction {
- get {
- return trans;
- }
- set {
- // FIXME: error handling
- trans = value;
- }
- }
- [MonoTODO]
- public UpdateRowSource UpdatedRowSource {
- // FIXME: do this once DbDataAdaptor
- // and DataRow are done
- get {
- throw new NotImplementedException ();
- }
- set {
- throw new NotImplementedException ();
- }
- }
- #endregion // Properties
- #region Destructors
- [MonoTODO]
- public void Dispose() {
- // FIXME: need proper way to release resources
- // Dispose(true);
- }
- [MonoTODO]
- ~SqlCommand() {
- // FIXME: need proper way to release resources
- // Dispose(false);
- }
- #endregion //Destructors
- }
- }
|