/// <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); } }
private ScriptExecutionResult DoBatchExecution(Batch batch) { Validate.IsNotNull(nameof(batch), batch); ScriptExecutionResult result = ScriptExecutionResult.Success; // TODO, fawinter: Do I need to keep this batch? if (batch.HasValidText) { try { // Parsing mode we execute only once if (conditions.IsParseOnly) { numBatchExecutionTimes = 1; } int timesLoop = numBatchExecutionTimes; if (numBatchExecutionTimes > 1) { RaiseBatchMessage(String.Format(CultureInfo.CurrentCulture, SR.EE_ExecutionInfo_InitilizingLoop, numBatchExecutionTimes)); } while (timesLoop > 0 && result != ScriptExecutionResult.Cancel && result != ScriptExecutionResult.Halted) { result = batch.Execute(connection, expectedShowPlan); Debug.Assert(connection != null); if (connection == null || connection.State != ConnectionState.Open) { result = ScriptExecutionResult.Halted; } if (result == ScriptExecutionResult.Failure) { if (errorAction == OnErrorAction.Ignore) { if (numBatchExecutionTimes > 1) { RaiseBatchMessage(SR.EE_BatchExecutionError_Ignoring); } } else { RaiseBatchMessage(SR.EE_BatchExecutionError_Halting); result = ScriptExecutionResult.Halted; } } timesLoop--; } if (result == ScriptExecutionResult.Cancel) { RaiseBatchMessage(String.Format(CultureInfo.CurrentCulture, SR.EE_ExecutionInfo_QueryCancelledbyUser)); } else { if (numBatchExecutionTimes > 1) { RaiseBatchMessage(String.Format(CultureInfo.CurrentCulture, SR.EE_ExecutionInfo_FinalizingLoop, numBatchExecutionTimes)); } } } catch (OutOfMemoryException) { throw; } catch (Exception ex) { // if anything goes wrong it will shutdown VS Logger.Write(LogLevel.Error, "Exception Caught in ExecutionEngine.DoBatchExecution(Batch) :" + ex.ToString()); result = ScriptExecutionResult.Failure; } } else { // TODO, fawinter: Success will be returned on an Empty text batch } return(result); }
/// <summary> /// Executes the batch text given the text span /// </summary> /// <param name="batchScript"></param> /// <param name="textSpan"></param> /// <param name="continueProcessing"></param> private void ExecuteBatchTextSpanInternal(string batchScript, TextSpan textSpan, out bool continueProcessing) { Debug.Assert(!String.IsNullOrEmpty(batchScript)); continueProcessing = true; if (batchScript.Trim().Length <= 0) { result |= ScriptExecutionResult.Success; return; } Debug.Assert(currentBatch != null); if (executionState == ExecutionState.Cancelling) { result = ScriptExecutionResult.Cancel; } else { currentBatch.Reset(); currentBatch.Text = batchScript; currentBatch.TextSpan = textSpan; currentBatch.BatchIndex = currentBatchIndex; currentBatchIndex++; if (conditions != null) { currentBatch.IsSuppressProviderMessageHeaders = conditions.IsSuppressProviderMessageHeaders; // TODO this is associated with Dacfx specific situations, so uncomment if need be //currentBatch.IsScriptExecutionTracked = conditions.IsScriptExecutionTracked; if (conditions.IsScriptExecutionTracked) { currentBatch.ScriptTrackingId = scriptTrackingId++; } } //ExecutingBatch state means currentBatch is valid to use from another thread to Cancel executionState = ExecutionState.ExecutingBatch; } ScriptExecutionResult batchResult = ScriptExecutionResult.Failure; if (result != ScriptExecutionResult.Cancel) { bool isExecutionDiscarded = false; try { RaiseBatchParserExecutionStarted(currentBatch, textSpan); if (!isLocalParse) { batchResult = DoBatchExecution(currentBatch); } else { batchResult = ScriptExecutionResult.Success; } } finally { isExecutionDiscarded = (executionState == ExecutionState.Discarded); if (executionState == ExecutionState.Cancelling || isExecutionDiscarded) { batchResult = ScriptExecutionResult.Cancel; } else { executionState = ExecutionState.Executing; } } if (!isExecutionDiscarded) { RaiseBatchParserExecutionFinished(currentBatch, batchResult); } } else { batchResult = ScriptExecutionResult.Cancel; } //if we're in Cancel or Halt state, do some special actions if (batchResult == ScriptExecutionResult.Cancel || batchResult == ScriptExecutionResult.Halted) { result = batchResult; continueProcessing = false; return; } else { result |= batchResult; } }
private ScriptExecutionResult CheckStateAndRead(IDataReader reader = null) { ScriptExecutionResult result = ScriptExecutionResult.Success; if (!isResultExpected) { lock (this) { if (state == BatchState.Cancelling) { result = ScriptExecutionResult.Cancel; } else { result = ScriptExecutionResult.Success; state = BatchState.Executed; } } } else { lock (this) { if (state == BatchState.Cancelling) { result = ScriptExecutionResult.Cancel; } else { state = BatchState.ProcessingResults; } } if (result != ScriptExecutionResult.Cancel) { ScriptExecutionResult batchExecutionResult = ScriptExecutionResult.Success; if (reader != null) { bool hasNextResult = false; do { // if there were no results coming from the server, then the FieldCount is 0 if (reader.FieldCount <= 0) { hasNextResult = reader.NextResult(); continue; } batchExecutionResult = ProcessResultSet(reader); if (batchExecutionResult != ScriptExecutionResult.Success) { result = batchExecutionResult; break; } RaiseBatchResultSetFinished(); hasNextResult = reader.NextResult(); } while (hasNextResult); } if (hasErrors) { Debug.WriteLine("DoBatchExecution: successfull processed result set, but there were errors shown to the user"); result = ScriptExecutionResult.Failure; } if (result != ScriptExecutionResult.Cancel) { lock (this) { state = BatchState.Executed; } } } } if (reader != null) { try { // reader.Close() doesn't actually close the reader // so explicitly dispose the reader reader.Dispose(); reader = null; } catch (OutOfMemoryException) { throw; } catch (SqlException) { // nothing } } return(result); }
private ScriptExecutionResult DoBatchExecutionImpl(IDbConnection connection, string script) { Validate.IsNotNull(nameof(connection), connection); lock (this) { if (state == BatchState.Cancelling) { state = BatchState.Initial; return(ScriptExecutionResult.Cancel); } } ScriptExecutionResult result = ScriptExecutionResult.Success; // SqlClient event handlers setup SqlInfoMessageEventHandler messageHandler = new SqlInfoMessageEventHandler(OnSqlInfoMessageCallback); StatementCompletedEventHandler statementCompletedHandler = null; DbConnectionWrapper connectionWrapper = new DbConnectionWrapper(connection); connectionWrapper.InfoMessage += messageHandler; IDbCommand command = connection.CreateCommand(); command.CommandText = script; command.CommandTimeout = execTimeout; DbCommandWrapper commandWrapper = null; if (isScriptExecutionTracked && DbCommandWrapper.IsSupportedCommand(command)) { statementCompletedHandler = new StatementCompletedEventHandler(OnStatementExecutionFinished); commandWrapper = new DbCommandWrapper(command); commandWrapper.StatementCompleted += statementCompletedHandler; } lock (this) { state = BatchState.Executing; this.command = command; command = null; } try { result = this.ExecuteCommand(); } catch (OutOfMemoryException) { throw; } catch (SqlException sqlEx) { result = HandleSqlException(sqlEx); } catch (Exception ex) { result = ScriptExecutionResult.Failure; HandleExceptionMessage(ex); } finally { if (messageHandler == null) { Logger.Write(LogLevel.Error, "Expected handler to be declared"); } if (null != connectionWrapper) { connectionWrapper.InfoMessage -= messageHandler; } if (commandWrapper != null) { if (statementCompletedHandler == null) { Logger.Write(LogLevel.Error, "Expect handler to be declared if we have a command wrapper"); } commandWrapper.StatementCompleted -= statementCompletedHandler; } lock (this) { state = BatchState.Initial; if (command != null) { command.Dispose(); command = null; } } } return(result); }
/// <summary> /// Called when parser is about to halt the execution /// </summary> private void OnHaltParser() { result = ScriptExecutionResult.Halted; }
// Capture the event once batch finish execution. private void OnBatchParserExecutionFinished(object sender, BatchParserExecutionFinishedEventArgs e) { executionResult = e.ExecutionResult; }