tiny_tds 2.1.2 → 3.0.0

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.
Files changed (51) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +470 -0
  3. data/.gitignore +2 -0
  4. data/CHANGELOG.md +39 -1
  5. data/Gemfile +0 -7
  6. data/ISSUE_TEMPLATE.md +1 -1
  7. data/README.md +50 -59
  8. data/Rakefile +15 -10
  9. data/VERSION +1 -1
  10. data/docker-compose.yml +34 -0
  11. data/ext/tiny_tds/client.c +100 -59
  12. data/ext/tiny_tds/client.h +5 -3
  13. data/ext/tiny_tds/extconf.rb +38 -16
  14. data/ext/tiny_tds/extconsts.rb +4 -10
  15. data/ext/tiny_tds/result.c +52 -45
  16. data/ext/tiny_tds/tiny_tds_ext.c +4 -1
  17. data/lib/tiny_tds/gem.rb +1 -6
  18. data/setup_cimgruby_dev.sh +25 -0
  19. data/start_dev.sh +21 -0
  20. data/tasks/native_gem.rake +15 -6
  21. data/tasks/ports/freetds.rb +1 -6
  22. data/tasks/ports/libiconv.rb +0 -17
  23. data/tasks/ports/openssl.rb +2 -18
  24. data/tasks/ports/recipe.rb +16 -4
  25. data/tasks/ports.rake +61 -40
  26. data/test/bin/install-mssql.ps1 +42 -0
  27. data/test/bin/install-mssqltools.sh +9 -0
  28. data/test/bin/setup_tinytds_db.sh +7 -0
  29. data/test/bin/setup_volume_permissions.sh +10 -0
  30. data/test/client_test.rb +101 -59
  31. data/test/gem_test.rb +25 -28
  32. data/test/result_test.rb +130 -182
  33. data/test/schema_test.rb +366 -388
  34. data/test/sql/db-create.sql +18 -0
  35. data/test/sql/db-login.sql +38 -0
  36. data/test/test_helper.rb +63 -31
  37. data/test/thread_test.rb +1 -1
  38. data/tiny_tds.gemspec +10 -7
  39. metadata +70 -52
  40. data/.travis.yml +0 -24
  41. data/BACKERS.md +0 -32
  42. data/appveyor.yml +0 -51
  43. data/test/appveyor/dbsetup.ps1 +0 -27
  44. data/test/appveyor/dbsetup.sql +0 -9
  45. data/test/bin/setup.sh +0 -19
  46. data/test/schema/sqlserver_2000.sql +0 -140
  47. data/test/schema/sqlserver_2005.sql +0 -140
  48. data/test/schema/sqlserver_2014.sql +0 -140
  49. data/test/schema/sqlserver_2016.sql +0 -140
  50. data/test/schema/sybase_ase.sql +0 -138
  51. /data/test/schema/{sqlserver_2008.sql → sqlserver_2017.sql} +0 -0
@@ -21,36 +21,58 @@ end
21
21
  do_help if arg_config('--help')
22
22
 
23
23
  # Make sure to check the ports path for the configured host
24
- host = RbConfig::CONFIG['host']
25
- project_dir = File.join(['..']*4)
26
- freetds_ports_dir = File.join(project_dir, 'ports', host, 'freetds', FREETDS_VERSION)
24
+ architecture = RbConfig::CONFIG['arch']
25
+
26
+ project_dir = File.expand_path("../../..", __FILE__)
27
+ freetds_ports_dir = File.join(project_dir, 'ports', architecture, 'freetds', FREETDS_VERSION)
27
28
  freetds_ports_dir = File.expand_path(freetds_ports_dir)
28
29
 
29
30
  # Add all the special path searching from the original tiny_tds build
30
- # order is important here! First in, last searched.
31
+ # order is important here! First in, first searched.
31
32
  DIRS = %w(
32
- /usr/local
33
33
  /opt/local
34
+ /usr/local
34
35
  )
35
36
 
