tiny_tds 2.1.2 → 3.2.1
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 -5
- data/.github/workflows/ci.yml +571 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +56 -1
- data/Gemfile +1 -8
- data/ISSUE_TEMPLATE.md +1 -1
- data/README.md +89 -89
- data/Rakefile +44 -30
- data/VERSION +1 -1
- data/docker-compose.yml +34 -0
- data/ext/tiny_tds/client.c +100 -59
- data/ext/tiny_tds/client.h +5 -3
- data/ext/tiny_tds/extconf.rb +173 -52
- data/ext/tiny_tds/extconsts.rb +4 -11
- data/ext/tiny_tds/result.c +52 -45
- data/ext/tiny_tds/tiny_tds_ext.c +4 -1
- data/lib/tiny_tds/bin.rb +12 -26
- data/lib/tiny_tds/client.rb +38 -42
- data/lib/tiny_tds/error.rb +0 -2
- data/lib/tiny_tds/gem.rb +5 -14
- data/lib/tiny_tds/result.rb +0 -2
- data/lib/tiny_tds/version.rb +1 -1
- data/lib/tiny_tds.rb +28 -47
- data/setup_cimgruby_dev.sh +25 -0
- data/start_dev.sh +21 -0
- data/tasks/native_gem.rake +12 -10
- data/tasks/package.rake +1 -3
- data/tasks/ports.rake +14 -77
- data/tasks/test.rake +3 -5
- data/test/bin/install-freetds.sh +2 -4
- data/test/bin/install-mssql.ps1 +42 -0
- data/test/bin/install-mssqltools.sh +9 -0
- data/test/bin/restore-from-native-gem.ps1 +10 -0
- data/test/bin/setup_tinytds_db.sh +7 -0
- data/test/bin/setup_volume_permissions.sh +10 -0
- data/test/client_test.rb +152 -116
- data/test/gem_test.rb +39 -118
- data/test/result_test.rb +285 -350
- data/test/schema_test.rb +369 -395
- data/test/sql/db-create.sql +18 -0
- data/test/sql/db-login.sql +38 -0
- data/test/test_helper.rb +112 -85
- data/test/thread_test.rb +22 -31
- data/tiny_tds.gemspec +28 -26
- metadata +85 -59
- data/.travis.yml +0 -24
- data/BACKERS.md +0 -32
- data/appveyor.yml +0 -51
- data/tasks/ports/freetds.rb +0 -37
- data/tasks/ports/libiconv.rb +0 -43
- data/tasks/ports/openssl.rb +0 -78
- data/tasks/ports/recipe.rb +0 -52
- data/test/appveyor/dbsetup.ps1 +0 -27
- data/test/appveyor/dbsetup.sql +0 -9
- data/test/benchmark/query.rb +0 -77
- data/test/benchmark/query_odbc.rb +0 -106
- data/test/benchmark/query_tinytds.rb +0 -126
- data/test/bin/setup.sh +0 -19
- data/test/schema/sqlserver_2000.sql +0 -140
- data/test/schema/sqlserver_2005.sql +0 -140
- data/test/schema/sqlserver_2014.sql +0 -140
- data/test/schema/sqlserver_2016.sql +0 -140
- data/test/schema/sybase_ase.sql +0 -138
- /data/test/schema/{sqlserver_2008.sql → sqlserver_2017.sql} +0 -0
data/ext/tiny_tds/result.c
CHANGED
@@ -86,26 +86,40 @@ static void dbcancel_ubf(DBPROCESS *client) {
|
|
86
86
|
static void nogvl_setup(DBPROCESS *client) {
|
87
87
|
GET_CLIENT_USERDATA(client);
|
88
88
|
userdata->nonblocking = 1;
|
89
|
+
userdata->nonblocking_errors_length = 0;
|
90
|
+
userdata->nonblocking_errors = malloc(ERRORS_STACK_INIT_SIZE * sizeof(tinytds_errordata));
|
91
|
+
userdata->nonblocking_errors_size = ERRORS_STACK_INIT_SIZE;
|
89
92
|
}
|
90
93
|
|
91
94
|
static void nogvl_cleanup(DBPROCESS *client) {
|
92
95
|
GET_CLIENT_USERDATA(client);
|
93
96
|
userdata->nonblocking = 0;
|
97
|
+
userdata->timing_out = 0;
|
94
98
|
/*
|
95
99
|
Now that the blocking operation is done, we can finally throw any
|
96
100
|
exceptions based on errors from SQL Server.
|
97
101
|
*/
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
userdata->
|
106
|
-
|
107
|
-
|
102
|
+
short int i;
|
103
|
+
for (i = 0; i < userdata->nonblocking_errors_length; i++) {
|
104
|
+
tinytds_errordata error = userdata->nonblocking_errors[i];
|
105
|
+
|
106
|
+
// lookahead to drain any info messages ahead of raising error
|
107
|
+
if (!error.is_message) {
|
108
|
+
short int j;
|
109
|
+
for (j = i; j < userdata->nonblocking_errors_length; j++) {
|
110
|
+
tinytds_errordata msg_error = userdata->nonblocking_errors[j];
|
111
|
+
if (msg_error.is_message) {
|
112
|
+
rb_tinytds_raise_error(client, msg_error);
|
113
|
+
}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
rb_tinytds_raise_error(client, error);
|
108
118
|
}
|
119
|
+
|
120
|
+
free(userdata->nonblocking_errors);
|
121
|
+
userdata->nonblocking_errors_length = 0;
|
122
|
+
userdata->nonblocking_errors_size = 0;
|
109
123
|
}
|
110
124
|
|
111
125
|
static RETCODE nogvl_dbsqlok(DBPROCESS *client) {
|
@@ -284,42 +298,34 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
|
|
284
298
|
}
|
285
299
|
break;
|
286
300
|
}
|
287
|
-
case
|
288
|
-
case
|
289
|
-
case
|
290
|
-
case
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
val = rb_funcall(cDate, intern_new, 3, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day));
|
298
|
-
break;
|
299
|
-
}
|
300
|
-
case 41: { // SYBMSTIME
|
301
|
-
VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
|
302
|
-
val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(1900), INT2NUM(1), INT2NUM(1), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
|
303
|
-
break;
|
304
|
-
}
|
305
|
-
case 42: { // SYBMSDATETIME2
|
306
|
-
VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
|
307
|
-
val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
|
308
|
-
break;
|
309
|
-
}
|
310
|
-
case 43: { // SYBMSDATETIMEOFFSET
|
311
|
-
long long numerator = ((long)dr2.second * (long long)1000000000) + (long long)dr2.nanosecond;
|
312
|
-
VALUE rational_sec = rb_Rational(LL2NUM(numerator), opt_onebil);
|
313
|
-
val = rb_funcall(rb_cTime, intern_new, 7, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day), INT2NUM(dr2.hour), INT2NUM(dr2.minute), rational_sec, INT2NUM(dr2.tzone*60));
|
314
|
-
break;
|
315
|
-
}
|
316
|
-
}
|
317
|
-
} else {
|
318
|
-
val = ENCODED_STR_NEW(data, data_len);
|
301
|
+
case SYBMSDATE:
|
302
|
+
case SYBMSTIME:
|
303
|
+
case SYBMSDATETIME2:
|
304
|
+
case SYBMSDATETIMEOFFSET: {
|
305
|
+
DBDATEREC2 dr2;
|
306
|
+
dbanydatecrack(rwrap->client, &dr2, coltype, data);
|
307
|
+
switch(coltype) {
|
308
|
+
case SYBMSDATE: {
|
309
|
+
val = rb_funcall(cDate, intern_new, 3, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day));
|
310
|
+
break;
|
319
311
|
}
|
320
|
-
|
321
|
-
|
322
|
-
|
312
|
+
case SYBMSTIME: {
|
313
|
+
VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
|
314
|
+
val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(1900), INT2NUM(1), INT2NUM(1), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
|
315
|
+
break;
|
316
|
+
}
|
317
|
+
case SYBMSDATETIME2: {
|
318
|
+
VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
|
319
|
+
val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
|
320
|
+
break;
|
321
|
+
}
|
322
|
+
case SYBMSDATETIMEOFFSET: {
|
323
|
+
long long numerator = ((long)dr2.second * (long long)1000000000) + (long long)dr2.nanosecond;
|
324
|
+
VALUE rational_sec = rb_Rational(LL2NUM(numerator), opt_onebil);
|
325
|
+
val = rb_funcall(rb_cTime, intern_new, 7, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day), INT2NUM(dr2.hour), INT2NUM(dr2.minute), rational_sec, INT2NUM(dr2.tzone*60));
|
326
|
+
break;
|
327
|
+
}
|
328
|
+
}
|
323
329
|
break;
|
324
330
|
}
|
325
331
|
case SYBCHAR:
|
@@ -570,6 +576,7 @@ void init_tinytds_result() {
|
|
570
576
|
cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
571
577
|
/* Define TinyTds::Result */
|
572
578
|
cTinyTdsResult = rb_define_class_under(mTinyTds, "Result", rb_cObject);
|
579
|
+
rb_undef_alloc_func(cTinyTdsResult);
|
573
580
|
/* Define TinyTds::Result Public Methods */
|
574
581
|
rb_define_method(cTinyTdsResult, "fields", rb_tinytds_result_fields, 0);
|
575
582
|
rb_define_method(cTinyTdsResult, "each", rb_tinytds_result_each, -1);
|
data/ext/tiny_tds/tiny_tds_ext.c
CHANGED
data/lib/tiny_tds/bin.rb
CHANGED
@@ -1,23 +1,22 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative
|
3
|
-
require
|
1
|
+
require_relative "version"
|
2
|
+
require_relative "gem"
|
3
|
+
require "shellwords"
|
4
4
|
|
5
5
|
module TinyTds
|
6
6
|
class Bin
|
7
|
-
|
8
7
|
attr_reader :name
|
9
8
|
|
10
9
|
class << self
|
11
10
|
def exe(name, *args)
|
12
11
|
bin = new(name)
|
13
|
-
puts bin.info unless args.any? { |x| x ==
|
12
|
+
puts bin.info unless args.any? { |x| x == "-q" }
|
14
13
|
bin.run(*args)
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
18
17
|
def initialize(name)
|
19
18
|
@root = Gem.root_path
|
20
|
-
@exts = (ENV[
|
19
|
+
@exts = (ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]) | [".exe"]
|
21
20
|
|
22
21
|
@name = name
|
23
22
|
@binstub = find_bin
|
@@ -33,7 +32,7 @@ module TinyTds
|
|
33
32
|
end
|
34
33
|
|
35
34
|
def path
|
36
|
-
@path ||= @exefile && File.exist?(@exefile) ? @exefile : which
|
35
|
+
@path ||= (@exefile && File.exist?(@exefile)) ? @exefile : which
|
37
36
|
end
|
38
37
|
|
39
38
|
def info
|
@@ -43,26 +42,26 @@ module TinyTds
|
|
43
42
|
private
|
44
43
|
|
45
44
|
def search_paths
|
46
|
-
ENV[
|
45
|
+
ENV["PATH"].split File::PATH_SEPARATOR
|
47
46
|
end
|
48
47
|
|
49
48
|
def with_ports_paths
|
50
|
-
old_path = ENV[
|
49
|
+
old_path = ENV["PATH"]
|
51
50
|
|
52
51
|
begin
|
53
|
-
ENV[
|
52
|
+
ENV["PATH"] = [
|
54
53
|
Gem.ports_bin_paths,
|
55
54
|
old_path
|
56
55
|
].flatten.join File::PATH_SEPARATOR
|
57
56
|
|
58
57
|
yield if block_given?
|
59
58
|
ensure
|
60
|
-
ENV[
|
59
|
+
ENV["PATH"] = old_path
|
61
60
|
end
|
62
61
|
end
|
63
62
|
|
64
63
|
def find_bin
|
65
|
-
File.join @root,
|
64
|
+
File.join @root, "bin", name
|
66
65
|
end
|
67
66
|
|
68
67
|
def find_exe
|
@@ -81,24 +80,11 @@ module TinyTds
|
|
81
80
|
exe = File.expand_path File.join(path, "#{name}#{ext}"), @root
|
82
81
|
next if exe == @binstub
|
83
82
|
next unless File.executable?(exe)
|
84
|
-
|
83
|
+
|
85
84
|
return exe
|
86
85
|
end
|
87
86
|
end
|
88
87
|
nil
|
89
88
|
end
|
90
|
-
|
91
|
-
# Implementation directly copied from ptools.
|
92
|
-
# https://github.com/djberg96/ptools
|
93
|
-
# https://opensource.org/licenses/Artistic-2.0
|
94
|
-
#
|
95
|
-
def binary?(file)
|
96
|
-
bytes = File.stat(file).blksize
|
97
|
-
return false unless bytes
|
98
|
-
bytes = 4096 if bytes > 4096
|
99
|
-
s = (File.read(file, bytes) || '')
|
100
|
-
s = s.encode('US-ASCII', undef: :replace).split(//)
|
101
|
-
((s.size - s.grep(' '..'~').size) / s.size.to_f) > 0.30
|
102
|
-
end
|
103
89
|
end
|
104
90
|
end
|
data/lib/tiny_tds/client.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module TinyTds
|
2
2
|
class Client
|
3
|
-
|
4
3
|
@default_query_options = {
|
5
4
|
as: :hash,
|
6
5
|
symbolize_keys: false,
|
@@ -13,7 +12,6 @@ module TinyTds
|
|
13
12
|
attr_reader :message_handler
|
14
13
|
|
15
14
|
class << self
|
16
|
-
|
17
15
|
attr_reader :default_query_options
|
18
16
|
|
19
17
|
# Most, if not all, iconv encoding names can be found by ruby. Just in case, you can
|
@@ -27,7 +25,6 @@ module TinyTds
|
|
27
25
|
def local_offset
|
28
26
|
::Time.local(2010).utc_offset.to_r / 86_400
|
29
27
|
end
|
30
|
-
|
31
28
|
end
|
32
29
|
|
33
30
|
# rubocop:disable Metrics/AbcSize
|
@@ -36,23 +33,23 @@ module TinyTds
|
|
36
33
|
# rubocop:disable Metrics/PerceivedComplexity
|
37
34
|
def initialize(opts = {})
|
38
35
|
if opts[:dataserver].to_s.empty? && opts[:host].to_s.empty?
|
39
|
-
raise ArgumentError,
|
36
|
+
raise ArgumentError, "missing :host option if no :dataserver given"
|
40
37
|
end
|
41
38
|
|
42
39
|
@message_handler = opts[:message_handler]
|
43
40
|
if @message_handler && !@message_handler.respond_to?(:call)
|
44
|
-
raise ArgumentError,
|
41
|
+
raise ArgumentError, ":message_handler must implement `call` (eg, a Proc or a Method)"
|
45
42
|
end
|
46
43
|
|
47
44
|
opts[:username] = parse_username(opts)
|
48
45
|
@query_options = self.class.default_query_options.dup
|
49
|
-
opts[:password] = opts[:password].to_s if opts[:password] && opts[:password].to_s.strip !=
|
50
|
-
opts[:appname] ||=
|
46
|
+
opts[:password] = opts[:password].to_s if opts[:password] && opts[:password].to_s.strip != ""
|
47
|
+
opts[:appname] ||= "TinyTds"
|
51
48
|
opts[:tds_version] = tds_versions_setter(opts)
|
52
49
|
opts[:use_utf16] = opts[:use_utf16].nil? || ["true", "1", "yes"].include?(opts[:use_utf16].to_s)
|
53
50
|
opts[:login_timeout] ||= 60
|
54
51
|
opts[:timeout] ||= 5
|
55
|
-
opts[:encoding] = opts[:encoding].nil? || opts[:encoding].casecmp(
|
52
|
+
opts[:encoding] = (opts[:encoding].nil? || opts[:encoding].casecmp("utf8").zero?) ? "UTF-8" : opts[:encoding].upcase
|
56
53
|
opts[:port] ||= 1433
|
57
54
|
opts[:dataserver] = "#{opts[:host]}:#{opts[:port]}" if opts[:dataserver].to_s.empty?
|
58
55
|
forced_integer_keys = [:login_timeout, :port, :timeout]
|
@@ -79,14 +76,14 @@ module TinyTds
|
|
79
76
|
host = opts[:host]
|
80
77
|
username = opts[:username]
|
81
78
|
return username if username.nil? || !opts[:azure]
|
82
|
-
return username if username.include?(
|
83
|
-
user, domain = username.split(
|
79
|
+
return username if username.include?("@") && !username.include?("database.windows.net")
|
80
|
+
user, domain = username.split("@")
|
84
81
|
domain ||= host
|
85
|
-
"#{user}@#{domain.split(
|
82
|
+
"#{user}@#{domain.split(".").first}"
|
86
83
|
end
|
87
84
|
|
88
85
|
def tds_versions_setter(opts = {})
|
89
|
-
v = opts[:tds_version] || ENV[
|
86
|
+
v = opts[:tds_version] || ENV["TDSVER"] || "7.3"
|
90
87
|
TDS_VERSIONS_SETTERS[v.to_s]
|
91
88
|
end
|
92
89
|
|
@@ -94,22 +91,22 @@ module TinyTds
|
|
94
91
|
# DBVERSION_xxx are used with dbsetversion()
|
95
92
|
#
|
96
93
|
TDS_VERSIONS_SETTERS = {
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
94
|
+
"unknown" => 0,
|
95
|
+
"46" => 1,
|
96
|
+
"100" => 2,
|
97
|
+
"42" => 3,
|
98
|
+
"70" => 4,
|
99
|
+
"7.0" => 4,
|
100
|
+
"71" => 5,
|
101
|
+
"7.1" => 5,
|
102
|
+
"80" => 5,
|
103
|
+
"8.0" => 5,
|
104
|
+
"72" => 6,
|
105
|
+
"7.2" => 6,
|
106
|
+
"90" => 6,
|
107
|
+
"9.0" => 6,
|
108
|
+
"73" => 7,
|
109
|
+
"7.3" => 7
|
113
110
|
}.freeze
|
114
111
|
|
115
112
|
# From sybdb.h comments:
|
@@ -117,20 +114,19 @@ module TinyTds
|
|
117
114
|
# The integer values of the constants are poorly chosen.
|
118
115
|
#
|
119
116
|
TDS_VERSIONS_GETTERS = {
|
120
|
-
0
|
121
|
-
1
|
122
|
-
2
|
123
|
-
3
|
124
|
-
4
|
125
|
-
5
|
126
|
-
6
|
127
|
-
7
|
128
|
-
8
|
129
|
-
9
|
130
|
-
10 => {
|
131
|
-
11 => {
|
132
|
-
12 => {
|
117
|
+
0 => {name: "DBTDS_UNKNOWN", description: "Unknown"},
|
118
|
+
1 => {name: "DBTDS_2_0", description: "Pre 4.0 SQL Server"},
|
119
|
+
2 => {name: "DBTDS_3_4", description: "Microsoft SQL Server (3.0)"},
|
120
|
+
3 => {name: "DBTDS_4_0", description: "4.0 SQL Server"},
|
121
|
+
4 => {name: "DBTDS_4_2", description: "4.2 SQL Server"},
|
122
|
+
5 => {name: "DBTDS_4_6", description: "2.0 OpenServer and 4.6 SQL Server."},
|
123
|
+
6 => {name: "DBTDS_4_9_5", description: "4.9.5 (NCR) SQL Server"},
|
124
|
+
7 => {name: "DBTDS_5_0", description: "5.0 SQL Server"},
|
125
|
+
8 => {name: "DBTDS_7_0", description: "Microsoft SQL Server 7.0"},
|
126
|
+
9 => {name: "DBTDS_7_1/DBTDS_8_0", description: "Microsoft SQL Server 2000"},
|
127
|
+
10 => {name: "DBTDS_7_2/DBTDS_9_0", description: "Microsoft SQL Server 2005"},
|
128
|
+
11 => {name: "DBTDS_7_3", description: "Microsoft SQL Server 2008"},
|
129
|
+
12 => {name: "DBTDS_7_4", description: "Microsoft SQL Server 2012/2014"}
|
133
130
|
}.freeze
|
134
|
-
|
135
131
|
end
|
136
132
|
end
|
data/lib/tiny_tds/error.rb
CHANGED
data/lib/tiny_tds/gem.rb
CHANGED
@@ -1,31 +1,22 @@
|
|
1
|
-
require
|
1
|
+
require "rbconfig"
|
2
2
|
|
3
3
|
module TinyTds
|
4
4
|
module Gem
|
5
5
|
class << self
|
6
6
|
def root_path
|
7
|
-
File.expand_path
|
7
|
+
File.expand_path "../../..", __FILE__
|
8
8
|
end
|
9
9
|
|
10
10
|
def ports_root_path
|
11
|
-
File.join(root_path,
|
11
|
+
File.join(root_path, "ports")
|
12
12
|
end
|
13
13
|
|
14
14
|
def ports_bin_paths
|
15
|
-
Dir.glob(File.join(ports_root_path,
|
15
|
+
Dir.glob(File.join(ports_root_path, "**", "bin"))
|
16
16
|
end
|
17
17
|
|
18
18
|
def ports_lib_paths
|
19
|
-
Dir.glob(File.join(ports_root_path,
|
20
|
-
end
|
21
|
-
|
22
|
-
def ports_host
|
23
|
-
h = RbConfig::CONFIG['host']
|
24
|
-
|
25
|
-
# Our fat binary builds with a i686-w64-mingw32 toolchain
|
26
|
-
# but ruby for windows x32-mingw32 reports i686-pc-mingw32
|
27
|
-
# so correct the host here
|
28
|
-
h.gsub('i686-pc-mingw32', 'i686-w64-mingw32')
|
19
|
+
Dir.glob(File.join(ports_root_path, "**", "lib"))
|
29
20
|
end
|
30
21
|
end
|
31
22
|
end
|
data/lib/tiny_tds/result.rb
CHANGED
data/lib/tiny_tds/version.rb
CHANGED
data/lib/tiny_tds.rb
CHANGED
@@ -1,61 +1,42 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
require 'bigdecimal'
|
4
|
-
require 'rational'
|
1
|
+
require "date"
|
2
|
+
require "bigdecimal"
|
5
3
|
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
4
|
+
require "tiny_tds/version"
|
5
|
+
require "tiny_tds/error"
|
6
|
+
require "tiny_tds/client"
|
7
|
+
require "tiny_tds/result"
|
8
|
+
require "tiny_tds/gem"
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
module TinyTds
|
11
|
+
# Is this file part of a fat binary gem with bundled freetds?
|
12
|
+
# This path must be enabled by add_dll_directory on Windows.
|
13
|
+
gplat = ::Gem::Platform.local
|
14
|
+
FREETDS_LIB_PATH = Dir[File.expand_path("../ports/#{gplat.cpu}-#{gplat.os}*/{bin,lib}", __dir__)].first
|
15
15
|
|
16
16
|
add_dll_path = proc do |path, &block|
|
17
|
-
|
18
|
-
require 'ruby_installer/runtime'
|
19
|
-
RubyInstaller::Runtime.add_dll_directory(path, &block)
|
20
|
-
rescue LoadError
|
21
|
-
old_path = ENV['PATH']
|
22
|
-
ENV['PATH'] = "#{path};#{old_path}"
|
17
|
+
if RUBY_PLATFORM =~ /(mswin|mingw)/i && path
|
23
18
|
begin
|
19
|
+
require "ruby_installer/runtime"
|
20
|
+
RubyInstaller::Runtime.add_dll_directory(path, &block)
|
21
|
+
rescue LoadError
|
22
|
+
old_path = ENV["PATH"]
|
23
|
+
ENV["PATH"] = "#{path};#{old_path}"
|
24
24
|
block.call
|
25
|
-
|
26
|
-
ENV['PATH'] = old_path
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
add_dll_paths = proc do |paths, &block|
|
32
|
-
if path=paths.shift
|
33
|
-
add_dll_path.call(path) do
|
34
|
-
add_dll_paths.call(paths, &block)
|
25
|
+
ENV["PATH"] = old_path
|
35
26
|
end
|
36
27
|
else
|
28
|
+
# libsybdb is found by a relative rpath in the cross compiled extension dll
|
29
|
+
# or by the system library loader
|
37
30
|
block.call
|
38
31
|
end
|
39
32
|
end
|
40
33
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
49
|
-
else
|
50
|
-
# Load dependent shared libraries into the process, so that they are already present,
|
51
|
-
# when tiny_tds.so is loaded. This ensures, that shared libraries are loaded even when
|
52
|
-
# the path is different between build and run time (e.g. Heroku).
|
53
|
-
ports_libs = File.join(TinyTds::Gem.ports_root_path,
|
54
|
-
"#{RbConfig::CONFIG['host']}/lib/*.so")
|
55
|
-
Dir[ports_libs].each do |lib|
|
56
|
-
require 'fiddle'
|
57
|
-
Fiddle.dlopen(lib)
|
34
|
+
add_dll_path.call(FREETDS_LIB_PATH) do
|
35
|
+
# Try the <major>.<minor> subdirectory for fat binary gems
|
36
|
+
major_minor = RUBY_VERSION[/^(\d+\.\d+)/] or
|
37
|
+
raise "Oops, can't extract the major/minor version from #{RUBY_VERSION.dump}"
|
38
|
+
require "tiny_tds/#{major_minor}/tiny_tds"
|
39
|
+
rescue LoadError
|
40
|
+
require "tiny_tds/tiny_tds"
|
58
41
|
end
|
59
|
-
|
60
|
-
require 'tiny_tds/tiny_tds'
|
61
42
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -x
|
4
|
+
set -e
|
5
|
+
|
6
|
+
# this should mirror the steps outlined in the circleci yml
|
7
|
+
echo "Installing mssql-tools..."
|
8
|
+
sleep 5
|
9
|
+
sudo -E ./test/bin/install-mssqltools.sh
|
10
|
+
|
11
|
+
echo "Configurating tinytds test database..."
|
12
|
+
sleep 5
|
13
|
+
./test/bin/setup_tinytds_db.sh
|
14
|
+
|
15
|
+
echo "Building openssl library..."
|
16
|
+
sleep 5
|
17
|
+
sudo -E ./test/bin/install-openssl.sh
|
18
|
+
|
19
|
+
echo "Building freetds library..."
|
20
|
+
sleep 5
|
21
|
+
sudo -E ./test/bin/install-freetds.sh
|
22
|
+
|
23
|
+
echo "Installing gems..."
|
24
|
+
sleep 5
|
25
|
+
bundle install
|
data/start_dev.sh
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -x
|
4
|
+
set -e
|
5
|
+
|
6
|
+
# set volume read/write permissions to work both outside and inside container
|
7
|
+
sudo ./test/bin/setup_volume_permissions.sh
|
8
|
+
|
9
|
+
docker-compose up -d
|
10
|
+
echo "Waiting for containers to start..."
|
11
|
+
sleep 10
|
12
|
+
|
13
|
+
# setup circleci ruby container for development
|
14
|
+
docker exec cimg_ruby bash -c './setup_cimgruby_dev.sh'
|
15
|
+
|
16
|
+
# enter container
|
17
|
+
set +x
|
18
|
+
echo "cimg/ruby container is ready for tiny_tds development.........."
|
19
|
+
echo "To enter container run: docker exec -it cimg_ruby /bin/bash"
|
20
|
+
echo "To build solution run: docker exec cimg_ruby bash -c 'bundle exec rake build'"
|
21
|
+
echo "To test solution run: docker exec cimg_ruby bash -c 'bundle exec rake test'"
|
data/tasks/native_gem.rake
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
|
1
|
+
CrossLibraries.each do |xlib|
|
2
|
+
platform = xlib.platform
|
2
3
|
|
3
|
-
desc
|
4
|
-
task
|
5
|
-
|
4
|
+
desc "Build fat binary gem for platform #{platform}"
|
5
|
+
task "gem:native:#{platform}" do
|
6
|
+
require "rake_compiler_dock"
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
RakeCompilerDock.sh <<-EOT, platform: platform
|
9
|
+
bundle install &&
|
10
|
+
rake native:#{platform} pkg/#{SPEC.full_name}-#{platform}.gem MAKEOPTS=-j`nproc` RUBY_CC_VERSION=#{RakeCompilerDock.set_ruby_cc_version("~> 2.7", "~> 3.0")} MAKEFLAGS="V=1"
|
11
|
+
EOT
|
12
|
+
end
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
RakeCompilerDock.sh build.join(' && ')
|
14
|
+
desc "Build the native binary gems"
|
15
|
+
multitask "gem:native" => "gem:native:#{platform}"
|
14
16
|
end
|