tiny_tds 2.1.6-x64-mingw-ucrt → 3.0.0-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +470 -0
  3. data/CHANGELOG.md +13 -0
  4. data/ISSUE_TEMPLATE.md +1 -1
  5. data/README.md +25 -45
  6. data/Rakefile +2 -6
  7. data/VERSION +1 -1
  8. data/docker-compose.yml +2 -2
  9. data/ext/tiny_tds/client.c +8 -15
  10. data/ext/tiny_tds/extconf.rb +1 -2
  11. data/ext/tiny_tds/extconsts.rb +4 -10
  12. data/ext/tiny_tds/result.c +27 -35
  13. data/ext/tiny_tds/tiny_tds_ext.c +4 -1
  14. data/lib/tiny_tds/3.1/tiny_tds.so +0 -0
  15. data/lib/tiny_tds/3.2/tiny_tds.so +0 -0
  16. data/lib/tiny_tds/3.3/tiny_tds.so +0 -0
  17. data/ports/x64-mingw-ucrt/freetds/{1.1.24 → 1.4.23}/bin/bsqldb.exe +0 -0
  18. data/ports/x64-mingw-ucrt/freetds/{1.1.24 → 1.4.23}/bin/datacopy.exe +0 -0
  19. data/ports/x64-mingw-ucrt/freetds/{1.1.24 → 1.4.23}/bin/defncopy.exe +0 -0
  20. data/ports/x64-mingw-ucrt/freetds/{1.1.24 → 1.4.23}/bin/freebcp.exe +0 -0
  21. data/ports/x64-mingw-ucrt/freetds/1.4.23/bin/libct-4.dll +0 -0
  22. data/ports/x64-mingw-ucrt/freetds/1.4.23/bin/libsybdb-5.dll +0 -0
  23. data/ports/x64-mingw-ucrt/freetds/{1.1.24 → 1.4.23}/bin/osql +84 -79
  24. data/ports/x64-mingw-ucrt/freetds/1.4.23/bin/tdspool.exe +0 -0
  25. data/ports/x64-mingw-ucrt/freetds/1.4.23/bin/tsql.exe +0 -0
  26. data/ports/x64-mingw-ucrt/freetds/{1.1.24 → 1.4.23}/lib/libct.la +3 -3
  27. data/ports/x64-mingw-ucrt/freetds/{1.1.24 → 1.4.23}/lib/libsybdb.la +3 -3
  28. data/ports/x64-mingw-ucrt/libiconv/{1.15 → 1.17}/bin/iconv.exe +0 -0
  29. data/ports/x64-mingw-ucrt/libiconv/{1.15 → 1.17}/bin/libcharset-1.dll +0 -0
  30. data/ports/x64-mingw-ucrt/libiconv/{1.15 → 1.17}/bin/libiconv-2.dll +0 -0
  31. data/ports/x64-mingw-ucrt/libiconv/{1.15 → 1.17}/lib/libcharset.dll.a +0 -0
  32. data/ports/x64-mingw-ucrt/libiconv/{1.15 → 1.17}/lib/libcharset.la +3 -3
  33. data/ports/x64-mingw-ucrt/libiconv/{1.15 → 1.17}/lib/libiconv.dll.a +0 -0
  34. data/ports/x64-mingw-ucrt/libiconv/{1.15 → 1.17}/lib/libiconv.la +4 -4
  35. data/ports/x64-mingw-ucrt/openssl/{1.1.1s → 3.4.0}/bin/c_rehash +46 -45
  36. data/ports/x64-mingw-ucrt/openssl/3.4.0/bin/libcrypto-3-x64.dll +0 -0
  37. data/ports/x64-mingw-ucrt/openssl/3.4.0/bin/libssl-3-x64.dll +0 -0
  38. data/ports/x64-mingw-ucrt/openssl/3.4.0/bin/openssl.exe +0 -0
  39. data/tasks/ports/freetds.rb +1 -6
  40. data/tasks/ports.rake +2 -2
  41. data/test/bin/install-mssql.ps1 +22 -11
  42. data/test/client_test.rb +2 -5
  43. data/test/gem_test.rb +0 -1
  44. data/test/result_test.rb +99 -192
  45. data/test/schema_test.rb +366 -388
  46. data/test/test_helper.rb +6 -37
  47. data/tiny_tds.gemspec +4 -3
  48. metadata +49 -44
  49. data/.circleci/config.yml +0 -407
  50. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/libct-4.dll +0 -0
  51. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/libsybdb-5.dll +0 -0
  52. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/tdspool.exe +0 -0
  53. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/tsql.exe +0 -0
  54. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/charset.alias +0 -4
  55. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/libcrypto-1_1-x64.dll +0 -0
  56. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/libssl-1_1-x64.dll +0 -0
  57. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/openssl.exe +0 -0
  58. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libcrypto.a +0 -0
  59. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libcrypto.dll.a +0 -0
  60. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libssl.a +0 -0
  61. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libssl.dll.a +0 -0
  62. data/test/schema/sqlserver_2000.sql +0 -140
  63. data/test/schema/sqlserver_2005.sql +0 -140
  64. data/test/schema/sqlserver_2014.sql +0 -140
  65. data/test/schema/sqlserver_2016.sql +0 -140
  66. data/test/schema/sybase_ase.sql +0 -138
  67. /data/ports/x64-mingw-ucrt/freetds/{1.1.24 → 1.4.23}/lib/libct.dll.a +0 -0
  68. /data/ports/x64-mingw-ucrt/freetds/{1.1.24 → 1.4.23}/lib/libsybdb.dll.a +0 -0
  69. /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' unless sqlserver_2000? # Will report -1
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' unless sqlserver_2000? # Will report -1
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
- return if sybase_ase? # On Sybase, sp_helpindex cannot be used inside a transaction since it does a
187
- # 'CREATE TABLE' command is not allowed within a multi-statement transaction
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 = "SELECT 1 AS [rs1] WHERE 1 = 0"
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
- if sqlserver?
387
- results1, results2 = @client.execute("EXEC sp_helpconstraint '[datatypes]'").each
388
- assert_equal [{"Object Name"=>"[datatypes]"}], results1
389
- constraint_info = results2.first
390
- assert constraint_info.key?("constraint_keys")
391
- assert constraint_info.key?("constraint_type")
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 unless sqlserver_2000? || sybase_ase?
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
- if sqlserver?
606
+ describe 'using :message_handler option' do
607
+ let(:messages) { Array.new }
616
608
 
