Skip to content

Commit 4ea829d

Browse files
committed
(FM-8879) Handle T-SQL Errors Properly
The previous commit that improved T-SQL error handling was incomplete. That commit (9b8a0fe) was not able to overcome an important issue. The issue was that if there was a successfull row insert into a table the `Errors` collection of the ADODB.Connection would be empty, even if an error was deliberately thrown using the `THROW` keyword. It turns out that the successfull row insert was causing a text return value, and it's a known issue that if values are returned to the object that the Errors collection will be empty. We know now that turning `SET NOCOUNT ON` in the beginning of the query will suppress that text status message and allow more errors to be properly detected in the ADODB.Connect object, and handled properly in the module's `onlyif` clause.
1 parent 8d44d62 commit 4ea829d

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

lib/puppet/property/sqlserver_tsql.rb

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class Puppet::Property::SqlserverTsql < Puppet::Property # rubocop:disable Style
66
quoted_value = value.gsub('\'', '\'\'')
77
erb_template = <<-TEMPLATE
88
BEGIN TRY
9+
SET NOCOUNT ON
910
DECLARE @sql_text as NVARCHAR(max);
1011
SET @sql_text = N'#{quoted_value}'
1112
EXECUTE sp_executesql @sql_text;

spec/acceptance/sqlserver_tsql_spec.rb

+31
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,37 @@ def ensure_sqlserver_database(db_name, _ensure_val = 'present')
162162
run_sql_query(run_sql_query_opts)
163163
end
164164

165+
it 'Run sqlserver_tsql WITH onlyif that does a table insert:' do
166+
# Initilize a new table name:
167+
@table_name = 'Table_' + SecureRandom.hex(3)
168+
@query = "USE #{db_name}; SELECT * FROM #{@table_name} WHERE id = 2;"
169+
pp = <<-MANIFEST
170+
sqlserver::config{'MSSQLSERVER':
171+
instance_name => 'MSSQLSERVER',
172+
admin_user => 'sa',
173+
admin_pass => 'Pupp3t1@',
174+
}
175+
sqlserver_tsql{'testsqlserver_tsql':
176+
instance => 'MSSQLSERVER',
177+
database => '#{db_name}',
178+
command => "INSERT #{@table_name} VALUES(2, 'name2', '[email protected]');",
179+
onlyif => "CREATE TABLE #{@table_name} (id INT, name VARCHAR(20), email VARCHAR(20));
180+
INSERT #{@table_name} VALUES(1, 'name', '[email protected]');
181+
THROW 5300, 'Throw to trigger second INSERT statement in command property', 10"
182+
}
183+
MANIFEST
184+
apply_manifest(pp, catch_failures: true)
185+
186+
puts "Validate #{@table_name} is NOT created:"
187+
run_sql_query_opts = {
188+
query: @query,
189+
sql_admin_user: @admin_user,
190+
sql_admin_pass: @admin_pass,
191+
expected_row_count: 1,
192+
}
193+
run_sql_query(run_sql_query_opts)
194+
end
195+
165196
it 'Negative test: Run tsql with invalid command:' do
166197
pp = <<-MANIFEST
167198
sqlserver::config{'MSSQLSERVER':

spec/unit/puppet/property/tsql_spec.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
it 'munges value to have begin and end try' do
1414
@node[:command] = 'function foo'
1515
@node[:onlyif] = 'exec bar'
16-
expect(@node[:onlyif]).to match(%r{BEGIN TRY\n\s+DECLARE @sql_text as NVARCHAR\(max\);\n\s+SET @sql_text = N'exec bar'\n\s+EXECUTE sp_executesql @sql_text;\nEND TRY})
17-
expect(@node[:command]).to match(%r{BEGIN TRY\n\s+DECLARE @sql_text as NVARCHAR\(max\);\n\s+SET @sql_text = N'function foo'\n\s+EXECUTE sp_executesql @sql_text;\nEND TRY})
16+
expect(@node[:onlyif]).to match(%r{BEGIN TRY\n\s+SET NOCOUNT ON\n\s+DECLARE @sql_text as NVARCHAR\(max\);\n\s+SET @sql_text = N'exec bar'\n\s+EXECUTE sp_executesql @sql_text;\nEND TRY})
17+
expect(@node[:command]).to match(%r{BEGIN TRY\n\s+SET NOCOUNT ON\n\s+DECLARE @sql_text as NVARCHAR\(max\);\n\s+SET @sql_text = N'function foo'\n\s+EXECUTE sp_executesql @sql_text;\nEND TRY})
1818
end
1919

2020
it 'properlies escape single quotes in queries' do

0 commit comments

Comments
 (0)