// Namespace: System.Data.OracleClient
//
// Authors:
-// Daniel Morgan <danmorg@sc.rr.com>
+// Daniel Morgan <danielmorgan@verizon.net>
// Tim Coleman <tim@timcoleman.com>
//
-// Copyright (C) Daniel Morgan, 2002
+// Copyright (C) Daniel Morgan, 2002, 2004-2005
// Copyright (C) Tim Coleman , 2003
//
// Licensed under the MIT/X11 License.
using System.ComponentModel;
using System.Data;
using System.Data.OracleClient.Oci;
+using System.Drawing.Design;
+using System.Text;
namespace System.Data.OracleClient {
- public class OracleCommand : Component, ICloneable, IDbCommand
+ [Designer ("Microsoft.VSDesigner.Data.VS.OracleCommandDesigner, " + Consts.AssemblyMicrosoft_VSDesigner)]
+ [ToolboxItem (true)]
+ public sealed class OracleCommand : Component, ICloneable, IDbCommand
{
#region Fields
- bool disposed = false;
CommandBehavior behavior;
string commandText;
CommandType commandType;
OracleTransaction transaction;
UpdateRowSource updatedRowSource;
- OciStatementHandle preparedStatement;
+ private OciStatementHandle preparedStatement;
OciStatementType statementType;
#endregion // Fields
UpdatedRowSource = UpdateRowSource.Both;
DesignTimeVisible = false;
- parameters = new OracleParameterCollection (this);
+ parameters = new OracleParameterCollection (this);
}
#endregion // Constructors
#region Properties
+ [DefaultValue ("")]
+ [RefreshProperties (RefreshProperties.All)]
+ [Editor ("Microsoft.VSDesigner.Data.Oracle.Design.OracleCommandTextEditor, " + Consts.AssemblyMicrosoft_VSDesigner, typeof(UITypeEditor))]
public string CommandText {
get { return commandText; }
set { commandText = value; }
}
+ [RefreshProperties (RefreshProperties.All)]
+ [DefaultValue (CommandType.Text)]
public 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;
+ }
}
+ [DefaultValue (null)]
+ [Editor ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner, typeof(UITypeEditor))]
public OracleConnection Connection {
get { return connection; }
set { connection = value; }
}
+ [DefaultValue (true)]
+ [Browsable (false)]
+ [DesignOnly (true)]
public bool DesignTimeVisible {
get { return designTimeVisible; }
set { designTimeVisible = value; }
set { }
}
+ [Editor ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner, typeof(UITypeEditor))]
+ [DefaultValue (null)]
IDbConnection IDbCommand.Connection {
get { return Connection; }
set {
}
}
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public OracleParameterCollection Parameters {
get { return parameters; }
}
+ [Browsable (false)]
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public OracleTransaction Transaction {
get { return transaction; }
set { transaction = value; }
}
+ [DefaultValue (UpdateRowSource.Both)]
public UpdateRowSource UpdatedRowSource {
get { return updatedRowSource; }
set { updatedRowSource = value; }
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]
[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;
+ }
+
+ internal void UpdateParameterValues ()
+ {
+ if (Parameters.Count > 0) {
+ foreach (OracleParameter parm in Parameters)
+ parm.Update (this);
+ }
}
internal void CloseDataReader ()
{
+ UpdateParameterValues ();
+
Connection.DataReader = null;
if ((behavior & CommandBehavior.CloseConnection) != 0)
Connection.Close ();
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)
{
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);
-
- statement.Dispose ();
+
return rowsAffected;
}
AssertConnectionIsOpen ();
AssertTransactionMatch ();
AssertCommandTextIsSet ();
+ bool useAutoCommit = false;
if (Transaction != null)
Transaction.AttachToServiceContext ();
+ else
+ useAutoCommit = true;
- return ExecuteNonQueryInternal (GetStatementHandle ());
+ OciStatementHandle statement = GetStatementHandle ();
+ try {
+ return ExecuteNonQueryInternal (statement, useAutoCommit);
+ }
+ finally {
+ SafeDisposeHandle (statement);
+ }
}
public int ExecuteOracleNonQuery (out OracleString rowid)
AssertConnectionIsOpen ();
AssertTransactionMatch ();
AssertCommandTextIsSet ();
+ bool useAutoCommit = false;
if (Transaction != null)
Transaction.AttachToServiceContext ();
+ else
+ useAutoCommit = true;
OciStatementHandle statement = GetStatementHandle ();
- int retval = ExecuteNonQueryInternal (statement);
+ try {
+ int retval = ExecuteNonQueryInternal (statement, useAutoCommit);
- OciRowIdDescriptor descriptor = (OciRowIdDescriptor) Environment.Allocate (OciHandleType.RowId);
- descriptor.SetHandle (statement.GetAttributeIntPtr (OciAttributeType.RowId, ErrorHandle));
+ OciRowIdDescriptor descriptor = (OciRowIdDescriptor) Environment.Allocate (OciHandleType.RowId);
+ descriptor.SetHandle (statement.GetAttributeIntPtr (OciAttributeType.RowId, ErrorHandle));
- rowid = new OracleString (descriptor.GetRowId (ErrorHandle));
+ rowid = new OracleString (descriptor.GetRowId (ErrorHandle));
- return retval;
+ return retval;
+ }
+ finally {
+ SafeDisposeHandle (statement);
+ }
}
[MonoTODO]
- public object ExecuteOracleScalar (out OracleString rowid)
+ public object ExecuteOracleScalar ()
{
- throw new NotImplementedException ();
+ object output = DBNull.Value;
+
+ 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 ();
+ switch (defineHandle.DataType) {
+ case OciDataType.Blob:
+ case OciDataType.Clob:
+ ((OracleLob) output).connection = Connection;
+ break;
+ }
+ }
+ UpdateParameterValues ();
+ }
+
+ return output;
+ }
+ finally {
+ SafeDisposeHandle (statement);
+ }
+ }
+
+ private bool IsNonQuery (OciStatementHandle statementHandle)
+ {
+ // 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 ()
AssertTransactionMatch ();
AssertCommandTextIsSet ();
AssertNoDataReader ();
+ bool hasRows = false;
- if (Transaction != null)
+ this.behavior = behavior;
+
+ if (Transaction != null)
Transaction.AttachToServiceContext ();
-
+
OciStatementHandle statement = GetStatementHandle ();
+ OracleDataReader rd = null;
- if (preparedStatement == null)
- statement.Prepare (CommandText);
- BindParameters (statement);
- statement.ExecuteQuery ();
+ try {
+ if (preparedStatement == null)
+ PrepareStatement (statement);
+ else
+ preparedStatement = null; // OracleDataReader releases the statement handle
+
+ bool isNonQuery = IsNonQuery (statement);
+
+ BindParameters (statement);
- return new OracleDataReader (this, statement);
+ if (isNonQuery)
+ ExecuteNonQueryInternal (statement, false);
+ else {
+ if ((behavior & CommandBehavior.SchemaOnly) != 0)
+ statement.ExecuteQuery (true);
+ else
+ hasRows = statement.ExecuteQuery (false);
+ }
+
+ rd = new OracleDataReader (this, statement, hasRows, behavior);
+ }
+ finally {
+ if (statement != null && rd == null)
+ statement.Dispose();
+ }
+
+ return rd;
}
public object ExecuteScalar ()
{
- object output;
+ object output = DBNull.Value;
AssertConnectionIsOpen ();
AssertTransactionMatch ();
Transaction.AttachToServiceContext ();
OciStatementHandle statement = GetStatementHandle ();
- if (preparedStatement == null)
- statement.Prepare (CommandText);
- BindParameters (statement);
-
- statement.ExecuteQuery ();
-
- if (statement.Fetch ())
- output = ((OciDefineHandle) statement.Values [0]).GetValue ();
- else
- output = DBNull.Value;
+ 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 = DBNull.Value;
+ else {
+ switch (defineHandle.DataType) {
+ case OciDataType.Blob:
+ case OciDataType.Clob:
+ OracleLob lob = (OracleLob) defineHandle.GetValue ();
+ lob.connection = Connection;
+ output = lob.Value;
+ lob.Close ();
+ break;
+ default:
+ output = defineHandle.GetValue ();
+ break;
+ }
+ }
+ }
+ else
+ output = DBNull.Value;
+ UpdateParameterValues ();
+ }
+ }
+ finally {
+ SafeDisposeHandle (statement);
+ }
return output;
}
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)
+ h.Dispose();
+ }
+
IDbDataParameter IDbCommand.CreateParameter ()
{
return CreateParameter ();
return ExecuteReader (behavior);
}
+ 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);
+ }
+
+ string sql = "call " + commandText + "(" + sb.ToString() + ")";
+ statement.Prepare (sql);
+ }
+ else // Text
+ statement.Prepare (commandText);
+ }
+
public void Prepare ()
{
AssertConnectionIsOpen ();
OciStatementHandle statement = GetStatementHandle ();
- statement.Prepare (CommandText);
+ PrepareStatement (statement);
preparedStatement = statement;
}