Skip to content

Commit 44b80f3

Browse files
committed
(MODULES-2312) Use sp_executesql to execute T-SQL
- Previously, the SQL server module executed arbitrary TSQL by injecting user supplied data into a template verbatim. Unfortunately this mechanism does nothing to address syntax errors, which will prevent the try / catch mechanism employed from working and propagating errors. The stored procedure sp_executesql can be used to execute arbitrary SQL strings, and will properly propagate an exception that can be caught, so use that method. Of note, since the user query is being placed into a string, it must have single quotes escaped properly. An additional test has been added to verify that single quotes are escaped as expected.
1 parent f7b31b7 commit 44b80f3

File tree

3 files changed

+15
-4
lines changed

3 files changed

+15
-4
lines changed

lib/puppet/property/sqlserver_tsql.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
class Puppet::Property::SqlserverTsql < Puppet::Property
44
desc 'TSQL property that we are going to wrap with a try catch'
55
munge do |value|
6+
quoted_value = value.gsub('\'', '\'\'')
67
erb_template = <<-TEMPLATE
78
BEGIN TRY
8-
#{value}
9+
DECLARE @sql_text as NVARCHAR(max);
10+
SET @sql_text = N'#{quoted_value}'
11+
EXECUTE sp_executesql @sql_text;
912
END TRY
1013
BEGIN CATCH
1114
DECLARE @msg as VARCHAR(max);

spec/unit/puppet/property/tsql_spec.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@
1414
it 'should munge value to have begin and end try' do
1515
@node[:command] = 'function foo'
1616
@node[:onlyif] = 'exec bar'
17-
expect(@node[:onlyif]).to match(/BEGIN TRY\n\s+exec bar\nEND TRY/)
18-
expect(@node[:command]).to match(/BEGIN TRY\n\s+function foo\nEND TRY/)
17+
expect(@node[:onlyif]).to match(/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/)
18+
expect(@node[:command]).to match(/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/)
19+
end
20+
21+
it 'should properly escape single quotes in queries' do
22+
@node[:command] = 'SELECT \'FOO\''
23+
expect(@node[:command]).to match(/SET @sql_text = N'SELECT \'\'FOO\'\'/)
1924
end
2025

2126
end

spec/unit/puppet/provider/sqlserver__tsql_spec.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ def stub_get_instance_config(config)
2222
end
2323

2424
def gen_query(query)
25+
quoted_query = query.gsub('\'', '\'\'')
2526
<<-PP
2627
BEGIN TRY
27-
#{query}
28+
DECLARE @sql_text as NVARCHAR(max);
29+
SET @sql_text = N'#{quoted_query}'
30+
EXECUTE sp_executesql @sql_text;
2831
END TRY
2932
BEGIN CATCH
3033
DECLARE @msg as VARCHAR(max);

0 commit comments

Comments
 (0)