tiny_tds 0.6.2-x64-mingw32 → 0.6.3.rc2-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.gitignore +0 -1
- data/CHANGELOG +22 -5
- data/CODE_OF_CONDUCT.md +31 -0
- data/Gemfile +0 -1
- data/README.md +29 -31
- data/Rakefile +52 -62
- data/appveyor.yml +48 -0
- data/ext/tiny_tds/client.c +11 -11
- data/ext/tiny_tds/extconf.rb +203 -6
- data/ext/tiny_tds/result.c +3 -35
- data/lib/tiny_tds.rb +25 -6
- data/lib/tiny_tds/client.rb +15 -17
- data/lib/tiny_tds/version.rb +2 -2
- data/test/client_test.rb +23 -23
- data/test/result_test.rb +80 -84
- data/test/schema/sqlserver_2014.sql +138 -0
- data/test/schema_test.rb +58 -59
- data/test/test_helper.rb +55 -46
- data/test/thread_test.rb +4 -4
- metadata +48 -42
- data/compile/rake-compiler-dev-box.patch +0 -31
- data/ext/patch/Makefile.in.diff +0 -29
- data/ext/patch/dblib-30-char-username.diff +0 -11
- data/ext/patch/sspi_w_kerberos.diff +0 -42
- data/tasks/ports.rake +0 -79
data/ext/tiny_tds/client.c
CHANGED
@@ -73,9 +73,9 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
|
|
73
73
|
/*
|
74
74
|
SYBETIME is the only error that can send INT_TIMEOUT or INT_CONTINUE,
|
75
75
|
but we don't ever want to automatically retry. Instead have the app
|
76
|
-
decide what to do.
|
77
|
-
in tds/util.c converts INT_TIMEOUT to INT_CONTINUE.
|
76
|
+
decide what to do.
|
78
77
|
*/
|
78
|
+
return_value = INT_TIMEOUT;
|
79
79
|
cancel = 1;
|
80
80
|
break;
|
81
81
|
|
@@ -233,7 +233,7 @@ static VALUE rb_tinytds_execute(VALUE self, VALUE sql) {
|
|
233
233
|
GET_CLIENT_WRAPPER(self);
|
234
234
|
rb_tinytds_client_reset_userdata(cwrap->userdata);
|
235
235
|
REQUIRE_OPEN_CLIENT(cwrap);
|
236
|
-
dbcmd(cwrap->client,
|
236
|
+
dbcmd(cwrap->client, StringValueCStr(sql));
|
237
237
|
if (dbsqlsend(cwrap->client) == FAIL) {
|
238
238
|
rb_warn("TinyTds: dbsqlsend() returned FAIL.\n");
|
239
239
|
return Qfalse;
|
@@ -316,25 +316,25 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
316
316
|
if (!NIL_P(version))
|
317
317
|
dbsetlversion(cwrap->login, NUM2INT(version));
|
318
318
|
if (!NIL_P(user))
|
319
|
-
dbsetluser(cwrap->login,
|
319
|
+
dbsetluser(cwrap->login, StringValueCStr(user));
|
320
320
|
if (!NIL_P(pass))
|
321
|
-
dbsetlpwd(cwrap->login,
|
321
|
+
dbsetlpwd(cwrap->login, StringValueCStr(pass));
|
322
322
|
if (!NIL_P(app))
|
323
|
-
dbsetlapp(cwrap->login,
|
323
|
+
dbsetlapp(cwrap->login, StringValueCStr(app));
|
324
324
|
if (!NIL_P(ltimeout))
|
325
325
|
dbsetlogintime(NUM2INT(ltimeout));
|
326
326
|
if (!NIL_P(timeout))
|
327
327
|
dbsettime(NUM2INT(timeout));
|
328
328
|
if (!NIL_P(charset))
|
329
|
-
DBSETLCHARSET(cwrap->login,
|
329
|
+
DBSETLCHARSET(cwrap->login, StringValueCStr(charset));
|
330
330
|
if (!NIL_P(database) && (azure == Qtrue)) {
|
331
331
|
#ifdef DBSETLDBNAME
|
332
|
-
DBSETLDBNAME(cwrap->login,
|
332
|
+
DBSETLDBNAME(cwrap->login, StringValueCStr(database));
|
333
333
|
#else
|
334
334
|
rb_warn("TinyTds: Azure connections not supported in this version of FreeTDS.\n");
|
335
335
|
#endif
|
336
336
|
}
|
337
|
-
cwrap->client = dbopen(cwrap->login,
|
337
|
+
cwrap->client = dbopen(cwrap->login, StringValueCStr(dataserver));
|
338
338
|
if (cwrap->client) {
|
339
339
|
cwrap->closed = 0;
|
340
340
|
cwrap->charset = charset;
|
@@ -343,10 +343,10 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
|
|
343
343
|
dbsetuserdata(cwrap->client, (BYTE*)cwrap->userdata);
|
344
344
|
cwrap->userdata->closed = 0;
|
345
345
|
if (!NIL_P(database) && (azure != Qtrue)) {
|
346
|
-
dbuse(cwrap->client,
|
346
|
+
dbuse(cwrap->client, StringValueCStr(database));
|
347
347
|
}
|
348
348
|
VALUE transposed_encoding = rb_funcall(cTinyTdsClient, intern_transpose_iconv_encoding, 1, charset);
|
349
|
-
cwrap->encoding = rb_enc_find(
|
349
|
+
cwrap->encoding = rb_enc_find(StringValueCStr(transposed_encoding));
|
350
350
|
if (dbtds(cwrap->client) <= 7) {
|
351
351
|
cwrap->identity_insert_sql = "SELECT CAST(@@IDENTITY AS bigint) AS Ident";
|
352
352
|
} else {
|
data/ext/tiny_tds/extconf.rb
CHANGED
@@ -3,10 +3,54 @@ ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
|
|
3
3
|
# :stopdoc:
|
4
4
|
|
5
5
|
require 'mkmf'
|
6
|
+
require 'mini_portile'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
# If your using 0.82, you may have to make a conf file to get it to work. For example:
|
10
|
+
# $ export FREETDSCONF='/opt/local/etc/freetds/freetds.conf'
|
11
|
+
ICONV_VERSION = ENV['TINYTDS_ICONV_VERSION'] || "1.14"
|
12
|
+
ICONV_SOURCE_URI = "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-#{ICONV_VERSION}.tar.gz"
|
13
|
+
|
14
|
+
OPENSSL_VERSION = ENV['TINYTDS_OPENSSL_VERSION'] || '1.0.2d'
|
15
|
+
OPENSSL_SOURCE_URI = "http://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz"
|
16
|
+
|
17
|
+
FREETDS_VERSION = ENV['TINYTDS_FREETDS_VERSION'] || "0.91"
|
18
|
+
FREETDS_VERSION_INFO = Hash.new { |h,k|
|
19
|
+
h[k] = {:files => "ftp://ftp.freetds.org/pub/freetds/stable/freetds-#{k}.tar.gz"}
|
20
|
+
}.merge({
|
21
|
+
"0.82" => {:files => "ftp://ftp.freetds.org/pub/freetds/old/0.82/freetds-0.82.tar.gz"},
|
22
|
+
"0.91" => {:files => "ftp://ftp.freetds.org/pub/freetds/stable/freetds-0.91.112.tar.gz"},
|
23
|
+
"current" => {:files => "ftp://ftp.freetds.org/pub/freetds/current/freetds-current.tar.gz"}
|
24
|
+
})
|
25
|
+
FREETDS_SOURCE_URI = FREETDS_VERSION_INFO[FREETDS_VERSION][:files]
|
6
26
|
|
7
27
|
# Shamelessly copied from nokogiri
|
8
28
|
#
|
9
29
|
|
30
|
+
def do_help
|
31
|
+
print <<HELP
|
32
|
+
usage: ruby #{$0} [options]
|
33
|
+
|
34
|
+
--enable-system-freetds / --disable-system-freetds
|
35
|
+
--enable-system-iconv / --disable-system-iconv
|
36
|
+
--enable-system-openssl / --disable-system-openssl
|
37
|
+
Force use of system or builtin freetds/iconv/openssl library.
|
38
|
+
Default is to prefer system libraries and fallback to builtin.
|
39
|
+
|
40
|
+
--with-freetds-dir=DIR
|
41
|
+
Use the freetds library placed under DIR.
|
42
|
+
|
43
|
+
--enable-lookup
|
44
|
+
Search for freetds through all paths in the PATH environment variable.
|
45
|
+
|
46
|
+
--enable-cross-build
|
47
|
+
Do cross-build.
|
48
|
+
HELP
|
49
|
+
exit! 0
|
50
|
+
end
|
51
|
+
|
52
|
+
do_help if arg_config('--help')
|
53
|
+
|
10
54
|
FREETDSDIR = ENV['FREETDS_DIR']
|
11
55
|
|
12
56
|
if FREETDSDIR.nil? || FREETDSDIR.empty?
|
@@ -40,6 +84,144 @@ def searchable_paths_with_directories(*directories)
|
|
40
84
|
end.flatten.compact
|
41
85
|
end
|
42
86
|
|
87
|
+
class BuildRecipe < MiniPortile
|
88
|
+
def initialize(name, version, files)
|
89
|
+
super(name, version)
|
90
|
+
self.files = files
|
91
|
+
self.target = File.expand_path('../../../ports', __FILE__)
|
92
|
+
# Prefer host_alias over host in order to use i586-mingw32msvc as
|
93
|
+
# correct compiler prefix for cross build, but use host if not set.
|
94
|
+
self.host = consolidated_host(RbConfig::CONFIG["host_alias"].empty? ? RbConfig::CONFIG["host"] : RbConfig::CONFIG["host_alias"])
|
95
|
+
self.patch_files = Dir[File.join(self.target, "patches", self.name, self.version, "*.diff")].sort
|
96
|
+
end
|
97
|
+
|
98
|
+
def consolidated_host(name)
|
99
|
+
# For ruby-1.9.3 we use newer mingw-w64 (i686-w64-mingw32) to build the shared libraries
|
100
|
+
# and mingw32 (i586-mingw32msvc) to build the extension.
|
101
|
+
name.gsub('i586-mingw32msvc', 'i686-w64-mingw32').
|
102
|
+
gsub('i686-pc-mingw32', 'i686-w64-mingw32')
|
103
|
+
end
|
104
|
+
|
105
|
+
def configure_defaults
|
106
|
+
[
|
107
|
+
"--host=#{host}", # build for specific target (host)
|
108
|
+
"--disable-static",
|
109
|
+
"--enable-shared",
|
110
|
+
]
|
111
|
+
end
|
112
|
+
|
113
|
+
def port_path
|
114
|
+
"#{target}/#{host}"
|
115
|
+
end
|
116
|
+
|
117
|
+
# When using rake-compiler-dock on Windows, the underlying Virtualbox shared
|
118
|
+
# folders don't support symlinks, but libiconv expects it for a build on
|
119
|
+
# Linux. We work around this limitation by using the temp dir for cooking.
|
120
|
+
def chdir_for_build
|
121
|
+
build_dir = ENV['RCD_HOST_RUBY_PLATFORM'].to_s =~ /mingw|mswin|cygwin/ ? '/tmp' : '.'
|
122
|
+
Dir.chdir(build_dir) do
|
123
|
+
yield
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def cook_and_activate
|
128
|
+
checkpoint = File.join(self.target, "#{self.name}-#{self.version}-#{self.host}.installed")
|
129
|
+
unless File.exist?(checkpoint)
|
130
|
+
chdir_for_build do
|
131
|
+
self.cook
|
132
|
+
end
|
133
|
+
FileUtils.touch checkpoint
|
134
|
+
end
|
135
|
+
self.activate
|
136
|
+
self
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def define_libssl_recipe(host)
|
141
|
+
BuildRecipe.new("openssl", OPENSSL_VERSION, [OPENSSL_SOURCE_URI]).tap do |recipe|
|
142
|
+
class << recipe
|
143
|
+
def extract_file(file, target)
|
144
|
+
filename = File.basename(file)
|
145
|
+
FileUtils.mkdir_p target
|
146
|
+
|
147
|
+
message "Extracting #{filename} into #{target}... "
|
148
|
+
result = `#{tar_exe} #{tar_compression_switch(filename)}xf "#{file}" -C "#{target}" 2>&1`
|
149
|
+
if $?.success?
|
150
|
+
output "OK"
|
151
|
+
else
|
152
|
+
# tar on windows returns error exit code, because it can not extract symlinks
|
153
|
+
output "ERROR (ignored)"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def configure
|
158
|
+
config = if host=~/mingw/
|
159
|
+
host=~/x86_64/ ? 'mingw64' : 'mingw'
|
160
|
+
end
|
161
|
+
args = [ "CFLAGS=-DDSO_WIN32",
|
162
|
+
"./Configure",
|
163
|
+
"no-shared",
|
164
|
+
configure_prefix,
|
165
|
+
config,
|
166
|
+
]
|
167
|
+
args.unshift("CROSS_COMPILE=#{host}-") if enable_config("cross-build")
|
168
|
+
|
169
|
+
execute "configure", "sh -c \"#{args.join(" ")}\""
|
170
|
+
end
|
171
|
+
|
172
|
+
def compile
|
173
|
+
super
|
174
|
+
# OpenSSL DLLs are called "libeay32.dll" and "ssleay32.dll" per default,
|
175
|
+
# regardless to the version. This is best suited to meet the Windows DLL hell.
|
176
|
+
# To avoid any conflicts we do a static build and build DLLs afterwards,
|
177
|
+
# with our own naming scheme.
|
178
|
+
execute "mkdef-libeay32", "(perl util/mkdef.pl 32 libeay >libeay32.def)"
|
179
|
+
execute "mkdef-ssleay32", "(perl util/mkdef.pl 32 ssleay >ssleay32.def)"
|
180
|
+
dllwrap = consolidated_host(RbConfig::CONFIG["DLLWRAP"])
|
181
|
+
execute "dllwrap-libeay32", "#{dllwrap} --dllname libeay32-#{version}-#{host}.dll --output-lib libcrypto.dll.a --def libeay32.def libcrypto.a -lwsock32 -lgdi32 -lcrypt32"
|
182
|
+
execute "dllwrap-ssleay32", "#{dllwrap} --dllname ssleay32-#{version}-#{host}.dll --output-lib libssl.dll.a --def ssleay32.def libssl.a libcrypto.dll.a"
|
183
|
+
end
|
184
|
+
|
185
|
+
def install
|
186
|
+
super
|
187
|
+
FileUtils.cp "#{work_path}/libeay32-#{version}-#{host}.dll", "#{path}/bin/"
|
188
|
+
FileUtils.cp "#{work_path}/ssleay32-#{version}-#{host}.dll", "#{path}/bin/"
|
189
|
+
FileUtils.cp "#{work_path}/libcrypto.dll.a", "#{path}/lib/"
|
190
|
+
FileUtils.cp "#{work_path}/libssl.dll.a", "#{path}/lib/"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def define_libiconv_recipe(host)
|
197
|
+
BuildRecipe.new("libiconv", ICONV_VERSION, [ICONV_SOURCE_URI])
|
198
|
+
.tap do |recipe|
|
199
|
+
# always produce position independent code
|
200
|
+
recipe.configure_options << "CFLAGS=-fPIC"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def define_freetds_recipe(host, libiconv, libssl)
|
205
|
+
BuildRecipe.new("freetds", FREETDS_VERSION, [FREETDS_SOURCE_URI])
|
206
|
+
.tap do |recipe|
|
207
|
+
with_tdsver = FREETDS_VERSION =~ /0\.8/ ? "--with-tdsver=8.0" : "--with-tdsver=7.1"
|
208
|
+
for_windows = recipe.host =~ /mswin|mingw/i
|
209
|
+
recipe.configure_options << '--with-pic'
|
210
|
+
recipe.configure_options << "--with-libiconv-prefix=#{libiconv.path}" if libiconv
|
211
|
+
recipe.configure_options << "--with-openssl=#{libssl.path}" if libssl
|
212
|
+
recipe.configure_options << '--sysconfdir=C:/Sites' if for_windows
|
213
|
+
recipe.configure_options << '--enable-sspi' if for_windows
|
214
|
+
recipe.configure_options << "--disable-odbc"
|
215
|
+
recipe.configure_options << with_tdsver
|
216
|
+
if libiconv
|
217
|
+
# For some reason freetds doesn't honor --with-libiconv-prefix
|
218
|
+
# so we have do add it by hand:
|
219
|
+
recipe.configure_options << "\"CFLAGS=-I#{libiconv.path}/include\""
|
220
|
+
recipe.configure_options << "\"LDFLAGS=-L#{libiconv.path}/lib -liconv\""
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
43
225
|
if RbConfig::CONFIG['target_os'] =~ /mswin32|mingw32/
|
44
226
|
lib_prefix = 'lib' unless RbConfig::CONFIG['target_os'] =~ /mingw32/
|
45
227
|
# There's no default include/lib dir on Windows. Let's just add the Ruby ones
|
@@ -77,10 +259,8 @@ FREETDS_LIB_DIRS = (searchable_paths_with_directories(['lib'],['lib','freetds'])
|
|
77
259
|
# lookup over searchable paths is great for native compilation, however, when
|
78
260
|
# cross compiling we need to specify our own paths.
|
79
261
|
if enable_config("lookup", true)
|
80
|
-
dir_config('iconv', FREETDS_HEADER_DIRS, FREETDS_LIB_DIRS)
|
81
262
|
dir_config('freetds', FREETDS_HEADER_DIRS, FREETDS_LIB_DIRS)
|
82
263
|
else
|
83
|
-
dir_config('iconv')
|
84
264
|
dir_config('freetds')
|
85
265
|
|
86
266
|
# remove LDFLAGS
|
@@ -91,11 +271,28 @@ def asplode(lib)
|
|
91
271
|
abort "-----\n#{lib} is missing.\n-----"
|
92
272
|
end
|
93
273
|
|
94
|
-
|
95
|
-
|
274
|
+
def freetds_usable?(lib_prefix)
|
275
|
+
have_header('sybfront.h') && have_header('sybdb.h') &&
|
276
|
+
find_library("#{lib_prefix}sybdb", 'tdsdbopen') &&
|
277
|
+
find_library("#{lib_prefix}ct", 'ct_bind')
|
278
|
+
end
|
279
|
+
|
280
|
+
# We use freetds, when available already, and fallback to compilation of ports
|
281
|
+
system_freetds = enable_config('system-freetds', ENV['TINYTDS_SKIP_PORTS'] || freetds_usable?(lib_prefix))
|
282
|
+
|
283
|
+
# We expect to have iconv and OpenSSL available on non-Windows systems
|
284
|
+
host = RbConfig::CONFIG["host"]
|
285
|
+
system_iconv = enable_config('system-iconv', host =~ /mingw|mswin/ ? false : true)
|
286
|
+
system_openssl = enable_config('system-openssl', host =~ /mingw|mswin/ ? false : true )
|
287
|
+
|
288
|
+
unless system_freetds
|
289
|
+
libssl = define_libssl_recipe(host).cook_and_activate unless system_openssl
|
290
|
+
libiconv = define_libiconv_recipe(host).cook_and_activate unless system_iconv
|
291
|
+
freetds = define_freetds_recipe(host, libiconv, libssl).cook_and_activate
|
292
|
+
dir_config('freetds', freetds.path + "/include", freetds.path + "/lib")
|
293
|
+
end
|
96
294
|
|
97
|
-
asplode 'freetds' unless
|
98
|
-
asplode 'freetds' unless find_library("#{lib_prefix}ct", 'ct_bind')
|
295
|
+
asplode 'freetds' unless freetds_usable?(lib_prefix)
|
99
296
|
|
100
297
|
create_makefile('tiny_tds/tiny_tds')
|
101
298
|
|
data/ext/tiny_tds/result.c
CHANGED
@@ -2,23 +2,12 @@
|
|
2
2
|
#include <tiny_tds_ext.h>
|
3
3
|
#include <stdint.h>
|
4
4
|
|
5
|
-
// TINY_TDS_MAX_TIME
|
6
|
-
|
7
|
-
#define TINY_TDS_MAX_TIME 315607276799ULL
|
8
|
-
|
9
|
-
|
10
|
-
// TINY_TDS_MIN_TIME
|
11
|
-
|
12
|
-
#define TINY_TDS_MIN_TIME 2678400ULL
|
13
|
-
|
14
|
-
|
15
5
|
// File Types/Vars
|
16
6
|
|
17
7
|
VALUE cTinyTdsResult;
|
18
8
|
extern VALUE mTinyTds, cTinyTdsClient, cTinyTdsError;
|
19
|
-
VALUE cBigDecimal, cDate
|
9
|
+
VALUE cBigDecimal, cDate;
|
20
10
|
VALUE opt_decimal_zero, opt_float_zero, opt_one, opt_zero, opt_four, opt_19hdr, opt_tenk, opt_onemil;
|
21
|
-
int opt_ruby_186;
|
22
11
|
static ID intern_new, intern_utc, intern_local, intern_localtime, intern_merge,
|
23
12
|
intern_civil, intern_new_offset, intern_plus, intern_divide, intern_Rational;
|
24
13
|
static ID sym_symbolize_keys, sym_as, sym_array, sym_cache_rows, sym_first, sym_timezone, sym_local, sym_utc, sym_empty_sets;
|
@@ -78,7 +67,7 @@ VALUE rb_tinytds_new_result_obj(tinytds_client_wrapper *cwrap) {
|
|
78
67
|
// No GVL Helpers
|
79
68
|
|
80
69
|
#define NOGVL_DBCALL(_dbfunction, _client) ( \
|
81
|
-
(RETCODE)
|
70
|
+
(RETCODE)rb_thread_call_without_gvl( \
|
82
71
|
(rb_blocking_function_t*)_dbfunction, _client, \
|
83
72
|
(rb_unblock_function_t*)dbcancel_ubf, _client ) \
|
84
73
|
)
|
@@ -293,25 +282,7 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
|
|
293
282
|
if (year+month+day+hour+min+sec+msec != 0) {
|
294
283
|
VALUE offset = (timezone == intern_local) ? rwrap->local_offset : opt_zero;
|
295
284
|
uint64_t seconds = (year*31557600ULL) + (month*2592000ULL) + (day*86400ULL) + (hour*3600ULL) + (min*60ULL) + sec;
|
296
|
-
|
297
|
-
if (seconds < TINY_TDS_MIN_TIME || seconds > TINY_TDS_MAX_TIME) {
|
298
|
-
VALUE datetime_sec = INT2NUM(sec);
|
299
|
-
if (msec != 0) {
|
300
|
-
if ((opt_ruby_186 == 1 && sec < 59) || (opt_ruby_186 != 1)) {
|
301
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
302
|
-
VALUE rational_msec = rb_Rational2(INT2NUM(msec*1000), opt_onemil);
|
303
|
-
#else
|
304
|
-
VALUE rational_msec = rb_funcall(rb_cObject, intern_Rational, 2, INT2NUM(msec*1000), opt_onemil);
|
305
|
-
#endif
|
306
|
-
datetime_sec = rb_funcall(datetime_sec, intern_plus, 1, rational_msec);
|
307
|
-
}
|
308
|
-
}
|
309
|
-
val = rb_funcall(cDateTime, intern_civil, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), datetime_sec, offset);
|
310
|
-
val = rb_funcall(val, intern_new_offset, 1, offset);
|
311
|
-
/* Use Time */
|
312
|
-
} else {
|
313
|
-
val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(msec*1000));
|
314
|
-
}
|
285
|
+
val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(msec*1000));
|
315
286
|
}
|
316
287
|
break;
|
317
288
|
}
|
@@ -547,7 +518,6 @@ void init_tinytds_result() {
|
|
547
518
|
/* Data Classes */
|
548
519
|
cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
549
520
|
cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
550
|
-
cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
|
551
521
|
/* Define TinyTds::Result */
|
552
522
|
cTinyTdsResult = rb_define_class_under(mTinyTds, "Result", rb_cObject);
|
553
523
|
/* Define TinyTds::Result Public Methods */
|
@@ -590,8 +560,6 @@ void init_tinytds_result() {
|
|
590
560
|
opt_19hdr = INT2NUM(1900);
|
591
561
|
opt_tenk = INT2NUM(10000);
|
592
562
|
opt_onemil = INT2NUM(1000000);
|
593
|
-
/* Ruby version flags */
|
594
|
-
opt_ruby_186 = (rb_eval_string("RUBY_VERSION == '1.8.6'") == Qtrue) ? 1 : 0;
|
595
563
|
/* Encoding */
|
596
564
|
#ifdef HAVE_RUBY_ENCODING_H
|
597
565
|
binaryEncoding = rb_enc_find("binary");
|
data/lib/tiny_tds.rb
CHANGED
@@ -9,11 +9,30 @@ require 'tiny_tds/client'
|
|
9
9
|
require 'tiny_tds/result'
|
10
10
|
|
11
11
|
# Support multiple ruby versions, fat binaries under Windows.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
if RUBY_PLATFORM =~ /mingw|mswin/ && RUBY_VERSION =~ /(\d+.\d+)/
|
13
|
+
ver = $1
|
14
|
+
# Set the PATH environment variable, so that the DLLs can be found.
|
15
|
+
old_path = ENV['PATH']
|
16
|
+
begin
|
17
|
+
# Do the same host consolidation as in extconf.rb
|
18
|
+
ports_dir = RbConfig::CONFIG["host"].gsub('i586-mingw32msvc', 'i686-w64-mingw32').
|
19
|
+
gsub('i686-pc-mingw32', 'i686-w64-mingw32')
|
20
|
+
ENV['PATH'] = "#{File.expand_path("../../ports/#{ports_dir}/bin", __FILE__)};#{old_path}"
|
21
|
+
require "tiny_tds/#{ver}/tiny_tds"
|
22
|
+
rescue LoadError
|
23
|
+
require 'tiny_tds/tiny_tds'
|
24
|
+
ensure
|
25
|
+
ENV['PATH'] = old_path
|
26
|
+
end
|
27
|
+
else
|
28
|
+
# Load dependent shared libraries into the process, so that they are already present,
|
29
|
+
# when tiny_tds.so is loaded. This ensures, that shared libraries are loaded even when
|
30
|
+
# the path is different between build and run time (e.g. Heroku).
|
31
|
+
ports_libs = File.expand_path("../../ports/#{RbConfig::CONFIG["host"]}/lib/*.so", __FILE__)
|
32
|
+
Dir[ports_libs].each do |lib|
|
33
|
+
require "fiddle"
|
34
|
+
Fiddle.dlopen(lib)
|
35
|
+
end
|
36
|
+
|
16
37
|
require 'tiny_tds/tiny_tds'
|
17
38
|
end
|
18
|
-
|
19
|
-
|
data/lib/tiny_tds/client.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module TinyTds
|
2
2
|
class Client
|
3
|
-
|
3
|
+
|
4
4
|
# From sybdb.h comments:
|
5
5
|
# DBVERSION_xxx are used with dbsetversion()
|
6
|
-
#
|
6
|
+
#
|
7
7
|
TDS_VERSIONS_SETTERS = {
|
8
8
|
'unknown' => 0,
|
9
9
|
'46' => 1,
|
@@ -19,7 +19,7 @@ module TinyTds
|
|
19
19
|
# From sybdb.h comments:
|
20
20
|
# DBTDS_xxx are returned by DBTDS()
|
21
21
|
# The integer values of the constants are poorly chosen.
|
22
|
-
#
|
22
|
+
#
|
23
23
|
TDS_VERSIONS_GETTERS = {
|
24
24
|
0 => {:name => 'DBTDS_UNKNOWN', :description => 'Unknown'},
|
25
25
|
1 => {:name => 'DBTDS_2_0', :description => 'Pre 4.0 SQL Server'},
|
@@ -33,7 +33,7 @@ module TinyTds
|
|
33
33
|
9 => {:name => 'DBTDS_7_1/DBTDS_8_0', :description => 'Microsoft SQL Server 2000'},
|
34
34
|
10 => {:name => 'DBTDS_7_2/DBTDS_9_0', :description => 'Microsoft SQL Server 2005'}
|
35
35
|
}.freeze
|
36
|
-
|
36
|
+
|
37
37
|
@@default_query_options = {
|
38
38
|
:as => :hash,
|
39
39
|
:symbolize_keys => false,
|
@@ -41,32 +41,29 @@ module TinyTds
|
|
41
41
|
:timezone => :local,
|
42
42
|
:empty_sets => true
|
43
43
|
}
|
44
|
-
|
44
|
+
|
45
45
|
attr_reader :query_options
|
46
|
-
|
46
|
+
|
47
47
|
class << self
|
48
|
-
|
48
|
+
|
49
49
|
def default_query_options
|
50
50
|
@@default_query_options
|
51
51
|
end
|
52
52
|
|
53
|
-
# Most, if not all, iconv encoding names can be found by ruby. Just in case, you can
|
54
|
-
# overide this method to return a string name that Encoding.find would work with. Default
|
53
|
+
# Most, if not all, iconv encoding names can be found by ruby. Just in case, you can
|
54
|
+
# overide this method to return a string name that Encoding.find would work with. Default
|
55
55
|
# is to return the passed encoding.
|
56
56
|
def transpose_iconv_encoding(encoding)
|
57
57
|
encoding
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
end
|
61
61
|
|
62
62
|
|
63
63
|
def initialize(opts={})
|
64
|
-
if opts[:password] && opts[:password].to_s.strip != ''
|
65
|
-
opts[:password] = opts[:password].to_s
|
66
|
-
warn 'FreeTDS may have issues with passwords longer than 30 characters!' if opts[:password].length > 30
|
67
|
-
end
|
68
64
|
raise ArgumentError, 'missing :host option if no :dataserver given' if opts[:dataserver].to_s.empty? && opts[:host].to_s.empty?
|
69
65
|
@query_options = @@default_query_options.dup
|
66
|
+
opts[:password] = opts[:password].to_s if opts[:password] && opts[:password].to_s.strip != ''
|
70
67
|
opts[:appname] ||= 'TinyTds'
|
71
68
|
opts[:tds_version] = TDS_VERSIONS_SETTERS[opts[:tds_version].to_s] || TDS_VERSIONS_SETTERS['71']
|
72
69
|
opts[:login_timeout] ||= 60
|
@@ -76,7 +73,7 @@ module TinyTds
|
|
76
73
|
opts[:dataserver] = "#{opts[:host]}:#{opts[:port]}" if opts[:dataserver].to_s.empty?
|
77
74
|
connect(opts)
|
78
75
|
end
|
79
|
-
|
76
|
+
|
80
77
|
def tds_version_info
|
81
78
|
info = TDS_VERSIONS_GETTERS[tds_version]
|
82
79
|
"#{info[:name]} - #{info[:description]}" if info
|
@@ -86,11 +83,12 @@ module TinyTds
|
|
86
83
|
!closed? && !dead?
|
87
84
|
end
|
88
85
|
|
86
|
+
|
89
87
|
private
|
90
|
-
|
88
|
+
|
91
89
|
def self.local_offset
|
92
90
|
::Time.local(2010).utc_offset.to_r / 86400
|
93
91
|
end
|
94
|
-
|
92
|
+
|
95
93
|
end
|
96
94
|
end
|