tiny_tds 0.5.1.rc1 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1 -1
- data/Gemfile +2 -2
- data/README.md +6 -2
- data/Rakefile +1 -0
- data/ext/tiny_tds/extconf.rb +70 -60
- data/lib/tiny_tds/client.rb +1 -0
- data/lib/tiny_tds/version.rb +1 -1
- data/test/client_test.rb +3 -3
- data/test/result_test.rb +43 -19
- data/test/schema/sybase_ase.sql +138 -0
- data/test/schema_test.rb +3 -3
- data/test/test_helper.rb +32 -4
- metadata +11 -15
data/CHANGELOG
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -288,15 +288,19 @@ $ rake native gem
|
|
288
288
|
$ gem install pkg/tiny_tds-X.X.X-#{platform}.gem
|
289
289
|
```
|
290
290
|
|
291
|
+
**Important:** You must use rubygems version 1.7.2 or higher. You will almost certainly hit a *Don't know how to build task...* error when running the `rake native gem` command if you do not. Please update rubygems! Here is a link on [how to upgrade or downgrade rubygems](http://rubygems.rubyforge.org/rubygems-update/UPGRADING_rdoc.html).
|
292
|
+
|
291
293
|
|
292
294
|
## Development & Testing
|
293
295
|
|
294
|
-
We use bundler for development. Simply run `bundle install` then `rake` to build the gem and run the unit tests. The tests assume you have created a database named `tinytdstest` accessible by a database owner named `tinytds`. Before running the test rake task, you may need to define a pair of environment variables that help the client connect to your specific FreeTDS database server name and which schema (2000, 2005, 2008 or
|
296
|
+
We use bundler for development. Simply run `bundle install` then `rake` to build the gem and run the unit tests. The tests assume you have created a database named `tinytdstest` accessible by a database owner named `tinytds`. Before running the test rake task, you may need to define a pair of environment variables that help the client connect to your specific FreeTDS database server name and which schema (2000, 2005, 2008, Azure or Sybase ASE) to use. For example:
|
295
297
|
|
296
298
|
```
|
297
299
|
$ rake TINYTDS_UNIT_DATASERVER=mydbserver TINYTDS_SCHEMA=sqlserver_2008
|
298
300
|
or
|
299
301
|
$ rake TINYTDS_UNIT_HOST=mydb.host.net TINYTDS_SCHEMA=sqlserver_azure
|
302
|
+
or
|
303
|
+
$ rake TINYTDS_UNIT_HOST=mydb.host.net TINYTDS_UNIT_PORT=5000 TINYTDS_SCHEMA=sybase_ase
|
300
304
|
```
|
301
305
|
|
302
306
|
If you do not want to use MiniPortile to compile a local project version of FreeTDS and instead use your local system version, use the `TINYTDS_SKIP_PORTS` environment variable. This will ignore any port tasks and will instead build and link to your system's FreeTDS installation as a normal gem install would.
|
@@ -323,7 +327,7 @@ $ rake TINYTDS_SKIP_PORTS=true
|
|
323
327
|
|
324
328
|
## About Me
|
325
329
|
|
326
|
-
My name is Ken Collins and I currently maintain the SQL Server adapter for ActiveRecord and wrote this library as my first cut into learning ruby C extensions. Hopefully it will help promote the power of ruby and the
|
330
|
+
My name is Ken Collins and I currently maintain the SQL Server adapter for ActiveRecord and wrote this library as my first cut into learning ruby C extensions. Hopefully it will help promote the power of ruby and the Rails framework to those that have not yet discovered it. My blog is http://metaskills.net and I can be found on twitter as @metaskills. Enjoy!
|
327
331
|
|
328
332
|
|
329
333
|
## Special Thanks
|
data/Rakefile
CHANGED
data/ext/tiny_tds/extconf.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
|
+
ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
|
2
|
+
|
3
|
+
# :stopdoc:
|
4
|
+
|
1
5
|
require 'mkmf'
|
2
6
|
|
3
|
-
|
4
|
-
|
7
|
+
# Shamelessly copied from nokogiri
|
8
|
+
#
|
9
|
+
LIBDIR = RbConfig::CONFIG['libdir']
|
10
|
+
INCLUDEDIR = RbConfig::CONFIG['includedir']
|
5
11
|
|
6
|
-
|
7
|
-
|
12
|
+
$CFLAGS << " #{ENV["CFLAGS"]}"
|
13
|
+
$LDFLAGS << " #{ENV["LDFLAGS"]}"
|
14
|
+
$LIBS << " #{ENV["LIBS"]}"
|
8
15
|
|
9
|
-
|
16
|
+
SEARCHABLE_PATHS = begin
|
10
17
|
eop_regexp = /#{File::SEPARATOR}bin$/
|
11
18
|
paths = ENV['PATH']
|
12
19
|
paths = paths.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
|
@@ -15,69 +22,72 @@ def root_paths
|
|
15
22
|
bin_paths.map{ |p| p.sub(eop_regexp,'') }.compact.reject{ |p| p.empty? }.uniq
|
16
23
|
end
|
17
24
|
|
18
|
-
def
|
19
|
-
|
25
|
+
def searchable_paths_with_directories(*directories)
|
26
|
+
SEARCHABLE_PATHS.map do |path|
|
27
|
+
directories.map do |paths|
|
28
|
+
dir = File.join path, *paths
|
29
|
+
File.directory?(dir) ? dir : nil
|
30
|
+
end.flatten.compact
|
31
|
+
end.flatten.compact
|
20
32
|
end
|
21
33
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
if RbConfig::CONFIG['target_os'] =~ /mswin32|mingw32/
|
35
|
+
lib_prefix = 'lib' unless RbConfig::CONFIG['target_os'] =~ /mingw32/
|
36
|
+
# There's no default include/lib dir on Windows. Let's just add the Ruby ones
|
37
|
+
# and resort on the search path specified by INCLUDE and LIB environment
|
38
|
+
# variables
|
39
|
+
HEADER_DIRS = [INCLUDEDIR]
|
40
|
+
LIB_DIRS = [LIBDIR]
|
41
|
+
else
|
42
|
+
lib_prefix = ''
|
43
|
+
HEADER_DIRS = [
|
44
|
+
# First search /opt/local for macports
|
45
|
+
'/opt/local/include',
|
46
|
+
# Then search /usr/local for people that installed from source
|
47
|
+
'/usr/local/include',
|
48
|
+
# Check the ruby install locations
|
49
|
+
INCLUDEDIR,
|
50
|
+
# Finally fall back to /usr
|
51
|
+
'/usr/include'
|
52
|
+
].reject{ |dir| !File.directory?(dir) }
|
53
|
+
LIB_DIRS = [
|
54
|
+
# First search /opt/local for macports
|
55
|
+
'/opt/local/lib',
|
56
|
+
# Then search /usr/local for people that installed from source
|
57
|
+
'/usr/local/lib',
|
58
|
+
# Check the ruby install locations
|
59
|
+
LIBDIR,
|
60
|
+
# Finally fall back to /usr
|
61
|
+
'/usr/lib',
|
62
|
+
].reject{ |dir| !File.directory?(dir) }
|
41
63
|
end
|
42
64
|
|
43
|
-
|
44
|
-
|
45
|
-
end
|
65
|
+
FREETDS_HEADER_DIRS = (searchable_paths_with_directories(['include'],['include','freetds']) + HEADER_DIRS).uniq
|
66
|
+
FREETDS_LIB_DIRS = (searchable_paths_with_directories(['lib'],['lib','freetds']) + LIB_DIRS).uniq
|
46
67
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
$CPPFLAGS = "-I#{dir} #{$CPPFLAGS}".strip
|
56
|
-
true
|
57
|
-
else
|
58
|
-
false
|
59
|
-
end
|
60
|
-
else
|
61
|
-
puts "#{message} no"
|
62
|
-
false
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
68
|
+
# lookup over searchable paths is great for native compilation, however, when
|
69
|
+
# cross compiling we need to specify our own paths.
|
70
|
+
if enable_config("lookup", true)
|
71
|
+
dir_config('iconv', FREETDS_HEADER_DIRS, FREETDS_LIB_DIRS)
|
72
|
+
dir_config('freetds', FREETDS_HEADER_DIRS, FREETDS_LIB_DIRS)
|
73
|
+
else
|
74
|
+
dir_config('iconv')
|
75
|
+
dir_config('freetds')
|
67
76
|
|
68
|
-
|
69
|
-
|
77
|
+
# remove LDFLAGS
|
78
|
+
$LDFLAGS = ENV.fetch("LDFLAGS", "")
|
70
79
|
end
|
71
80
|
|
72
|
-
|
73
|
-
|
74
|
-
abort "-----\nCan not find FreeTDS's db-lib or include directory.\n-----"
|
75
|
-
end
|
76
|
-
else
|
77
|
-
$LDFLAGS = ENV.fetch("LDFLAGS")
|
78
|
-
unless have_freetds_libraries?(*FREETDS_LIBRARIES) && have_freetds_headers?(*FREETDS_HEADERS)
|
79
|
-
abort "-----\nCan not find FreeTDS's db-lib or include directory.\n-----"
|
80
|
-
end
|
81
|
+
def asplode(lib)
|
82
|
+
abort "-----\n#{lib} is missing.\n-----"
|
81
83
|
end
|
82
84
|
|
85
|
+
asplode 'libiconv' unless have_func('iconv_open', 'iconv.h') || have_library('iconv', 'iconv_open', 'iconv.h')
|
86
|
+
asplode 'freetds' unless have_header('sybfront.h') && have_header('sybdb.h')
|
87
|
+
|
88
|
+
asplode 'freetds' unless find_library("#{lib_prefix}sybdb", 'tdsdbopen')
|
89
|
+
asplode 'freetds' unless find_library("#{lib_prefix}ct", 'ct_bind')
|
90
|
+
|
83
91
|
create_makefile('tiny_tds/tiny_tds')
|
92
|
+
|
93
|
+
# :startdoc:
|
data/lib/tiny_tds/client.rb
CHANGED
@@ -54,6 +54,7 @@ module TinyTds
|
|
54
54
|
|
55
55
|
|
56
56
|
def initialize(opts={})
|
57
|
+
warn 'FreeTDS may have issues with passwords longer than 30 characters!' if opts[:password].to_s.length > 30
|
57
58
|
raise ArgumentError, 'missing :username option' if opts[:username].to_s.empty?
|
58
59
|
raise ArgumentError, 'missing :host option if no :dataserver given' if opts[:dataserver].to_s.empty? && opts[:host].to_s.empty?
|
59
60
|
@query_options = @@default_query_options.dup
|
data/lib/tiny_tds/version.rb
CHANGED
data/test/client_test.rb
CHANGED
@@ -7,7 +7,7 @@ class ClientTest < TinyTds::TestCase
|
|
7
7
|
setup do
|
8
8
|
@client = new_connection
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
should 'not be closed' do
|
12
12
|
assert !@client.closed?
|
13
13
|
assert @client.active?
|
@@ -46,7 +46,7 @@ class ClientTest < TinyTds::TestCase
|
|
46
46
|
end
|
47
47
|
|
48
48
|
should 'be able to use :host/:port connection' do
|
49
|
-
client = new_connection :dataserver => nil, :host => ENV['TINYTDS_UNIT_HOST'], :port => 1433
|
49
|
+
client = new_connection :dataserver => nil, :host => ENV['TINYTDS_UNIT_HOST'], :port => ENV['TINYTDS_UNIT_PORT'] || 1433
|
50
50
|
end unless sqlserver_azure?
|
51
51
|
|
52
52
|
end
|
@@ -136,7 +136,7 @@ class ClientTest < TinyTds::TestCase
|
|
136
136
|
if sqlserver_azure?
|
137
137
|
assert_match %r{server name cannot be determined}i, e.message, 'ignore if non-english test run'
|
138
138
|
else
|
139
|
-
assert_equal 18456, e.db_error_number
|
139
|
+
assert_equal sybase_ase? ? 4002 : 18456, e.db_error_number
|
140
140
|
assert_equal 14, e.severity
|
141
141
|
assert_match %r{login failed}i, e.message, 'ignore if non-english test run'
|
142
142
|
end
|
data/test/result_test.rb
CHANGED
@@ -369,14 +369,22 @@ class ResultTest < TinyTds::TestCase
|
|
369
369
|
end
|
370
370
|
|
371
371
|
should 'from a stored procedure' do
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
372
|
+
if sqlserver?
|
373
|
+
results1, results2 = @client.execute("EXEC sp_helpconstraint '[datatypes]'").each
|
374
|
+
assert_equal [{"Object Name"=>"[datatypes]"}], results1
|
375
|
+
constraint_info = results2.first
|
376
|
+
assert constraint_info.key?("constraint_keys")
|
377
|
+
assert constraint_info.key?("constraint_type")
|
378
|
+
assert constraint_info.key?("constraint_name")
|
379
|
+
elsif sybase_ase?
|
380
|
+
results1, results2 = @client.execute("EXEC sp_helpconstraint 'datatypes'").each
|
381
|
+
assert results1['name'] =~ /^datatypes_bit/
|
382
|
+
assert results1['defintion'] == 'DEFAULT 0'
|
383
|
+
assert results2['name'] =~ /^datatypes_id/
|
384
|
+
assert results2['defintion'] =~ /^PRIMARY KEY/
|
385
|
+
end
|
378
386
|
end
|
379
|
-
|
387
|
+
|
380
388
|
context 'using :empty_sets TRUE' do
|
381
389
|
|
382
390
|
setup do
|
@@ -565,7 +573,7 @@ class ResultTest < TinyTds::TestCase
|
|
565
573
|
insert_and_select_datatype :nvarchar_max
|
566
574
|
end
|
567
575
|
|
568
|
-
end unless sqlserver_2000?
|
576
|
+
end unless sqlserver_2000? || sybase_ase?
|
569
577
|
|
570
578
|
end
|
571
579
|
|
@@ -576,20 +584,36 @@ class ResultTest < TinyTds::TestCase
|
|
576
584
|
assert_equal [], @client.execute('').each
|
577
585
|
end
|
578
586
|
|
579
|
-
|
580
|
-
|
581
|
-
|
587
|
+
if sybase_ase?
|
588
|
+
|
589
|
+
should 'not raise an error when severity is 10 or less' do
|
590
|
+
(1..10).to_a.each do |severity|
|
591
|
+
@client.execute("RAISERROR(N'Test #{severity} severity', #{severity}, 1)").do
|
592
|
+
end
|
582
593
|
end
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
594
|
+
|
595
|
+
should 'raise an error when severity is greater than 10' do
|
596
|
+
action = lambda { @client.execute("RAISERROR(N'Test 11 severity', 11, 1)").do }
|
597
|
+
assert_raise_tinytds_error(action) do |e|
|
598
|
+
assert_equal "Test 11 severity", e.message
|
599
|
+
assert_equal 11, e.severity
|
600
|
+
assert_equal 50000, e.db_error_number
|
601
|
+
end
|
591
602
|
end
|
603
|
+
|
604
|
+
else
|
605
|
+
|
606
|
+
should 'raise an error' do
|
607
|
+
action = lambda { @client.execute("RAISERROR 99999 'Hello World'").do }
|
608
|
+
assert_raise_tinytds_error(action) do |e|
|
609
|
+
assert_equal "Hello World", e.message
|
610
|
+
assert_equal 16, e.severity # predefined on ASE
|
611
|
+
assert_equal 99999, e.db_error_number
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
592
615
|
end
|
616
|
+
|
593
617
|
|
594
618
|
should 'throw an error when you execute another query with other results pending' do
|
595
619
|
result1 = @client.execute(@query1)
|
@@ -0,0 +1,138 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
|
4
|
+
* Binary Data - Our test binary data is a 1 pixel gif. The basic (raw) data is below. Quoting this data
|
5
|
+
would involve this (encode) method and be (encoded) with the 0x prefix for raw SQL. In other clients the
|
6
|
+
(raw_db) value without the 0x prefix would need to be (packed) again yield the original (raw) value.
|
7
|
+
|
8
|
+
(raw) - "GIF89a\001\000\001\000\221\000\000\377\377\377\377\377\377\376\001\002\000\000\000!\371\004\004\024\000\377\000,\000\000\000\000\001\000\001\000\000\002\002D\001\000;"
|
9
|
+
(encode) - "0x#{raw.unpack("H*")[0]}"
|
10
|
+
(encoded) - "0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b"
|
11
|
+
(raw_db) - "47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b"
|
12
|
+
(packed) - [raw_db].pack('H*')
|
13
|
+
|
14
|
+
*/
|
15
|
+
|
16
|
+
CREATE TABLE [datatypes] (
|
17
|
+
[id] [int] IDENTITY NOT NULL PRIMARY KEY,
|
18
|
+
[bigint] [bigint] NULL,
|
19
|
+
[binary_50] [binary](50) NULL,
|
20
|
+
[bit] [bit] DEFAULT 0,
|
21
|
+
[char_10] [char](10) NULL,
|
22
|
+
[date] [date] NULL,
|
23
|
+
[datetime] [datetime] NULL,
|
24
|
+
-- [datetime2_7] [datetime2](7) NULL,
|
25
|
+
-- [datetimeoffset_2] [datetimeoffset](2) NULL,
|
26
|
+
-- [datetimeoffset_7] [datetimeoffset](7) NULL,
|
27
|
+
[decimal_9_2] [decimal](9, 2) NULL,
|
28
|
+
[decimal_16_4] [decimal](16, 4) NULL,
|
29
|
+
[float] [float] NULL,
|
30
|
+
-- [geography] [geography] NULL,
|
31
|
+
-- [geometry] [geometry] NULL,
|
32
|
+
-- [hierarchyid] [hierarchyid] NULL,
|
33
|
+
[image] [image] NULL,
|
34
|
+
[int] [int] NULL,
|
35
|
+
[money] [money] NULL,
|
36
|
+
[nchar_10] [nchar](10) NULL,
|
37
|
+
-- [ntext] [ntext] NULL,
|
38
|
+
[numeric_18_0] [numeric](18, 0) NULL,
|
39
|
+
[numeric_36_2] [numeric](36, 2) NULL,
|
40
|
+
[nvarchar_50] [nvarchar](50) NULL,
|
41
|
+
-- [nvarchar_max] [nvarchar](max) NULL,
|
42
|
+
[real] [real] NULL,
|
43
|
+
[smalldatetime] [smalldatetime] NULL,
|
44
|
+
[smallint] [smallint] NULL,
|
45
|
+
[smallmoney] [smallmoney] NULL,
|
46
|
+
[text] [text] NULL,
|
47
|
+
-- [time_2] [time](2) NULL,
|
48
|
+
-- [time_7] [time](7) NULL,
|
49
|
+
[timestamp] [timestamp] NULL,
|
50
|
+
[tinyint] [tinyint] NULL,
|
51
|
+
-- [uniqueidentifier] [uniqueidentifier] NULL,
|
52
|
+
[varbinary_50] [varbinary](50) NULL,
|
53
|
+
-- [varbinary_max] [varbinary](max) NULL,
|
54
|
+
[varchar_50] [varchar](50) NULL
|
55
|
+
-- [varchar_max] [varchar](max) NULL,
|
56
|
+
-- [xml] [xml] NULL
|
57
|
+
)
|
58
|
+
|
59
|
+
SET IDENTITY_INSERT [dbo].[datatypes] ON
|
60
|
+
|
61
|
+
INSERT INTO [datatypes] ([id], [bigint]) VALUES ( 11, -9223372036854775807 )
|
62
|
+
INSERT INTO [datatypes] ([id], [bigint]) VALUES ( 12, 9223372036854775806 )
|
63
|
+
INSERT INTO [datatypes] ([id], [binary_50]) VALUES ( 21, 0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b )
|
64
|
+
INSERT INTO [datatypes] ([id], [bit]) VALUES ( 31, 1 )
|
65
|
+
INSERT INTO [datatypes] ([id], [bit]) VALUES ( 32, 0 )
|
66
|
+
INSERT INTO [datatypes] ([id], [char_10]) VALUES ( 41, '1234567890' )
|
67
|
+
INSERT INTO [datatypes] ([id], [char_10]) VALUES ( 42, '12345678' )
|
68
|
+
INSERT INTO [datatypes] ([id], [date]) VALUES ( 51, '0001-01-01' )
|
69
|
+
INSERT INTO [datatypes] ([id], [date]) VALUES ( 52, '9999-12-31' )
|
70
|
+
INSERT INTO [datatypes] ([id], [datetime]) VALUES ( 61, '1753-01-01T00:00:00.000' )
|
71
|
+
INSERT INTO [datatypes] ([id], [datetime]) VALUES ( 62, '9999-12-31T23:59:59.997' )
|
72
|
+
INSERT INTO [datatypes] ([id], [datetime]) VALUES ( 63, '2010-01-01T12:34:56.123' )
|
73
|
+
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 71, '0001-01-01T00:00:00.0000000Z' )
|
74
|
+
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 72, '1984-01-24T04:20:00.0000000-08:00' )
|
75
|
+
-- INSERT INTO [datatypes] ([id], [datetime2_7]) VALUES ( 73, '9999-12-31T23:59:59.9999999Z' )
|
76
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_2]) VALUES ( 81, '1984-01-24T04:20:00.0000000-08:00' ) -- 1984-01-24 04:20:00.00 -08:00
|
77
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_2]) VALUES ( 82, '1984-01-24T04:20:00.0000000Z' ) -- 1984-01-24 04:20:00.00 +00:00
|
78
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_2]) VALUES ( 83, '9999-12-31T23:59:59.9999999Z' ) -- 9999-12-31 23:59:59.99 +00:00
|
79
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_7]) VALUES ( 84, '1984-01-24T04:20:00.0000000-08:00' ) -- 1984-01-24 04:20:00.0000000 -08:00
|
80
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_7]) VALUES ( 85, '1984-01-24T04:20:00.0000000Z' ) -- 1984-01-24 04:20:00.0000000 +00:00
|
81
|
+
-- INSERT INTO [datatypes] ([id], [datetimeoffset_7]) VALUES ( 86, '9999-12-31T23:59:59.9999999Z' ) -- 9999-12-31 23:59:59.9999999 +00:00
|
82
|
+
INSERT INTO [datatypes] ([id], [decimal_9_2]) VALUES ( 91, 12345.01 )
|
83
|
+
INSERT INTO [datatypes] ([id], [decimal_9_2]) VALUES ( 92, 1234567.89 )
|
84
|
+
INSERT INTO [datatypes] ([id], [decimal_16_4]) VALUES ( 93, 0.0 )
|
85
|
+
INSERT INTO [datatypes] ([id], [decimal_16_4]) VALUES ( 94, 123456789012.3456 )
|
86
|
+
INSERT INTO [datatypes] ([id], [float]) VALUES ( 101, 123.00000001 )
|
87
|
+
INSERT INTO [datatypes] ([id], [float]) VALUES ( 102, 0.0 )
|
88
|
+
INSERT INTO [datatypes] ([id], [float]) VALUES ( 103, 123.45 )
|
89
|
+
-- INSERT INTO [datatypes] ([id], [geography]) VALUES ( 111, geography::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656)', 4326) ) -- 0xE610000001148716D9CEF7D34740D7A3703D0A975EC08716D9CEF7D34740CBA145B6F3955EC0
|
90
|
+
-- INSERT INTO [datatypes] ([id], [geometry]) VALUES ( 121, geometry::STGeomFromText('LINESTRING (100 100, 20 180, 180 180)', 0) ) -- 0x0000000001040300000000000000000059400000000000005940000000000000344000000000008066400000000000806640000000000080664001000000010000000001000000FFFFFFFF0000000002
|
91
|
+
-- INSERT INTO [datatypes] ([id], [hierarchyid]) VALUES ( 131, CAST('/1/' AS hierarchyid) ) -- 0x58
|
92
|
+
-- INSERT INTO [datatypes] ([id], [hierarchyid]) VALUES ( 132, CAST('/2/' AS hierarchyid) ) -- 0x68
|
93
|
+
INSERT INTO [datatypes] ([id], [image]) VALUES ( 141, 0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b )
|
94
|
+
INSERT INTO [datatypes] ([id], [int]) VALUES ( 151, -2147483647 )
|
95
|
+
INSERT INTO [datatypes] ([id], [int]) VALUES ( 152, 2147483646 )
|
96
|
+
INSERT INTO [datatypes] ([id], [money]) VALUES ( 161, 4.20 )
|
97
|
+
INSERT INTO [datatypes] ([id], [money]) VALUES ( 162, -922337203685477.5807 )
|
98
|
+
INSERT INTO [datatypes] ([id], [money]) VALUES ( 163, 922337203685477.5806 )
|
99
|
+
INSERT INTO [datatypes] ([id], [nchar_10]) VALUES ( 171, N'1234567890' )
|
100
|
+
INSERT INTO [datatypes] ([id], [nchar_10]) VALUES ( 172, N'123456åå' )
|
101
|
+
INSERT INTO [datatypes] ([id], [nchar_10]) VALUES ( 173, N'abc123' )
|
102
|
+
-- INSERT INTO [datatypes] ([id], [ntext]) VALUES ( 181, N'test ntext' )
|
103
|
+
-- INSERT INTO [datatypes] ([id], [ntext]) VALUES ( 182, N'test ntext åå' )
|
104
|
+
INSERT INTO [datatypes] ([id], [numeric_18_0]) VALUES ( 191, 191 )
|
105
|
+
INSERT INTO [datatypes] ([id], [numeric_18_0]) VALUES ( 192, 123456789012345678 )
|
106
|
+
INSERT INTO [datatypes] ([id], [numeric_36_2]) VALUES ( 193, 12345678901234567890.01 )
|
107
|
+
INSERT INTO [datatypes] ([id], [numeric_36_2]) VALUES ( 194, 123.46 )
|
108
|
+
INSERT INTO [datatypes] ([id], [nvarchar_50]) VALUES ( 201, N'test nvarchar_50' )
|
109
|
+
INSERT INTO [datatypes] ([id], [nvarchar_50]) VALUES ( 202, N'test nvarchar_50 åå' )
|
110
|
+
-- INSERT INTO [datatypes] ([id], [nvarchar_max]) VALUES ( 211, N'test nvarchar_max' )
|
111
|
+
-- INSERT INTO [datatypes] ([id], [nvarchar_max]) VALUES ( 212, N'test nvarchar_max åå' )
|
112
|
+
INSERT INTO [datatypes] ([id], [real]) VALUES ( 221, 123.45 )
|
113
|
+
INSERT INTO [datatypes] ([id], [real]) VALUES ( 222, 0.0 )
|
114
|
+
INSERT INTO [datatypes] ([id], [real]) VALUES ( 223, 0.00001 )
|
115
|
+
INSERT INTO [datatypes] ([id], [smalldatetime]) VALUES ( 231, '1901-01-01T15:45:00.000' ) -- 1901-01-01 15:45:00
|
116
|
+
INSERT INTO [datatypes] ([id], [smalldatetime]) VALUES ( 232, '2078-06-05T04:20:00.000' ) -- 2078-06-05 04:20:00
|
117
|
+
INSERT INTO [datatypes] ([id], [smallint]) VALUES ( 241, -32767 )
|
118
|
+
INSERT INTO [datatypes] ([id], [smallint]) VALUES ( 242, 32766 )
|
119
|
+
INSERT INTO [datatypes] ([id], [smallmoney]) VALUES ( 251, 4.20 )
|
120
|
+
INSERT INTO [datatypes] ([id], [smallmoney]) VALUES ( 252, -214748.3647 )
|
121
|
+
INSERT INTO [datatypes] ([id], [smallmoney]) VALUES ( 253, 214748.3646 )
|
122
|
+
INSERT INTO [datatypes] ([id], [text]) VALUES ( 271, 'test text' )
|
123
|
+
-- INSERT INTO [datatypes] ([id], [time_2]) VALUES ( 281, '1901-01-01T15:45:00.0100001Z' ) -- 15:45:00.01
|
124
|
+
-- INSERT INTO [datatypes] ([id], [time_2]) VALUES ( 282, '1984-01-24T04:20:00.0000001-08:00' ) -- 04:20:00.00
|
125
|
+
-- INSERT INTO [datatypes] ([id], [time_7]) VALUES ( 283, '1901-01-01T15:45:00.0100001Z' ) -- 15:45:00.0100001
|
126
|
+
-- INSERT INTO [datatypes] ([id], [time_7]) VALUES ( 284, '1984-01-24T04:20:00.0000001-08:00' ) -- 04:20:00.0000001
|
127
|
+
INSERT INTO [datatypes] ([id], [tinyint]) VALUES ( 301, 0 )
|
128
|
+
INSERT INTO [datatypes] ([id], [tinyint]) VALUES ( 302, 255 )
|
129
|
+
-- INSERT INTO [datatypes] ([id], [uniqueidentifier]) VALUES ( 311, NEWID() )
|
130
|
+
INSERT INTO [datatypes] ([id], [varbinary_50]) VALUES ( 321, 0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b )
|
131
|
+
-- INSERT INTO [datatypes] ([id], [varbinary_max]) VALUES ( 331, 0x47494638396101000100910000fffffffffffffe010200000021f904041400ff002c00000000010001000002024401003b )
|
132
|
+
INSERT INTO [datatypes] ([id], [varchar_50]) VALUES ( 341, 'test varchar_50' )
|
133
|
+
-- INSERT INTO [datatypes] ([id], [varchar_max]) VALUES ( 351, 'test varchar_max' )
|
134
|
+
-- INSERT INTO [datatypes] ([id], [xml]) VALUES ( 361, '<foo><bar>batz</bar></foo>' )
|
135
|
+
|
136
|
+
SET IDENTITY_INSERT [datatypes] OFF
|
137
|
+
|
138
|
+
|
data/test/schema_test.rb
CHANGED
@@ -7,7 +7,7 @@ class SchemaTest < TinyTds::TestCase
|
|
7
7
|
|
8
8
|
setup do
|
9
9
|
@@current_schema_loaded ||= load_current_schema
|
10
|
-
@client
|
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
|
|
@@ -159,7 +159,7 @@ class SchemaTest < TinyTds::TestCase
|
|
159
159
|
large_value = "x" * 5000
|
160
160
|
large_value_id = @client.execute("INSERT INTO [datatypes] ([ntext]) VALUES (N'#{large_value}')").insert
|
161
161
|
assert_equal large_value, find_value(large_value_id, :ntext)
|
162
|
-
end
|
162
|
+
end unless sybase_ase?
|
163
163
|
|
164
164
|
should 'cast numeric' do
|
165
165
|
assert_instance_of BigDecimal, find_value(191, :numeric_18_0)
|
@@ -257,7 +257,7 @@ class SchemaTest < TinyTds::TestCase
|
|
257
257
|
should 'cast 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
|
-
end
|
260
|
+
end unless sybase_ase?
|
261
261
|
|
262
262
|
should 'cast varbinary' do
|
263
263
|
value = find_value(321, :varbinary_50)
|
data/test/test_helper.rb
CHANGED
@@ -16,7 +16,7 @@ class DateTime
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
TINYTDS_SCHEMAS = ['sqlserver_2000', 'sqlserver_2005', 'sqlserver_2008', 'sqlserver_azure'].freeze
|
19
|
+
TINYTDS_SCHEMAS = ['sqlserver_2000', 'sqlserver_2005', 'sqlserver_2008', 'sqlserver_azure', 'sybase_ase'].freeze
|
20
20
|
|
21
21
|
module TinyTds
|
22
22
|
class TestCase < MiniTest::Spec
|
@@ -33,8 +33,15 @@ module TinyTds
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
def sqlserver?
|
37
|
+
current_schema =~ /sqlserver/
|
38
|
+
end
|
39
|
+
|
36
40
|
end
|
37
41
|
|
42
|
+
teardown do
|
43
|
+
@client.close if @client.is_a?(TinyTds::Client)
|
44
|
+
end
|
38
45
|
|
39
46
|
protected
|
40
47
|
|
@@ -48,9 +55,15 @@ module TinyTds
|
|
48
55
|
self.class.current_schema
|
49
56
|
end
|
50
57
|
|
58
|
+
def sqlserver?
|
59
|
+
self.class.sqlserver?
|
60
|
+
end
|
61
|
+
|
51
62
|
def new_connection(options={})
|
52
63
|
client = TinyTds::Client.new(connection_options(options))
|
53
|
-
|
64
|
+
if sybase_ase?
|
65
|
+
client.execute("SET ANSINULL ON").do
|
66
|
+
elsif !sqlserver_azure?
|
54
67
|
client.execute("SET ANSI_DEFAULTS ON").do
|
55
68
|
client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
|
56
69
|
client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
|
@@ -59,10 +72,11 @@ module TinyTds
|
|
59
72
|
end
|
60
73
|
|
61
74
|
def connection_options(options={})
|
62
|
-
username = sqlserver_azure? ? ENV['TINYTDS_UNIT_AZURE_USER'] : 'tinytds'
|
63
|
-
password = sqlserver_azure? ? ENV['TINYTDS_UNIT_AZURE_PASS'] : ''
|
75
|
+
username = sqlserver_azure? ? ENV['TINYTDS_UNIT_AZURE_USER'] : ENV['TINYTDS_UNIT_USER'] || 'tinytds'
|
76
|
+
password = sqlserver_azure? ? ENV['TINYTDS_UNIT_AZURE_PASS'] : ENV['TINYTDS_UNIT_PASS'] || ''
|
64
77
|
{ :dataserver => ENV['TINYTDS_UNIT_DATASERVER'],
|
65
78
|
:host => ENV['TINYTDS_UNIT_HOST'],
|
79
|
+
:port => ENV['TINYTDS_UNIT_PORT'],
|
66
80
|
:username => username,
|
67
81
|
:password => password,
|
68
82
|
:database => 'tinytdstest',
|
@@ -139,6 +153,7 @@ module TinyTds
|
|
139
153
|
loader = new_connection
|
140
154
|
schema_file = File.expand_path File.join(File.dirname(__FILE__), 'schema', "#{current_schema}.sql")
|
141
155
|
schema_sql = ruby18? ? File.read(schema_file) : File.open(schema_file,"rb:UTF-8") { |f|f.read }
|
156
|
+
|
142
157
|
loader.execute(drop_sql).each
|
143
158
|
loader.execute(schema_sql).cancel
|
144
159
|
loader.execute(sp_sql).cancel
|
@@ -147,6 +162,19 @@ module TinyTds
|
|
147
162
|
end
|
148
163
|
|
149
164
|
def drop_sql
|
165
|
+
sybase_ase? ? drop_sql_sybase : drop_sql_microsoft
|
166
|
+
end
|
167
|
+
|
168
|
+
def drop_sql_sybase
|
169
|
+
%|IF EXISTS(
|
170
|
+
SELECT 1 FROM sysobjects WHERE type = 'U' AND name = 'datatypes'
|
171
|
+
) DROP TABLE datatypes
|
172
|
+
IF EXISTS(
|
173
|
+
SELECT 1 FROM sysobjects WHERE type = 'P' AND name = 'tinytds_TestReturnCodes'
|
174
|
+
) DROP PROCEDURE tinytds_TestReturnCodes|
|
175
|
+
end
|
176
|
+
|
177
|
+
def drop_sql_microsoft
|
150
178
|
%|IF EXISTS (
|
151
179
|
SELECT TABLE_NAME
|
152
180
|
FROM INFORMATION_SCHEMA.TABLES
|
metadata
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiny_tds
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 9
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 5
|
9
9
|
- 1
|
10
|
-
|
11
|
-
- 1
|
12
|
-
version: 0.5.1.rc1
|
10
|
+
version: 0.5.1
|
13
11
|
platform: ruby
|
14
12
|
authors:
|
15
13
|
- Ken Collins
|
@@ -18,8 +16,7 @@ autorequire:
|
|
18
16
|
bindir: bin
|
19
17
|
cert_chain: []
|
20
18
|
|
21
|
-
date:
|
22
|
-
default_executable:
|
19
|
+
date: 2012-01-23 00:00:00 Z
|
23
20
|
dependencies: []
|
24
21
|
|
25
22
|
description: TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library. Developed for the ActiveRecord SQL Server adapter.
|
@@ -62,9 +59,9 @@ files:
|
|
62
59
|
- test/schema/sqlserver_2005.sql
|
63
60
|
- test/schema/sqlserver_2008.sql
|
64
61
|
- test/schema/sqlserver_azure.sql
|
62
|
+
- test/schema/sybase_ase.sql
|
65
63
|
- test/schema_test.rb
|
66
64
|
- test/test_helper.rb
|
67
|
-
has_rdoc: true
|
68
65
|
homepage: http://github.com/rails-sqlserver/tiny_tds
|
69
66
|
licenses: []
|
70
67
|
|
@@ -85,18 +82,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
83
|
none: false
|
87
84
|
requirements:
|
88
|
-
- - "
|
85
|
+
- - ">="
|
89
86
|
- !ruby/object:Gem::Version
|
90
|
-
hash:
|
87
|
+
hash: 3
|
91
88
|
segments:
|
92
|
-
-
|
93
|
-
|
94
|
-
- 1
|
95
|
-
version: 1.3.1
|
89
|
+
- 0
|
90
|
+
version: "0"
|
96
91
|
requirements: []
|
97
92
|
|
98
93
|
rubyforge_project:
|
99
|
-
rubygems_version: 1.
|
94
|
+
rubygems_version: 1.8.15
|
100
95
|
signing_key:
|
101
96
|
specification_version: 3
|
102
97
|
summary: TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library.
|
@@ -111,5 +106,6 @@ test_files:
|
|
111
106
|
- test/schema/sqlserver_2005.sql
|
112
107
|
- test/schema/sqlserver_2008.sql
|
113
108
|
- test/schema/sqlserver_azure.sql
|
109
|
+
- test/schema/sybase_ase.sql
|
114
110
|
- test/schema_test.rb
|
115
111
|
- test/test_helper.rb
|