/// <summary> /// Called when a new result set has to be processed /// </summary> /// <param name="resultSet"></param> private void RaiseBatchResultSetProcessing(IDataReader dataReader, ShowPlanType expectedShowPlan) { EventHandler <BatchResultSetEventArgs> cache = BatchResultSetProcessing; if (cache != null) { BatchResultSetEventArgs args = new BatchResultSetEventArgs(dataReader, expectedShowPlan); BatchResultSetProcessing(this, args); } }
/// <summary> /// Resets the object to its initial state /// </summary> public void Reset() { lock (this) { state = BatchState.Initial; command = null; textSpan = new TextSpan(); totalAffectedRows = 0; hasErrors = false; expectedShowPlan = ShowPlanType.None; isSuppressProviderMessageHeaders = false; scriptTrackingId = 0; isScriptExecutionTracked = false; } }
/// <summary> /// Executes the batch /// </summary> /// <param name="connection">Connection to use</param> /// <param name="expectedShowPlan">ShowPlan type to be used</param> /// <returns>result of execution</returns> /// <remarks> /// It does not return until execution is finished /// We may have received a Cancel request by the time this function is called /// </remarks> public ScriptExecutionResult Execute(IDbConnection connection, ShowPlanType expectedShowPlan) { Validate.IsNotNull(nameof(connection), connection); //makes sure that the batch is not in use lock (this) { Debug.Assert(command == null, "SQLCommand is NOT null"); if (command != null) { command = null; } } this.expectedShowPlan = expectedShowPlan; return(DoBatchExecutionImpl(connection, sqlText)); }
/// <summary> /// Default constructor /// </summary> /// <param name="dataReader"></param> internal BatchResultSetEventArgs(IDataReader dataReader, ShowPlanType expectedShowPlan) { this.dataReader = dataReader; this.expectedShowPlan = expectedShowPlan; }
/// <summary> /// Create a set of batches to be executed before and after the script is executed /// </summary> /// <remarks> /// This is the way some server side settings can be set. Additionally, it supports /// a way to wrap the script execution within a transaction block /// </remarks> private void CreatePrePostConditionBatches() { StringBuilder scriptPreBatches = new StringBuilder(); StringBuilder scriptPostBatches = new StringBuilder(); int serverVersion = 8; if (connection != null && connection.State == ConnectionState.Open) { serverVersion = new Version(ReliableConnectionHelper.ReadServerVersion(connection)).Major; } ConfigurePrePostConditionBatches(preConditionBatches); ConfigurePrePostConditionBatches(postConditionBatches); if (conditions.IsNoExec) { scriptPreBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.NoExecStatement(false)); } if (conditions.IsStatisticsIO) { scriptPreBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.StatisticsIOStatement(true)); scriptPostBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.StatisticsIOStatement(false)); } if (conditions.IsStatisticsTime) { scriptPreBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.StatisticsTimeStatement(true)); scriptPostBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.StatisticsTimeStatement(false)); } if (conditions.IsEstimatedShowPlan) { if (serverVersion >= 9) { scriptPreBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.ShowPlanXmlStatement(true)); scriptPostBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.ShowPlanXmlStatement(false)); expectedShowPlan = ShowPlanType.EstimatedXmlShowPlan; } else { scriptPreBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.ShowPlanAllStatement(true)); scriptPostBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.ShowPlanAllStatement(false)); expectedShowPlan = ShowPlanType.EstimatedExecutionShowPlan; } } else if (conditions.IsActualShowPlan) { if (serverVersion >= 9) { scriptPreBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.StatisticsXmlStatement(true)); scriptPostBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.StatisticsXmlStatement(false)); expectedShowPlan = ShowPlanType.ActualXmlShowPlan; } else { scriptPreBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.StatisticsProfileStatement(true)); scriptPostBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.StatisticsProfileStatement(false)); expectedShowPlan = ShowPlanType.ActualExecutionShowPlan; } } if (conditions.IsTransactionWrapped) { scriptPreBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.BeginTransactionStatement); // issuing a Rollback or a Commit will depend on the script execution result } if (conditions.IsParseOnly) { scriptPreBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.ParseOnlyStatement(true)); scriptPostBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.ParseOnlyStatement(false)); } if (conditions.IsNoExec) { scriptPreBatches.AppendFormat(CultureInfo.InvariantCulture, "{0} ", ExecutionEngineConditions.NoExecStatement(true)); } if (conditions.IsShowPlanText && !conditions.IsEstimatedShowPlan && !conditions.IsActualShowPlan) { // SET SHOWPLAN_TEXT cannot be used with other statements in the batch preConditionBatches.Insert(0, new Batch( string.Format(CultureInfo.CurrentCulture, "{0} ", ExecutionEngineConditions.ShowPlanTextStatement(true)), false, executionTimeout)); postConditionBatches.Insert(0, new Batch( string.Format(CultureInfo.CurrentCulture, "{0} ", ExecutionEngineConditions.ShowPlanTextStatement(false)), false, executionTimeout)); } string preBatches = scriptPreBatches.ToString().Trim(); string postBatches = scriptPostBatches.ToString().Trim(); if (scriptPreBatches.Length > 0) { preConditionBatches.Add(new Batch(preBatches, false, executionTimeout)); } if (scriptPostBatches.Length > 0) { postConditionBatches.Add(new Batch(postBatches, false, executionTimeout)); } }
/// <summary> /// Executes the script (on a separated thread) /// </summary> private void DoExecute(bool isBatchParser) { //we should not be in the middle of execution here if (executionState == ExecutionState.Executing || executionState == ExecutionState.ExecutingBatch) { throw new InvalidOperationException(SR.EE_ExecutionNotYetCompleteError); } executionState = ExecutionState.Initial; result = ScriptExecutionResult.Failure; currentBatchIndex = 0; currentBatch.ExecutionTimeout = executionTimeout; expectedShowPlan = ShowPlanType.None; if (!isLocalParse) { errorAction = conditions.IsHaltOnError ? OnErrorAction.Exit : OnErrorAction.Ignore; CreatePrePostConditionBatches(); } ConfigureBatchEventHandlers(currentBatch, batchEventHandlers, true); // do we have a cancel request already? lock (stateSyncLock) { if (executionState == ExecutionState.Cancelling) { RaiseScriptExecutionFinished(ScriptExecutionResult.Cancel); return; } Debug.Assert(executionState == ExecutionState.Initial); executionState = ExecutionState.Executing; } if ((result = ExecutePrePostConditionBatches(preConditionBatches)) == ScriptExecutionResult.Success) { DoScriptExecution(isBatchParser); } if (!CheckForDiscardedConnection()) { if (!isLocalParse) { if (conditions.IsTransactionWrapped && !conditions.IsParseOnly) { if (result == ScriptExecutionResult.Success) { postConditionBatches.Add(new Batch(ExecutionEngineConditions.CommitTransactionStatement, false, executionTimeout)); } else { postConditionBatches.Add(new Batch(ExecutionEngineConditions.RollbackTransactionStatement, false, executionTimeout)); } } // no need to update the result value as it has been updated by the DoScriptExecution() ExecutePrePostConditionBatches(postConditionBatches); } //fire an event that we're done with execution of all batches if (result == ScriptExecutionResult.Halted) //remap into failure { result = ScriptExecutionResult.Failure; } RaiseScriptExecutionFinished(result); } }
/// <summary> /// Executes the batch /// </summary> /// <param name="connection">Connection to use</param> /// <param name="expectedShowPlan">ShowPlan type to be used</param> /// <returns>result of execution</returns> /// <remarks> /// It does not return until execution is finished /// We may have received a Cancel request by the time this function is called /// </remarks> public ScriptExecutionResult Execute(SqlConnection connection, ShowPlanType expectedShowPlan) { // FUTURE CLEANUP: Remove in favor of general signature (IDbConnection) - #920978 return(Execute((IDbConnection)connection, expectedShowPlan)); }