X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Data.OracleClient%2FSystem.Data.OracleClient%2FOracleCommand.cs;h=db39d3d551fe0ba6d4a1031cce61ca67fd66604e;hb=7e234e0af7c05b9adadf9cba632c528aac1333d5;hp=3aba07142a1e790c71dfee3d34d5dd5ded86d131;hpb=fe3197aa40b9c08dc1d83963067c01bfd74fceba;p=mono.git diff --git a/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleCommand.cs b/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleCommand.cs old mode 100755 new mode 100644 index 3aba07142a1..db39d3d551f --- a/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleCommand.cs +++ b/mcs/class/System.Data.OracleClient/System.Data.OracleClient/OracleCommand.cs @@ -1,4 +1,4 @@ -// +// // OracleCommand.cs // // Part of the Mono class libraries at @@ -7,11 +7,12 @@ // Assembly: System.Data.OracleClient.dll // Namespace: System.Data.OracleClient // -// Authors: -// Daniel Morgan +// Authors: +// Daniel Morgan // Tim Coleman +// Marek Safar // -// Copyright (C) Daniel Morgan, 2002 +// Copyright (C) Daniel Morgan, 2002, 2004-2005 // Copyright (C) Tim Coleman , 2003 // // Licensed under the MIT/X11 License. @@ -20,10 +21,26 @@ using System; using System.ComponentModel; using System.Data; +#if NET_2_0 +using System.Data.Common; +#endif using System.Data.OracleClient.Oci; - -namespace System.Data.OracleClient { - public class OracleCommand : Component, ICloneable, IDbCommand +using System.Drawing.Design; +using System.Text; + +namespace System.Data.OracleClient +{ +#if NET_2_0 + [DefaultEvent ("RecordsAffected")] +#endif + [Designer ("Microsoft.VSDesigner.Data.VS.OracleCommandDesigner, " + Consts.AssemblyMicrosoft_VSDesigner)] + [ToolboxItem (true)] + public sealed class OracleCommand : +#if NET_2_0 + DbCommand, ICloneable +#else + Component, ICloneable, IDbCommand +#endif { #region Fields @@ -35,9 +52,9 @@ namespace System.Data.OracleClient { OracleParameterCollection parameters; OracleTransaction transaction; UpdateRowSource updatedRowSource; - OciStatementHandle preparedStatement; - OciStatementType statementType; + + int moreResults; #endregion // Fields @@ -60,37 +77,102 @@ namespace System.Data.OracleClient { public OracleCommand (string commandText, OracleConnection connection, OracleTransaction tx) { + moreResults = -1; preparedStatement = null; CommandText = commandText; Connection = connection; Transaction = tx; CommandType = CommandType.Text; UpdatedRowSource = UpdateRowSource.Both; - DesignTimeVisible = false; - - parameters = new OracleParameterCollection (this); + DesignTimeVisible = true; + parameters = new OracleParameterCollection (); } #endregion // Constructors #region Properties - public string CommandText { - get { return commandText; } + [DefaultValue ("")] + [RefreshProperties (RefreshProperties.All)] + [Editor ("Microsoft.VSDesigner.Data.Oracle.Design.OracleCommandTextEditor, " + Consts.AssemblyMicrosoft_VSDesigner, typeof(UITypeEditor))] + public +#if NET_2_0 + override +#endif + string CommandText { + get { + if (commandText == null) + return string.Empty; + + return commandText; + } set { commandText = value; } } - public CommandType CommandType { + [RefreshProperties (RefreshProperties.All)] + [DefaultValue (CommandType.Text)] + public +#if NET_2_0 + override +#endif + CommandType CommandType { get { return commandType; } - set { commandType = value; } + set { + if (value == CommandType.TableDirect) + throw new ArgumentException ("OracleClient provider does not support TableDirect CommandType."); + commandType = value; + } } - public OracleConnection Connection { + [DefaultValue (null)] + [Editor ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner, typeof(UITypeEditor))] + public +#if NET_2_0 + new +#endif + OracleConnection Connection { get { return connection; } set { connection = value; } } - public bool DesignTimeVisible { +#if NET_2_0 + [Browsable (false)] + [EditorBrowsable (EditorBrowsableState.Never)] + [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public override int CommandTimeout { + get { return 0; } + set { } + } + + [MonoTODO] + protected override DbConnection DbConnection { + get { return Connection; } + set { Connection = (OracleConnection) value; } + } + + [MonoTODO] + protected override DbParameterCollection DbParameterCollection { + get { return Parameters; } + } + + [MonoTODO] + protected override DbTransaction DbTransaction { + get { return Transaction; } + set { Transaction = (OracleTransaction) value; } + } +#endif + + [DefaultValue (true)] + [Browsable (false)] + [DesignOnly (true)] +#if NET_2_0 + [EditorBrowsable (EditorBrowsableState.Never)] +#endif + public +#if NET_2_0 + override +#endif + bool DesignTimeVisible { get { return designTimeVisible; } set { designTimeVisible = value; } } @@ -103,16 +185,18 @@ namespace System.Data.OracleClient { get { return Connection.ErrorHandle; } } +#if !NET_2_0 int IDbCommand.CommandTimeout { get { return 0; } set { } } + [Editor ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner, typeof(UITypeEditor))] + [DefaultValue (null)] IDbConnection IDbCommand.Connection { get { return Connection; } - set { - if (!(value is OracleConnection)) - throw new InvalidCastException ("The value was not a valid OracleConnection."); + set { + // InvalidCastException is expected when types do not match Connection = (OracleConnection) value; } } @@ -123,23 +207,39 @@ namespace System.Data.OracleClient { IDbTransaction IDbCommand.Transaction { get { return Transaction; } - set { - if (!(value is OracleTransaction)) - throw new ArgumentException (); - Transaction = (OracleTransaction) value; + set { + // InvalidCastException is expected when types do not match + Transaction = (OracleTransaction) value; } } +#endif - public OracleParameterCollection Parameters { + [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + public +#if NET_2_0 + new +#endif + OracleParameterCollection Parameters { get { return parameters; } } - public OracleTransaction Transaction { + [Browsable (false)] + [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public +#if NET_2_0 + new +#endif + OracleTransaction Transaction { get { return transaction; } set { transaction = value; } } - public UpdateRowSource UpdatedRowSource { + [DefaultValue (UpdateRowSource.Both)] + public +#if NET_2_0 + override +#endif + UpdateRowSource UpdatedRowSource { get { return updatedRowSource; } set { updatedRowSource = value; } } @@ -150,7 +250,7 @@ namespace System.Data.OracleClient { private void AssertCommandTextIsSet () { - if (CommandText == String.Empty || CommandText == null) + if (CommandText.Length == 0) throw new InvalidOperationException ("The command text for this Command has not been set."); } @@ -160,12 +260,6 @@ namespace System.Data.OracleClient { throw new InvalidOperationException ("An open Connection object is required to continue."); } - private void AssertNoDataReader () - { - if (Connection.DataReader != null) - throw new InvalidOperationException ("There is already an open DataReader associated with this Connection which must be closed first."); - } - private void AssertTransactionMatch () { if (Connection.Transaction != null && Transaction != Connection.Transaction) @@ -174,12 +268,16 @@ namespace System.Data.OracleClient { private void BindParameters (OciStatementHandle statement) { - foreach (OracleParameter p in Parameters) - p.Bind (statement, Connection); + for (int p = 0; p < Parameters.Count; p++) + Parameters[p].Bind (statement, Connection, (uint) p); } [MonoTODO] - public void Cancel () + public +#if NET_2_0 + override +#endif + void Cancel () { throw new NotImplementedException (); } @@ -187,7 +285,83 @@ namespace System.Data.OracleClient { [MonoTODO] public object Clone () { - throw new NotImplementedException (); + // create a new OracleCommand object with the same properties + + OracleCommand cmd = new OracleCommand (); + + cmd.CommandText = this.CommandText; + cmd.CommandType = this.CommandType; + + // FIXME: not sure if I should set the same object here + // or get a clone of these too + cmd.Connection = this.Connection; + cmd.Transaction = this.Transaction; + + foreach (OracleParameter parm in this.Parameters) { + + OracleParameter newParm = cmd.CreateParameter (); + + newParm.DbType = parm.DbType; + newParm.Direction = parm.Direction; + newParm.IsNullable = parm.IsNullable; + newParm.Offset = parm.Offset; + newParm.OracleType = parm.OracleType; + newParm.ParameterName = parm.ParameterName; + //newParm.Precision = parm.Precision; + //newParm.Scale = parm.Scale; + newParm.SourceColumn = parm.SourceColumn; + newParm.SourceVersion = parm.SourceVersion; + newParm.Value = parm.Value; + + cmd.Parameters.Add (newParm); + } + + //cmd.Container = this.Container; + cmd.DesignTimeVisible = this.DesignTimeVisible; + //cmd.DesignMode = this.DesignMode; + cmd.Site = this.Site; + //cmd.UpdateRowSource = this.UpdateRowSource; + + return cmd; + } + +#if NET_2_0 + protected override DbParameter CreateDbParameter () + { + return CreateParameter (); + } + + protected override DbDataReader ExecuteDbDataReader (CommandBehavior behavior) + { + return ExecuteReader (behavior); + } +#endif + + internal void UpdateParameterValues () + { + moreResults = -1; + if (Parameters.Count > 0) { + bool foundCursor = false; + for (int p = 0; p < Parameters.Count; p++) { + OracleParameter parm = Parameters [p]; + if (parm.OracleType.Equals (OracleType.Cursor)) { + if (!foundCursor && parm.Direction != ParameterDirection.Input) { + // if there are multiple REF CURSORs, + // you only can get the first cursor for now + // because user of OracleDataReader + // will do a NextResult to get the next + // REF CURSOR (if it exists) + foundCursor = true; + parm.Update (this); + if (p + 1 == Parameters.Count) + moreResults = -1; + else + moreResults = p; + } + } else + parm.Update (this); + } + } } internal void CloseDataReader () @@ -197,103 +371,227 @@ namespace System.Data.OracleClient { Connection.Close (); } - public OracleParameter CreateParameter () + public +#if NET_2_0 + new +#endif + OracleParameter CreateParameter () { return new OracleParameter (); } - private int ExecuteNonQueryInternal (OciStatementHandle statement) + internal void DeriveParameters () { + if (commandType != CommandType.StoredProcedure) + throw new InvalidOperationException (String.Format ("OracleCommandBuilder DeriveParameters only supports CommandType.StoredProcedure, not CommandType.{0}", commandType)); + + //OracleParameterCollection localParameters = new OracleParameterCollection (this); + + throw new NotImplementedException (); + } + + private int ExecuteNonQueryInternal (OciStatementHandle statement, bool useAutoCommit) + { + moreResults = -1; + if (preparedStatement == null) - statement.Prepare (CommandText); + PrepareStatement (statement); + + bool isNonQuery = IsNonQuery (statement); BindParameters (statement); - statement.ExecuteNonQuery (); + if (isNonQuery == true) + statement.ExecuteNonQuery (useAutoCommit); + else + statement.ExecuteQuery (false); + + UpdateParameterValues (); int rowsAffected = statement.GetAttributeInt32 (OciAttributeType.RowCount, ErrorHandle); - + return rowsAffected; } - public int ExecuteNonQuery () + public +#if NET_2_0 + override +#endif + int ExecuteNonQuery () { + moreResults = -1; + AssertConnectionIsOpen (); AssertTransactionMatch (); AssertCommandTextIsSet (); + bool useAutoCommit = false; if (Transaction != null) Transaction.AttachToServiceContext (); + else + useAutoCommit = true; OciStatementHandle statement = GetStatementHandle (); try { - return ExecuteNonQueryInternal (statement); - } - finally { + return ExecuteNonQueryInternal (statement, useAutoCommit); + } finally { SafeDisposeHandle (statement); } } public int ExecuteOracleNonQuery (out OracleString rowid) { + moreResults = -1; + AssertConnectionIsOpen (); AssertTransactionMatch (); AssertCommandTextIsSet (); + bool useAutoCommit = false; if (Transaction != null) Transaction.AttachToServiceContext (); + else + useAutoCommit = true; OciStatementHandle statement = GetStatementHandle (); try { - int retval = ExecuteNonQueryInternal (statement); + int retval = ExecuteNonQueryInternal (statement, useAutoCommit); + OciRowIdDescriptor rowIdDescriptor = statement.GetAttributeRowIdDescriptor (ErrorHandle, Environment); + string srowid = rowIdDescriptor.GetRowIdToString (ErrorHandle); + rowid = new OracleString (srowid); + rowIdDescriptor = null; + return retval; + } finally { + SafeDisposeHandle (statement); + } + } - OciRowIdDescriptor descriptor = (OciRowIdDescriptor) Environment.Allocate (OciHandleType.RowId); - descriptor.SetHandle (statement.GetAttributeIntPtr (OciAttributeType.RowId, ErrorHandle)); + public object ExecuteOracleScalar () + { + moreResults = -1; - rowid = new OracleString (descriptor.GetRowId (ErrorHandle)); + object output = DBNull.Value; - return retval; - } - finally { + AssertConnectionIsOpen (); + AssertTransactionMatch (); + AssertCommandTextIsSet (); + + if (Transaction != null) + Transaction.AttachToServiceContext (); + + OciStatementHandle statement = GetStatementHandle (); + try { + if (preparedStatement == null) + PrepareStatement (statement); + + bool isNonQuery = IsNonQuery (statement); + + BindParameters (statement); + + if (isNonQuery == true) + ExecuteNonQueryInternal (statement, false); + else { + statement.ExecuteQuery (false); + + if (statement.Fetch ()) { + OciDefineHandle defineHandle = (OciDefineHandle) statement.Values [0]; + if (!defineHandle.IsNull) + output = defineHandle.GetOracleValue (Connection.SessionFormatProvider, Connection); + switch (defineHandle.DataType) { + case OciDataType.Blob: + case OciDataType.Clob: + ((OracleLob) output).connection = Connection; + break; + } + } + UpdateParameterValues (); + } + + return output; + } finally { SafeDisposeHandle (statement); } } - [MonoTODO] - public object ExecuteOracleScalar (out OracleString rowid) + private bool IsNonQuery (OciStatementHandle statementHandle) { - throw new NotImplementedException (); + // assumes Prepare() has been called prior to calling this function + + OciStatementType statementType = statementHandle.GetStatementType (); + if (statementType.Equals (OciStatementType.Select)) + return false; + + return true; } - public OracleDataReader ExecuteReader () + public +#if NET_2_0 + new +#endif + OracleDataReader ExecuteReader () { return ExecuteReader (CommandBehavior.Default); } - public OracleDataReader ExecuteReader (CommandBehavior behavior) + public +#if NET_2_0 + new +#endif + OracleDataReader ExecuteReader (CommandBehavior behavior) { AssertConnectionIsOpen (); AssertTransactionMatch (); AssertCommandTextIsSet (); - AssertNoDataReader (); - if (Transaction != null) + moreResults = -1; + + bool hasRows = false; + + this.behavior = behavior; + + if (Transaction != null) Transaction.AttachToServiceContext (); - + OciStatementHandle statement = GetStatementHandle (); OracleDataReader rd = null; - try { + + try { if (preparedStatement == null) - statement.Prepare (CommandText); + PrepareStatement (statement); else preparedStatement = null; // OracleDataReader releases the statement handle + bool isNonQuery = IsNonQuery (statement); + BindParameters (statement); - statement.ExecuteQuery (); - rd = new OracleDataReader (this, statement); - } - finally { + if (isNonQuery) + ExecuteNonQueryInternal (statement, false); + else { + if ((behavior & CommandBehavior.SchemaOnly) != 0) + statement.ExecuteQuery (true); + else + hasRows = statement.ExecuteQuery (false); + + UpdateParameterValues (); + } + + if (Parameters.Count > 0) { + for (int p = 0; p < Parameters.Count; p++) { + OracleParameter parm = Parameters [p]; + if (parm.OracleType.Equals (OracleType.Cursor)) { + if (parm.Direction != ParameterDirection.Input) { + rd = (OracleDataReader) parm.Value; + break; + } + } + } + } + + if (rd == null) + rd = new OracleDataReader (this, statement, hasRows, behavior); + + } finally { if (statement != null && rd == null) statement.Dispose(); } @@ -301,9 +599,14 @@ namespace System.Data.OracleClient { return rd; } - public object ExecuteScalar () + public +#if NET_2_0 + override +#endif + object ExecuteScalar () { - object output; + moreResults = -1; + object output = null;//if we find nothing we return this AssertConnectionIsOpen (); AssertTransactionMatch (); @@ -315,41 +618,98 @@ namespace System.Data.OracleClient { OciStatementHandle statement = GetStatementHandle (); try { if (preparedStatement == null) - statement.Prepare (CommandText); - BindParameters (statement); + PrepareStatement (statement); - statement.ExecuteQuery (); + bool isNonQuery = IsNonQuery (statement); - if (statement.Fetch ()) - output = ((OciDefineHandle) statement.Values [0]).GetValue (); - else - output = DBNull.Value; - } - finally { + BindParameters (statement); + + if (isNonQuery == true) + ExecuteNonQueryInternal (statement, false); + else { + statement.ExecuteQuery (false); + + if (statement.Fetch ()) { + OciDefineHandle defineHandle = (OciDefineHandle) statement.Values [0]; + if (!defineHandle.IsNull) + { + switch (defineHandle.DataType) { + case OciDataType.Blob: + case OciDataType.Clob: + OracleLob lob = (OracleLob) defineHandle.GetValue ( + Connection.SessionFormatProvider, Connection); + lob.connection = Connection; + output = lob.Value; + lob.Close (); + break; + default: + output = defineHandle.GetValue ( + Connection.SessionFormatProvider, Connection); + break; + } + } + } + UpdateParameterValues (); + } + } finally { SafeDisposeHandle (statement); } return output; } + internal OciStatementHandle GetNextResult () + { + if (moreResults == -1) + return null; + + if (Parameters.Count > 0) { + int p = moreResults + 1; + + if (p >= Parameters.Count) { + moreResults = -1; + return null; + } + + for (; p < Parameters.Count; p++) { + OracleParameter parm = Parameters [p]; + if (parm.OracleType.Equals (OracleType.Cursor)) { + if (parm.Direction != ParameterDirection.Input) { + if (p + 1 == Parameters.Count) + moreResults = -1; + else + moreResults = p; + return parm.GetOutRefCursor (this); + + } + } + } + } + + moreResults = -1; + return null; + } + private OciStatementHandle GetStatementHandle () { AssertConnectionIsOpen (); - if (preparedStatement != null) + if (preparedStatement != null) return preparedStatement; - + OciStatementHandle h = (OciStatementHandle) Connection.Environment.Allocate (OciHandleType.Statement); h.ErrorHandle = Connection.ErrorHandle; h.Service = Connection.ServiceContext; + h.Command = this; return h; } private void SafeDisposeHandle (OciStatementHandle h) { - if (h != null && h != preparedStatement) + if (h != null && h != preparedStatement) h.Dispose(); } +#if !NET_2_0 IDbDataParameter IDbCommand.CreateParameter () { return CreateParameter (); @@ -364,15 +724,46 @@ namespace System.Data.OracleClient { { return ExecuteReader (behavior); } +#endif - public void Prepare () + void PrepareStatement (OciStatementHandle statement) + { + if (commandType == CommandType.StoredProcedure) { + StringBuilder sb = new StringBuilder (); + if (Parameters.Count > 0) + foreach (OracleParameter parm in Parameters) { + if (sb.Length > 0) + sb.Append (","); + sb.Append (parm.ParameterName + "=>:" + parm.ParameterName); + } + + string sql = "begin " + commandText + "(" + sb.ToString() + "); end;"; + statement.Prepare (sql); + } else // Text + statement.Prepare (commandText); + } + + public +#if NET_2_0 + override +#endif + void Prepare () { AssertConnectionIsOpen (); OciStatementHandle statement = GetStatementHandle (); - statement.Prepare (CommandText); + PrepareStatement (statement); preparedStatement = statement; } + protected override void Dispose (bool disposing) + { + if (disposing) + if (Parameters.Count > 0) + foreach (OracleParameter parm in Parameters) + parm.FreeHandle (); + base.Dispose (disposing); + } + #endregion // Methods } }