tiny_tds 2.1.7 → 3.0.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +470 -0
- data/CHANGELOG.md +10 -0
- data/ISSUE_TEMPLATE.md +1 -1
- data/README.md +25 -45
- data/Rakefile +1 -5
- 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 +3 -2
- metadata +23 -14
- data/.circleci/config.yml +0 -409
- 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
|