tiny_tds 0.5.1 → 0.5.2.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -0
- data/Gemfile +3 -11
- data/README.md +13 -2
- data/ext/tiny_tds/client.c +3 -0
- data/lib/tiny_tds/version.rb +1 -1
- data/tasks/ports.rake +3 -3
- data/test/client_test.rb +21 -19
- data/test/result_test.rb +94 -72
- data/test/schema_test.rb +39 -39
- data/test/test_helper.rb +3 -3
- metadata +93 -11
data/CHANGELOG
CHANGED
@@ -1,4 +1,11 @@
|
|
1
1
|
|
2
|
+
* 0.5.2 *
|
3
|
+
|
4
|
+
* Move test system to real MiniTest::Spec. All tests pass on Azure too.
|
5
|
+
|
6
|
+
* Raise and handle encoding errors on DB writes. Fixes #89.
|
7
|
+
|
8
|
+
|
2
9
|
* 0.5.1 *
|
3
10
|
|
4
11
|
* Change how we configure with iconv, basically it is always needed. Fixes #11 & #69.
|
data/Gemfile
CHANGED
@@ -1,14 +1,6 @@
|
|
1
|
-
|
2
1
|
source :rubygems
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
gem 'rake-compiler', '0.8.0'
|
8
|
-
end
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
gem 'm', :platform => :ruby_19
|
9
6
|
|
10
|
-
group :test do
|
11
|
-
gem 'mini_shoulda', '0.3.0'
|
12
|
-
gem 'activesupport', '2.3.5'
|
13
|
-
gem 'bench_press', '0.3.1'
|
14
|
-
end
|
data/README.md
CHANGED
@@ -33,7 +33,7 @@ Although we search for FreeTDS's libraries and headers, you may have to specify
|
|
33
33
|
|
34
34
|
TinyTDS is developed against FreeTDS 0.82 & 0.91, the latest is recommended. It is tested with SQL Server 2000, 2005, 2008 and Azure. Below are a few QA style notes about installing FreeTDS.
|
35
35
|
|
36
|
-
* **Do I need to install FreeTDS?** Yes! Somehow, someway,
|
36
|
+
* **Do I need to install FreeTDS?** Yes! Somehow, someway, you are going to need FreeTDS for TinyTDS to compile against. You can avoid installing FreeTDS on your system by using our projects usage of rake-compiler and mini_portile to compile and package a native gem just for you. See the "Using MiniPortile" section below.
|
37
37
|
|
38
38
|
* **OK, I am installing FreeTDS, how do I configure it?** Contrary to what most people think, you do not need to specially configure FreeTDS in any way for client libraries like TinyTDS to use it. About the only requirement is that you compile it with libiconv for proper encoding support. FreeTDS must also be compiled with OpenSSL (or the like) to use it with Azure. See the "Using TinyTDS with Azure" section below for more info.
|
39
39
|
|
@@ -68,7 +68,7 @@ Creating a new client takes a hash of options. For valid iconv encoding options,
|
|
68
68
|
|
69
69
|
* :username - The database server user.
|
70
70
|
* :password - The user password.
|
71
|
-
* :dataserver -
|
71
|
+
* :dataserver - Can be the name for your data server as defined in freetds.conf. Raw hostname or hostname:port will work here too. FreeTDS says that named instance like 'localhost\SQLEXPRESS' work too, but I highly suggest that you use the :host and :port options below. [Google how to find your host port if you are using named instances](http://bit.ly/xAf2jm) or [go here](http://msdn.microsoft.com/en-us/library/ms181087.aspx).
|
72
72
|
* :host - Used if :dataserver blank. Can be an host name or IP.
|
73
73
|
* :port - Defaults to 1433. Only used if :host is used.
|
74
74
|
* :database - The default database to use.
|
@@ -259,6 +259,10 @@ result.each(:first => true) # => [{'id' => 24}]
|
|
259
259
|
By default row caching is turned on because the SQL Server adapter for ActiveRecord would not work without it. I hope to find some time to create some performance patches for ActiveRecord that would allow it to take advantages of lazily created yielded rows from result objects. Currently only TinyTDS and the Mysql2 gem allow such a performance gain.
|
260
260
|
|
261
261
|
|
262
|
+
## Encoding Error Handling
|
263
|
+
|
264
|
+
TinyTDS takes an opinionated stance on how we handle encoding errors. First, we treat errors differently on reads vs. writes. Our opinion is that if you are reading bad data due to your client's encoding option, you would rather just find `?`'marks in your strings vs being blocked with exceptions. This is how things wold work via ODBC or SMS. On the other hand, writes will raise an exception. In this case we raise the SYBEICONVO/2402 error message which has a description of `Error converting characters into server's character set. Some character(s) could not be converted.`. Even though the severity of this message is only a `4` and TinyTDS will automatically strip/ignore unknown characters, we feel you should know that you are inserting bad encodings. In this way, a transaction can be rolled back, etc. Remember, any database write that has bad characters due to the client encoding will still be written to the database, but it is up to you rollback said write if needed. Most ORMs like ActiveRecord handle this scenario just fine.
|
265
|
+
|
262
266
|
|
263
267
|
## Using TinyTDS With Rails & The ActiveRecord SQL Server adapter.
|
264
268
|
|
@@ -272,6 +276,8 @@ As of version 2.3.11 & 3.0.3 of the adapter, you can specify a `:dblib` mode in
|
|
272
276
|
|
273
277
|
TinyTDS is fully tested with the Azure platform. You must set the `:azure => true` connection option when connecting. This is needed to specify the default database name in the login packet since Azure has no notion of `USE [database]`. You must use the latest FreeTDS 0.91. FreeTDS must be compiled with OpenSSL too.
|
274
278
|
|
279
|
+
IMPORTANT: Do not use `username@server.database.windows.net` for the username connection option! You must use the shorter `username@server` instead!
|
280
|
+
|
275
281
|
|
276
282
|
## Using MiniPortile
|
277
283
|
|
@@ -338,6 +344,11 @@ My name is Ken Collins and I currently maintain the SQL Server adapter for Activ
|
|
338
344
|
* Josh Clayton of Thoughtbot for writing about ruby C extensions. - http://robots.thoughtbot.com/post/1037240922/get-your-c-on
|
339
345
|
|
340
346
|
|
347
|
+
## Donators
|
348
|
+
|
349
|
+
I am trying to save up for a Happy Hacking pro keyboard. Help me out via GitTip! https://www.gittip.com/metaskills/
|
350
|
+
|
351
|
+
|
341
352
|
## License
|
342
353
|
|
343
354
|
TinyTDS is Copyright (c) 2010-2011 Ken Collins, <ken@metaskills.net> and is distributed under the MIT license. Windows binaries contain precompiled versions of FreeTDS <http://www.freetds.org/> which is licensed under the GNU LGPL license at <http://www.gnu.org/licenses/lgpl-2.0.html>
|
data/ext/tiny_tds/client.c
CHANGED
data/lib/tiny_tds/version.rb
CHANGED
data/tasks/ports.rake
CHANGED
@@ -8,9 +8,9 @@ namespace :ports do
|
|
8
8
|
ICONV_VERSION = "1.13.1"
|
9
9
|
FREETDS_VERSION = ENV['TINYTDS_FREETDS_082'] ? "0.82" : "0.91"
|
10
10
|
FREETDS_VERSION_INFO = {
|
11
|
-
"0.82" => {:files => "http://ibiblio.org/
|
12
|
-
# "0.82" => {:files => "http://ibiblio.org/
|
13
|
-
"0.91" => {:files => "http://ibiblio.org/
|
11
|
+
"0.82" => {:files => "http://mirrors.ibiblio.org/freetds/old/0.82/freetds-0.82.tar.gz"},
|
12
|
+
# "0.82" => {:files => "http://mirrors.ibiblio.org/freetds/old/0.82/freetds-patched.tgz"},
|
13
|
+
"0.91" => {:files => "http://mirrors.ibiblio.org/freetds/stable/freetds-0.91.tar.gz"} }
|
14
14
|
|
15
15
|
directory "ports"
|
16
16
|
|
data/test/client_test.rb
CHANGED
@@ -1,19 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'test_helper'
|
2
3
|
|
3
4
|
class ClientTest < TinyTds::TestCase
|
4
5
|
|
5
|
-
|
6
|
+
describe 'With valid credentials' do
|
6
7
|
|
7
|
-
|
8
|
+
before do
|
8
9
|
@client = new_connection
|
9
10
|
end
|
10
11
|
|
11
|
-
|
12
|
+
it 'must not be closed' do
|
12
13
|
assert !@client.closed?
|
13
14
|
assert @client.active?
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
+
it 'allows client connection to be closed' do
|
17
18
|
assert @client.close
|
18
19
|
assert @client.closed?
|
19
20
|
assert !@client.active?
|
@@ -23,21 +24,21 @@ class ClientTest < TinyTds::TestCase
|
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
+
it 'has getters for the tds version information (brittle since conf takes precedence)' do
|
27
28
|
assert_equal 9, @client.tds_version
|
28
29
|
assert_equal 'DBTDS_7_1 - Microsoft SQL Server 2000', @client.tds_version_info
|
29
30
|
end
|
30
31
|
|
31
|
-
|
32
|
+
it 'uses UTF-8 client charset/encoding by default' do
|
32
33
|
assert_equal 'UTF-8', @client.charset
|
33
34
|
assert_equal Encoding.find('UTF-8'), @client.encoding if ruby19?
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
+
it 'has a #escape method used for quote strings' do
|
37
38
|
assert_equal "''hello''", @client.escape("'hello'")
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
+
it 'allows valid iconv character set' do
|
41
42
|
['CP850', 'CP1252', 'ISO-8859-1'].each do |encoding|
|
42
43
|
client = new_connection(:encoding => encoding)
|
43
44
|
assert_equal encoding, client.charset
|
@@ -45,23 +46,23 @@ class ClientTest < TinyTds::TestCase
|
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
|
-
|
49
|
+
it 'must be able to use :host/:port connection' do
|
49
50
|
client = new_connection :dataserver => nil, :host => ENV['TINYTDS_UNIT_HOST'], :port => ENV['TINYTDS_UNIT_PORT'] || 1433
|
50
51
|
end unless sqlserver_azure?
|
51
52
|
|
52
53
|
end
|
53
54
|
|
54
|
-
|
55
|
+
describe 'With in-valid options' do
|
55
56
|
|
56
|
-
|
57
|
+
it 'raises an argument error when no :host given and :dataserver is blank' do
|
57
58
|
assert_raises(ArgumentError) { new_connection :dataserver => nil, :host => nil }
|
58
59
|
end
|
59
60
|
|
60
|
-
|
61
|
+
it 'raises an argument error when no :username is supplied' do
|
61
62
|
assert_raises(ArgumentError) { TinyTds::Client.new :username => nil }
|
62
63
|
end
|
63
64
|
|
64
|
-
|
65
|
+
it 'raises TinyTds exception with undefined :dataserver' do
|
65
66
|
options = connection_options :login_timeout => 1, :dataserver => '127.0.0.2'
|
66
67
|
action = lambda { new_connection(options) }
|
67
68
|
assert_raise_tinytds_error(action) do |e|
|
@@ -72,7 +73,7 @@ class ClientTest < TinyTds::TestCase
|
|
72
73
|
assert_new_connections_work
|
73
74
|
end
|
74
75
|
|
75
|
-
|
76
|
+
it 'raises TinyTds exception with long query past :timeout option' do
|
76
77
|
client = new_connection :timeout => 1
|
77
78
|
action = lambda { client.execute("WaitFor Delay '00:00:02'").do }
|
78
79
|
assert_raise_tinytds_error(action) do |e|
|
@@ -84,14 +85,14 @@ class ClientTest < TinyTds::TestCase
|
|
84
85
|
assert_new_connections_work
|
85
86
|
end
|
86
87
|
|
87
|
-
|
88
|
+
it 'must not timeout per sql batch when not under transaction' do
|
88
89
|
client = new_connection :timeout => 2
|
89
90
|
client.execute("WaitFor Delay '00:00:01'").do
|
90
91
|
client.execute("WaitFor Delay '00:00:01'").do
|
91
92
|
client.execute("WaitFor Delay '00:00:01'").do
|
92
93
|
end
|
93
94
|
|
94
|
-
|
95
|
+
it 'must not timeout per sql batch when under transaction' do
|
95
96
|
client = new_connection :timeout => 2
|
96
97
|
begin
|
97
98
|
client.execute("BEGIN TRANSACTION").do
|
@@ -103,7 +104,8 @@ class ClientTest < TinyTds::TestCase
|
|
103
104
|
end
|
104
105
|
end
|
105
106
|
|
106
|
-
|
107
|
+
it 'must run this test to prove we account for dropped connections' do
|
108
|
+
skip
|
107
109
|
begin
|
108
110
|
client = new_connection :login_timeout => 2, :timeout => 2
|
109
111
|
assert_client_works(client)
|
@@ -129,7 +131,7 @@ class ClientTest < TinyTds::TestCase
|
|
129
131
|
end
|
130
132
|
end
|
131
133
|
|
132
|
-
|
134
|
+
it 'raises TinyTds exception with wrong :username' do
|
133
135
|
options = connection_options :username => 'willnotwork'
|
134
136
|
action = lambda { new_connection(options) }
|
135
137
|
assert_raise_tinytds_error(action) do |e|
|
@@ -144,7 +146,7 @@ class ClientTest < TinyTds::TestCase
|
|
144
146
|
assert_new_connections_work
|
145
147
|
end
|
146
148
|
|
147
|
-
|
149
|
+
it 'fails miserably with unknown encoding option' do
|
148
150
|
options = connection_options :encoding => 'ISO-WTF'
|
149
151
|
action = lambda { new_connection(options) }
|
150
152
|
assert_raise_tinytds_error(action) do |e|
|
data/test/result_test.rb
CHANGED
@@ -3,24 +3,24 @@ require 'test_helper'
|
|
3
3
|
|
4
4
|
class ResultTest < TinyTds::TestCase
|
5
5
|
|
6
|
-
|
6
|
+
describe 'Basic query and result' do
|
7
7
|
|
8
|
-
|
8
|
+
before do
|
9
9
|
@@current_schema_loaded ||= load_current_schema
|
10
10
|
@client = new_connection
|
11
11
|
@query1 = 'SELECT 1 AS [one]'
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
it 'has included Enumerable' do
|
15
15
|
assert TinyTds::Result.ancestors.include?(Enumerable)
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
it 'responds to #each' do
|
19
19
|
result = @client.execute(@query1)
|
20
20
|
assert result.respond_to?(:each)
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
it 'returns all results for #each with no block' do
|
24
24
|
result = @client.execute(@query1)
|
25
25
|
data = result.each
|
26
26
|
row = data.first
|
@@ -29,7 +29,7 @@ class ResultTest < TinyTds::TestCase
|
|
29
29
|
assert_instance_of Hash, row, 'hash is the default query option'
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
it 'returns all results for #each with a block yielding a row at a time' do
|
33
33
|
result = @client.execute(@query1)
|
34
34
|
data = result.each do |row|
|
35
35
|
assert_instance_of Hash, row, 'hash is the default query option'
|
@@ -37,7 +37,7 @@ class ResultTest < TinyTds::TestCase
|
|
37
37
|
assert_instance_of Array, data
|
38
38
|
end
|
39
39
|
|
40
|
-
|
40
|
+
it 'allows successive calls to each returning the same data' do
|
41
41
|
result = @client.execute(@query1)
|
42
42
|
data = result.each
|
43
43
|
result.each
|
@@ -45,7 +45,7 @@ class ResultTest < TinyTds::TestCase
|
|
45
45
|
assert_equal data.first.object_id, result.each.first.object_id
|
46
46
|
end
|
47
47
|
|
48
|
-
|
48
|
+
it 'returns hashes with string keys' do
|
49
49
|
result = @client.execute(@query1)
|
50
50
|
row = result.each(:as => :hash, :symbolize_keys => false).first
|
51
51
|
assert_instance_of Hash, row
|
@@ -53,7 +53,7 @@ class ResultTest < TinyTds::TestCase
|
|
53
53
|
assert_equal ['one'], result.fields
|
54
54
|
end
|
55
55
|
|
56
|
-
|
56
|
+
it 'returns hashes with symbol keys' do
|
57
57
|
result = @client.execute(@query1)
|
58
58
|
row = result.each(:as => :hash, :symbolize_keys => true).first
|
59
59
|
assert_instance_of Hash, row
|
@@ -61,21 +61,21 @@ class ResultTest < TinyTds::TestCase
|
|
61
61
|
assert_equal [:one], result.fields
|
62
62
|
end
|
63
63
|
|
64
|
-
|
64
|
+
it 'returns arrays with string fields' do
|
65
65
|
result = @client.execute(@query1)
|
66
66
|
row = result.each(:as => :array, :symbolize_keys => false).first
|
67
67
|
assert_instance_of Array, row
|
68
68
|
assert_equal ['one'], result.fields
|
69
69
|
end
|
70
70
|
|
71
|
-
|
71
|
+
it 'returns arrays with symbol fields' do
|
72
72
|
result = @client.execute(@query1)
|
73
73
|
row = result.each(:as => :array, :symbolize_keys => true).first
|
74
74
|
assert_instance_of Array, row
|
75
75
|
assert_equal [:one], result.fields
|
76
76
|
end
|
77
77
|
|
78
|
-
|
78
|
+
it 'must be able to turn :cache_rows option off' do
|
79
79
|
result = @client.execute(@query1)
|
80
80
|
local = []
|
81
81
|
result.each(:cache_rows => false) do |row|
|
@@ -86,7 +86,7 @@ class ResultTest < TinyTds::TestCase
|
|
86
86
|
assert_equal ['one'], result.fields, 'should still cache field names'
|
87
87
|
end
|
88
88
|
|
89
|
-
|
89
|
+
it 'must be able to get the first result row only' do
|
90
90
|
load_current_schema
|
91
91
|
big_query = "SELECT [id] FROM [datatypes]"
|
92
92
|
one = @client.execute(big_query).each(:first => true)
|
@@ -95,12 +95,12 @@ class ResultTest < TinyTds::TestCase
|
|
95
95
|
assert one.size == 1
|
96
96
|
end
|
97
97
|
|
98
|
-
|
98
|
+
it 'copes with no results when using first option' do
|
99
99
|
data = @client.execute("SELECT [id] FROM [datatypes] WHERE [id] = -1").each(:first => true)
|
100
100
|
assert_equal [], data
|
101
101
|
end
|
102
102
|
|
103
|
-
|
103
|
+
it 'must delete, insert and find data' do
|
104
104
|
rollback_transaction(@client) do
|
105
105
|
text = 'test insert and delete'
|
106
106
|
@client.execute("DELETE FROM [datatypes] WHERE [varchar_50] IS NOT NULL").do
|
@@ -111,7 +111,7 @@ class ResultTest < TinyTds::TestCase
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
-
|
114
|
+
it 'must insert and find unicode data' do
|
115
115
|
rollback_transaction(@client) do
|
116
116
|
text = '✓'
|
117
117
|
@client.execute("DELETE FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").do
|
@@ -121,7 +121,7 @@ class ResultTest < TinyTds::TestCase
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
-
|
124
|
+
it 'must delete and update with affected rows support and insert with identity support in native sql' do
|
125
125
|
rollback_transaction(@client) do
|
126
126
|
text = 'test affected rows sql'
|
127
127
|
@client.execute("DELETE FROM [datatypes]").do
|
@@ -131,7 +131,7 @@ class ResultTest < TinyTds::TestCase
|
|
131
131
|
pk1 = @client.execute("SELECT SCOPE_IDENTITY() AS Ident").each.first['Ident']
|
132
132
|
assert_instance_of BigDecimal, pk1, 'native is numeric(38,0) for SCOPE_IDENTITY() function'
|
133
133
|
pk2 = @client.execute("SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident").each.first['Ident']
|
134
|
-
assert_instance_of Fixnum, pk2, 'we
|
134
|
+
assert_instance_of Fixnum, pk2, 'we it be able to CAST to bigint'
|
135
135
|
assert_equal pk2, pk1.to_i, 'just making sure the 2 line up'
|
136
136
|
@client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do
|
137
137
|
afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first['AffectedRows']
|
@@ -139,7 +139,7 @@ class ResultTest < TinyTds::TestCase
|
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
142
|
-
|
142
|
+
it 'has a #do method that cancels result rows and returns affected rows natively' do
|
143
143
|
rollback_transaction(@client) do
|
144
144
|
text = 'test affected rows native'
|
145
145
|
count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count']
|
@@ -152,7 +152,7 @@ class ResultTest < TinyTds::TestCase
|
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
155
|
-
|
155
|
+
it 'allows native affected rows using #do to work under transaction' do
|
156
156
|
rollback_transaction(@client) do
|
157
157
|
text = 'test affected rows native in transaction'
|
158
158
|
@client.execute("BEGIN TRANSACTION").do
|
@@ -164,7 +164,7 @@ class ResultTest < TinyTds::TestCase
|
|
164
164
|
end
|
165
165
|
end
|
166
166
|
|
167
|
-
|
167
|
+
it 'has an #insert method that cancels result rows and returns the SCOPE_IDENTITY() natively' do
|
168
168
|
rollback_transaction(@client) do
|
169
169
|
text = 'test scope identity rows native'
|
170
170
|
@client.execute("DELETE FROM [datatypes] WHERE [varchar_50] = '#{text}'").do
|
@@ -175,7 +175,7 @@ class ResultTest < TinyTds::TestCase
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
178
|
-
|
178
|
+
it 'returns bigint for #insert when needed' do
|
179
179
|
return if sqlserver_azure? # We can not alter clustered index like this test does.
|
180
180
|
rollback_transaction(@client) do
|
181
181
|
seed = 9223372036854775805
|
@@ -190,7 +190,7 @@ class ResultTest < TinyTds::TestCase
|
|
190
190
|
end
|
191
191
|
end
|
192
192
|
|
193
|
-
|
193
|
+
it 'must be able to begin/commit transactions with raw sql' do
|
194
194
|
rollback_transaction(@client) do
|
195
195
|
@client.execute("BEGIN TRANSACTION").do
|
196
196
|
@client.execute("DELETE FROM [datatypes]").do
|
@@ -200,7 +200,7 @@ class ResultTest < TinyTds::TestCase
|
|
200
200
|
end
|
201
201
|
end
|
202
202
|
|
203
|
-
|
203
|
+
it 'must be able to begin/rollback transactions with raw sql' do
|
204
204
|
load_current_schema
|
205
205
|
@client.execute("BEGIN TRANSACTION").do
|
206
206
|
@client.execute("DELETE FROM [datatypes]").do
|
@@ -209,21 +209,21 @@ class ResultTest < TinyTds::TestCase
|
|
209
209
|
0.wont_equal count
|
210
210
|
end
|
211
211
|
|
212
|
-
|
212
|
+
it 'has a #fields accessor with logic default and valid outcome' do
|
213
213
|
result = @client.execute(@query1)
|
214
214
|
result.fields.must_equal ['one']
|
215
215
|
result.each
|
216
216
|
result.fields.must_equal ['one']
|
217
217
|
end
|
218
218
|
|
219
|
-
|
219
|
+
it 'always returns an array for fields for all sql' do
|
220
220
|
result = @client.execute("USE [tinytdstest]")
|
221
221
|
result.fields.must_equal []
|
222
222
|
result.do
|
223
223
|
result.fields.must_equal []
|
224
224
|
end
|
225
225
|
|
226
|
-
|
226
|
+
it 'returns fields even when no results are found' do
|
227
227
|
no_results_query = "SELECT [id], [varchar_50] FROM [datatypes] WHERE [varchar_50] = 'NOTFOUND'"
|
228
228
|
# Fields before each.
|
229
229
|
result = @client.execute(no_results_query)
|
@@ -236,13 +236,13 @@ class ResultTest < TinyTds::TestCase
|
|
236
236
|
result.fields.must_equal ['id','varchar_50']
|
237
237
|
end
|
238
238
|
|
239
|
-
|
239
|
+
it 'allows the result to be canceled before reading' do
|
240
240
|
result = @client.execute(@query1)
|
241
241
|
result.cancel
|
242
242
|
@client.execute(@query1).each
|
243
243
|
end
|
244
244
|
|
245
|
-
|
245
|
+
it 'works in tandem with the client when needing to find out if client has sql sent and result is canceled or not' do
|
246
246
|
# Default state.
|
247
247
|
@client = TinyTds::Client.new(connection_options)
|
248
248
|
@client.sqlsent?.must_equal false
|
@@ -296,12 +296,12 @@ class ResultTest < TinyTds::TestCase
|
|
296
296
|
@client.canceled?.must_equal true
|
297
297
|
end
|
298
298
|
|
299
|
-
|
299
|
+
it 'use same string object for hash keys' do
|
300
300
|
data = @client.execute("SELECT [id], [bigint] FROM [datatypes]").each
|
301
301
|
assert_equal data.first.keys.map{ |r| r.object_id }, data.last.keys.map{ |r| r.object_id }
|
302
302
|
end
|
303
303
|
|
304
|
-
|
304
|
+
it 'has properly encoded column names with symbol keys' do
|
305
305
|
col_name = "öäüß"
|
306
306
|
@client.execute("DROP TABLE [test_encoding]").do rescue nil
|
307
307
|
@client.execute("CREATE TABLE [dbo].[test_encoding] ( [#{col_name}] [nvarchar](10) NOT NULL )").do
|
@@ -314,7 +314,7 @@ class ResultTest < TinyTds::TestCase
|
|
314
314
|
assert_equal col_name.to_sym, row.keys.first
|
315
315
|
end unless sqlserver_azure?
|
316
316
|
|
317
|
-
|
317
|
+
it 'allows #return_code to work with stored procedures and reset per sql batch' do
|
318
318
|
assert_nil @client.return_code
|
319
319
|
result = @client.execute("EXEC tinytds_TestReturnCodes")
|
320
320
|
assert_equal [{"one"=>1}], result.each
|
@@ -326,9 +326,9 @@ class ResultTest < TinyTds::TestCase
|
|
326
326
|
assert_nil result.return_code
|
327
327
|
end
|
328
328
|
|
329
|
-
|
329
|
+
describe 'with multiple result sets' do
|
330
330
|
|
331
|
-
|
331
|
+
before do
|
332
332
|
@empty_select = "SELECT 1 AS [rs1] WHERE 1 = 0"
|
333
333
|
@double_select = "SELECT 1 AS [rs1]
|
334
334
|
SELECT 2 AS [rs2]"
|
@@ -343,7 +343,7 @@ class ResultTest < TinyTds::TestCase
|
|
343
343
|
SELECT 3 AS [rs3] WHERE 1 = 0"
|
344
344
|
end
|
345
345
|
|
346
|
-
|
346
|
+
it 'handles a command buffer with double selects' do
|
347
347
|
result = @client.execute(@double_select)
|
348
348
|
result_sets = result.each
|
349
349
|
assert_equal 2, result_sets.size
|
@@ -361,14 +361,14 @@ class ResultTest < TinyTds::TestCase
|
|
361
361
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
362
362
|
end
|
363
363
|
|
364
|
-
|
364
|
+
it 'yields each row for each result set' do
|
365
365
|
data = []
|
366
366
|
result_sets = @client.execute(@double_select).each { |row| data << row }
|
367
367
|
assert_equal data.first, result_sets.first[0]
|
368
368
|
assert_equal data.last, result_sets.last[0]
|
369
369
|
end
|
370
370
|
|
371
|
-
|
371
|
+
it 'works from a stored procedure' do
|
372
372
|
if sqlserver?
|
373
373
|
results1, results2 = @client.execute("EXEC sp_helpconstraint '[datatypes]'").each
|
374
374
|
assert_equal [{"Object Name"=>"[datatypes]"}], results1
|
@@ -385,25 +385,25 @@ class ResultTest < TinyTds::TestCase
|
|
385
385
|
end
|
386
386
|
end
|
387
387
|
|
388
|
-
|
388
|
+
describe 'using :empty_sets TRUE' do
|
389
389
|
|
390
|
-
|
390
|
+
before do
|
391
391
|
@old_query_option_value = TinyTds::Client.default_query_options[:empty_sets]
|
392
392
|
TinyTds::Client.default_query_options[:empty_sets] = true
|
393
393
|
@client = new_connection
|
394
394
|
end
|
395
395
|
|
396
|
-
|
396
|
+
after do
|
397
397
|
TinyTds::Client.default_query_options[:empty_sets] = @old_query_option_value
|
398
398
|
end
|
399
399
|
|
400
|
-
|
400
|
+
it 'handles a basic empty result set' do
|
401
401
|
result = @client.execute(@empty_select)
|
402
402
|
assert_equal [], result.each
|
403
403
|
assert_equal ['rs1'], result.fields
|
404
404
|
end
|
405
405
|
|
406
|
-
|
406
|
+
it 'includes empty result sets by default - using 1st empty buffer' do
|
407
407
|
result = @client.execute(@triple_select_1st_empty)
|
408
408
|
result_sets = result.each
|
409
409
|
assert_equal 3, result_sets.size
|
@@ -423,7 +423,7 @@ class ResultTest < TinyTds::TestCase
|
|
423
423
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
424
424
|
end
|
425
425
|
|
426
|
-
|
426
|
+
it 'includes empty result sets by default - using 2nd empty buffer' do
|
427
427
|
result = @client.execute(@triple_select_2nd_empty)
|
428
428
|
result_sets = result.each
|
429
429
|
assert_equal 3, result_sets.size
|
@@ -443,7 +443,7 @@ class ResultTest < TinyTds::TestCase
|
|
443
443
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
444
444
|
end
|
445
445
|
|
446
|
-
|
446
|
+
it 'includes empty result sets by default - using 3rd empty buffer' do
|
447
447
|
result = @client.execute(@triple_select_3rd_empty)
|
448
448
|
result_sets = result.each
|
449
449
|
assert_equal 3, result_sets.size
|
@@ -465,25 +465,25 @@ class ResultTest < TinyTds::TestCase
|
|
465
465
|
|
466
466
|
end
|
467
467
|
|
468
|
-
|
468
|
+
describe 'using :empty_sets FALSE' do
|
469
469
|
|
470
|
-
|
470
|
+
before do
|
471
471
|
@old_query_option_value = TinyTds::Client.default_query_options[:empty_sets]
|
472
472
|
TinyTds::Client.default_query_options[:empty_sets] = false
|
473
473
|
@client = new_connection
|
474
474
|
end
|
475
475
|
|
476
|
-
|
476
|
+
after do
|
477
477
|
TinyTds::Client.default_query_options[:empty_sets] = @old_query_option_value
|
478
478
|
end
|
479
479
|
|
480
|
-
|
480
|
+
it 'handles a basic empty result set' do
|
481
481
|
result = @client.execute(@empty_select)
|
482
482
|
assert_equal [], result.each
|
483
483
|
assert_equal ['rs1'], result.fields
|
484
484
|
end
|
485
485
|
|
486
|
-
|
486
|
+
it 'must not include empty result sets by default - using 1st empty buffer' do
|
487
487
|
result = @client.execute(@triple_select_1st_empty)
|
488
488
|
result_sets = result.each
|
489
489
|
assert_equal 2, result_sets.size
|
@@ -501,7 +501,7 @@ class ResultTest < TinyTds::TestCase
|
|
501
501
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
502
502
|
end
|
503
503
|
|
504
|
-
|
504
|
+
it 'must not include empty result sets by default - using 2nd empty buffer' do
|
505
505
|
result = @client.execute(@triple_select_2nd_empty)
|
506
506
|
result_sets = result.each
|
507
507
|
assert_equal 2, result_sets.size
|
@@ -519,7 +519,7 @@ class ResultTest < TinyTds::TestCase
|
|
519
519
|
assert_equal result.each.object_id, result.each.object_id, 'same cached rows'
|
520
520
|
end
|
521
521
|
|
522
|
-
|
522
|
+
it 'must not include empty result sets by default - using 3rd empty buffer' do
|
523
523
|
result = @client.execute(@triple_select_3rd_empty)
|
524
524
|
result_sets = result.each
|
525
525
|
assert_equal 2, result_sets.size
|
@@ -541,35 +541,35 @@ class ResultTest < TinyTds::TestCase
|
|
541
541
|
|
542
542
|
end
|
543
543
|
|
544
|
-
|
544
|
+
describe 'when casting to native ruby values' do
|
545
545
|
|
546
|
-
|
546
|
+
it 'returns fixnum for 1' do
|
547
547
|
value = @client.execute('SELECT 1 AS [fixnum]').each.first['fixnum']
|
548
548
|
assert_equal 1, value
|
549
549
|
end
|
550
550
|
|
551
|
-
|
551
|
+
it 'returns nil for NULL' do
|
552
552
|
value = @client.execute('SELECT NULL AS [null]').each.first['null']
|
553
553
|
assert_equal nil, value
|
554
554
|
end
|
555
555
|
|
556
556
|
end
|
557
557
|
|
558
|
-
|
558
|
+
describe 'with data type' do
|
559
559
|
|
560
|
-
|
560
|
+
describe 'char max' do
|
561
561
|
|
562
|
-
|
562
|
+
before do
|
563
563
|
@big_text = 'x' * 2_000_000
|
564
564
|
@old_textsize = @client.execute("SELECT @@TEXTSIZE AS [textsize]").each.first['textsize'].inspect
|
565
565
|
@client.execute("SET TEXTSIZE #{(@big_text.length*2)+1}").do
|
566
566
|
end
|
567
567
|
|
568
|
-
|
568
|
+
it 'must insert and select large varchar_max' do
|
569
569
|
insert_and_select_datatype :varchar_max
|
570
570
|
end
|
571
571
|
|
572
|
-
|
572
|
+
it 'must insert and select large nvarchar_max' do
|
573
573
|
insert_and_select_datatype :nvarchar_max
|
574
574
|
end
|
575
575
|
|
@@ -577,22 +577,22 @@ class ResultTest < TinyTds::TestCase
|
|
577
577
|
|
578
578
|
end
|
579
579
|
|
580
|
-
|
580
|
+
describe 'when shit happens' do
|
581
581
|
|
582
|
-
|
582
|
+
it 'copes with nil or empty buffer' do
|
583
583
|
assert_raises(TypeError) { @client.execute(nil) }
|
584
584
|
assert_equal [], @client.execute('').each
|
585
585
|
end
|
586
586
|
|
587
587
|
if sybase_ase?
|
588
588
|
|
589
|
-
|
589
|
+
it 'must not raise an error when severity is 10 or less' do
|
590
590
|
(1..10).to_a.each do |severity|
|
591
591
|
@client.execute("RAISERROR(N'Test #{severity} severity', #{severity}, 1)").do
|
592
592
|
end
|
593
593
|
end
|
594
594
|
|
595
|
-
|
595
|
+
it 'raises an error when severity is greater than 10' do
|
596
596
|
action = lambda { @client.execute("RAISERROR(N'Test 11 severity', 11, 1)").do }
|
597
597
|
assert_raise_tinytds_error(action) do |e|
|
598
598
|
assert_equal "Test 11 severity", e.message
|
@@ -603,19 +603,19 @@ class ResultTest < TinyTds::TestCase
|
|
603
603
|
|
604
604
|
else
|
605
605
|
|
606
|
-
|
607
|
-
action = lambda { @client.execute("RAISERROR
|
606
|
+
it 'raises an error' do
|
607
|
+
action = lambda { @client.execute("RAISERROR (N'Hello World', 16, 1)").do }
|
608
608
|
assert_raise_tinytds_error(action) do |e|
|
609
609
|
assert_equal "Hello World", e.message
|
610
610
|
assert_equal 16, e.severity # predefined on ASE
|
611
|
-
assert_equal
|
611
|
+
assert_equal 50000, e.db_error_number
|
612
612
|
end
|
613
|
+
assert_followup_query
|
613
614
|
end
|
614
615
|
|
615
616
|
end
|
616
|
-
|
617
617
|
|
618
|
-
|
618
|
+
it 'throws an error when you execute another query with other results pending' do
|
619
619
|
result1 = @client.execute(@query1)
|
620
620
|
action = lambda { @client.execute(@query1) }
|
621
621
|
assert_raise_tinytds_error(action) do |e|
|
@@ -625,7 +625,7 @@ class ResultTest < TinyTds::TestCase
|
|
625
625
|
end
|
626
626
|
end
|
627
627
|
|
628
|
-
|
628
|
+
it 'must error gracefully with bad table name' do
|
629
629
|
action = lambda { @client.execute('SELECT * FROM [foobar]').each }
|
630
630
|
assert_raise_tinytds_error(action) do |e|
|
631
631
|
assert_match %r|invalid object name.*foobar|i, e.message
|
@@ -635,7 +635,7 @@ class ResultTest < TinyTds::TestCase
|
|
635
635
|
assert_followup_query
|
636
636
|
end
|
637
637
|
|
638
|
-
|
638
|
+
it 'must error gracefully with incorrect syntax' do
|
639
639
|
action = lambda { @client.execute('this will not work').each }
|
640
640
|
assert_raise_tinytds_error(action) do |e|
|
641
641
|
assert_match %r|incorrect syntax|i, e.message
|
@@ -644,8 +644,30 @@ class ResultTest < TinyTds::TestCase
|
|
644
644
|
end
|
645
645
|
assert_followup_query
|
646
646
|
end
|
647
|
-
|
648
|
-
|
647
|
+
|
648
|
+
it 'must not error at all from reading non-convertable charcters and just use ? marks' do
|
649
|
+
@client = new_connection :encoding => 'ASCII'
|
650
|
+
@client.charset.must_equal 'ASCII'
|
651
|
+
find_value(202, :nvarchar_50).must_equal 'test nvarchar_50 ??'
|
652
|
+
end
|
653
|
+
|
654
|
+
it 'must error gracefully from writing non-convertable characters' do
|
655
|
+
@client = new_connection :encoding => 'ASCII'
|
656
|
+
@client.charset.must_equal 'ASCII'
|
657
|
+
rollback_transaction(@client) do
|
658
|
+
text = 'Test ✓'
|
659
|
+
@client.execute("DELETE FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").do
|
660
|
+
action = lambda { @client.execute("INSERT INTO [datatypes] ([nvarchar_50]) VALUES ('#{text}')").do }
|
661
|
+
assert_raise_tinytds_error(action) do |e|
|
662
|
+
e.message.must_match %r{Error converting characters into server's character set}i
|
663
|
+
e.severity.must_equal 4
|
664
|
+
e.db_error_number.must_equal 2402
|
665
|
+
end
|
666
|
+
assert_followup_query
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
it 'errors gracefully with incorrect syntax in sp_executesql' do
|
649
671
|
if @client.freetds_091_or_higer?
|
650
672
|
action = lambda { @client.execute("EXEC sp_executesql N'this will not work'").each }
|
651
673
|
assert_raise_tinytds_error(action) do |e|
|
data/test/schema_test.rb
CHANGED
@@ -3,42 +3,42 @@ require 'test_helper'
|
|
3
3
|
|
4
4
|
class SchemaTest < TinyTds::TestCase
|
5
5
|
|
6
|
-
|
6
|
+
describe 'Casting SQL Server schema' do
|
7
7
|
|
8
|
-
|
8
|
+
before do
|
9
9
|
@@current_schema_loaded ||= load_current_schema
|
10
10
|
@client = new_connection
|
11
11
|
@gif1px = ruby19? ? File.read('test/schema/1px.gif',:mode=>"rb:BINARY") : File.read('test/schema/1px.gif')
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
describe 'for shared types' do
|
15
15
|
|
16
|
-
|
16
|
+
it 'casts bigint' do
|
17
17
|
assert_equal -9223372036854775807, find_value(11, :bigint)
|
18
18
|
assert_equal 9223372036854775806, find_value(12, :bigint)
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
it 'casts binary' do
|
22
22
|
binary_value = sqlserver_azure? ? @gif1px : @gif1px+"\000"
|
23
23
|
value = find_value(21, :binary_50)
|
24
24
|
assert_equal binary_value, value
|
25
25
|
assert_binary_encoding(value)
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
it 'casts bit' do
|
29
29
|
assert_equal true, find_value(31, :bit)
|
30
30
|
assert_equal false, find_value(32, :bit)
|
31
31
|
assert_equal nil, find_value(21, :bit)
|
32
32
|
end
|
33
33
|
|
34
|
-
|
34
|
+
it 'casts char' do
|
35
35
|
partial_char = sqlserver_azure? ? '12345678' : '12345678 '
|
36
36
|
assert_equal '1234567890', find_value(41, :char_10)
|
37
37
|
assert_equal partial_char, find_value(42, :char_10)
|
38
38
|
assert_utf8_encoding find_value(42, :char_10)
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
it 'casts datetime' do
|
42
42
|
if ruby18? && ruby32bit?
|
43
43
|
# 1753-01-01T00:00:00.000
|
44
44
|
v = find_value 61, :datetime
|
@@ -112,7 +112,7 @@ class SchemaTest < TinyTds::TestCase
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
-
|
115
|
+
it 'casts decimal' do
|
116
116
|
assert_instance_of BigDecimal, find_value(91, :decimal_9_2)
|
117
117
|
assert_equal BigDecimal.new('12345.01'), find_value(91, :decimal_9_2)
|
118
118
|
assert_equal BigDecimal.new('1234567.89'), find_value(92, :decimal_9_2)
|
@@ -120,38 +120,38 @@ class SchemaTest < TinyTds::TestCase
|
|
120
120
|
assert_equal BigDecimal.new('123456789012.3456'), find_value(94, :decimal_16_4)
|
121
121
|
end
|
122
122
|
|
123
|
-
|
123
|
+
it 'casts float' do
|
124
124
|
assert_equal 123.00000001, find_value(101,:float)
|
125
125
|
assert_equal 0.0, find_value(102,:float)
|
126
126
|
assert_equal find_value(102,:float).object_id, find_value(102,:float).object_id, 'use global zero float'
|
127
127
|
assert_equal 123.45, find_value(103,:float)
|
128
128
|
end
|
129
129
|
|
130
|
-
|
130
|
+
it 'casts image' do
|
131
131
|
value = find_value(141,:image)
|
132
132
|
assert_equal @gif1px, value
|
133
133
|
assert_binary_encoding(value)
|
134
134
|
end
|
135
135
|
|
136
|
-
|
136
|
+
it 'casts int' do
|
137
137
|
assert_equal -2147483647, find_value(151, :int)
|
138
138
|
assert_equal 2147483646, find_value(152, :int)
|
139
139
|
end
|
140
140
|
|
141
|
-
|
141
|
+
it 'casts money' do
|
142
142
|
assert_instance_of BigDecimal, find_value(161, :money)
|
143
143
|
assert_equal BigDecimal.new('4.20'), find_value(161, :money)
|
144
144
|
assert_equal BigDecimal.new('922337203685477.5806'), find_value(163 ,:money)
|
145
145
|
assert_equal BigDecimal.new('-922337203685477.5807'), find_value(162 ,:money)
|
146
146
|
end
|
147
147
|
|
148
|
-
|
148
|
+
it 'casts nchar' do
|
149
149
|
assert_equal '1234567890', find_value(171, :nchar_10)
|
150
150
|
assert_equal '123456åå ', find_value(172, :nchar_10)
|
151
151
|
assert_equal 'abc123 ', find_value(173, :nchar_10)
|
152
152
|
end
|
153
153
|
|
154
|
-
|
154
|
+
it 'casts ntext' do
|
155
155
|
assert_equal 'test ntext', find_value(181, :ntext)
|
156
156
|
assert_equal 'test ntext åå', find_value(182, :ntext)
|
157
157
|
assert_utf8_encoding find_value(182, :ntext)
|
@@ -161,7 +161,7 @@ class SchemaTest < TinyTds::TestCase
|
|
161
161
|
assert_equal large_value, find_value(large_value_id, :ntext)
|
162
162
|
end unless sybase_ase?
|
163
163
|
|
164
|
-
|
164
|
+
it 'casts numeric' do
|
165
165
|
assert_instance_of BigDecimal, find_value(191, :numeric_18_0)
|
166
166
|
assert_equal BigDecimal('191'), find_value(191, :numeric_18_0)
|
167
167
|
assert_equal BigDecimal('123456789012345678'), find_value(192, :numeric_18_0)
|
@@ -169,20 +169,20 @@ class SchemaTest < TinyTds::TestCase
|
|
169
169
|
assert_equal BigDecimal('123.46'), find_value(194, :numeric_36_2)
|
170
170
|
end
|
171
171
|
|
172
|
-
|
172
|
+
it 'casts nvarchar' do
|
173
173
|
assert_equal 'test nvarchar_50', find_value(201, :nvarchar_50)
|
174
174
|
assert_equal 'test nvarchar_50 åå', find_value(202, :nvarchar_50)
|
175
175
|
assert_utf8_encoding find_value(202, :nvarchar_50)
|
176
176
|
end
|
177
177
|
|
178
|
-
|
178
|
+
it 'casts real' do
|
179
179
|
assert_in_delta 123.45, find_value(221, :real), 0.01
|
180
180
|
assert_equal 0.0, find_value(222, :real)
|
181
181
|
assert_equal find_value(222, :real).object_id, find_value(222, :real).object_id, 'use global zero float'
|
182
182
|
assert_in_delta 0.00001, find_value(223, :real), 0.000001
|
183
183
|
end
|
184
184
|
|
185
|
-
|
185
|
+
it 'casts smalldatetime' do
|
186
186
|
if ruby18? && ruby32bit?
|
187
187
|
# 1901-01-01 15:45:00
|
188
188
|
v = find_value 231, :smalldatetime
|
@@ -232,40 +232,40 @@ class SchemaTest < TinyTds::TestCase
|
|
232
232
|
end
|
233
233
|
end
|
234
234
|
|
235
|
-
|
235
|
+
it 'casts smallint' do
|
236
236
|
assert_equal -32767, find_value(241, :smallint)
|
237
237
|
assert_equal 32766, find_value(242, :smallint)
|
238
238
|
end
|
239
239
|
|
240
|
-
|
240
|
+
it 'casts smallmoney' do
|
241
241
|
assert_instance_of BigDecimal, find_value(251, :smallmoney)
|
242
242
|
assert_equal BigDecimal.new("4.20"), find_value(251, :smallmoney)
|
243
243
|
assert_equal BigDecimal.new("-214748.3647"), find_value(252, :smallmoney)
|
244
244
|
assert_equal BigDecimal.new("214748.3646"), find_value(253, :smallmoney)
|
245
245
|
end
|
246
246
|
|
247
|
-
|
247
|
+
it 'casts text' do
|
248
248
|
assert_equal 'test text', find_value(271, :text)
|
249
249
|
assert_utf8_encoding find_value(271, :text)
|
250
250
|
end
|
251
251
|
|
252
|
-
|
252
|
+
it 'casts tinyint' do
|
253
253
|
assert_equal 0, find_value(301, :tinyint)
|
254
254
|
assert_equal 255, find_value(302, :tinyint)
|
255
255
|
end
|
256
256
|
|
257
|
-
|
257
|
+
it 'casts uniqueidentifier' do
|
258
258
|
assert_match %r|\w{8}-\w{4}-\w{4}-\w{4}-\w{12}|, find_value(311, :uniqueidentifier)
|
259
259
|
assert_utf8_encoding find_value(311, :uniqueidentifier)
|
260
260
|
end unless sybase_ase?
|
261
261
|
|
262
|
-
|
262
|
+
it 'casts varbinary' do
|
263
263
|
value = find_value(321, :varbinary_50)
|
264
264
|
assert_equal @gif1px, value
|
265
265
|
assert_binary_encoding(value)
|
266
266
|
end
|
267
267
|
|
268
|
-
|
268
|
+
it 'casts varchar' do
|
269
269
|
assert_equal 'test varchar_50', find_value(341, :varchar_50)
|
270
270
|
assert_utf8_encoding find_value(341, :varchar_50)
|
271
271
|
end
|
@@ -273,27 +273,27 @@ class SchemaTest < TinyTds::TestCase
|
|
273
273
|
end
|
274
274
|
|
275
275
|
|
276
|
-
|
276
|
+
describe 'for 2005 and up' do
|
277
277
|
|
278
|
-
|
278
|
+
it 'casts nvarchar(max)' do
|
279
279
|
assert_equal 'test nvarchar_max', find_value(211, :nvarchar_max)
|
280
280
|
assert_equal 'test nvarchar_max åå', find_value(212, :nvarchar_max)
|
281
281
|
assert_utf8_encoding find_value(212, :nvarchar_max)
|
282
282
|
end
|
283
283
|
|
284
|
-
|
284
|
+
it 'casts varbinary(max)' do
|
285
285
|
value = find_value(331, :varbinary_max)
|
286
286
|
assert_equal @gif1px, value
|
287
287
|
assert_binary_encoding(value)
|
288
288
|
end
|
289
289
|
|
290
|
-
|
290
|
+
it 'casts varchar(max)' do
|
291
291
|
value = find_value(351, :varchar_max)
|
292
292
|
assert_equal 'test varchar_max', value
|
293
293
|
assert_utf8_encoding(value)
|
294
294
|
end
|
295
295
|
|
296
|
-
|
296
|
+
it 'casts xml' do
|
297
297
|
value = find_value(361, :xml)
|
298
298
|
assert_equal '<foo><bar>batz</bar></foo>', value
|
299
299
|
assert_utf8_encoding(value)
|
@@ -302,7 +302,7 @@ class SchemaTest < TinyTds::TestCase
|
|
302
302
|
end if sqlserver_2005? || sqlserver_2008? || sqlserver_azure?
|
303
303
|
|
304
304
|
|
305
|
-
|
305
|
+
describe 'for 2008 and up' do
|
306
306
|
|
307
307
|
# These data types always come back as SYBTEXT and there is no way I can
|
308
308
|
# find out the column's human readable name.
|
@@ -318,37 +318,37 @@ class SchemaTest < TinyTds::TestCase
|
|
318
318
|
# rb_warn("SYBTEXT: dbcolutype: %s", dbcolutype(rwrap->client, col));
|
319
319
|
# rb_warn("SYBTEXT: dbcolutype: %ld", dbcolutype(rwrap->client, col));
|
320
320
|
|
321
|
-
#
|
321
|
+
# it 'casts date' do
|
322
322
|
# value = find_value 51, :date
|
323
323
|
# assert_equal '', value
|
324
324
|
# end
|
325
325
|
#
|
326
|
-
#
|
326
|
+
# it 'casts datetime2' do
|
327
327
|
# value = find_value 72, :datetime2_7
|
328
328
|
# assert_equal '', value
|
329
329
|
# end
|
330
330
|
#
|
331
|
-
#
|
331
|
+
# it 'casts datetimeoffset' do
|
332
332
|
# value = find_value 81, :datetimeoffset_2
|
333
333
|
# assert_equal '', value
|
334
334
|
# end
|
335
335
|
#
|
336
|
-
#
|
336
|
+
# it 'casts geography' do
|
337
337
|
# value = find_value 111, :geography
|
338
338
|
# assert_equal '', value
|
339
339
|
# end
|
340
340
|
#
|
341
|
-
#
|
341
|
+
# it 'casts geometry' do
|
342
342
|
# value = find_value 121, :geometry
|
343
343
|
# assert_equal '', value
|
344
344
|
# end
|
345
345
|
#
|
346
|
-
#
|
346
|
+
# it 'casts hierarchyid' do
|
347
347
|
# value = find_value 131, :hierarchyid
|
348
348
|
# assert_equal '', value
|
349
349
|
# end
|
350
350
|
#
|
351
|
-
#
|
351
|
+
# it 'casts time' do
|
352
352
|
# value = find_value 283, :time_7
|
353
353
|
# assert_equal '', value
|
354
354
|
# end
|
data/test/test_helper.rb
CHANGED
@@ -3,7 +3,7 @@ require 'rubygems'
|
|
3
3
|
require 'bundler'
|
4
4
|
Bundler.setup
|
5
5
|
require 'tiny_tds'
|
6
|
-
require '
|
6
|
+
require 'minitest/spec'
|
7
7
|
require 'minitest/autorun'
|
8
8
|
|
9
9
|
class DateTime
|
@@ -39,7 +39,7 @@ module TinyTds
|
|
39
39
|
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
after do
|
43
43
|
@client.close if @client.is_a?(TinyTds::Client)
|
44
44
|
end
|
45
45
|
|
@@ -88,7 +88,7 @@ module TinyTds
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def assert_client_works(client)
|
91
|
-
client.execute("SELECT 'client_works' as [client_works]").each
|
91
|
+
client.execute("SELECT 'client_works' as [client_works]").each.must_equal [{'client_works' => 'client_works'}]
|
92
92
|
end
|
93
93
|
|
94
94
|
def assert_new_connections_work
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiny_tds
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 1037666241
|
5
|
+
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 5
|
9
|
+
- 2
|
10
|
+
- rc
|
9
11
|
- 1
|
10
|
-
version: 0.5.
|
12
|
+
version: 0.5.2.rc1
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- Ken Collins
|
@@ -16,9 +18,86 @@ autorequire:
|
|
16
18
|
bindir: bin
|
17
19
|
cert_chain: []
|
18
20
|
|
19
|
-
date: 2012-
|
20
|
-
|
21
|
-
|
21
|
+
date: 2012-09-23 00:00:00 -04:00
|
22
|
+
default_executable:
|
23
|
+
dependencies:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: rake
|
26
|
+
prerelease: false
|
27
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
hash: 63
|
33
|
+
segments:
|
34
|
+
- 0
|
35
|
+
- 9
|
36
|
+
- 2
|
37
|
+
version: 0.9.2
|
38
|
+
type: :development
|
39
|
+
version_requirements: *id001
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: mini_portile
|
42
|
+
prerelease: false
|
43
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - "="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
hash: 19
|
49
|
+
segments:
|
50
|
+
- 0
|
51
|
+
- 3
|
52
|
+
- 0
|
53
|
+
version: 0.3.0
|
54
|
+
type: :development
|
55
|
+
version_requirements: *id002
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rake-compiler
|
58
|
+
prerelease: false
|
59
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - "="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
hash: 61
|
65
|
+
segments:
|
66
|
+
- 0
|
67
|
+
- 8
|
68
|
+
- 1
|
69
|
+
version: 0.8.1
|
70
|
+
type: :development
|
71
|
+
version_requirements: *id003
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: activesupport
|
74
|
+
prerelease: false
|
75
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ~>
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
hash: 7
|
81
|
+
segments:
|
82
|
+
- 3
|
83
|
+
- 0
|
84
|
+
version: "3.0"
|
85
|
+
type: :development
|
86
|
+
version_requirements: *id004
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: minitest
|
89
|
+
prerelease: false
|
90
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
hash: 3
|
96
|
+
segments:
|
97
|
+
- 0
|
98
|
+
version: "0"
|
99
|
+
type: :development
|
100
|
+
version_requirements: *id005
|
22
101
|
description: TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library. Developed for the ActiveRecord SQL Server adapter.
|
23
102
|
email:
|
24
103
|
- ken@metaskills.net
|
@@ -62,6 +141,7 @@ files:
|
|
62
141
|
- test/schema/sybase_ase.sql
|
63
142
|
- test/schema_test.rb
|
64
143
|
- test/test_helper.rb
|
144
|
+
has_rdoc: true
|
65
145
|
homepage: http://github.com/rails-sqlserver/tiny_tds
|
66
146
|
licenses: []
|
67
147
|
|
@@ -82,16 +162,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
82
162
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
163
|
none: false
|
84
164
|
requirements:
|
85
|
-
- - "
|
165
|
+
- - ">"
|
86
166
|
- !ruby/object:Gem::Version
|
87
|
-
hash:
|
167
|
+
hash: 25
|
88
168
|
segments:
|
89
|
-
-
|
90
|
-
|
169
|
+
- 1
|
170
|
+
- 3
|
171
|
+
- 1
|
172
|
+
version: 1.3.1
|
91
173
|
requirements: []
|
92
174
|
|
93
175
|
rubyforge_project:
|
94
|
-
rubygems_version: 1.
|
176
|
+
rubygems_version: 1.6.2
|
95
177
|
signing_key:
|
96
178
|
specification_version: 3
|
97
179
|
summary: TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library.
|