tiny_tds 2.1.6 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +470 -0
- data/CHANGELOG.md +13 -0
- data/ISSUE_TEMPLATE.md +1 -1
- data/README.md +25 -45
- data/Rakefile +2 -6
- data/VERSION +1 -1
- data/docker-compose.yml +2 -2
- data/ext/tiny_tds/client.c +8 -15
- data/ext/tiny_tds/extconf.rb +1 -2
- data/ext/tiny_tds/extconsts.rb +4 -10
- data/ext/tiny_tds/result.c +27 -35
- data/ext/tiny_tds/tiny_tds_ext.c +4 -1
- data/tasks/ports/freetds.rb +1 -6
- data/tasks/ports.rake +2 -2
- data/test/bin/install-mssql.ps1 +22 -11
- data/test/client_test.rb +2 -5
- data/test/gem_test.rb +0 -1
- data/test/result_test.rb +99 -192
- data/test/schema_test.rb +366 -388
- data/test/test_helper.rb +6 -37
- data/tiny_tds.gemspec +4 -3
- metadata +25 -16
- data/.circleci/config.yml +0 -407
- data/test/schema/sqlserver_2000.sql +0 -140
- data/test/schema/sqlserver_2005.sql +0 -140
- data/test/schema/sqlserver_2014.sql +0 -140
- data/test/schema/sqlserver_2016.sql +0 -140
- data/test/schema/sybase_ase.sql +0 -138
- /data/test/schema/{sqlserver_2008.sql → sqlserver_2017.sql} +0 -0
data/test/result_test.rb
CHANGED
@@ -154,7 +154,7 @@ class ResultTest < TinyTds::TestCase
|
|
154
154
|
inserted_rows = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
|
155
155
|
assert_equal 1, inserted_rows, 'should have inserted row for one above'
|
156
156
|
updated_rows = @client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do
|
157
|
-
assert_equal 1, updated_rows, 'should have updated row for one above'
|
157
|
+
assert_equal 1, updated_rows, 'should have updated row for one above'
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
@@ -166,7 +166,7 @@ class ResultTest < TinyTds::TestCase
|
|
166
166
|
inserted_rows = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
|
167
167
|
assert_equal 1, inserted_rows, 'should have inserted row for one above'
|
168
168
|
updated_rows = @client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do
|
169
|
-
assert_equal 1, updated_rows, 'should have updated row for one above'
|
169
|
+
assert_equal 1, updated_rows, 'should have updated row for one above'
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
@@ -177,19 +177,18 @@ class ResultTest < TinyTds::TestCase
|
|
177
177
|
@client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do
|
178
178
|
sql_identity = @client.execute(@client.identity_sql).each.first['Ident']
|
179
179
|
native_identity = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").insert
|
180
|
-
assert_equal sql_identity+1, native_identity
|
180
|
+
assert_equal sql_identity + 1, native_identity
|
181
181
|
end
|
182
182
|
end
|
183
183
|
|
184
184
|
it 'returns bigint for #insert when needed' do
|
185
185
|
return if sqlserver_azure? # We can not alter clustered index like this test does.
|
186
|
-
|
187
|
-
|
188
|
-
# and and sp_helpindex creates a temporary table #spindtab.
|
186
|
+
# 'CREATE TABLE' command is not allowed within a multi-statement transaction
|
187
|
+
# and and sp_helpindex creates a temporary table #spindtab.
|
189
188
|
rollback_transaction(@client) do
|
190
189
|
seed = 9223372036854775805
|
191
190
|
@client.execute("DELETE FROM [datatypes]").do
|
192
|
-
id_constraint_name = @client.execute("EXEC sp_helpindex [datatypes]").detect{ |row| row['index_keys'] == 'id' }['index_name']
|
191
|
+
id_constraint_name = @client.execute("EXEC sp_helpindex [datatypes]").detect { |row| row['index_keys'] == 'id' }['index_name']
|
193
192
|
@client.execute("ALTER TABLE [datatypes] DROP CONSTRAINT [#{id_constraint_name}]").do
|
194
193
|
@client.execute("ALTER TABLE [datatypes] DROP COLUMN [id]").do
|
195
194
|
@client.execute("ALTER TABLE [datatypes] ADD [id] [bigint] NOT NULL IDENTITY(1,1) PRIMARY KEY").do
|
@@ -236,13 +235,13 @@ class ResultTest < TinyTds::TestCase
|
|
236
235
|
no_results_query = "SELECT [id], [varchar_50] FROM [datatypes] WHERE [varchar_50] = 'NOTFOUND'"
|
237
236
|
# Fields before each.
|
238
237
|
result = @client.execute(no_results_query)
|
239
|
-
_(result.fields).must_equal ['id','varchar_50']
|
238
|
+
_(result.fields).must_equal ['id', 'varchar_50']
|
240
239
|
result.each
|
241
|
-
_(result.fields).must_equal ['id','varchar_50']
|
240
|
+
_(result.fields).must_equal ['id', 'varchar_50']
|
242
241
|
# Each then fields
|
243
242
|
result = @client.execute(no_results_query)
|
244
243
|
result.each
|
245
|
-
_(result.fields).must_equal ['id','varchar_50']
|
244
|
+
_(result.fields).must_equal ['id', 'varchar_50']
|
246
245
|
end
|
247
246
|
|
248
247
|
it 'allows the result to be canceled before reading' do
|
@@ -307,7 +306,7 @@ class ResultTest < TinyTds::TestCase
|
|
307
306
|
|
308
307
|
it 'use same string object for hash keys' do
|
309
308
|
data = @client.execute("SELECT [id], [bigint] FROM [datatypes]").each
|
310
|
-
assert_equal data.first.keys.map{ |r| r.object_id }, data.last.keys.map{ |r| r.object_id }
|
309
|
+
assert_equal data.first.keys.map { |r| r.object_id }, data.last.keys.map { |r| r.object_id }
|
311
310
|
end
|
312
311
|
|
313
312
|
it 'has properly encoded column names with symbol keys' do
|
@@ -326,7 +325,7 @@ class ResultTest < TinyTds::TestCase
|
|
326
325
|
it 'allows #return_code to work with stored procedures and reset per sql batch' do
|
327
326
|
assert_nil @client.return_code
|
328
327
|
result = @client.execute("EXEC tinytds_TestReturnCodes")
|
329
|
-
assert_equal [{"one"=>1}], result.each
|
328
|
+
assert_equal [{ "one" => 1 }], result.each
|
330
329
|
assert_equal 420, @client.return_code
|
331
330
|
assert_equal 420, result.return_code
|
332
331
|
result = @client.execute('SELECT 1 as [one]')
|
@@ -343,7 +342,7 @@ class ResultTest < TinyTds::TestCase
|
|
343
342
|
describe 'with multiple result sets' do
|
344
343
|
|
345
344
|
before do
|
346
|
-
@empty_select
|
345
|
+
@empty_select = "SELECT 1 AS [rs1] WHERE 1 = 0"
|
347
346
|
@double_select = "SELECT 1 AS [rs1]
|
348
347
|
SELECT 2 AS [rs2]"
|
349
348
|
@triple_select_1st_empty = "SELECT 1 AS [rs1] WHERE 1 = 0
|
@@ -361,8 +360,8 @@ class ResultTest < TinyTds::TestCase
|
|
361
360
|
result = @client.execute(@double_select)
|
362
361
|
result_sets = result.each
|
363
362
|
assert_equal 2, result_sets.size
|
364
|
-
assert_equal [{'rs1' => 1}], result_sets.first
|
365
|
-
assert_equal [{'rs2' => 2}], result_sets.last
|
363
|
+
assert_equal [{ 'rs1' => 1 }], result_sets.first
|
364
|
+
assert_equal [{ 'rs2' => 2 }], result_sets.last
|
366
365
|
assert_equal [['rs1'], ['rs2']], result.fields
|
367
366
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
368
367
|
# As array
|
@@ -383,20 +382,12 @@ class ResultTest < TinyTds::TestCase
|
|
383
382
|
end
|
384
383
|
|
385
384
|
it 'works from a stored procedure' do
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
assert constraint_info.key?("constraint_name")
|
393
|
-
elsif sybase_ase?
|
394
|
-
results1, results2 = @client.execute("EXEC sp_helpconstraint 'datatypes'").each
|
395
|
-
assert results1['name'] =~ /^datatypes_bit/
|
396
|
-
assert results1['defintion'] == 'DEFAULT 0'
|
397
|
-
assert results2['name'] =~ /^datatypes_id/
|
398
|
-
assert results2['defintion'] =~ /^PRIMARY KEY/
|
399
|
-
end
|
385
|
+
results1, results2 = @client.execute("EXEC sp_helpconstraint '[datatypes]'").each
|
386
|
+
assert_equal [{ "Object Name" => "[datatypes]" }], results1
|
387
|
+
constraint_info = results2.first
|
388
|
+
assert constraint_info.key?("constraint_keys")
|
389
|
+
assert constraint_info.key?("constraint_type")
|
390
|
+
assert constraint_info.key?("constraint_name")
|
400
391
|
end
|
401
392
|
|
402
393
|
describe 'using :empty_sets TRUE' do
|
@@ -423,8 +414,8 @@ class ResultTest < TinyTds::TestCase
|
|
423
414
|
result_sets = result.each
|
424
415
|
assert_equal 3, result_sets.size
|
425
416
|
assert_equal [], result_sets[0]
|
426
|
-
assert_equal [{'rs2' => 2}], result_sets[1]
|
427
|
-
assert_equal [{'rs3' => 3}], result_sets[2]
|
417
|
+
assert_equal [{ 'rs2' => 2 }], result_sets[1]
|
418
|
+
assert_equal [{ 'rs3' => 3 }], result_sets[2]
|
428
419
|
assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields
|
429
420
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
430
421
|
# As array
|
@@ -442,9 +433,9 @@ class ResultTest < TinyTds::TestCase
|
|
442
433
|
result = @client.execute(@triple_select_2nd_empty)
|
443
434
|
result_sets = result.each
|
444
435
|
assert_equal 3, result_sets.size
|
445
|
-
assert_equal [{'rs1' => 1}], result_sets[0]
|
436
|
+
assert_equal [{ 'rs1' => 1 }], result_sets[0]
|
446
437
|
assert_equal [], result_sets[1]
|
447
|
-
assert_equal [{'rs3' => 3}], result_sets[2]
|
438
|
+
assert_equal [{ 'rs3' => 3 }], result_sets[2]
|
448
439
|
assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields
|
449
440
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
450
441
|
# As array
|
@@ -462,8 +453,8 @@ class ResultTest < TinyTds::TestCase
|
|
462
453
|
result = @client.execute(@triple_select_3rd_empty)
|
463
454
|
result_sets = result.each
|
464
455
|
assert_equal 3, result_sets.size
|
465
|
-
assert_equal [{'rs1' => 1}], result_sets[0]
|
466
|
-
assert_equal [{'rs2' => 2}], result_sets[1]
|
456
|
+
assert_equal [{ 'rs1' => 1 }], result_sets[0]
|
457
|
+
assert_equal [{ 'rs2' => 2 }], result_sets[1]
|
467
458
|
assert_equal [], result_sets[2]
|
468
459
|
assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields
|
469
460
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
@@ -503,8 +494,8 @@ class ResultTest < TinyTds::TestCase
|
|
503
494
|
result = @client.execute(@triple_select_1st_empty)
|
504
495
|
result_sets = result.each
|
505
496
|
assert_equal 2, result_sets.size
|
506
|
-
assert_equal [{'rs2' => 2}], result_sets[0]
|
507
|
-
assert_equal [{'rs3' => 3}], result_sets[1]
|
497
|
+
assert_equal [{ 'rs2' => 2 }], result_sets[0]
|
498
|
+
assert_equal [{ 'rs3' => 3 }], result_sets[1]
|
508
499
|
assert_equal [['rs2'], ['rs3']], result.fields
|
509
500
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
510
501
|
# As array
|
@@ -521,8 +512,8 @@ class ResultTest < TinyTds::TestCase
|
|
521
512
|
result = @client.execute(@triple_select_2nd_empty)
|
522
513
|
result_sets = result.each
|
523
514
|
assert_equal 2, result_sets.size
|
524
|
-
assert_equal [{'rs1' => 1}], result_sets[0]
|
525
|
-
assert_equal [{'rs3' => 3}], result_sets[1]
|
515
|
+
assert_equal [{ 'rs1' => 1 }], result_sets[0]
|
516
|
+
assert_equal [{ 'rs3' => 3 }], result_sets[1]
|
526
517
|
assert_equal [['rs1'], ['rs3']], result.fields
|
527
518
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
528
519
|
# As array
|
@@ -539,8 +530,8 @@ class ResultTest < TinyTds::TestCase
|
|
539
530
|
result = @client.execute(@triple_select_3rd_empty)
|
540
531
|
result_sets = result.each
|
541
532
|
assert_equal 2, result_sets.size
|
542
|
-
assert_equal [{'rs1' => 1}], result_sets[0]
|
543
|
-
assert_equal [{'rs2' => 2}], result_sets[1]
|
533
|
+
assert_equal [{ 'rs1' => 1 }], result_sets[0]
|
534
|
+
assert_equal [{ 'rs2' => 2 }], result_sets[1]
|
544
535
|
assert_equal [['rs1'], ['rs2']], result.fields
|
545
536
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
546
537
|
# As array
|
@@ -590,7 +581,7 @@ class ResultTest < TinyTds::TestCase
|
|
590
581
|
before do
|
591
582
|
@big_text = 'x' * 2_000_000
|
592
583
|
@old_textsize = @client.execute("SELECT @@TEXTSIZE AS [textsize]").each.first['textsize'].inspect
|
593
|
-
@client.execute("SET TEXTSIZE #{(@big_text.length*2)+1}").do
|
584
|
+
@client.execute("SET TEXTSIZE #{(@big_text.length * 2) + 1}").do
|
594
585
|
end
|
595
586
|
|
596
587
|
it 'must insert and select large varchar_max' do
|
@@ -601,7 +592,7 @@ class ResultTest < TinyTds::TestCase
|
|
601
592
|
insert_and_select_datatype :nvarchar_max
|
602
593
|
end
|
603
594
|
|
604
|
-
end
|
595
|
+
end
|
605
596
|
|
606
597
|
end
|
607
598
|
|
@@ -612,189 +603,105 @@ class ResultTest < TinyTds::TestCase
|
|
612
603
|
assert_equal [], @client.execute('').each
|
613
604
|
end
|
614
605
|
|
615
|
-
|
606
|
+
describe 'using :message_handler option' do
|
607
|
+
let(:messages) { Array.new }
|
616
608
|
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
close_client
|
622
|
-
@client = new_connection message_handler: Proc.new { |m| messages << m }
|
623
|
-
end
|
624
|
-
|
625
|
-
after do
|
626
|
-
messages.clear
|
627
|
-
end
|
609
|
+
before do
|
610
|
+
close_client
|
611
|
+
@client = new_connection message_handler: Proc.new { |m| messages << m }
|
612
|
+
end
|
628
613
|
|
629
|
-
|
630
|
-
|
631
|
-
|
614
|
+
after do
|
615
|
+
messages.clear
|
616
|
+
end
|
632
617
|
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
msg = "Test #{severity} severity"
|
637
|
-
state = rand(1..255)
|
638
|
-
@client.execute("RAISERROR(N'#{msg}', #{severity}, #{state})").do
|
639
|
-
m = messages.first
|
640
|
-
assert_equal 1, messages.length, 'there should be one message after one raiserror'
|
641
|
-
assert_equal msg, m.message, 'message text'
|
642
|
-
assert_equal severity, m.severity, 'message severity' unless severity == 10 && m.severity.to_i == 0
|
643
|
-
assert_equal state, m.os_error_number, 'message state'
|
644
|
-
end
|
645
|
-
end
|
618
|
+
it 'has a message handler that responds to call' do
|
619
|
+
assert @client.message_handler.respond_to?(:call)
|
620
|
+
end
|
646
621
|
|
647
|
-
|
622
|
+
it 'calls the provided message handler when severity is 10 or less' do
|
623
|
+
(1..10).to_a.each do |severity|
|
648
624
|
messages.clear
|
649
|
-
msg =
|
650
|
-
|
625
|
+
msg = "Test #{severity} severity"
|
626
|
+
state = rand(1..255)
|
627
|
+
@client.execute("RAISERROR(N'#{msg}', #{severity}, #{state})").do
|
651
628
|
m = messages.first
|
652
|
-
assert_equal 1, messages.length, 'there should be one message after one
|
629
|
+
assert_equal 1, messages.length, 'there should be one message after one raiserror'
|
653
630
|
assert_equal msg, m.message, 'message text'
|
654
|
-
|
655
|
-
|
656
|
-
it 'must raise an error preceded by a `print` message' do
|
657
|
-
messages.clear
|
658
|
-
action = lambda { @client.execute("EXEC tinytds_TestPrintWithError").do }
|
659
|
-
assert_raise_tinytds_error(action) do |e|
|
660
|
-
assert_equal 'hello', messages.first.message, 'message text'
|
661
|
-
|
662
|
-
assert_equal "Error following print", e.message
|
663
|
-
assert_equal 16, e.severity
|
664
|
-
assert_equal 50000, e.db_error_number
|
665
|
-
end
|
666
|
-
end
|
667
|
-
|
668
|
-
it 'calls the provided message handler for each of a series of `print` messages' do
|
669
|
-
messages.clear
|
670
|
-
@client.execute("EXEC tinytds_TestSeveralPrints").do
|
671
|
-
assert_equal ['hello 1', 'hello 2', 'hello 3'], messages.map { |e| e.message }, 'message list'
|
672
|
-
end
|
673
|
-
|
674
|
-
it 'should flush info messages before raising error in cases of timeout' do
|
675
|
-
@client = new_connection timeout: 1, message_handler: Proc.new { |m| messages << m }
|
676
|
-
action = lambda { @client.execute("print 'hello'; waitfor delay '00:00:02'").do }
|
677
|
-
messages.clear
|
678
|
-
assert_raise_tinytds_error(action) do |e|
|
679
|
-
assert_match %r{timed out}i, e.message, 'ignore if non-english test run'
|
680
|
-
assert_equal 6, e.severity
|
681
|
-
assert_equal 20003, e.db_error_number
|
682
|
-
assert_equal 'hello', messages.first&.message, 'message text'
|
683
|
-
end
|
684
|
-
end
|
685
|
-
|
686
|
-
it 'should print info messages before raising error in cases of timeout' do
|
687
|
-
@client = new_connection timeout: 1, message_handler: Proc.new { |m| messages << m }
|
688
|
-
action = lambda { @client.execute("raiserror('hello', 1, 1) with nowait; waitfor delay '00:00:02'").do }
|
689
|
-
messages.clear
|
690
|
-
assert_raise_tinytds_error(action) do |e|
|
691
|
-
assert_match %r{timed out}i, e.message, 'ignore if non-english test run'
|
692
|
-
assert_equal 6, e.severity
|
693
|
-
assert_equal 20003, e.db_error_number
|
694
|
-
assert_equal 'hello', messages.first&.message, 'message text'
|
695
|
-
end
|
631
|
+
assert_equal severity, m.severity, 'message severity' unless severity == 10 && m.severity.to_i == 0
|
632
|
+
assert_equal state, m.os_error_number, 'message state'
|
696
633
|
end
|
697
634
|
end
|
698
635
|
|
699
|
-
it '
|
700
|
-
|
701
|
-
|
702
|
-
|
636
|
+
it 'calls the provided message handler for `print` messages' do
|
637
|
+
messages.clear
|
638
|
+
msg = 'hello'
|
639
|
+
@client.execute("PRINT '#{msg}'").do
|
640
|
+
m = messages.first
|
641
|
+
assert_equal 1, messages.length, 'there should be one message after one print statement'
|
642
|
+
assert_equal msg, m.message, 'message text'
|
703
643
|
end
|
704
644
|
|
705
|
-
it '
|
706
|
-
|
645
|
+
it 'must raise an error preceded by a `print` message' do
|
646
|
+
messages.clear
|
647
|
+
action = lambda { @client.execute("EXEC tinytds_TestPrintWithError").do }
|
707
648
|
assert_raise_tinytds_error(action) do |e|
|
708
|
-
assert_equal
|
709
|
-
|
649
|
+
assert_equal 'hello', messages.first.message, 'message text'
|
650
|
+
|
651
|
+
assert_equal "Error following print", e.message
|
652
|
+
assert_equal 16, e.severity
|
710
653
|
assert_equal 50000, e.db_error_number
|
711
654
|
end
|
712
655
|
end
|
713
656
|
|
714
|
-
|
657
|
+
it 'calls the provided message handler for each of a series of `print` messages' do
|
658
|
+
messages.clear
|
659
|
+
@client.execute("EXEC tinytds_TestSeveralPrints").do
|
660
|
+
assert_equal ['hello 1', 'hello 2', 'hello 3'], messages.map { |e| e.message }, 'message list'
|
661
|
+
end
|
715
662
|
|
716
|
-
it '
|
717
|
-
|
663
|
+
it 'should flush info messages before raising error in cases of timeout' do
|
664
|
+
@client = new_connection timeout: 1, message_handler: Proc.new { |m| messages << m }
|
665
|
+
action = lambda { @client.execute("print 'hello'; waitfor delay '00:00:02'").do }
|
666
|
+
messages.clear
|
718
667
|
assert_raise_tinytds_error(action) do |e|
|
719
|
-
|
720
|
-
assert_equal
|
721
|
-
assert_equal
|
668
|
+
assert_match %r{timed out}i, e.message, 'ignore if non-english test run'
|
669
|
+
assert_equal 6, e.severity
|
670
|
+
assert_equal 20003, e.db_error_number
|
671
|
+
assert_equal 'hello', messages.first&.message, 'message text'
|
722
672
|
end
|
723
|
-
assert_followup_query
|
724
673
|
end
|
725
674
|
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
675
|
+
it 'should print info messages before raising error in cases of timeout' do
|
676
|
+
@client = new_connection timeout: 1, message_handler: Proc.new { |m| messages << m }
|
677
|
+
action = lambda { @client.execute("raiserror('hello', 1, 1) with nowait; waitfor delay '00:00:02'").do }
|
678
|
+
messages.clear
|
679
|
+
assert_raise_tinytds_error(action) do |e|
|
680
|
+
assert_match %r{timed out}i, e.message, 'ignore if non-english test run'
|
681
|
+
assert_equal 6, e.severity
|
682
|
+
assert_equal 20003, e.db_error_number
|
683
|
+
assert_equal 'hello', messages.first&.message, 'message text'
|
684
|
+
end
|
735
685
|
end
|
736
686
|
end
|
737
687
|
|
738
|
-
it 'must error
|
739
|
-
|
740
|
-
|
741
|
-
pattern = sybase_ase? ? /foobar not found/ : %r|invalid object name.*foobar|i
|
742
|
-
assert_match pattern, e.message
|
743
|
-
assert_equal 16, e.severity
|
744
|
-
assert_equal 208, e.db_error_number
|
688
|
+
it 'must not raise an error when severity is 10 or less' do
|
689
|
+
(1..10).to_a.each do |severity|
|
690
|
+
@client.execute("RAISERROR(N'Test #{severity} severity', #{severity}, 1)").do
|
745
691
|
end
|
746
|
-
assert_followup_query
|
747
692
|
end
|
748
693
|
|
749
|
-
it '
|
750
|
-
action = lambda { @client.execute('
|
694
|
+
it 'raises an error when severity is greater than 10' do
|
695
|
+
action = lambda { @client.execute("RAISERROR(N'Test 11 severity', 11, 1)").do }
|
751
696
|
assert_raise_tinytds_error(action) do |e|
|
752
|
-
|
753
|
-
assert_equal
|
754
|
-
assert_equal
|
697
|
+
assert_equal "Test 11 severity", e.message
|
698
|
+
assert_equal 11, e.severity
|
699
|
+
assert_equal 50000, e.db_error_number
|
755
700
|
end
|
756
|
-
assert_followup_query
|
757
701
|
end
|
758
|
-
|
759
|
-
it 'must not error at all from reading non-convertable charcters and just use ? marks' do
|
760
|
-
close_client
|
761
|
-
@client = new_connection :encoding => 'ASCII'
|
762
|
-
_(@client.charset).must_equal 'ASCII'
|
763
|
-
_(find_value(202, :nvarchar_50)).must_equal 'test nvarchar_50 ??'
|
764
|
-
end
|
765
|
-
|
766
|
-
it 'must error gracefully from writing non-convertable characters' do
|
767
|
-
close_client
|
768
|
-
@client = new_connection :encoding => 'ASCII'
|
769
|
-
_(@client.charset).must_equal 'ASCII'
|
770
|
-
rollback_transaction(@client) do
|
771
|
-
text = 'Test ✓'
|
772
|
-
@client.execute("DELETE FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").do
|
773
|
-
action = lambda { @client.execute("INSERT INTO [datatypes] ([nvarchar_50]) VALUES ('#{text}')").do }
|
774
|
-
assert_raise_tinytds_error(action) do |e|
|
775
|
-
_(e.message).must_match %r{Unclosed quotation mark}i
|
776
|
-
_(e.severity).must_equal 15
|
777
|
-
_(e.db_error_number).must_equal 105
|
778
|
-
end
|
779
|
-
assert_followup_query
|
780
|
-
end
|
781
|
-
end
|
782
|
-
|
783
|
-
it 'errors gracefully with incorrect syntax in sp_executesql' do
|
784
|
-
action = lambda { @client.execute("EXEC sp_executesql N'this will not work'").each }
|
785
|
-
assert_raise_tinytds_error(action) do |e|
|
786
|
-
assert_match %r|incorrect syntax|i, e.message
|
787
|
-
assert_equal 15, e.severity
|
788
|
-
assert_equal 156, e.db_error_number
|
789
|
-
end
|
790
|
-
assert_followup_query
|
791
|
-
end unless sybase_ase?
|
792
|
-
|
793
702
|
end
|
794
|
-
|
795
703
|
end
|
796
704
|
|
797
|
-
|
798
705
|
protected
|
799
706
|
|
800
707
|
def assert_followup_query
|