tiny_tds 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,284 @@
1
+ # encoding: utf-8
2
+ require 'test_helper'
3
+
4
+ class SchemaTest < TinyTds::TestCase
5
+
6
+ context 'Casting SQL Server schema' do
7
+
8
+ setup do
9
+ @@current_schema_loaded ||= load_current_schema
10
+ @client ||= new_connection
11
+ @gif1px = ruby19? ? File.read('test/schema/1px.gif',:mode=>"rb:BINARY") : File.read('test/schema/1px.gif')
12
+ end
13
+
14
+ context 'for shared types' do
15
+
16
+ should 'cast bigint' do
17
+ assert_equal -9223372036854775807, find_value(11, :bigint)
18
+ assert_equal 9223372036854775806, find_value(12, :bigint)
19
+ end
20
+
21
+ should 'cast binary' do
22
+ binary_value = sqlserver_azure? ? @gif1px : @gif1px+"\000"
23
+ value = find_value(21, :binary_50)
24
+ assert_equal binary_value, value
25
+ assert_binary_encoding(value)
26
+ end
27
+
28
+ should 'cast bit' do
29
+ assert_equal true, find_value(31, :bit)
30
+ assert_equal false, find_value(32, :bit)
31
+ assert_equal nil, find_value(21, :bit)
32
+ end
33
+
34
+ should 'cast char' do
35
+ partial_char = sqlserver_azure? ? '12345678' : '12345678 '
36
+ assert_equal '1234567890', find_value(41, :char_10)
37
+ assert_equal partial_char, find_value(42, :char_10)
38
+ assert_utf8_encoding find_value(42, :char_10)
39
+ end
40
+
41
+ should 'cast datetime' do
42
+ # 1753-01-01T00:00:00.000
43
+ v = find_value 61, :datetime
44
+ assert_instance_of DateTime, v, 'not in range of Time class'
45
+ assert_equal 1753, v.year
46
+ assert_equal 01, v.month
47
+ assert_equal 01, v.day
48
+ assert_equal 0, v.hour
49
+ assert_equal 0, v.min
50
+ assert_equal 0, v.sec
51
+ assert_equal 0, v.usec
52
+ # 9999-12-31T23:59:59.997
53
+ v = find_value 62, :datetime
54
+ assert_instance_of DateTime, v, 'not in range of Time class'
55
+ assert_equal 9999, v.year
56
+ assert_equal 12, v.month
57
+ assert_equal 31, v.day
58
+ assert_equal 23, v.hour
59
+ assert_equal 59, v.min
60
+ assert_equal 59, v.sec
61
+ assert_equal 997000, v.usec unless ruby186?
62
+ assert_equal local_offset, find_value(61, :datetime, :timezone => :local).offset
63
+ assert_equal 0, find_value(61, :datetime, :timezone => :utc).offset
64
+ # 2010-01-01T12:34:56.123
65
+ v = find_value 63, :datetime
66
+ assert_instance_of Time, v, 'in range of Time class'
67
+ assert_equal 2010, v.year
68
+ assert_equal 01, v.month
69
+ assert_equal 01, v.day
70
+ assert_equal 12, v.hour
71
+ assert_equal 34, v.min
72
+ assert_equal 56, v.sec
73
+ assert_equal 123000, v.usec
74
+ assert_equal utc_offset, find_value(63, :datetime, :timezone => :local).utc_offset
75
+ assert_equal 0, find_value(63, :datetime, :timezone => :utc).utc_offset
76
+ end
77
+
78
+ should 'cast decimal' do
79
+ assert_instance_of BigDecimal, find_value(91, :decimal_9_2)
80
+ assert_equal BigDecimal.new('12345.01'), find_value(91, :decimal_9_2)
81
+ assert_equal BigDecimal.new('1234567.89'), find_value(92, :decimal_9_2)
82
+ assert_equal BigDecimal.new('0.0'), find_value(93, :decimal_16_4)
83
+ assert_equal BigDecimal.new('123456789012.3456'), find_value(94, :decimal_16_4)
84
+ end
85
+
86
+ should 'cast float' do
87
+ assert_equal 123.00000001, find_value(101,:float)
88
+ assert_equal 0.0, find_value(102,:float)
89
+ assert_equal find_value(102,:float).object_id, find_value(102,:float).object_id, 'use global zero float'
90
+ assert_equal 123.45, find_value(103,:float)
91
+ end
92
+
93
+ should 'cast image' do
94
+ value = find_value(141,:image)
95
+ assert_equal @gif1px, value
96
+ assert_binary_encoding(value)
97
+ end
98
+
99
+ should 'cast int' do
100
+ assert_equal -2147483647, find_value(151, :int)
101
+ assert_equal 2147483646, find_value(152, :int)
102
+ end
103
+
104
+ should 'cast money' do
105
+ assert_instance_of BigDecimal, find_value(161, :money)
106
+ assert_equal BigDecimal.new('4.20'), find_value(161, :money)
107
+ assert_equal BigDecimal.new('922337203685477.5806'), find_value(163 ,:money)
108
+ assert_equal BigDecimal.new('-922337203685477.5807'), find_value(162 ,:money)
109
+ end
110
+
111
+ should 'cast nchar' do
112
+ assert_equal '1234567890', find_value(171, :nchar_10)
113
+ assert_equal '123456åå ', find_value(172, :nchar_10)
114
+ assert_equal 'abc123 ', find_value(173, :nchar_10)
115
+ end
116
+
117
+ should 'cast ntext' do
118
+ assert_equal 'test ntext', find_value(181, :ntext)
119
+ assert_equal 'test ntext åå', find_value(182, :ntext)
120
+ assert_utf8_encoding find_value(182, :ntext)
121
+ # If this test fails, try setting the "text size" in your freetds.conf. See: http://www.freetds.org/faq.html#textdata
122
+ large_value = "x" * 5000
123
+ large_value_id = @client.execute("INSERT INTO [datatypes] ([ntext]) VALUES (N'#{large_value}')").insert
124
+ assert_equal large_value, find_value(large_value_id, :ntext)
125
+ end
126
+
127
+ should 'cast numeric' do
128
+ assert_instance_of BigDecimal, find_value(191, :numeric_18_0)
129
+ assert_equal BigDecimal('191'), find_value(191, :numeric_18_0)
130
+ assert_equal BigDecimal('123456789012345678'), find_value(192, :numeric_18_0)
131
+ assert_equal BigDecimal('12345678901234567890.01'), find_value(193, :numeric_36_2)
132
+ assert_equal BigDecimal('123.46'), find_value(194, :numeric_36_2)
133
+ end
134
+
135
+ should 'cast nvarchar' do
136
+ assert_equal 'test nvarchar_50', find_value(201, :nvarchar_50)
137
+ assert_equal 'test nvarchar_50 åå', find_value(202, :nvarchar_50)
138
+ assert_utf8_encoding find_value(202, :nvarchar_50)
139
+ end
140
+
141
+ should 'cast real' do
142
+ assert_in_delta 123.45, find_value(221, :real), 0.01
143
+ assert_equal 0.0, find_value(222, :real)
144
+ assert_equal find_value(222, :real).object_id, find_value(222, :real).object_id, 'use global zero float'
145
+ assert_in_delta 0.00001, find_value(223, :real), 0.000001
146
+ end
147
+
148
+ should 'cast smalldatetime' do
149
+ # 1901-01-01 15:45:00
150
+ v = find_value 231, :smalldatetime
151
+ assert_instance_of DateTime, v
152
+ assert_equal 1901, v.year
153
+ assert_equal 01, v.month
154
+ assert_equal 01, v.day
155
+ assert_equal 15, v.hour
156
+ assert_equal 45, v.min
157
+ assert_equal 00, v.sec
158
+ assert_equal local_offset, find_value(231, :smalldatetime, :timezone => :local).offset
159
+ assert_equal 0, find_value(231, :smalldatetime, :timezone => :utc).offset
160
+ # 2078-06-05 04:20:00
161
+ v = find_value 232, :smalldatetime
162
+ assert_instance_of DateTime, v
163
+ assert_equal 2078, v.year
164
+ assert_equal 06, v.month
165
+ assert_equal 05, v.day
166
+ assert_equal 04, v.hour
167
+ assert_equal 20, v.min
168
+ assert_equal 00, v.sec
169
+ assert_equal local_offset, find_value(232, :smalldatetime, :timezone => :local).offset
170
+ assert_equal 0, find_value(232, :smalldatetime, :timezone => :utc).offset
171
+ end
172
+
173
+ should 'cast smallint' do
174
+ assert_equal -32767, find_value(241, :smallint)
175
+ assert_equal 32766, find_value(242, :smallint)
176
+ end
177
+
178
+ should 'cast smallmoney' do
179
+ assert_instance_of BigDecimal, find_value(251, :smallmoney)
180
+ assert_equal BigDecimal.new("4.20"), find_value(251, :smallmoney)
181
+ assert_equal BigDecimal.new("-214748.3647"), find_value(252, :smallmoney)
182
+ assert_equal BigDecimal.new("214748.3646"), find_value(253, :smallmoney)
183
+ end
184
+
185
+ should 'cast text' do
186
+ assert_equal 'test text', find_value(271, :text)
187
+ assert_utf8_encoding find_value(271, :text)
188
+ end
189
+
190
+ should 'cast tinyint' do
191
+ assert_equal 0, find_value(301, :tinyint)
192
+ assert_equal 255, find_value(302, :tinyint)
193
+ end
194
+
195
+ should 'cast uniqueidentifier' do
196
+ assert_match %r|\w{8}-\w{4}-\w{4}-\w{4}-\w{12}|, find_value(311, :uniqueidentifier)
197
+ assert_utf8_encoding find_value(311, :uniqueidentifier)
198
+ end
199
+
200
+ should 'cast varbinary' do
201
+ value = find_value(321, :varbinary_50)
202
+ assert_equal @gif1px, value
203
+ assert_binary_encoding(value)
204
+ end
205
+
206
+ should 'cast varchar' do
207
+ assert_equal 'test varchar_50', find_value(341, :varchar_50)
208
+ assert_utf8_encoding find_value(341, :varchar_50)
209
+ end
210
+
211
+ end
212
+
213
+
214
+ context 'for 2005 and up' do
215
+
216
+ should 'cast nvarchar(max)' do
217
+ assert_equal 'test nvarchar_max', find_value(211, :nvarchar_max)
218
+ assert_equal 'test nvarchar_max åå', find_value(212, :nvarchar_max)
219
+ assert_utf8_encoding find_value(212, :nvarchar_max)
220
+ end
221
+
222
+ should 'cast varbinary(max)' do
223
+ value = find_value(331, :varbinary_max)
224
+ assert_equal @gif1px, value
225
+ assert_binary_encoding(value)
226
+ end
227
+
228
+ should 'cast varchar(max)' do
229
+ value = find_value(351, :varchar_max)
230
+ assert_equal 'test varchar_max', value
231
+ assert_utf8_encoding(value)
232
+ end
233
+
234
+ should 'cast xml' do
235
+ value = find_value(361, :xml)
236
+ assert_equal '<foo><bar>batz</bar></foo>', value
237
+ assert_utf8_encoding(value)
238
+ end
239
+
240
+ end if sqlserver_2005? || sqlserver_2008? || sqlserver_azure?
241
+
242
+
243
+ context 'for 2008 and up' do
244
+
245
+ should 'cast date' do
246
+
247
+ end
248
+
249
+ should 'cast datetime2' do
250
+
251
+ end
252
+
253
+ should 'cast datetimeoffset' do
254
+
255
+ end
256
+
257
+ should 'cast geography' do
258
+
259
+ end
260
+
261
+ should 'cast geometry' do
262
+
263
+ end
264
+
265
+ should 'cast hierarchyid' do
266
+
267
+ end
268
+
269
+ should 'cast time' do
270
+
271
+ end
272
+
273
+ end if sqlserver_2008? || sqlserver_azure?
274
+
275
+ end
276
+
277
+
278
+
279
+ end
280
+
281
+
282
+
283
+
284
+
@@ -0,0 +1,199 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ Bundler.setup
5
+ require 'tiny_tds'
6
+ require 'mini_shoulda'
7
+ require 'minitest/autorun'
8
+
9
+ class DateTime
10
+ def usec
11
+ if RUBY_VERSION >= '1.9'
12
+ (sec_fraction * 1_000_000).to_i
13
+ else
14
+ (sec_fraction * 60 * 60 * 24 * (10**6)).to_i
15
+ end
16
+ end
17
+ end
18
+
19
+ TINYTDS_SCHEMAS = ['sqlserver_2000', 'sqlserver_2005', 'sqlserver_2008', 'sqlserver_azure'].freeze
20
+
21
+ module TinyTds
22
+ class TestCase < MiniTest::Spec
23
+
24
+ class << self
25
+
26
+ def current_schema
27
+ ENV['TINYTDS_SCHEMA'] || 'sqlserver_2008'
28
+ end
29
+
30
+ TINYTDS_SCHEMAS.each do |schema|
31
+ define_method "#{schema}?" do
32
+ schema == self.current_schema
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ setup do
39
+
40
+ end
41
+
42
+ teardown do
43
+ ENV['TDSPORT'] = nil
44
+ ENV['TDSHOST'] = nil
45
+ end
46
+
47
+
48
+ protected
49
+
50
+ TINYTDS_SCHEMAS.each do |schema|
51
+ define_method "#{schema}?" do
52
+ schema == self.class.current_schema
53
+ end
54
+ end
55
+
56
+ def current_schema
57
+ self.class.current_schema
58
+ end
59
+
60
+ def new_connection(options={})
61
+ client = TinyTds::Client.new(connection_options(options))
62
+ unless sqlserver_azure?
63
+ client.execute("SET ANSI_DEFAULTS ON").do
64
+ client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
65
+ client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
66
+ end
67
+ client
68
+ end
69
+
70
+ def connection_options(options={})
71
+ username = sqlserver_azure? ? ENV['TINYTDS_UNIT_AZURE_USER'] : 'tinytds'
72
+ password = sqlserver_azure? ? ENV['TINYTDS_UNIT_AZURE_PASS'] : ''
73
+ { :dataserver => ENV['TINYTDS_UNIT_DATASERVER'],
74
+ :host => ENV['TINYTDS_UNIT_HOST'],
75
+ :username => username,
76
+ :password => password,
77
+ :database => 'tinytdstest',
78
+ :appname => 'TinyTds Dev',
79
+ :login_timeout => 5,
80
+ :timeout => 5,
81
+ :azure => sqlserver_azure?
82
+ }.merge(options)
83
+ end
84
+
85
+ def assert_client_works(client)
86
+ client.execute("SELECT 'client_works' as [client_works]").each
87
+ end
88
+
89
+ def assert_new_connections_work
90
+ client = new_connection
91
+ client.execute("SELECT 'new_connections_work' as [new_connections_work]").each
92
+ end
93
+
94
+ def assert_raise_tinytds_error(action)
95
+ error_raised = false
96
+ begin
97
+ action.call
98
+ rescue TinyTds::Error => e
99
+ error_raised = true
100
+ end
101
+ assert error_raised, 'expected a TinyTds::Error but none happened'
102
+ yield e
103
+ end
104
+
105
+ def inspect_tinytds_exception
106
+ begin
107
+ yield
108
+ rescue TinyTds::Error => e
109
+ props = { :source => e.source, :message => e.message, :severity => e.severity,
110
+ :db_error_number => e.db_error_number, :os_error_number => e.os_error_number }
111
+ raise "TinyTds::Error - #{props.inspect}"
112
+ end
113
+ end
114
+
115
+ def assert_binary_encoding(value)
116
+ assert_equal Encoding.find('BINARY'), value.encoding if ruby19?
117
+ end
118
+
119
+ def assert_utf8_encoding(value)
120
+ assert_equal Encoding.find('UTF-8'), value.encoding if ruby19?
121
+ end
122
+
123
+ def ruby18?
124
+ RUBY_VERSION < '1.9'
125
+ end
126
+
127
+ def ruby186?
128
+ RUBY_VERSION == '1.8.6'
129
+ end
130
+
131
+ def ruby19?
132
+ RUBY_VERSION >= '1.9'
133
+ end
134
+
135
+ def ruby192?
136
+ RUBY_VERSION == '1.9.2'
137
+ end
138
+
139
+ def rubyRbx?
140
+ RUBY_DESCRIPTION =~ /rubinius/i
141
+ end
142
+
143
+ def load_current_schema
144
+ loader = new_connection
145
+ schema_file = File.expand_path File.join(File.dirname(__FILE__), 'schema', "#{current_schema}.sql")
146
+ schema_sql = ruby18? ? File.read(schema_file) : File.open(schema_file,"rb:UTF-8") { |f|f.read }
147
+ loader.execute(drop_sql).each
148
+ loader.execute(schema_sql).cancel
149
+ loader.execute(sp_sql).cancel
150
+ loader.close
151
+ true
152
+ end
153
+
154
+ def drop_sql
155
+ %|IF EXISTS (
156
+ SELECT TABLE_NAME
157
+ FROM INFORMATION_SCHEMA.TABLES
158
+ WHERE TABLE_CATALOG = 'tinytdstest'
159
+ AND TABLE_TYPE = 'BASE TABLE'
160
+ AND TABLE_NAME = 'datatypes'
161
+ ) DROP TABLE [datatypes]
162
+ IF EXISTS (
163
+ SELECT name FROM sysobjects
164
+ WHERE name = 'tinytds_TestReturnCodes' AND type = 'P'
165
+ ) DROP PROCEDURE tinytds_TestReturnCodes|
166
+ end
167
+
168
+ def sp_sql
169
+ %|CREATE PROCEDURE tinytds_TestReturnCodes
170
+ AS
171
+ SELECT 1 as [one]
172
+ RETURN(420) |
173
+ end
174
+
175
+ def find_value(id, column, query_options={})
176
+ query_options[:timezone] ||= :utc
177
+ sql = "SELECT [#{column}] FROM [datatypes] WHERE [id] = #{id}"
178
+ @client.execute(sql).each(query_options).first[column.to_s]
179
+ end
180
+
181
+ def local_offset
182
+ TinyTds::Client.local_offset
183
+ end
184
+
185
+ def utc_offset
186
+ ::Time.local(2010).utc_offset
187
+ end
188
+
189
+ def rollback_transaction(client)
190
+ client.execute("BEGIN TRANSACTION").do
191
+ yield
192
+ ensure
193
+ client.execute("ROLLBACK TRANSACTION").do
194
+ end
195
+
196
+
197
+ end
198
+ end
199
+