617
- describe 'using :message_handler option' do
618
- let(:messages) { Array.new }
619
-
620
- before do
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
- it 'has a message handler that responds to call' do
630
- assert @client.message_handler.respond_to?(:call)
631
- end
614
+ after do
615
+ messages.clear
616
+ end
632
617
 
633
- it 'calls the provided message handler when severity is 10 or less' do
634
- (1..10).to_a.each do |severity|
635
- messages.clear
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
- it 'calls the provided message handler for `print` messages' do
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 = 'hello'
650
- @client.execute("PRINT '#{msg}'").do
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 print statement'
629
+ assert_equal 1, messages.length, 'there should be one message after one raiserror'
653
630
  assert_equal msg, m.message, 'message text'
654
- end
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 'must not raise an error when severity is 10 or less' do
700
- (1..10).to_a.each do |severity|
701
- @client.execute("RAISERROR(N'Test #{severity} severity', #{severity}, 1)").do
702
- end
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 'raises an error when severity is greater than 10' do
706
- action = lambda { @client.execute("RAISERROR(N'Test 11 severity', 11, 1)").do }
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 "Test 11 severity", e.message
709
- assert_equal 11, e.severity
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
- else
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 'raises an error' do
717
- action = lambda { @client.execute("RAISERROR 50000 N'Hello World'").do }
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
- assert_equal "Hello World", e.message
720
- assert_equal 16, e.severity # predefined on ASE
721
- assert_equal 50000, e.db_error_number
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
- end
727
-
728
- it 'throws an error when you execute another query with other results pending' do
729
- @client.execute(@query1)
730
- action = lambda { @client.execute(@query1) }
731
- assert_raise_tinytds_error(action) do |e|
732
- assert_match %r|with results pending|i, e.message
733
- assert_equal 7, e.severity
734
- assert_equal 20019, e.db_error_number
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 gracefully with bad table name' do
739
- action = lambda { @client.execute('SELECT * FROM [foobar]').each }
740
- assert_raise_tinytds_error(action) do |e|
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 'must error gracefully with incorrect syntax' do
750
- action = lambda { @client.execute('this will not work').each }
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
- assert_match %r|incorrect syntax|i, e.message
753
- assert_equal 15, e.severity
754
- assert_equal 156, e.db_error_number
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