36
- # Grab freetds environment variable for use by people on services like
37
- # Heroku who they can't easily use bundler config to set directories
38
- DIRS.push(ENV['FREETDS_DIR']) if ENV.has_key?('FREETDS_DIR')
37
+ if RbConfig::CONFIG['host_os'] =~ /darwin/i
38
+ # Ruby below 2.7 seems to label the host CPU on Apple Silicon as aarch64
39
+ # 2.7 and above print is as ARM64
40
+ target_host_cpu = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7') ? 'aarch64' : 'arm64'
41
+
42
+ if RbConfig::CONFIG['host_cpu'] == target_host_cpu
43
+ # Homebrew on Apple Silicon installs into /opt/hombrew
44
+ # https://docs.brew.sh/Installation
45
+ # On Intel Macs, it is /usr/local, so no changes necessary to DIRS
46
+ DIRS.unshift("/opt/homebrew")
47
+ end
48
+ end
49
+
50
+ if ENV["RI_DEVKIT"] && ENV["MINGW_PREFIX"] # RubyInstaller Support
51
+ DIRS.unshift(File.join(ENV["RI_DEVKIT"], ENV["MINGW_PREFIX"]))
52
+ end
39
53
 
40
54
  # Add the ports directory if it exists for local developer builds
41
- DIRS.push(freetds_ports_dir) if File.directory?(freetds_ports_dir)
55
+ DIRS.unshift(freetds_ports_dir) if File.directory?(freetds_ports_dir)
56
+
57
+ # Grab freetds environment variable for use by people on services like
58
+ # Heroku who they can't easily use bundler config to set directories
59
+ DIRS.unshift(ENV['FREETDS_DIR']) if ENV.has_key?('FREETDS_DIR')
42
60
 
43
61
  # Add the search paths for freetds configured above
44
- DIRS.each do |path|
45
- idir = "#{path}/include"
62
+ ldirs = DIRS.flat_map do |path|
46
63
  ldir = "#{path}/lib"
64
+ [ldir, "#{ldir}/freetds"]
65
+ end
47
66
 
48
- dir_config('freetds',
49
- [idir, "#{idir}/freetds"],
50
- [ldir, "#{ldir}/freetds"]
51
- )
67
+ idirs = DIRS.flat_map do |path|
68
+ idir = "#{path}/include"
69
+ [idir, "#{idir}/freetds"]
52
70
  end
53
71
 
