do_sqlserver 0.10.1-java
Sign up to get free protection for your applications and to get access to all the features.
- data/CONNECTING.markdown +41 -0
- data/ChangeLog.markdown +25 -0
- data/FAQS.markdown +8 -0
- data/INSTALL.markdown +76 -0
- data/LICENSE +21 -0
- data/README.markdown +110 -0
- data/Rakefile +56 -0
- data/lib/dbd_odbc_patch.rb +50 -0
- data/lib/do_sqlserver.rb +296 -0
- data/lib/do_sqlserver/do_sqlserver.jar +0 -0
- data/lib/do_sqlserver/transaction.rb +36 -0
- data/lib/do_sqlserver/version.rb +5 -0
- data/spec/command_spec.rb +9 -0
- data/spec/connection_spec.rb +21 -0
- data/spec/encoding_spec.rb +8 -0
- data/spec/reader_spec.rb +8 -0
- data/spec/result_spec.rb +16 -0
- data/spec/spec_helper.rb +147 -0
- data/spec/typecast/array_spec.rb +8 -0
- data/spec/typecast/bigdecimal_spec.rb +9 -0
- data/spec/typecast/boolean_spec.rb +9 -0
- data/spec/typecast/byte_array_spec.rb +31 -0
- data/spec/typecast/class_spec.rb +8 -0
- data/spec/typecast/date_spec.rb +11 -0
- data/spec/typecast/datetime_spec.rb +9 -0
- data/spec/typecast/float_spec.rb +9 -0
- data/spec/typecast/integer_spec.rb +8 -0
- data/spec/typecast/nil_spec.rb +10 -0
- data/spec/typecast/other_spec.rb +8 -0
- data/spec/typecast/range_spec.rb +8 -0
- data/spec/typecast/string_spec.rb +8 -0
- data/spec/typecast/time_spec.rb +8 -0
- data/tasks/compile.rake +29 -0
- data/tasks/release.rake +14 -0
- data/tasks/spec.rake +23 -0
- metadata +161 -0
Binary file
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module DataObjects
|
2
|
+
|
3
|
+
module SqlServer
|
4
|
+
|
5
|
+
class Transaction < DataObjects::Transaction
|
6
|
+
|
7
|
+
def begin
|
8
|
+
connection.instance_variable_get("@connection").autocommit = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def commit
|
12
|
+
connection.instance_variable_get("@connection").commit
|
13
|
+
ensure
|
14
|
+
connection.instance_variable_get("@connection").autocommit = true
|
15
|
+
end
|
16
|
+
|
17
|
+
def rollback
|
18
|
+
connection.instance_variable_get("@connection").rollback
|
19
|
+
ensure
|
20
|
+
connection.instance_variable_get("@connection").autocommit = true
|
21
|
+
end
|
22
|
+
|
23
|
+
def rollback_prepared
|
24
|
+
# TODO: what should be done differently?
|
25
|
+
rollback
|
26
|
+
end
|
27
|
+
|
28
|
+
def prepare
|
29
|
+
# TODO: what should be done here?
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
4
|
+
require 'data_objects/spec/connection_spec'
|
5
|
+
|
6
|
+
describe DataObjects::SqlServer::Connection do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@driver = CONFIG.scheme
|
10
|
+
@user = CONFIG.user
|
11
|
+
@password = CONFIG.pass
|
12
|
+
@host = CONFIG.host
|
13
|
+
@port = CONFIG.port
|
14
|
+
@database = CONFIG.database
|
15
|
+
end
|
16
|
+
|
17
|
+
behaves_like 'a Connection'
|
18
|
+
#behaves_like 'a Connection with authentication support'
|
19
|
+
# FIXME: behaves_like 'a Connection with JDBC URL support' if JRUBY
|
20
|
+
behaves_like 'a Connection via JDNI' if JRUBY
|
21
|
+
end
|
data/spec/reader_spec.rb
ADDED
data/spec/result_spec.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
4
|
+
require 'data_objects/spec/result_spec'
|
5
|
+
|
6
|
+
# splitting the descibe into two separate declaration avoids
|
7
|
+
# concurrent execution of the "behaves_like ....."
|
8
|
+
# needed by some databases (sqlite3)
|
9
|
+
|
10
|
+
describe DataObjects::SqlServer::Result do
|
11
|
+
behaves_like 'a Result'
|
12
|
+
end
|
13
|
+
|
14
|
+
describe DataObjects::SqlServer::Result do
|
15
|
+
behaves_like 'a Result which returns inserted keys'
|
16
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
$TESTING=true
|
2
|
+
JRUBY = RUBY_PLATFORM =~ /java/
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'date'
|
6
|
+
require 'ostruct'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
driver_lib = File.expand_path('../../lib', __FILE__)
|
10
|
+
$LOAD_PATH.unshift(driver_lib) unless $LOAD_PATH.include?(driver_lib)
|
11
|
+
|
12
|
+
# Prepend data_objects/do_jdbc in the repository to the load path.
|
13
|
+
# DO NOT USE installed gems, except when running the specs from gem.
|
14
|
+
repo_root = File.expand_path('../../..', __FILE__)
|
15
|
+
(['data_objects'] << ('do_jdbc' if JRUBY)).compact.each do |lib|
|
16
|
+
lib_path = "#{repo_root}/#{lib}/lib"
|
17
|
+
$LOAD_PATH.unshift(lib_path) if File.directory?(lib_path) && !$LOAD_PATH.include?(lib_path)
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'data_objects'
|
21
|
+
require 'data_objects/spec/bacon'
|
22
|
+
require 'do_sqlserver'
|
23
|
+
|
24
|
+
DataObjects::SqlServer.logger = DataObjects::Logger.new(STDOUT, :off)
|
25
|
+
at_exit { DataObjects.logger.flush }
|
26
|
+
|
27
|
+
CONFIG = OpenStruct.new
|
28
|
+
CONFIG.scheme = 'sqlserver'
|
29
|
+
CONFIG.user = ENV['DO_SQLSERVER_USER'] || 'do_test'
|
30
|
+
CONFIG.pass = ENV['DO_SQLSERVER_PASS'] || 'do_test'
|
31
|
+
CONFIG.host = ENV['DO_SQLSERVER_HOST'] || 'localhost'
|
32
|
+
CONFIG.port = ENV['DO_SQLSERVER_PORT'] || '1433'
|
33
|
+
CONFIG.instance = ENV['DO_SQLSERVER_INSTANCE'] || 'SQLEXPRESS'
|
34
|
+
CONFIG.database = ENV['DO_SQLSERVER_DATABASE'] || "/do_test;instance=#{CONFIG.instance};"
|
35
|
+
|
36
|
+
CONFIG.uri = ENV["DO_SQLSERVER_SPEC_URI"] ||"#{CONFIG.scheme}://#{CONFIG.user}:#{CONFIG.pass}@#{CONFIG.host}:#{CONFIG.port}#{CONFIG.database}"
|
37
|
+
CONFIG.sleep = "WAITFOR DELAY '00:00:01'"
|
38
|
+
|
39
|
+
module DataObjectsSpecHelpers
|
40
|
+
|
41
|
+
def setup_test_environment
|
42
|
+
conn = DataObjects::Connection.new(CONFIG.uri)
|
43
|
+
|
44
|
+
conn.create_command(<<-EOF).execute_non_query
|
45
|
+
IF OBJECT_ID('invoices') IS NOT NULL DROP TABLE invoices
|
46
|
+
EOF
|
47
|
+
|
48
|
+
conn.create_command(<<-EOF).execute_non_query
|
49
|
+
IF OBJECT_ID('users') IS NOT NULL DROP TABLE users
|
50
|
+
EOF
|
51
|
+
|
52
|
+
conn.create_command(<<-EOF).execute_non_query
|
53
|
+
IF OBJECT_ID('widgets') IS NOT NULL DROP TABLE widgets
|
54
|
+
EOF
|
55
|
+
|
56
|
+
conn.create_command(<<-EOF).execute_non_query
|
57
|
+
CREATE TABLE "users" (
|
58
|
+
"id" int NOT NULL IDENTITY,
|
59
|
+
"name" nvarchar(200) default 'Billy' NULL,
|
60
|
+
"fired_at" timestamp,
|
61
|
+
PRIMARY KEY ("id")
|
62
|
+
);
|
63
|
+
EOF
|
64
|
+
|
65
|
+
conn.create_command(<<-EOF).execute_non_query
|
66
|
+
CREATE TABLE "invoices" (
|
67
|
+
"id" int NOT NULL IDENTITY,
|
68
|
+
"invoice_number" varchar(50) NOT NULL,
|
69
|
+
PRIMARY KEY ("id")
|
70
|
+
);
|
71
|
+
EOF
|
72
|
+
|
73
|
+
conn.create_command(<<-EOF).execute_non_query
|
74
|
+
CREATE TABLE "widgets" (
|
75
|
+
"id" int NOT NULL IDENTITY,
|
76
|
+
"code" char(8) default 'A14' NULL,
|
77
|
+
"name" varchar(200) default 'Super Widget' NULL,
|
78
|
+
"shelf_location" nvarchar(max) NULL,
|
79
|
+
"description" nvarchar(max) NULL,
|
80
|
+
"image_data" image NULL,
|
81
|
+
"ad_description" varchar(8000) NULL,
|
82
|
+
"ad_image" image NULL,
|
83
|
+
"whitepaper_text" nvarchar(max) NULL,
|
84
|
+
"cad_drawing" image NULL,
|
85
|
+
"flags" bit default 0,
|
86
|
+
"number_in_stock" smallint default 500,
|
87
|
+
"number_sold" int default 0,
|
88
|
+
"super_number" bigint default 9223372036854775807,
|
89
|
+
"weight" float default 1.23,
|
90
|
+
"cost1" real default 10.23,
|
91
|
+
"cost2" decimal(8,2) default 50.23,
|
92
|
+
"release_date" smalldatetime default '2008-02-14', -- date type is SQL Server 2008 only
|
93
|
+
"release_datetime" datetime default '2008-02-14 00:31:12',
|
94
|
+
"release_timestamp" smalldatetime /* default '2008-02-14 00:31:31' */,
|
95
|
+
-- "status" enum('active','out of stock') NOT NULL default 'active',
|
96
|
+
PRIMARY KEY ("id")
|
97
|
+
);
|
98
|
+
EOF
|
99
|
+
|
100
|
+
1.upto(16) do |n|
|
101
|
+
conn.create_command(<<-EOF).execute_non_query(::Extlib::ByteArray.new("CAD \001 \000 DRAWING"))
|
102
|
+
insert into widgets(code, name, shelf_location, description, image_data, ad_description, ad_image, whitepaper_text, cad_drawing, super_number, weight)
|
103
|
+
VALUES ('W#{n.to_s.rjust(7,"0")}', 'Widget #{n}', 'A14', 'This is a description', 'IMAGE DATA', 'Buy this product now!', 'AD IMAGE DATA', 'String', ?, 1234, 13.4);
|
104
|
+
EOF
|
105
|
+
end
|
106
|
+
|
107
|
+
conn.create_command(<<-EOF).execute_non_query
|
108
|
+
update widgets set flags = 1 where id = 2
|
109
|
+
EOF
|
110
|
+
|
111
|
+
conn.create_command(<<-EOF).execute_non_query
|
112
|
+
update widgets set ad_description = NULL where id = 3
|
113
|
+
EOF
|
114
|
+
|
115
|
+
conn.create_command(<<-EOF).execute_non_query
|
116
|
+
update widgets set flags = NULL where id = 4
|
117
|
+
EOF
|
118
|
+
|
119
|
+
conn.create_command(<<-EOF).execute_non_query
|
120
|
+
update widgets set cost1 = NULL where id = 5
|
121
|
+
EOF
|
122
|
+
|
123
|
+
conn.create_command(<<-EOF).execute_non_query
|
124
|
+
update widgets set cost2 = NULL where id = 6
|
125
|
+
EOF
|
126
|
+
|
127
|
+
conn.create_command(<<-EOF).execute_non_query
|
128
|
+
update widgets set release_date = NULL where id = 7
|
129
|
+
EOF
|
130
|
+
|
131
|
+
conn.create_command(<<-EOF).execute_non_query
|
132
|
+
update widgets set release_datetime = NULL where id = 8
|
133
|
+
EOF
|
134
|
+
|
135
|
+
# (cannot update a Timestamp column w/MSSQL)
|
136
|
+
# so we use a smalldatetime
|
137
|
+
conn.create_command(<<-EOF).execute_non_query
|
138
|
+
update widgets set release_timestamp = NULL where id = 9
|
139
|
+
EOF
|
140
|
+
|
141
|
+
conn.close
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
include DataObjectsSpecHelpers
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
require 'data_objects/spec/typecast/bigdecimal_spec'
|
5
|
+
|
6
|
+
describe 'DataObjects::SqlServer with BigDecimal' do
|
7
|
+
behaves_like 'supporting BigDecimal'
|
8
|
+
behaves_like 'supporting BigDecimal autocasting'
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
require 'data_objects/spec/typecast/boolean_spec'
|
5
|
+
|
6
|
+
describe 'DataObjects::SqlServer with Boolean' do
|
7
|
+
behaves_like 'supporting Boolean'
|
8
|
+
behaves_like 'supporting Boolean autocasting'
|
9
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
require 'data_objects/spec/typecast/byte_array_spec'
|
5
|
+
|
6
|
+
describe 'DataObjects::SqlServer with ByteArray' do
|
7
|
+
# behaves_like 'supporting ByteArray'
|
8
|
+
#
|
9
|
+
# ByteArray is not yet supported on JRuby:
|
10
|
+
#
|
11
|
+
# Like Postgres, SQL Server doesn't typecast bytea type to integer, decimal,
|
12
|
+
# etc. In other words,
|
13
|
+
# @connection.create_command("SELECT id FROM widgets WHERE id = ?").execute_reader(::Extlib::ByteArray.new("2"))
|
14
|
+
# results in the equivalent to the following query being executed:
|
15
|
+
# SELECT id FROM widgets WHERE id = 0x32
|
16
|
+
# BUT 0x32 as a parameter = (decimal) 50
|
17
|
+
# NOT the ASCII char for '2'.
|
18
|
+
#
|
19
|
+
# Other drivers (Postgres) override #setPreparedStatementParam in their
|
20
|
+
# DriverDefinition implementations and use ps.getParameterMetadata() to let
|
21
|
+
# the JDBC driver handle the casting.
|
22
|
+
#
|
23
|
+
# Unfortunately, we can't rely on ps.getParameterMetadata() because of the
|
24
|
+
# following bug in jTDS:
|
25
|
+
# https://sourceforge.net/tracker/?func=detail&aid=2220192&group_id=33291&atid=407762
|
26
|
+
# getParameterClassName(idx) => java.lang.Object
|
27
|
+
# getParameterTypeName(idx) => null
|
28
|
+
# getParameterType(idx) => 0 (NULL)
|
29
|
+
#
|
30
|
+
# Without this information we don't know what we should be casting to!
|
31
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
require 'data_objects/spec/typecast/date_spec'
|
5
|
+
|
6
|
+
describe 'DataObjects::SqlServer with Date' do
|
7
|
+
behaves_like 'supporting Date'
|
8
|
+
|
9
|
+
# SqlServer will cast DATE type to Time
|
10
|
+
# behaves_like 'supporting Date autocasting'
|
11
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
require 'data_objects/spec/typecast/datetime_spec'
|
5
|
+
|
6
|
+
describe 'DataObjects::SqlServer with DateTime' do
|
7
|
+
behaves_like 'supporting DateTime'
|
8
|
+
# behaves_like 'supporting DateTime autocasting'
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
require 'data_objects/spec/typecast/float_spec'
|
5
|
+
|
6
|
+
describe 'DataObjects::SqlServer with Float' do
|
7
|
+
behaves_like 'supporting Float'
|
8
|
+
# behaves_like 'supporting Float autocasting'
|
9
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
require 'data_objects/spec/typecast/nil_spec'
|
5
|
+
|
6
|
+
describe 'DataObjects::SqlServer with Nil' do
|
7
|
+
behaves_like 'supporting Nil'
|
8
|
+
behaves_like 'supporting writing an Nil'
|
9
|
+
behaves_like 'supporting Nil autocasting'
|
10
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
require 'data_objects/spec/typecast/other_spec'
|
5
|
+
|
6
|
+
describe 'DataObjects::H2 with other (unknown) type' do
|
7
|
+
behaves_like 'supporting other (unknown) type'
|
8
|
+
end
|
data/tasks/compile.rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
begin
|
2
|
+
gem 'rake-compiler', '~>0.7'
|
3
|
+
require 'rake/javaextensiontask'
|
4
|
+
|
5
|
+
# Hack to avoid "allocator undefined for Proc" issue when unpacking Gems:
|
6
|
+
# gemspec provided by Jeweler uses Rake::FileList for files, test_files and
|
7
|
+
# extra_rdoc_files, and procs cannot be marshalled.
|
8
|
+
def gemspec
|
9
|
+
@clean_gemspec ||= eval("#{Rake.application.jeweler.gemspec.to_ruby}") # $SAFE = 3\n
|
10
|
+
end
|
11
|
+
|
12
|
+
Rake::JavaExtensionTask.new('do_sqlserver', gemspec) do |ext|
|
13
|
+
ext.ext_dir = 'ext-java/src/main/java'
|
14
|
+
ext.lib_dir = 'lib/do_sqlserver'
|
15
|
+
ext.debug = ENV.has_key?('DO_JAVA_DEBUG') && ENV['DO_JAVA_DEBUG']
|
16
|
+
ext.classpath = '../do_jdbc/lib/do_jdbc_internal.jar'
|
17
|
+
end
|
18
|
+
|
19
|
+
# do_sqlserver is only available for JRuby: the normal behaviour of
|
20
|
+
# rake-compiler is to only chain 'compile:PLATFORM' tasks to 'compile' where
|
21
|
+
# PLATFORM is the platform of the current interpreter (i.e. 'compile:java'
|
22
|
+
# to 'compile' only if running on JRuby). However, we always want to compile
|
23
|
+
# for Java, even if running from MRI.
|
24
|
+
task 'compile:do_sqlserver' => ['compile:do_sqlserver:java']
|
25
|
+
task 'compile' => ['compile:java']
|
26
|
+
|
27
|
+
rescue LoadError
|
28
|
+
warn "To compile, install rake-compiler (gem install rake-compiler)"
|
29
|
+
end
|