private OdbcDataReader ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader, object[] methodArguments, ODBC32.SQL_API odbcApiMethod) { // MDAC 68324 OdbcDataReader localReader = null; try { DisposeDeadDataReader(); // this is a no-op if cmdState is not Fetching ValidateConnectionAndTransaction(method); // cmdState will change to Executing if (0 != (CommandBehavior.SingleRow & behavior)) { // CommandBehavior.SingleRow implies CommandBehavior.SingleResult behavior |= CommandBehavior.SingleResult; } ODBC32.RetCode retcode; OdbcStatementHandle stmt = GetStatementHandle().StatementHandle; _cmdWrapper.Canceling = false; if (null != _weakDataReaderReference) { if (_weakDataReaderReference.IsAlive) { object target = _weakDataReaderReference.Target; if (null != target && _weakDataReaderReference.IsAlive) { if (!((OdbcDataReader)target).IsClosed) { throw ADP.OpenReaderExists(); // MDAC 66411 } } } } localReader = new OdbcDataReader(this, _cmdWrapper, behavior); //Set command properties //Not all drivers support timeout. So fail silently if error if (!Connection.ProviderInfo.NoQueryTimeout) { TrySetStatementAttribute(stmt, ODBC32.SQL_ATTR.QUERY_TIMEOUT, (IntPtr)this.CommandTimeout); } // todo: If we remember the state we can omit a lot of SQLSetStmtAttrW calls ... // if we do not create a reader we do not even need to do that if (needReader) { if (Connection.IsV3Driver) { if (!Connection.ProviderInfo.NoSqlSoptSSNoBrowseTable && !Connection.ProviderInfo.NoSqlSoptSSHiddenColumns) { // Need to get the metadata information //SQLServer actually requires browse info turned on ahead of time... //Note: We ignore any failures, since this is SQLServer specific //We won't specialcase for SQL Server but at least for non-V3 drivers if (localReader.IsBehavior(CommandBehavior.KeyInfo)) { if (!_cmdWrapper._ssKeyInfoModeOn) { TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.NOBROWSETABLE, (IntPtr)ODBC32.SQL_NB.ON); TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.HIDDEN_COLUMNS, (IntPtr)ODBC32.SQL_HC.ON); _cmdWrapper._ssKeyInfoModeOff = false; _cmdWrapper._ssKeyInfoModeOn = true; } } else { if (!_cmdWrapper._ssKeyInfoModeOff) { TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.NOBROWSETABLE, (IntPtr)ODBC32.SQL_NB.OFF); TrySetStatementAttribute(stmt, (ODBC32.SQL_ATTR)ODBC32.SQL_SOPT_SS.HIDDEN_COLUMNS, (IntPtr)ODBC32.SQL_HC.OFF); _cmdWrapper._ssKeyInfoModeOff = true; _cmdWrapper._ssKeyInfoModeOn = false; } } } } } if (localReader.IsBehavior(CommandBehavior.KeyInfo) || localReader.IsBehavior(CommandBehavior.SchemaOnly)) { retcode = stmt.Prepare(CommandText); if (ODBC32.RetCode.SUCCESS != retcode) { _connection.HandleError(stmt, retcode); } } bool mustRelease = false; CNativeBuffer parameterBuffer = _cmdWrapper._nativeParameterBuffer; RuntimeHelpers.PrepareConstrainedRegions(); try { //Handle Parameters //Note: We use the internal variable as to not instante a new object collection, //for the common case of using no parameters. if ((null != _parameterCollection) && (0 < _parameterCollection.Count)) { int parameterBufferSize = _parameterCollection.CalcParameterBufferSize(this); if (null == parameterBuffer || parameterBuffer.Length < parameterBufferSize) { if (null != parameterBuffer) { parameterBuffer.Dispose(); } parameterBuffer = new CNativeBuffer(parameterBufferSize); _cmdWrapper._nativeParameterBuffer = parameterBuffer; } else { parameterBuffer.ZeroMemory(); } parameterBuffer.DangerousAddRef(ref mustRelease); _parameterCollection.Bind(this, _cmdWrapper, parameterBuffer); } if (!localReader.IsBehavior(CommandBehavior.SchemaOnly)) { // Can't get the KeyInfo after command execution (SQL Server only since it does not support multiple // results on the same connection). Stored procedures (SP) do not return metadata before actual execution // Need to check the column count since the command type may not be set to SP for a SP. if ((localReader.IsBehavior(CommandBehavior.KeyInfo) || localReader.IsBehavior(CommandBehavior.SchemaOnly)) && (CommandType != CommandType.StoredProcedure)) { short cColsAffected; retcode = stmt.NumberOfResultColumns(out cColsAffected); if (retcode == ODBC32.RetCode.SUCCESS || retcode == ODBC32.RetCode.SUCCESS_WITH_INFO) { if (cColsAffected > 0) { localReader.GetSchemaTable(); } } else if (retcode == ODBC32.RetCode.NO_DATA) { // do nothing } else { // any other returncode indicates an error _connection.HandleError(stmt, retcode); } } switch (odbcApiMethod) { case ODBC32.SQL_API.SQLEXECDIRECT: if (localReader.IsBehavior(CommandBehavior.KeyInfo) || _isPrepared) { //Already prepared, so use SQLExecute retcode = stmt.Execute(); // Build metadata here // localReader.GetSchemaTable(); } else { #if DEBUG //if (AdapterSwitches.OleDbTrace.TraceInfo) { // ADP.DebugWriteLine("SQLExecDirectW: " + CommandText); //} #endif //SQLExecDirect retcode = stmt.ExecuteDirect(CommandText); } break; case ODBC32.SQL_API.SQLTABLES: retcode = stmt.Tables((string)methodArguments[0], //TableCatalog (string)methodArguments[1], //TableSchema, (string)methodArguments[2], //TableName (string)methodArguments[3]); //TableType break; case ODBC32.SQL_API.SQLCOLUMNS: retcode = stmt.Columns((string)methodArguments[0], //TableCatalog (string)methodArguments[1], //TableSchema (string)methodArguments[2], //TableName (string)methodArguments[3]); //ColumnName break; case ODBC32.SQL_API.SQLPROCEDURES: retcode = stmt.Procedures((string)methodArguments[0], //ProcedureCatalog (string)methodArguments[1], //ProcedureSchema (string)methodArguments[2]); //procedureName break; case ODBC32.SQL_API.SQLPROCEDURECOLUMNS: retcode = stmt.ProcedureColumns((string)methodArguments[0], //ProcedureCatalog (string)methodArguments[1], //ProcedureSchema (string)methodArguments[2], //procedureName (string)methodArguments[3]); //columnName break; case ODBC32.SQL_API.SQLSTATISTICS: retcode = stmt.Statistics((string)methodArguments[0], //TableCatalog (string)methodArguments[1], //TableSchema (string)methodArguments[2], //TableName (short)methodArguments[3], //IndexTrpe (short)methodArguments[4]); //Accuracy break; case ODBC32.SQL_API.SQLGETTYPEINFO: retcode = stmt.GetTypeInfo((short)methodArguments[0]); //SQL Type break; default: // this should NEVER happen Debug.Fail("ExecuteReaderObjectcalled with unsupported ODBC API method."); throw ADP.InvalidOperation(method.ToString()); } //Note: Execute will return NO_DATA for Update/Delete non-row returning queries if ((ODBC32.RetCode.SUCCESS != retcode) && (ODBC32.RetCode.NO_DATA != retcode)) { _connection.HandleError(stmt, retcode); } } // end SchemaOnly } finally { if (mustRelease) { parameterBuffer.DangerousRelease(); } } _weakDataReaderReference = new WeakReference(localReader); // XXXCommand.Execute should position reader on first row returning result // any exceptions in the initial non-row returning results should be thrown // from ExecuteXXX not the DataReader if (!localReader.IsBehavior(CommandBehavior.SchemaOnly)) { localReader.FirstResult(); } _cmdState = ConnectionState.Fetching; } finally { if (ConnectionState.Fetching != _cmdState) { if (null != localReader) { // clear bindings so we don't grab output parameters on a failed execute if (null != _parameterCollection) { _parameterCollection.ClearBindings(); } ((IDisposable)localReader).Dispose(); } if (ConnectionState.Closed != _cmdState) { _cmdState = ConnectionState.Closed; } } } return(localReader); }
private OdbcDataReader ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader, object[] methodArguments, ODBC32.SQL_API odbcApiMethod) { OdbcDataReader target = null; try { ODBC32.RetCode typeInfo; this.DisposeDeadDataReader(); this.ValidateConnectionAndTransaction(method); if ((CommandBehavior.SingleRow & behavior) != CommandBehavior.Default) { behavior |= CommandBehavior.SingleResult; } OdbcStatementHandle statementHandle = this.GetStatementHandle().StatementHandle; this._cmdWrapper.Canceling = false; if ((this.weakDataReaderReference != null) && this.weakDataReaderReference.IsAlive) { object obj2 = this.weakDataReaderReference.Target; if (((obj2 != null) && this.weakDataReaderReference.IsAlive) && !((OdbcDataReader)obj2).IsClosed) { throw ADP.OpenReaderExists(); } } target = new OdbcDataReader(this, this._cmdWrapper, behavior); if (!this.Connection.ProviderInfo.NoQueryTimeout) { this.TrySetStatementAttribute(statementHandle, ODBC32.SQL_ATTR.QUERY_TIMEOUT, (IntPtr)this.CommandTimeout); } if ((needReader && this.Connection.IsV3Driver) && (!this.Connection.ProviderInfo.NoSqlSoptSSNoBrowseTable && !this.Connection.ProviderInfo.NoSqlSoptSSHiddenColumns)) { if (target.IsBehavior(CommandBehavior.KeyInfo)) { if (!this._cmdWrapper._ssKeyInfoModeOn) { this.TrySetStatementAttribute(statementHandle, (ODBC32.SQL_ATTR) 0x4cc, (IntPtr)1L); this.TrySetStatementAttribute(statementHandle, ODBC32.SQL_ATTR.SQL_COPT_SS_TXN_ISOLATION, (IntPtr)1L); this._cmdWrapper._ssKeyInfoModeOff = false; this._cmdWrapper._ssKeyInfoModeOn = true; } } else if (!this._cmdWrapper._ssKeyInfoModeOff) { this.TrySetStatementAttribute(statementHandle, (ODBC32.SQL_ATTR) 0x4cc, (IntPtr)0L); this.TrySetStatementAttribute(statementHandle, ODBC32.SQL_ATTR.SQL_COPT_SS_TXN_ISOLATION, (IntPtr)0L); this._cmdWrapper._ssKeyInfoModeOff = true; this._cmdWrapper._ssKeyInfoModeOn = false; } } if (target.IsBehavior(CommandBehavior.KeyInfo) || target.IsBehavior(CommandBehavior.SchemaOnly)) { typeInfo = statementHandle.Prepare(this.CommandText); if (typeInfo != ODBC32.RetCode.SUCCESS) { this._connection.HandleError(statementHandle, typeInfo); } } bool success = false; CNativeBuffer parameterBuffer = this._cmdWrapper._nativeParameterBuffer; RuntimeHelpers.PrepareConstrainedRegions(); try { if ((this._parameterCollection != null) && (0 < this._parameterCollection.Count)) { int initialSize = this._parameterCollection.CalcParameterBufferSize(this); if ((parameterBuffer == null) || (parameterBuffer.Length < initialSize)) { if (parameterBuffer != null) { parameterBuffer.Dispose(); } parameterBuffer = new CNativeBuffer(initialSize); this._cmdWrapper._nativeParameterBuffer = parameterBuffer; } else { parameterBuffer.ZeroMemory(); } parameterBuffer.DangerousAddRef(ref success); this._parameterCollection.Bind(this, this._cmdWrapper, parameterBuffer); } if (target.IsBehavior(CommandBehavior.SchemaOnly)) { goto Label_0443; } if ((target.IsBehavior(CommandBehavior.KeyInfo) || target.IsBehavior(CommandBehavior.SchemaOnly)) && (this.CommandType != System.Data.CommandType.StoredProcedure)) { short num2; typeInfo = statementHandle.NumberOfResultColumns(out num2); switch (typeInfo) { case ODBC32.RetCode.SUCCESS: case ODBC32.RetCode.SUCCESS_WITH_INFO: if (num2 > 0) { target.GetSchemaTable(); } goto Label_029A; } if (typeInfo != ODBC32.RetCode.NO_DATA) { this._connection.HandleError(statementHandle, typeInfo); } } Label_029A: switch (odbcApiMethod) { case ODBC32.SQL_API.SQLEXECDIRECT: if (target.IsBehavior(CommandBehavior.KeyInfo) || this._isPrepared) { typeInfo = statementHandle.Execute(); } else { typeInfo = statementHandle.ExecuteDirect(this.CommandText); } break; case ODBC32.SQL_API.SQLCOLUMNS: typeInfo = statementHandle.Columns((string)methodArguments[0], (string)methodArguments[1], (string)methodArguments[2], (string)methodArguments[3]); break; case ODBC32.SQL_API.SQLSTATISTICS: typeInfo = statementHandle.Statistics((string)methodArguments[0], (string)methodArguments[1], (string)methodArguments[2], (short)methodArguments[3], (short)methodArguments[4]); break; case ODBC32.SQL_API.SQLTABLES: typeInfo = statementHandle.Tables((string)methodArguments[0], (string)methodArguments[1], (string)methodArguments[2], (string)methodArguments[3]); break; case ODBC32.SQL_API.SQLGETTYPEINFO: typeInfo = statementHandle.GetTypeInfo((short)methodArguments[0]); break; case ODBC32.SQL_API.SQLPROCEDURECOLUMNS: typeInfo = statementHandle.ProcedureColumns((string)methodArguments[0], (string)methodArguments[1], (string)methodArguments[2], (string)methodArguments[3]); break; case ODBC32.SQL_API.SQLPROCEDURES: typeInfo = statementHandle.Procedures((string)methodArguments[0], (string)methodArguments[1], (string)methodArguments[2]); break; default: throw ADP.InvalidOperation(method.ToString()); } if ((typeInfo != ODBC32.RetCode.SUCCESS) && (ODBC32.RetCode.NO_DATA != typeInfo)) { this._connection.HandleError(statementHandle, typeInfo); } } finally { if (success) { parameterBuffer.DangerousRelease(); } } Label_0443: this.weakDataReaderReference = new WeakReference(target); if (!target.IsBehavior(CommandBehavior.SchemaOnly)) { target.FirstResult(); } this.cmdState = ConnectionState.Fetching; } finally { if (ConnectionState.Fetching != this.cmdState) { if (target != null) { if (this._parameterCollection != null) { this._parameterCollection.ClearBindings(); } target.Dispose(); } if (this.cmdState != ConnectionState.Closed) { this.cmdState = ConnectionState.Closed; } } } return(target); }