Skip to content

Commit 4ebc3e2

Browse files
committed
(MODULES-6281) Return Errors from T-SQL
The sqlserver_tsql resource does not handle errors returned from T-SQL statements properly. The errors come back from the query but unless the phrase 'SQL Server' was included in the error text, the error was not then passed back to the user/logs. This change ensure that errors returned are passed back properly by inspecting the Errors property of the ADO object used to run the query. Note that this may not behave as expected if the error that occurrs is of sufficently low severity that a rowset, even if empty, is also returned. If a rowset is returned by the ADO object, the object will not populate the Errors property, and there is no way to tell a low severity error occurred. For instance 'Select 1/0' returns a low severity division by zero error, and an empty rowset. Because the empty rowset exists, the error cannot be seen. It is up to the user to ensure that the errors they want to catch are of sufficienty severity that execution of the query is halted.
1 parent 45d9721 commit 4ebc3e2

3 files changed

Lines changed: 20 additions & 18 deletions

File tree

lib/puppet_x/sqlserver/sql_connection.rb

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ def open_and_run_command(query, config)
99
open(config)
1010
execute(query)
1111
rescue win32_exception => e
12-
return ResultOutput.new(true, e.message)
12+
return ResultOutput.new(true, e.message, @connection)
1313
ensure
1414
close
1515
end
1616

17-
ResultOutput.new(false, nil)
17+
ResultOutput.new(false, nil, @connection)
1818
end
1919

2020
private
@@ -92,23 +92,23 @@ def win32_exception
9292
class ResultOutput
9393
attr_reader :exitstatus, :error_message, :raw_error_message
9494

95-
def initialize(has_errors, error_message)
95+
def initialize(has_errors, error_message, connection)
9696
@exitstatus = has_errors ? 1 : 0
97-
if error_message
98-
@raw_error_message = error_message
99-
@error_message = parse_for_error(error_message)
97+
98+
if !connection.nil?
99+
if !connection.Errors(0).nil?
100+
@error_message = connection.Errors(0).Description
101+
end
102+
end
103+
104+
if (@error_message.nil?) && (!error_message.nil?)
105+
@error_message = error_message
100106
end
101107
end
102108

103109
def has_errors
104110
@exitstatus != 0
105111
end
106-
107-
private
108-
def parse_for_error(result)
109-
match = result.match(/SQL Server\n\s*(.*)/i)
110-
match[1] unless match == nil
111-
end
112112
end
113113
end
114114
end

spec/spec_helper.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,3 @@
1010
e.syntax = [:should, :expect]
1111
end
1212
end
13-

spec/unit/puppet_x/sql_connection_spec.rb

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88

99
def stub_connection
1010
@connection = mock()
11+
error = mock()
12+
error.stubs(:Description).returns("SQL Connection error has happened")
1113
subject.stubs(:create_connection).returns(@connection)
1214
@connection.stubs(:State).returns(PuppetX::Sqlserver::CONNECTION_CLOSED)
15+
@connection.stubs(:Errors).returns(error)
1316
subject.stubs(:win32_exception).returns(Exception)
1417
end
1518

@@ -20,11 +23,11 @@ def stub_connection
2023
@connection.stubs(:Open).with('Provider=SQLNCLI11;Initial Catalog=master;Application Name=Puppet;Data Source=.;DataTypeComptibility=80;User ID=sa;Password=Pupp3t1@')
2124
end
2225
it 'should not raise an error but populate has_errors with message' do
23-
subject.stubs(:execute).raises(Exception.new("SQL Server\n error has happened"))
26+
subject.stubs(:execute).raises(Exception.new("An error has happened"))
2427
expect {
2528
result = subject.open_and_run_command('whacka whacka whacka', config)
2629
expect(result.exitstatus).to eq(1)
27-
expect(result.error_message).to eq('error has happened')
30+
expect(result.error_message).to eq('SQL Connection error has happened')
2831
}.to_not raise_error(Exception)
2932

3033
end
@@ -116,12 +119,12 @@ def stub_connection
116119
it {
117120
subject.stubs(:win32_exception).returns(Exception)
118121
subject.expects(:open).with({:admin_user => 'sa', :admin_pass => 'Pupp3t1@', :instance_name => 'MSSQLSERVER'})
119-
subject.expects(:execute).with('SELECT * FROM sys.databases').raises(Exception.new("SQL Server\ninvalid syntax provider"))
122+
subject.expects(:execute).with('SELECT * FROM sys.databases').raises(Exception.new("Invalid syntax provider"))
120123
subject.expects(:close).once
121124
result =
122125
subject.open_and_run_command('SELECT * FROM sys.databases', config)
123126
expect(result.exitstatus).to eq(1)
124-
expect(result.error_message).to eq('invalid syntax provider')
127+
expect(result.error_message).to eq('Invalid syntax provider')
125128
}
126129
end
127130
context 'open connection failure' do
@@ -132,7 +135,7 @@ def stub_connection
132135
expect {
133136
result = subject.open_and_run_command('whacka whacka whacka', config)
134137
expect(result.exitstatus).to eq(1)
135-
expect(result.error_message).to eq 'ConnectionFailed'
138+
expect(result.error_message).to eq 'SQL Connection error has happened'
136139
}.to_not raise_error(Exception)
137140
}
138141
end

0 commit comments

Comments
 (0)