From 2b7179d04efba91708399f2366edf14e2c0edd4f Mon Sep 17 00:00:00 2001 From: Steffen Date: Tue, 28 Nov 2023 18:40:07 +0100 Subject: [PATCH] fixed GO error continue --- CHANGELOG.md | 4 +++ src/PsSmo/InvokeCommandCommand.cs | 51 ++++++++++++++++++++----------- test/Invoke-Command.Tests.ps1 | 4 +-- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9217151..d7b4868 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated System.Management.Automation to 7.2.16 and PowerShell 7.2.16. - Updated Microsoft.Data.SqlClient to 5.1.1. +### Fixed + +- ErrorAction Continue did not executed batches after an SQL error. + ## [1.2.1] - 2023-09-05 ### Added diff --git a/src/PsSmo/InvokeCommandCommand.cs b/src/PsSmo/InvokeCommandCommand.cs index 6da3ed5..0ad9943 100644 --- a/src/PsSmo/InvokeCommandCommand.cs +++ b/src/PsSmo/InvokeCommandCommand.cs @@ -2,6 +2,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.Specialized; using System.IO; using System.Management.Automation; using System.Text.RegularExpressions; @@ -45,24 +46,30 @@ protected override void ProcessRecord() break; case "File": - WriteVerbose($"Execute SQL script from file '{ InputFile.FullName }'."); + WriteVerbose($"Execute SQL script from file '{InputFile.FullName}'."); Text = File.ReadAllText(InputFile.FullName); break; default: throw new NotImplementedException($"ParameterSetName {ParameterSetName} is not implemented"); } - try - { - Instance.ConnectionContext.ExecuteNonQuery(sqlCommand: ProcessSqlCmdText(Text, ProcessVariables(Variables))); - } - catch (PipelineStoppedException) - { - throw; - } - catch (Exception ex) + + foreach (var sqlCommand in ProcessSqlCmdText(Text, ProcessVariables(Variables))) { - WriteError(new ErrorRecord(ex, ex.GetType().Name, ErrorCategory.NotSpecified, Text)); + try + { + Instance.ConnectionContext.ExecuteNonQuery( + sqlCommand: sqlCommand + ); + } + catch (PipelineStoppedException) + { + throw; + } + catch (Exception ex) + { + WriteError(new ErrorRecord(ex, ex.GetType().Name, ErrorCategory.NotSpecified, Text)); + } } } @@ -81,11 +88,12 @@ private static Dictionary ProcessVariables(Hashtable variables) return variableDictionary; } - private string ProcessSqlCmdText(string text, Dictionary variables) + private StringCollection ProcessSqlCmdText(string text, Dictionary variables) { variables ??= new Dictionary(); var result = new List(); + var resultCollection = new List>() { result }; var variableRegex = new Regex(@"\$\((\w*)\)"); var setVarRegex = new Regex(@":setvar (\w+) ?""(.+)?"""); var blockCommentRegex = new Regex(@"/\*(.|\n)*?\*/"); @@ -99,14 +107,20 @@ private string ProcessSqlCmdText(string text, Dictionary variabl foreach (var line in processedText.Split(Environment.NewLine)) { - if (line.Trim().StartsWith(":on error", StringComparison.CurrentCultureIgnoreCase)) + if (line.Trim().StartsWith("GO", StringComparison.CurrentCultureIgnoreCase)) + { + result = new List(); + resultCollection.Add(result); + } + else if (line.Trim().StartsWith(":on error", StringComparison.CurrentCultureIgnoreCase)) { WriteWarning(":on error is not implemented"); } else if (line.Trim().StartsWith(":setvar", StringComparison.CurrentCultureIgnoreCase)) { var match = setVarRegex.Match(line); - if (match.Success) { + if (match.Success) + { var variable = match.Groups[1].Value; var value = match.Groups[2].Value; variables[variable] = value; @@ -119,7 +133,7 @@ private string ProcessSqlCmdText(string text, Dictionary variabl else { var processedLine = line; - foreach(var variable in variables) + foreach (var variable in variables) { processedLine = processedLine.Replace($"$({variable.Key})", variable.Value); } @@ -127,7 +141,7 @@ private string ProcessSqlCmdText(string text, Dictionary variabl var match = variableRegex.Match(input: processedLine); if (match.Success) { - foreach(var variable in variables) + foreach (var variable in variables) { WriteWarning($"$({variable.Key}) = '{variable.Value}'"); } @@ -137,7 +151,10 @@ private string ProcessSqlCmdText(string text, Dictionary variabl result.Add(processedLine); } } - return string.Join(separator: Environment.NewLine, result); + var batchCollection = new StringCollection(); + foreach (var batch in resultCollection) + batchCollection.Add(string.Join(separator: Environment.NewLine, batch)); + return batchCollection; } } } diff --git a/test/Invoke-Command.Tests.ps1 b/test/Invoke-Command.Tests.ps1 index f925104..0ca7d40 100644 --- a/test/Invoke-Command.Tests.ps1 +++ b/test/Invoke-Command.Tests.ps1 @@ -59,8 +59,8 @@ PRINT 'bar' $InformationOutput[0].MessageData | Should -Be "SELECT 1/0`r`nPRINT 'foo'" $ErrorOutput[0].Exception.Message | Should -Be 'An exception occurred while executing a Transact-SQL statement or batch.' $ErrorOutput[0].Exception.InnerException.Errors[0].Message | Should -Be 'Divide by zero error encountered.' - # $InformationOutput[1].MessageData | Should -Be "PRINT 'bar'" # still a bug - # $VerboseOutput[1].Message | Should -Be 'bar' + $InformationOutput[1].MessageData | Should -Be "PRINT 'bar'" + $VerboseOutput[1].Message | Should -Be 'bar' } }