tiny_tds 0.6.2-x64-mingw32 → 0.6.3.rc2-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|