72
+ puts "looking for freetds headers in the following directories:\n#{idirs.map{|a| " - #{a}\n"}.join}"
73
+ puts "looking for freetds library in the following directories:\n#{ldirs.map{|a| " - #{a}\n"}.join}"
74
+ dir_config('freetds', idirs, ldirs)
75
+
54
76
  have_dependencies = [
55
77
  find_header('sybfront.h'),
56
78
  find_header('sybdb.h'),
@@ -61,7 +83,7 @@ have_dependencies = [
61
83
  end
62
84
 
63
85
  unless have_dependencies
64
- abort 'Failed! Do you have FreeTDS 0.95.80 or higher installed?'
86
+ abort 'Failed! Do you have FreeTDS 1.0.0 or higher installed?'
65
87
  end
66
88
 
67
89
  create_makefile('tiny_tds/tiny_tds')
@@ -1,15 +1,9 @@
1
1
 
2
- ICONV_VERSION = ENV['TINYTDS_ICONV_VERSION'] || "1.15"
2
+ ICONV_VERSION = ENV['TINYTDS_ICONV_VERSION'] || "1.17"
3
3
  ICONV_SOURCE_URI = "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-#{ICONV_VERSION}.tar.gz"
4
4
 
5
- OPENSSL_VERSION = ENV['TINYTDS_OPENSSL_VERSION'] || '1.1.0e'
5
+ OPENSSL_VERSION = ENV['TINYTDS_OPENSSL_VERSION'] || '3.4.0'
6
6
  OPENSSL_SOURCE_URI = "https://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz"
7
7
 
8
- FREETDS_VERSION = ENV['TINYTDS_FREETDS_VERSION'] || "1.00.27"
9
- FREETDS_VERSION_INFO = Hash.new { |h,k|
10
- h[k] = {files: "http://www.freetds.org/files/stable/freetds-#{k}.tar.bz2"}
11
- }
12
- FREETDS_VERSION_INFO['1.00'] = {files: 'http://www.freetds.org/files/stable/freetds-1.00.tar.bz2'}
13
- FREETDS_VERSION_INFO['0.99'] = {files: 'http://www.freetds.org/files/current/freetds-dev.0.99.678.tar.gz'}
14
- FREETDS_VERSION_INFO['0.95'] = {files: 'http://www.freetds.org/files/stable/freetds-0.95.92.tar.gz'}
15
- FREETDS_SOURCE_URI = FREETDS_VERSION_INFO[FREETDS_VERSION][:files]
8
+ FREETDS_VERSION = ENV['TINYTDS_FREETDS_VERSION'] || '1.4.23'
9
+ FREETDS_SOURCE_URI = "http://www.freetds.org/files/stable/freetds-#{FREETDS_VERSION}.tar.bz2"
@@ -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
- if (userdata->nonblocking_error.is_set) {
99
- userdata->nonblocking_error.is_set = 0;
100
- rb_tinytds_raise_error(client,
101
- userdata->nonblocking_error.is_message,
102
- userdata->nonblocking_error.cancel,
103
- userdata->nonblocking_error.error,
104
- userdata->nonblocking_error.source,
105
- userdata->nonblocking_error.severity,
106
- userdata->nonblocking_error.dberr,
107
- userdata->nonblocking_error.oserr);
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 40: // SYBMSDATE
288
- case 41: // SYBMSTIME
289
- case 42: // SYBMSDATETIME2
290
- case 43: { // SYBMSDATETIMEOFFSET
291
- #ifdef DBVERSION_73
292
- if (dbtds(rwrap->client) >= DBTDS_7_3) {
293
- DBDATEREC2 dr2;
294
- dbanydatecrack(rwrap->client, &dr2, coltype, data);
295
- switch(coltype) {
296
- case 40: { // SYBMSDATE
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
- #else
321
- val = ENCODED_STR_NEW(data, data_len);
322
- #endif
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);
@@ -1,6 +1,9 @@
1
-
2
1
  #include <tiny_tds_ext.h>
3
2
 
3
+ #ifndef DBVERSION_73
4
+ #error "DBVERSION_73 is not defined. Aborting compilation."
5
+ #endif
6
+
4
7
  VALUE mTinyTds, cTinyTdsError;
5
8
 
6
9
  void Init_tiny_tds() {
data/lib/tiny_tds/gem.rb CHANGED
@@ -20,12 +20,7 @@ module TinyTds
20
20
  end
21
21
 
22
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')
23
+ RbConfig::CONFIG["arch"]
29
24
  end
30
25
  end
31
26
  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'"
@@ -1,14 +1,23 @@
1
1
  # encoding: UTF-8
2
2
 
3
- desc 'Build the windows binary gems per rake-compiler-dock'
4
- task 'gem:windows' => ['ports:cross'] do
3
+ desc 'Build the native binary gems using rake-compiler-dock'
4
+ task 'gem:native' => ['ports:cross'] do
5
5
  require 'rake_compiler_dock'
6
6
 
7
7
  # make sure to install our bundle
8
- build = ['bundle']
8
+ sh "bundle package --all" # Avoid repeated downloads of gems by using gem files from the host.
9
9
 
10
- # and finally build the native gem
11
- build << 'rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 CFLAGS="-Wall" MAKE="make -j`nproc`"'
10
+ GEM_PLATFORM_HOSTS.each do |plat, meta|
11
+ RakeCompilerDock.sh "bundle --local && RUBY_CC_VERSION=#{meta[:ruby_versions]} rake native:#{plat} gem", platform: plat
12
+ end
13
+ end
14
+
15
+ # assumes you are in a container provided by Rake compiler
16
+ # if not, use the task above
17
+ task 'gem:for_platform', [:gem_platform] do |_task, args|
18
+ args.with_defaults(gem_platform: RbConfig::CONFIG["arch"])
12
19
 
13
- RakeCompilerDock.sh build.join(' && ')
20
+ sh "bundle install"
21
+ Rake::Task["ports:compile"].invoke(GEM_PLATFORM_HOSTS[args.gem_platform][:host], args.gem_platform)
22
+ sh "RUBY_CC_VERSION=#{GEM_PLATFORM_HOSTS[args.gem_platform][:ruby_versions]} rake native:#{args.gem_platform} gem"
14
23
  end
@@ -15,12 +15,7 @@ module Ports
15
15
 
16
16
  opts << '--with-pic'
17
17
  opts << '--disable-odbc'
18
-
19
- if version =~ /0\.91/
20
- opts << '--with-tdsver=7.1'
21
- else
22
- opts << '--with-tdsver=7.3'
23
- end
18
+ opts << '--with-tdsver=7.3'
24
19
 
25
20
  if windows?
26
21
  opts << '--sysconfdir=C:/Sites'
@@ -8,25 +8,8 @@ module Ports
8
8
  set_patches
9
9
  end
10
10
 
11
- def cook
12
- chdir_for_build do
13
- super
14
- end
15
- self
16
- end
17
-
18
11
  private
19
12
 
20
- # When using rake-compiler-dock on Windows, the underlying Virtualbox shared
21
- # folders don't support symlinks, but libiconv expects it for a build on
22
- # Linux. We work around this limitation by using the temp dir for cooking.
23
- def chdir_for_build
24
- build_dir = ENV['RCD_HOST_RUBY_PLATFORM'].to_s =~ /mingw|mswin|cygwin/ ? '/tmp' : '.'
25
- Dir.chdir(build_dir) do
26
- yield
27
- end
28
- end
29
-
30
13
  def configure_defaults
31
14
  [
32
15
  "--host=#{@host}",
@@ -27,27 +27,11 @@ module Ports
27
27
 
28
28
  private
29
29
 
30
- def execute(action, command, options={})
31
- # OpenSSL Requires Perl >= 5.10, while the Ruby devkit uses MSYS1 with Perl 5.8.8.
32
- # To overcome this, prepend Git's usr/bin to the PATH.
33
- # It has MSYS2 with a recent version of perl.
34
- prev_path = ENV['PATH']
35
- if host =~ /mingw/ && IO.popen(["perl", "-e", "print($])"], &:read).to_f < 5.010
36
- git_perl = 'C:/Program Files/Git/usr/bin'
37
- if File.directory?(git_perl)
38
- ENV['PATH'] = "#{git_perl}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
39
- ENV['PERL'] = 'perl'
40
- end
41
- end
42
-
43
- super
44
- ENV['PATH'] = prev_path
45
- end
46
-
47
30
  def configure_defaults
48
31
  opts = [
49
32
  'shared',
50
- target_arch
33
+ target_arch,
34
+ "--openssldir=#{path}",
51
35
  ]
52
36
 
53
37
  if cross_build?
@@ -5,17 +5,30 @@ require 'rbconfig'
5
5
 
6
6
  module Ports
7
7
  class Recipe < MiniPortile
8
+ attr_writer :gem_platform
9
+
8
10
  def cook
9
- checkpoint = "ports/#{name}-#{version}-#{host}.installed"
11
+ checkpoint = "ports/checkpoints/#{name}-#{version}-#{gem_platform}.installed"
10
12
 
11
13
  unless File.exist? checkpoint
12
14
  super
15
+ FileUtils.mkdir_p("ports/checkpoints")
13
16
  FileUtils.touch checkpoint
14
17
  end
15
18
  end
16
19
 
17
20
  private
18
21
 
22
+ attr_reader :gem_platform
23
+
24
+ def port_path
25
+ "#{@target}/#{gem_platform}/#{@name}/#{@version}"
26
+ end
27
+
28
+ def tmp_path
29
+ "tmp/#{gem_platform}/ports/#{@name}/#{@version}"
30
+ end
31
+
19
32
  def configure_defaults
20
33
  [
21
34
  "--host=#{@host}",
@@ -38,9 +51,9 @@ module Ports
38
51
 
39
52
  def get_patches(libname, version)
40
53
  patches = []
41
-
54
+
42
55
  patch_path = File.expand_path(
43
- File.join('..','..','..','patches',libname,version),
56
+ File.join('..','..','..','patches',libname,version),
44
57
  __FILE__
45
58
  )
46
59
 
@@ -49,4 +62,3 @@ module Ports
49
62
  end
50
63
  end
51
64
  end
52
-
data/tasks/ports.rake CHANGED
@@ -6,64 +6,70 @@ require_relative 'ports/openssl'
6
6
  require_relative 'ports/freetds'
7
7
  require_relative '../ext/tiny_tds/extconsts'
8
8
 
9
- OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE if defined? OpenSSL
10
-
11
9
  namespace :ports do
12
- openssl = Ports::Openssl.new(OPENSSL_VERSION)
13
- libiconv = Ports::Libiconv.new(ICONV_VERSION)
14
- freetds = Ports::Freetds.new(FREETDS_VERSION)
10
+ libraries_to_compile = {
11
+ openssl: Ports::Openssl.new(OPENSSL_VERSION),
12
+ libiconv: Ports::Libiconv.new(ICONV_VERSION),
13
+ freetds: Ports::Freetds.new(FREETDS_VERSION)
14
+ }
15
15
 
16
16
  directory "ports"
17
+ CLEAN.include "ports/*mingw*"
18
+ CLEAN.include "ports/*.installed"
19
+
20
+ task :openssl, [:host, :gem_platform] do |_task, args|
21
+ args.with_defaults(host: RbConfig::CONFIG['host'], gem_platform: RbConfig::CONFIG["arch"])
17
22
 
18
- task :openssl, [:host] do |task, args|
19
- args.with_defaults(host: RbConfig::CONFIG['host'])
23
+ libraries_to_compile[:openssl].files = [OPENSSL_SOURCE_URI]
24
+ libraries_to_compile[:openssl].host = args.host
25
+ libraries_to_compile[:openssl].gem_platform = args.gem_platform
20
26
 
21
- openssl.files = [OPENSSL_SOURCE_URI]
22
- openssl.host = args.host
23
- openssl.cook
24
- openssl.activate
27
+ libraries_to_compile[:openssl].cook
28
+ libraries_to_compile[:openssl].activate
25
29
  end
26
30
 
27
- task :libiconv, [:host] do |task, args|
28
- args.with_defaults(host: RbConfig::CONFIG['host'])
31
+ task :libiconv, [:host, :gem_platform] do |_task, args|
32
+ args.with_defaults(host: RbConfig::CONFIG['host'], gem_platform: RbConfig::CONFIG["arch"])
29
33
 
30
- libiconv.files = [ICONV_SOURCE_URI]
31
- libiconv.host = args.host
32
- libiconv.cook
33
- libiconv.activate
34
+ libraries_to_compile[:libiconv].files = [ICONV_SOURCE_URI]
35
+ libraries_to_compile[:libiconv].host = args.host
36
+ libraries_to_compile[:libiconv].gem_platform = args.gem_platform
37
+ libraries_to_compile[:libiconv].cook
38
+ libraries_to_compile[:libiconv].activate
34
39
  end
35
40
 
36
- task :freetds, [:host] do |task, args|
37
- args.with_defaults(host: RbConfig::CONFIG['host'])
41
+ task :freetds, [:host, :gem_platform] do |_task, args|
42
+ args.with_defaults(host: RbConfig::CONFIG['host'], gem_platform: RbConfig::CONFIG["arch"])
38
43
 
39
- freetds.files = [FREETDS_SOURCE_URI]
40
- freetds.host = args.host
44
+ libraries_to_compile[:freetds].files = [FREETDS_SOURCE_URI]
45
+ libraries_to_compile[:freetds].host = args.host
46
+ libraries_to_compile[:freetds].gem_platform = args.gem_platform
41
47
 
42
- if openssl
48
+ if libraries_to_compile[:openssl]
43
49
  # freetds doesn't have an option that will provide an rpath
44
50
  # so we do it manually
45
- ENV['OPENSSL_CFLAGS'] = "-Wl,-rpath -Wl,#{openssl.path}/lib"
51
+ ENV['OPENSSL_CFLAGS'] = "-Wl,-rpath -Wl,#{libraries_to_compile[:openssl].path}/lib64"
46
52
  # Add the pkgconfig file with MSYS2'ish path, to prefer our ports build
47
53
  # over MSYS2 system OpenSSL.
48
- ENV['PKG_CONFIG_PATH'] = "#{openssl.path.gsub(/^(\w):/i){"/"+$1.downcase}}/lib/pkgconfig:#{ENV['PKG_CONFIG_PATH']}"
49
- freetds.configure_options << "--with-openssl=#{openssl.path}"
54
+ ENV['PKG_CONFIG_PATH'] = "#{libraries_to_compile[:openssl].path.gsub(/^(\w):/i) { "/" + $1.downcase }}/lib64/pkgconfig:#{ENV['PKG_CONFIG_PATH']}"
55
+ libraries_to_compile[:freetds].configure_options << "--with-openssl=#{libraries_to_compile[:openssl].path}"
50
56
  end
51
57
 
52
- if libiconv
53
- freetds.configure_options << "--with-libiconv-prefix=#{libiconv.path}"
58
+ if libraries_to_compile[:libiconv]
59
+ libraries_to_compile[:freetds].configure_options << "--with-libiconv-prefix=#{libraries_to_compile[:libiconv].path}"
54
60
  end
55
61
 
56
- freetds.cook
57
- freetds.activate
62
+ libraries_to_compile[:freetds].cook
63
+ libraries_to_compile[:freetds].activate
58
64
  end
59
65
 
60
- task :compile, [:host] do |task,args|
61
- args.with_defaults(host: RbConfig::CONFIG['host'])
66
+ task :compile, [:host, :gem_platform] do |_task, args|
67
+ args.with_defaults(host: RbConfig::CONFIG['host'], gem_platform: RbConfig::CONFIG["arch"])
62
68
 
63
- puts "Compiling ports for #{args.host}..."
69
+ puts "Compiling ports for #{args.host} (Ruby platform #{args.gem_platform}) ..."
64
70
 
65
- ['openssl','libiconv','freetds'].each do |lib|
66
- Rake::Task["ports:#{lib}"].invoke(args.host)
71
+ libraries_to_compile.keys.each do |lib|
72
+ Rake::Task["ports:#{lib}"].invoke(args.host, args.gem_platform)
67
73
  end
68
74
  end
69
75
 
@@ -71,15 +77,30 @@ namespace :ports do
71
77
  task 'cross' do
72
78
  require 'rake_compiler_dock'
73
79
 
74
- # make sure to install our bundle
75
- build = ['bundle']
76
-
77
80
  # build the ports for all our cross compile hosts
78
- GEM_PLATFORM_HOSTS.each do |gem_platform, host|
79
- build << "rake ports:compile[#{host}] MAKE='make -j`nproc`'"
81
+ GEM_PLATFORM_HOSTS.each do |gem_platform, meta|
82
+ # make sure to install our bundle
83
+ build = ['bundle']
84
+ build << "RUBY_CC_VERSION=#{meta[:ruby_versions]} rake ports:compile[#{meta[:host]},#{gem_platform}] MAKE='make -j`nproc`'"
85
+ RakeCompilerDock.sh build.join(' && '), platform: gem_platform
86
+ end
87
+ end
88
+
89
+ desc "Notes the actual versions for the compiled ports into a file"
90
+ task "version_file", [:gem_platform] do |_task, args|
91
+ args.with_defaults(gem_platform: RbConfig::CONFIG["arch"])
92
+
93
+ ports_version = {}
94
+
95
+ libraries_to_compile.each do |library, library_recipe|
96
+ ports_version[library] = library_recipe.version
80
97
  end
81
98
 
82
- RakeCompilerDock.sh build.join(' && ')
99
+ ports_version[:platform] = args.gem_platform
100
+
101
+ File.open(".ports_versions", "w") do |f|
102
+ f.write ports_version
103
+ end
83
104
  end
84
105
  end
85
106
 
@@ -0,0 +1,42 @@
1
+ param ([int] $Version)
2
+
3
+ $ProgressPreference = 'SilentlyContinue'
4
+
5
+ $DownloadLinkTable = @{
6
+ 2017 = "https://go.microsoft.com/fwlink/?linkid=829176";
7
+ 2019 = "https://download.microsoft.com/download/7/c/1/7c14e92e-bdcb-4f89-b7cf-93543e7112d1/SQLEXPR_x64_ENU.exe";
8
+ 2022 = "https://download.microsoft.com/download/3/8/d/38de7036-2433-4207-8eae-06e247e17b25/SQLEXPR_x64_ENU.exe";
9
+ }
10
+
11
+ $MajorVersionTable = @{
12
+ 2017 = 14;
13
+ 2019 = 15;
14
+ 2022 = 16;
15
+ }
16
+
17
+ if (-not(Test-path "C:\Downloads")) {
18
+ mkdir "C:\Downloads"
19
+ }
20
+
21
+ $sqlInstallationFile = "C:\Downloads\sqlexpress.exe"
22
+ if (-not(Test-path $sqlInstallationFile -PathType leaf)) {
23
+ Write-Host "Downloading SQL Express ..."
24
+ Invoke-WebRequest -Uri $DownloadLinkTable[$Version] -OutFile "C:\Downloads\sqlexpress.exe"
25
+ }
26
+
27
+ Write-Host "Installing SQL Express ..."
28
+ Start-Process -Wait -FilePath "C:\Downloads\sqlexpress.exe" -ArgumentList /qs, /x:"C:\Downloads\setup"
29
+ C:\Downloads\setup\setup.exe /q /ACTION=Install /INSTANCENAME=SQLEXPRESS /FEATURES=SQLEngine /UPDATEENABLED=0 /SQLSVCACCOUNT='NT AUTHORITY\System' /SQLSYSADMINACCOUNTS='BUILTIN\ADMINISTRATORS' /TCPENABLED=1 /NPENABLED=0 /IACCEPTSQLSERVERLICENSETERMS
30
+
31
+ Write-Host "Configuring SQL Express ..."
32
+ stop-service MSSQL`$SQLEXPRESS
33
+ set-itemproperty -path "HKLM:\software\microsoft\microsoft sql server\mssql$($MajorVersionTable[$Version]).SQLEXPRESS\mssqlserver\supersocketnetlib\tcp\ipall" -name tcpdynamicports -value ''
34
+ set-itemproperty -path "HKLM:\software\microsoft\microsoft sql server\mssql$($MajorVersionTable[$Version]).SQLEXPRESS\mssqlserver\supersocketnetlib\tcp\ipall" -name tcpport -value 1433
35
+ set-itemproperty -path "HKLM:\software\microsoft\microsoft sql server\mssql$($MajorVersionTable[$Version]).SQLEXPRESS\mssqlserver\" -name LoginMode -value 2
36
+
37
+ Write-Host "Starting SQL Express ..."
38
+ start-service MSSQL`$SQLEXPRESS
39
+
40
+ Write-Host "Configuring MSSQL for TinyTDS ..."
41
+ & sqlcmd -i './test/sql/db-create.sql'
42
+ & sqlcmd -i './test/sql/db-login.sql'
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -x
4
+ set -e
5
+
6
+ curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
7
+ curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list
8
+ sudo apt-get update
9
+ sudo ACCEPT_EULA=Y apt-get -y install mssql-tools unixodbc-dev