tiny_tds 0.4.5.rc1-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/CHANGELOG +99 -0
- data/Gemfile +18 -0
- data/MIT-LICENSE +22 -0
- data/NOTES +11 -0
- data/README.rdoc +277 -0
- data/Rakefile +52 -0
- data/ext/tiny_tds/client.c +347 -0
- data/ext/tiny_tds/client.h +35 -0
- data/ext/tiny_tds/extconf.rb +84 -0
- data/ext/tiny_tds/result.c +493 -0
- data/ext/tiny_tds/result.h +36 -0
- data/ext/tiny_tds/tiny_tds_ext.c +12 -0
- data/ext/tiny_tds/tiny_tds_ext.h +18 -0
- data/lib/tiny_tds/1.8/tiny_tds.so +0 -0
- data/lib/tiny_tds/1.9/tiny_tds.so +0 -0
- data/lib/tiny_tds/client.rb +79 -0
- data/lib/tiny_tds/error.rb +29 -0
- data/lib/tiny_tds/result.rb +8 -0
- data/lib/tiny_tds/version.rb +3 -0
- data/lib/tiny_tds.rb +19 -0
- data/tasks/ports.rake +58 -0
- data/test/benchmark/query.rb +77 -0
- data/test/benchmark/query_odbc.rb +106 -0
- data/test/benchmark/query_tinytds.rb +111 -0
- data/test/client_test.rb +163 -0
- data/test/result_test.rb +437 -0
- data/test/schema/1px.gif +0 -0
- data/test/schema/sqlserver_2000.sql +138 -0
- data/test/schema/sqlserver_2005.sql +138 -0
- data/test/schema/sqlserver_2008.sql +138 -0
- data/test/schema/sqlserver_azure.sql +138 -0
- data/test/schema_test.rb +284 -0
- data/test/test_helper.rb +190 -0
- metadata +117 -0
data/test/result_test.rb
ADDED
@@ -0,0 +1,437 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class ResultTest < TinyTds::TestCase
|
5
|
+
|
6
|
+
context 'Basic query and result' do
|
7
|
+
|
8
|
+
setup do
|
9
|
+
@@current_schema_loaded ||= load_current_schema
|
10
|
+
@client = new_connection
|
11
|
+
@query1 = 'SELECT 1 AS [one]'
|
12
|
+
end
|
13
|
+
|
14
|
+
should 'have included Enumerable' do
|
15
|
+
assert TinyTds::Result.ancestors.include?(Enumerable)
|
16
|
+
end
|
17
|
+
|
18
|
+
should 'respond to #each' do
|
19
|
+
result = @client.execute(@query1)
|
20
|
+
assert result.respond_to?(:each)
|
21
|
+
end
|
22
|
+
|
23
|
+
should 'return all results for #each with no block' do
|
24
|
+
result = @client.execute(@query1)
|
25
|
+
data = result.each
|
26
|
+
row = data.first
|
27
|
+
assert_instance_of Array, data
|
28
|
+
assert_equal 1, data.size
|
29
|
+
assert_instance_of Hash, row, 'hash is the default query option'
|
30
|
+
end
|
31
|
+
|
32
|
+
should 'return all results for #each with a block yielding a row at a time' do
|
33
|
+
result = @client.execute(@query1)
|
34
|
+
data = result.each do |row|
|
35
|
+
assert_instance_of Hash, row, 'hash is the default query option'
|
36
|
+
end
|
37
|
+
assert_instance_of Array, data
|
38
|
+
end
|
39
|
+
|
40
|
+
should 'allow successive calls to each returning the same data' do
|
41
|
+
result = @client.execute(@query1)
|
42
|
+
data = result.each
|
43
|
+
result.each
|
44
|
+
assert_equal data.object_id, result.each.object_id
|
45
|
+
assert_equal data.first.object_id, result.each.first.object_id
|
46
|
+
end
|
47
|
+
|
48
|
+
should 'return hashes with string keys' do
|
49
|
+
result = @client.execute(@query1)
|
50
|
+
row = result.each(:as => :hash, :symbolize_keys => false).first
|
51
|
+
assert_instance_of Hash, row
|
52
|
+
assert_equal ['one'], row.keys
|
53
|
+
assert_equal ['one'], result.fields
|
54
|
+
end
|
55
|
+
|
56
|
+
should 'return hashes with symbol keys' do
|
57
|
+
result = @client.execute(@query1)
|
58
|
+
row = result.each(:as => :hash, :symbolize_keys => true).first
|
59
|
+
assert_instance_of Hash, row
|
60
|
+
assert_equal [:one], row.keys
|
61
|
+
assert_equal [:one], result.fields
|
62
|
+
end
|
63
|
+
|
64
|
+
should 'return arrays with string fields' do
|
65
|
+
result = @client.execute(@query1)
|
66
|
+
row = result.each(:as => :array, :symbolize_keys => false).first
|
67
|
+
assert_instance_of Array, row
|
68
|
+
assert_equal ['one'], result.fields
|
69
|
+
end
|
70
|
+
|
71
|
+
should 'return arrays with symbol fields' do
|
72
|
+
result = @client.execute(@query1)
|
73
|
+
row = result.each(:as => :array, :symbolize_keys => true).first
|
74
|
+
assert_instance_of Array, row
|
75
|
+
assert_equal [:one], result.fields
|
76
|
+
end
|
77
|
+
|
78
|
+
should 'be able to turn :cache_rows option off' do
|
79
|
+
result = @client.execute(@query1)
|
80
|
+
local = []
|
81
|
+
result.each(:cache_rows => false) do |row|
|
82
|
+
local << row
|
83
|
+
end
|
84
|
+
assert local.first, 'should have iterated over each row'
|
85
|
+
assert_equal [], result.each, 'should not have been cached'
|
86
|
+
assert_equal ['one'], result.fields, 'should still cache field names'
|
87
|
+
end
|
88
|
+
|
89
|
+
should 'be able to get the first result row only' do
|
90
|
+
load_current_schema
|
91
|
+
big_query = "SELECT [id] FROM [datatypes]"
|
92
|
+
one = @client.execute(big_query).each(:first => true)
|
93
|
+
many = @client.execute(big_query).each
|
94
|
+
assert many.size > 1
|
95
|
+
assert one.size == 1
|
96
|
+
end
|
97
|
+
|
98
|
+
should 'cope with no results when using first option' do
|
99
|
+
data = @client.execute("SELECT [id] FROM [datatypes] WHERE [id] = -1").each(:first => true)
|
100
|
+
assert_equal [], data
|
101
|
+
end
|
102
|
+
|
103
|
+
should 'delete, insert and find data' do
|
104
|
+
rollback_transaction(@client) do
|
105
|
+
text = 'test insert and delete'
|
106
|
+
@client.execute("DELETE FROM [datatypes] WHERE [varchar_50] IS NOT NULL").do
|
107
|
+
@client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
|
108
|
+
row = @client.execute("SELECT [varchar_50] FROM [datatypes] WHERE [varchar_50] IS NOT NULL").each.first
|
109
|
+
assert row
|
110
|
+
assert_equal text, row['varchar_50']
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
should 'insert and find unicode data' do
|
115
|
+
rollback_transaction(@client) do
|
116
|
+
text = '✓'
|
117
|
+
@client.execute("DELETE FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").do
|
118
|
+
@client.execute("INSERT INTO [datatypes] ([nvarchar_50]) VALUES (N'#{text}')").do
|
119
|
+
row = @client.execute("SELECT [nvarchar_50] FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").each.first
|
120
|
+
assert_equal text, row['nvarchar_50']
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
should 'delete and update with affected rows support and insert with identity support in native sql' do
|
125
|
+
rollback_transaction(@client) do
|
126
|
+
text = 'test affected rows sql'
|
127
|
+
@client.execute("DELETE FROM [datatypes]").do
|
128
|
+
afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first['AffectedRows']
|
129
|
+
assert_instance_of Fixnum, afrows
|
130
|
+
@client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
|
131
|
+
pk1 = @client.execute("SELECT SCOPE_IDENTITY() AS Ident").each.first['Ident']
|
132
|
+
assert_instance_of BigDecimal, pk1, 'native is numeric(38,0) for SCOPE_IDENTITY() function'
|
133
|
+
pk2 = @client.execute("SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident").each.first['Ident']
|
134
|
+
assert_instance_of Fixnum, pk2, 'we should be able to CAST to bigint'
|
135
|
+
assert_equal pk2, pk1.to_i, 'just making sure the 2 line up'
|
136
|
+
@client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do
|
137
|
+
afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first['AffectedRows']
|
138
|
+
assert_equal 1, afrows
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
should 'have a #do method that cancels result rows and returns affected rows natively' do
|
143
|
+
rollback_transaction(@client) do
|
144
|
+
text = 'test affected rows native'
|
145
|
+
count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count']
|
146
|
+
deleted_rows = @client.execute("DELETE FROM [datatypes]").do
|
147
|
+
assert_equal count, deleted_rows, 'should have deleted rows equal to count'
|
148
|
+
inserted_rows = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
|
149
|
+
assert_equal 1, inserted_rows, 'should have inserted row for one above'
|
150
|
+
updated_rows = @client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do
|
151
|
+
assert_equal 1, updated_rows, 'should have updated row for one above' unless sqlserver_2000? # Will report -1
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
should 'allow native affected rows using #do to work under transaction' do
|
156
|
+
rollback_transaction(@client) do
|
157
|
+
text = 'test affected rows native in transaction'
|
158
|
+
@client.execute("BEGIN TRANSACTION").do
|
159
|
+
@client.execute("DELETE FROM [datatypes]").do
|
160
|
+
inserted_rows = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
|
161
|
+
assert_equal 1, inserted_rows, 'should have inserted row for one above'
|
162
|
+
updated_rows = @client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do
|
163
|
+
assert_equal 1, updated_rows, 'should have updated row for one above' unless sqlserver_2000? # Will report -1
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
should 'have an #insert method that cancels result rows and returns the SCOPE_IDENTITY() natively' do
|
168
|
+
rollback_transaction(@client) do
|
169
|
+
text = 'test scope identity rows native'
|
170
|
+
@client.execute("DELETE FROM [datatypes] WHERE [varchar_50] = '#{text}'").do
|
171
|
+
@client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
|
172
|
+
sql_identity = @client.execute("SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident").each.first['Ident']
|
173
|
+
native_identity = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").insert
|
174
|
+
assert_equal sql_identity+1, native_identity
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
should 'be able to begin/commit transactions with raw sql' do
|
179
|
+
rollback_transaction(@client) do
|
180
|
+
@client.execute("BEGIN TRANSACTION").do
|
181
|
+
@client.execute("DELETE FROM [datatypes]").do
|
182
|
+
@client.execute("COMMIT TRANSACTION").do
|
183
|
+
count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count']
|
184
|
+
assert_equal 0, count
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
should 'be able to begin/rollback transactions with raw sql' do
|
189
|
+
load_current_schema
|
190
|
+
@client.execute("BEGIN TRANSACTION").do
|
191
|
+
@client.execute("DELETE FROM [datatypes]").do
|
192
|
+
@client.execute("ROLLBACK TRANSACTION").do
|
193
|
+
count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count']
|
194
|
+
0.wont_equal count
|
195
|
+
end
|
196
|
+
|
197
|
+
should 'have a #fields accessor with logic default and valid outcome' do
|
198
|
+
result = @client.execute(@query1)
|
199
|
+
result.fields.must_equal ['one']
|
200
|
+
result.each
|
201
|
+
result.fields.must_equal ['one']
|
202
|
+
end
|
203
|
+
|
204
|
+
should 'always return an array for fields for all sql' do
|
205
|
+
result = @client.execute("USE [tinytdstest]")
|
206
|
+
result.fields.must_equal []
|
207
|
+
result.do
|
208
|
+
result.fields.must_equal []
|
209
|
+
end
|
210
|
+
|
211
|
+
should 'return fields even when no results are found' do
|
212
|
+
no_results_query = "SELECT [id], [varchar_50] FROM [datatypes] WHERE [varchar_50] = 'NOTFOUND'"
|
213
|
+
# Fields before each.
|
214
|
+
result = @client.execute(no_results_query)
|
215
|
+
result.fields.must_equal ['id','varchar_50']
|
216
|
+
result.each
|
217
|
+
result.fields.must_equal ['id','varchar_50']
|
218
|
+
# Each then fields
|
219
|
+
result = @client.execute(no_results_query)
|
220
|
+
result.each
|
221
|
+
result.fields.must_equal ['id','varchar_50']
|
222
|
+
end
|
223
|
+
|
224
|
+
should 'allow the result to be canceled before reading' do
|
225
|
+
result = @client.execute(@query1)
|
226
|
+
result.cancel
|
227
|
+
@client.execute(@query1).each
|
228
|
+
end
|
229
|
+
|
230
|
+
should 'work in tandem with the client when needing to find out if client has sql sent and result is canceled or not' do
|
231
|
+
# Default state.
|
232
|
+
@client = TinyTds::Client.new(connection_options)
|
233
|
+
@client.sqlsent?.must_equal false
|
234
|
+
@client.canceled?.must_equal false
|
235
|
+
# With active result before and after cancel.
|
236
|
+
result = @client.execute(@query1)
|
237
|
+
@client.sqlsent?.must_equal true
|
238
|
+
@client.canceled?.must_equal false
|
239
|
+
result.cancel
|
240
|
+
@client.sqlsent?.must_equal false
|
241
|
+
@client.canceled?.must_equal true
|
242
|
+
assert result.cancel, 'must be safe to call again'
|
243
|
+
# With each and no block.
|
244
|
+
@client.execute(@query1).each
|
245
|
+
@client.sqlsent?.must_equal false
|
246
|
+
@client.canceled?.must_equal false
|
247
|
+
# With each and block.
|
248
|
+
@client.execute(@query1).each do |row|
|
249
|
+
@client.sqlsent?.must_equal true, 'when iterating over each row in a block'
|
250
|
+
@client.canceled?.must_equal false
|
251
|
+
end
|
252
|
+
@client.sqlsent?.must_equal false
|
253
|
+
@client.canceled?.must_equal false
|
254
|
+
# With each and block canceled half way thru.
|
255
|
+
count = @client.execute("SELECT COUNT([id]) AS [count] FROM [datatypes]").each[0]['count']
|
256
|
+
assert count > 10, 'since we want to cancel early for test'
|
257
|
+
result = @client.execute("SELECT [id] FROM [datatypes]")
|
258
|
+
index = 0
|
259
|
+
result.each do |row|
|
260
|
+
break if index > 10
|
261
|
+
index += 1
|
262
|
+
end
|
263
|
+
@client.sqlsent?.must_equal true
|
264
|
+
@client.canceled?.must_equal false
|
265
|
+
result.cancel
|
266
|
+
@client.sqlsent?.must_equal false
|
267
|
+
@client.canceled?.must_equal true
|
268
|
+
# With do method.
|
269
|
+
@client.execute(@query1).do
|
270
|
+
@client.sqlsent?.must_equal false
|
271
|
+
@client.canceled?.must_equal true
|
272
|
+
# With insert method.
|
273
|
+
rollback_transaction(@client) do
|
274
|
+
@client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('test')").insert
|
275
|
+
@client.sqlsent?.must_equal false
|
276
|
+
@client.canceled?.must_equal true
|
277
|
+
end
|
278
|
+
# With first
|
279
|
+
@client.execute("SELECT [id] FROM [datatypes]").each(:first => true)
|
280
|
+
@client.sqlsent?.must_equal false
|
281
|
+
@client.canceled?.must_equal true
|
282
|
+
end
|
283
|
+
|
284
|
+
should 'use same string object for hash keys' do
|
285
|
+
data = @client.execute("SELECT [id], [bigint] FROM [datatypes]").each
|
286
|
+
assert_equal data.first.keys.map{ |r| r.object_id }, data.last.keys.map{ |r| r.object_id }
|
287
|
+
end
|
288
|
+
|
289
|
+
should 'have properly encoded column names' do
|
290
|
+
col_name = "öäüß"
|
291
|
+
@client.execute("DROP TABLE [test_encoding]").do rescue nil
|
292
|
+
@client.execute("CREATE TABLE [dbo].[test_encoding] ( [#{col_name}] [nvarchar](10) NOT NULL )").do
|
293
|
+
@client.execute("INSERT INTO [test_encoding] ([#{col_name}]) VALUES (N'#{col_name}')").do
|
294
|
+
result = @client.execute("SELECT [#{col_name}] FROM [test_encoding]")
|
295
|
+
row = result.each.first
|
296
|
+
assert_equal col_name, result.fields.first
|
297
|
+
assert_equal col_name, row.keys.first
|
298
|
+
assert_utf8_encoding result.fields.first
|
299
|
+
assert_utf8_encoding row.keys.first
|
300
|
+
end unless sqlserver_azure?
|
301
|
+
|
302
|
+
should 'allow #return_code to work with stored procedures and reset per sql batch' do
|
303
|
+
assert_nil @client.return_code
|
304
|
+
result = @client.execute("EXEC tinytds_TestReturnCodes")
|
305
|
+
assert_equal [{"one"=>1}], result.each
|
306
|
+
assert_equal 420, @client.return_code
|
307
|
+
assert_equal 420, result.return_code
|
308
|
+
result = @client.execute('SELECT 1 as [one]')
|
309
|
+
result.each
|
310
|
+
assert_nil @client.return_code
|
311
|
+
assert_nil result.return_code
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'with multiple result sets' do
|
315
|
+
|
316
|
+
setup do
|
317
|
+
@double_select = "SELECT 1 AS [rs1]\nSELECT 2 AS [rs2]"
|
318
|
+
end
|
319
|
+
|
320
|
+
should 'handle a command buffer with double selects' do
|
321
|
+
result = @client.execute(@double_select)
|
322
|
+
result_sets = result.each
|
323
|
+
assert_equal 2, result_sets.size
|
324
|
+
assert_equal [{'rs1' => 1}], result_sets.first
|
325
|
+
assert_equal [{'rs2' => 2}], result_sets.last
|
326
|
+
assert_equal [['rs1'],['rs2']], result.fields
|
327
|
+
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
328
|
+
# As array
|
329
|
+
result = @client.execute(@double_select)
|
330
|
+
result_sets = result.each(:as => :array)
|
331
|
+
assert_equal 2, result_sets.size
|
332
|
+
assert_equal [[1]], result_sets.first
|
333
|
+
assert_equal [[2]], result_sets.last
|
334
|
+
assert_equal [['rs1'],['rs2']], result.fields
|
335
|
+
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
336
|
+
end
|
337
|
+
|
338
|
+
should 'yield each row for each result set' do
|
339
|
+
data = []
|
340
|
+
result_sets = @client.execute(@double_select).each { |row| data << row }
|
341
|
+
assert_equal data.first, result_sets.first[0]
|
342
|
+
assert_equal data.last, result_sets.last[0]
|
343
|
+
end
|
344
|
+
|
345
|
+
should 'from a stored procedure' do
|
346
|
+
results1, results2 = @client.execute("EXEC sp_helpconstraint '[datatypes]'").each
|
347
|
+
assert_equal [{"Object Name"=>"[datatypes]"}], results1
|
348
|
+
constraint_info = results2.first
|
349
|
+
assert constraint_info.key?("constraint_keys")
|
350
|
+
assert constraint_info.key?("constraint_type")
|
351
|
+
assert constraint_info.key?("constraint_name")
|
352
|
+
end
|
353
|
+
|
354
|
+
should 'ignore empty result sets' do
|
355
|
+
rollback_transaction(@client) do
|
356
|
+
@client.execute("DELETE FROM [datatypes]").do
|
357
|
+
id = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('test empty result sets')").insert
|
358
|
+
sql = %|
|
359
|
+
SET NOCOUNT ON
|
360
|
+
DECLARE @row_number TABLE (row int identity(1,1), id int)
|
361
|
+
INSERT INTO @row_number (id)
|
362
|
+
SELECT [datatypes].[id] FROM [datatypes]
|
363
|
+
SET NOCOUNT OFF
|
364
|
+
SELECT id FROM @row_number|
|
365
|
+
result = @client.execute(sql)
|
366
|
+
result.each.must_equal [{"id"=>id}]
|
367
|
+
result.fields.must_equal ['id']
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
|
373
|
+
context 'when casting to native ruby values' do
|
374
|
+
|
375
|
+
should 'return fixnum for 1' do
|
376
|
+
value = @client.execute('SELECT 1 AS [fixnum]').each.first['fixnum']
|
377
|
+
assert_equal 1, value
|
378
|
+
end
|
379
|
+
|
380
|
+
should 'return nil for NULL' do
|
381
|
+
value = @client.execute('SELECT NULL AS [null]').each.first['null']
|
382
|
+
assert_equal nil, value
|
383
|
+
end
|
384
|
+
|
385
|
+
end
|
386
|
+
|
387
|
+
context 'when shit happens' do
|
388
|
+
|
389
|
+
should 'cope with nil or empty buffer' do
|
390
|
+
assert_raises(TypeError) { @client.execute(nil) }
|
391
|
+
assert_equal [], @client.execute('').each
|
392
|
+
end
|
393
|
+
|
394
|
+
should 'throw an error when you execute another query with other results pending' do
|
395
|
+
result1 = @client.execute(@query1)
|
396
|
+
action = lambda { @client.execute(@query1) }
|
397
|
+
assert_raise_tinytds_error(action) do |e|
|
398
|
+
assert_match %r|with results pending|i, e.message
|
399
|
+
assert_equal 7, e.severity
|
400
|
+
assert_equal 20019, e.db_error_number
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
should 'error gracefully with bad table name' do
|
405
|
+
action = lambda { @client.execute('SELECT * FROM [foobar]').each }
|
406
|
+
assert_raise_tinytds_error(action) do |e|
|
407
|
+
assert_match %r|invalid object name.*foobar|i, e.message
|
408
|
+
assert_equal 16, e.severity
|
409
|
+
assert_equal 208, e.db_error_number
|
410
|
+
end
|
411
|
+
assert_followup_query
|
412
|
+
end
|
413
|
+
|
414
|
+
should 'error gracefully with invalid syntax' do
|
415
|
+
action = lambda { @client.execute('this will not work').each }
|
416
|
+
assert_raise_tinytds_error(action) do |e|
|
417
|
+
assert_match %r|incorrect syntax|i, e.message
|
418
|
+
assert_equal 15, e.severity
|
419
|
+
assert_equal 156, e.db_error_number
|
420
|
+
end
|
421
|
+
assert_followup_query
|
422
|
+
end
|
423
|
+
|
424
|
+
end
|
425
|
+
|
426
|
+
end
|
427
|
+
|
428
|
+
|
429
|
+
protected
|
430
|
+
|
431
|
+
def assert_followup_query
|
432
|
+
result = @client.execute(@query1)
|
433
|
+
assert_equal 1, result.each.first['one']
|
434
|
+
end
|
435
|
+
|
436
|
+
end
|
437
|
+
|
data/test/schema/1px.gif
ADDED
Binary file
|
@@ -0,0 +1,138 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
|
4
|
+
* Binary Data - Our test binary data is a 1 pixel gif. The basic (raw) data is below. Quoting this data
|
5
|
+
would involve this (encode) method and be (encoded) with the 0x prefix for raw SQL. In other clients the
|
6
|
+
(raw_db) value without the 0x prefix would need to be (packed) again yield the original (raw) value.
|
7
|
+
|
8
|
+
(raw) - "GIF89a\001\000\001\000\221\000\000\377\377\377\377\377\377\376\001\002\000\000\000!\371\004\004\024\000\377\000,\000\000\000\000\001\000\001\000\000\002\002D\001\000;"
|
9
|
+
(encode) - "0x#{raw.unpack("H*")[0]}"
|
10
|
+
(encoded) - "0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b"
|
11
|
+
(raw_db) - "47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b"
|
12
|
+
(packed) - [raw_db].pack('H*')
|
13
|
+
|
14
|
+
*/
|
15
|
+
|
16
|
+
CREATE TABLE [dbo].[datatypes] (
|
17
|
+
[id] [int] NOT NULL IDENTITY(1,1) PRIMARY KEY,
|
18
|
+
[bigint] [bigint] NULL,
|
19
|
+
[binary_50] [binary](50) NULL,
|
20
|
+
[bit] [bit] NULL,
|
21
|
+
[char_10] [char](10) NULL,
|
22
|
+
-- [date] [date] NULL,
|
23
|
+
[datetime] [datetime] NULL,
|
24
|
+
-- [datetime2_7] [datetime2](7) NULL,
|
25
|
+
-- [datetimeoffset_2] [datetimeoffset](2) NULL,
|
26
|
+
-- [datetimeoffset_7] [datetimeoffset](7) NULL,
|
27
|
+
[decimal_9_2] [decimal](9, 2) NULL,
|
28
|
+
[decimal_16_4] [decimal](16, 4) NULL,
|
29
|
+
[float] [float] NULL,
|
30
|
+
-- [geography] [geography] NULL,
|
31
|
+
-- [geometry] [geometry] NULL,
|
32
|
+
-- [hierarchyid] [hierarchyid] NULL,
|
33
|
+
[image] [image] NULL,
|
34
|
+
[int] [int] NULL,
|
35
|
+
[money] [money] NULL,
|
36
|
+
[nchar_10] [nchar](10) NULL,
|
37
|
+
[ntext] [ntext] NULL,
|
38
|
+
[numeric_18_0] [numeric](18, 0) NULL,
|
39
|
+
[numeric_36_2] [numeric](36, 2) NULL,
|
40
|
+
[nvarchar_50] [nvarchar](50) NULL,
|
41
|
+
-- [nvarchar_max] [nvarchar](max) NULL,
|
42
|
+
[real] [real] NULL,
|
43
|
+
[smalldatetime] [smalldatetime] NULL,
|
44
|
+
[smallint] [smallint] NULL,
|
45
|
+
[smallmoney] [smallmoney] NULL,
|
46
|
+
[text] [text] NULL,
|
47
|
+
-- [time_2] [time](2) NULL,
|
48
|
+
-- [time_7] [time](7) NULL,
|
49
|
+
[timestamp] [timestamp] NULL,
|
50
|
+
[tinyint] [tinyint] NULL,
|
51
|
+
[uniqueidentifier] [uniqueidentifier] NULL,
|
52
|
+
[varbinary_50] [varbinary](50) NULL,
|
53
|
+
-- [varbinary_max] [varbinary](max) NULL,
|
54
|
+
[varchar_50] [varchar](50) NULL
|
55
|
+
-- [varchar_max] [varchar](max) NULL,
|
56
|
+
-- [xml] [xml] NULL
|
57
|
+
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
|
58
|
+
|
59
|
+
SET IDENTITY_INSERT [datatypes] ON
|
60
|
+
|
61
|
+
INSERT INTO [datatypes] ([id], [bigint]) VALUES ( 11, -9223372036854775807 )
|
62
|
+
INSERT INTO [datatypes] ([id], [bigint]) VALUES ( 12, 9223372036854775806 )
|
63
|
+
INSERT INTO [datatypes] ([id], [binary_50]) VALUES ( 21, 0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b )
|
64
|
+
INSERT INTO [datatypes] ([id], [bit]) VALUES ( 31, 1 )
|
65
|
+
INSERT INTO [datatypes] ([id], [bit]) VALUES ( 32, 0 )
|
66
|
+
INSERT INTO [datatypes] ([id], [char_10]) VALUES ( 41, '1234567890' )
|
67
|
+
INSERT INTO [datatypes] ([id], [char_10]) VALUES ( 42, '12345678' )
|
68
|
+
-- INSERT INTO [datatypes] ([id], [date]) VALUES ( 51, '0001-01-01' )
|
69
|
+
-- INSERT INTO [datatypes] ([id], [date]) VALUES ( 52, '9999-12-31' )
|
70
|
+
INSERT INTO [datatypes] ([id], [datetime]) VALUES ( 61, '1753-01-01T00:00:00.000' )
|
71
|
+
INSERT INTO [datatypes] ([id], [datetime]) VALUES ( 62, '9999-12-31T23:59:59.997' )
|
72
|
+
INSERT INTO [datatypes] ([id], [datetime]) VALUES ( 63, '2010-01-01T12:34:56.123' )
|
73
|
+
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 71, '0001-01-01T00:00:00.0000000Z' )
|
74
|
+
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 72, '1984-01-24T04:20:00.0000000-08:00' )
|
75
|
+
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 73, '9999-12-31T23:59:59.9999999Z' )
|
76
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_2]) VALUES ( 81, '1984-01-24T04:20:00.0000000-08:00' ) -- 1984-01-24 04:20:00.00 -08:00
|
77
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_2]) VALUES ( 82, '1984-01-24T04:20:00.0000000Z' ) -- 1984-01-24 04:20:00.00 +00:00
|
78
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_2]) VALUES ( 83, '9999-12-31T23:59:59.9999999Z' ) -- 9999-12-31 23:59:59.99 +00:00
|
79
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_7]) VALUES ( 84, '1984-01-24T04:20:00.0000000-08:00' ) -- 1984-01-24 04:20:00.0000000 -08:00
|
80
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_7]) VALUES ( 85, '1984-01-24T04:20:00.0000000Z' ) -- 1984-01-24 04:20:00.0000000 +00:00
|
81
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_7]) VALUES ( 86, '9999-12-31T23:59:59.9999999Z' ) -- 9999-12-31 23:59:59.9999999 +00:00
|
82
|
+
INSERT INTO [datatypes] ([id], [decimal_9_2]) VALUES ( 91, 12345.01 )
|
83
|
+
INSERT INTO [datatypes] ([id], [decimal_9_2]) VALUES ( 92, 1234567.89 )
|
84
|
+
INSERT INTO [datatypes] ([id], [decimal_16_4]) VALUES ( 93, 0.0 )
|
85
|
+
INSERT INTO [datatypes] ([id], [decimal_16_4]) VALUES ( 94, 123456789012.3456 )
|
86
|
+
INSERT INTO [datatypes] ([id], [float]) VALUES ( 101, 123.00000001 )
|
87
|
+
INSERT INTO [datatypes] ([id], [float]) VALUES ( 102, 0.0 )
|
88
|
+
INSERT INTO [datatypes] ([id], [float]) VALUES ( 103, 123.45 )
|
89
|
+
-- INSERT INTO [datatypes] ([id], [geography]) VALUES ( 111, geography::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656)', 4326) ) -- 0xE610000001148716D9CEF7D34740D7A3703D0A975EC08716D9CEF7D34740CBA145B6F3955EC0
|
90
|
+
-- INSERT INTO [datatypes] ([id], [geometry]) VALUES ( 121, geometry::STGeomFromText('LINESTRING (100 100, 20 180, 180 180)', 0) ) -- 0x0000000001040300000000000000000059400000000000005940000000000000344000000000008066400000000000806640000000000080664001000000010000000001000000FFFFFFFF0000000002
|
91
|
+
-- INSERT INTO [datatypes] ([id], [hierarchyid]) VALUES ( 131, CAST('/1/' AS hierarchyid) ) -- 0x58
|
92
|
+
-- INSERT INTO [datatypes] ([id], [hierarchyid]) VALUES ( 132, CAST('/2/' AS hierarchyid) ) -- 0x68
|
93
|
+
INSERT INTO [datatypes] ([id], [image]) VALUES ( 141, 0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b )
|
94
|
+
INSERT INTO [datatypes] ([id], [int]) VALUES ( 151, -2147483647 )
|
95
|
+
INSERT INTO [datatypes] ([id], [int]) VALUES ( 152, 2147483646 )
|
96
|
+
INSERT INTO [datatypes] ([id], [money]) VALUES ( 161, 4.20 )
|
97
|
+
INSERT INTO [datatypes] ([id], [money]) VALUES ( 162, -922337203685477.5807 )
|
98
|
+
INSERT INTO [datatypes] ([id], [money]) VALUES ( 163, 922337203685477.5806 )
|
99
|
+
INSERT INTO [datatypes] ([id], [nchar_10]) VALUES ( 171, N'1234567890' )
|
100
|
+
INSERT INTO [datatypes] ([id], [nchar_10]) VALUES ( 172, N'123456åå' )
|
101
|
+
INSERT INTO [datatypes] ([id], [nchar_10]) VALUES ( 173, N'abc123' )
|
102
|
+
INSERT INTO [datatypes] ([id], [ntext]) VALUES ( 181, N'test ntext' )
|
103
|
+
INSERT INTO [datatypes] ([id], [ntext]) VALUES ( 182, N'test ntext åå' )
|
104
|
+
INSERT INTO [datatypes] ([id], [numeric_18_0]) VALUES ( 191, 191 )
|
105
|
+
INSERT INTO [datatypes] ([id], [numeric_18_0]) VALUES ( 192, 123456789012345678 )
|
106
|
+
INSERT INTO [datatypes] ([id], [numeric_36_2]) VALUES ( 193, 12345678901234567890.01 )
|
107
|
+
INSERT INTO [datatypes] ([id], [numeric_36_2]) VALUES ( 194, 123.46 )
|
108
|
+
INSERT INTO [datatypes] ([id], [nvarchar_50]) VALUES ( 201, N'test nvarchar_50' )
|
109
|
+
INSERT INTO [datatypes] ([id], [nvarchar_50]) VALUES ( 202, N'test nvarchar_50 åå' )
|
110
|
+
-- INSERT INTO [datatypes] ([id], [nvarchar_max]) VALUES ( 211, N'test nvarchar_max' )
|
111
|
+
-- INSERT INTO [datatypes] ([id], [nvarchar_max]) VALUES ( 212, N'test nvarchar_max åå' )
|
112
|
+
INSERT INTO [datatypes] ([id], [real]) VALUES ( 221, 123.45 )
|
113
|
+
INSERT INTO [datatypes] ([id], [real]) VALUES ( 222, 0.0 )
|
114
|
+
INSERT INTO [datatypes] ([id], [real]) VALUES ( 223, 0.00001 )
|
115
|
+
INSERT INTO [datatypes] ([id], [smalldatetime]) VALUES ( 231, '1901-01-01T15:45:00.000' ) -- 1901-01-01 15:45:00
|
116
|
+
INSERT INTO [datatypes] ([id], [smalldatetime]) VALUES ( 232, '2078-06-05T04:20:00.000' ) -- 2078-06-05 04:20:00
|
117
|
+
INSERT INTO [datatypes] ([id], [smallint]) VALUES ( 241, -32767 )
|
118
|
+
INSERT INTO [datatypes] ([id], [smallint]) VALUES ( 242, 32766 )
|
119
|
+
INSERT INTO [datatypes] ([id], [smallmoney]) VALUES ( 251, 4.20 )
|
120
|
+
INSERT INTO [datatypes] ([id], [smallmoney]) VALUES ( 252, -214748.3647 )
|
121
|
+
INSERT INTO [datatypes] ([id], [smallmoney]) VALUES ( 253, 214748.3646 )
|
122
|
+
INSERT INTO [datatypes] ([id], [text]) VALUES ( 271, 'test text' )
|
123
|
+
-- INSERT INTO [datatypes] ([id], [time_2]) VALUES ( 281, '1901-01-01T15:45:00.0100001Z' ) -- 15:45:00.01
|
124
|
+
-- INSERT INTO [datatypes] ([id], [time_2]) VALUES ( 282, '1984-01-24T04:20:00.0000001-08:00' ) -- 04:20:00.00
|
125
|
+
-- INSERT INTO [datatypes] ([id], [time_7]) VALUES ( 283, '1901-01-01T15:45:00.0100001Z' ) -- 15:45:00.0100001
|
126
|
+
-- INSERT INTO [datatypes] ([id], [time_7]) VALUES ( 284, '1984-01-24T04:20:00.0000001-08:00' ) -- 04:20:00.0000001
|
127
|
+
INSERT INTO [datatypes] ([id], [tinyint]) VALUES ( 301, 0 )
|
128
|
+
INSERT INTO [datatypes] ([id], [tinyint]) VALUES ( 302, 255 )
|
129
|
+
INSERT INTO [datatypes] ([id], [uniqueidentifier]) VALUES ( 311, NEWID() )
|
130
|
+
INSERT INTO [datatypes] ([id], [varbinary_50]) VALUES ( 321, 0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b )
|
131
|
+
-- INSERT INTO [datatypes] ([id], [varbinary_max]) VALUES ( 331, 0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b )
|
132
|
+
INSERT INTO [datatypes] ([id], [varchar_50]) VALUES ( 341, 'test varchar_50' )
|
133
|
+
-- INSERT INTO [datatypes] ([id], [varchar_max]) VALUES ( 351, 'test varchar_max' )
|
134
|
+
-- INSERT INTO [datatypes] ([id], [xml]) VALUES ( 361, '<foo><bar>batz</bar></foo>' )
|
135
|
+
|
136
|
+
SET IDENTITY_INSERT [datatypes] OFF
|
137
|
+
|
138
|
+
|