tiny_tds 2.1.6-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +407 -0
  3. data/.codeclimate.yml +20 -0
  4. data/.gitattributes +1 -0
  5. data/.gitignore +22 -0
  6. data/.rubocop.yml +31 -0
  7. data/CHANGELOG.md +280 -0
  8. data/CODE_OF_CONDUCT.md +31 -0
  9. data/Gemfile +2 -0
  10. data/ISSUE_TEMPLATE.md +38 -0
  11. data/MIT-LICENSE +23 -0
  12. data/README.md +504 -0
  13. data/Rakefile +62 -0
  14. data/VERSION +1 -0
  15. data/bin/defncopy-ttds +3 -0
  16. data/bin/tsql-ttds +3 -0
  17. data/docker-compose.yml +34 -0
  18. data/exe/.keep +0 -0
  19. data/ext/tiny_tds/client.c +499 -0
  20. data/ext/tiny_tds/client.h +53 -0
  21. data/ext/tiny_tds/extconf.rb +92 -0
  22. data/ext/tiny_tds/extconsts.rb +15 -0
  23. data/ext/tiny_tds/result.c +634 -0
  24. data/ext/tiny_tds/result.h +32 -0
  25. data/ext/tiny_tds/tiny_tds_ext.c +12 -0
  26. data/ext/tiny_tds/tiny_tds_ext.h +17 -0
  27. data/lib/tiny_tds/3.1/tiny_tds.so +0 -0
  28. data/lib/tiny_tds/3.2/tiny_tds.so +0 -0
  29. data/lib/tiny_tds/bin.rb +104 -0
  30. data/lib/tiny_tds/client.rb +136 -0
  31. data/lib/tiny_tds/error.rb +14 -0
  32. data/lib/tiny_tds/gem.rb +27 -0
  33. data/lib/tiny_tds/result.rb +7 -0
  34. data/lib/tiny_tds/version.rb +3 -0
  35. data/lib/tiny_tds.rb +61 -0
  36. data/patches/freetds/1.00.27/0001-mingw_missing_inet_pton.diff +34 -0
  37. data/patches/freetds/1.00.27/0002-Don-t-use-MSYS2-file-libws2_32.diff +28 -0
  38. data/patches/libiconv/1.14/1-avoid-gets-error.patch +17 -0
  39. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/bsqldb.exe +0 -0
  40. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/datacopy.exe +0 -0
  41. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/defncopy.exe +0 -0
  42. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/freebcp.exe +0 -0
  43. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/libct-4.dll +0 -0
  44. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/libsybdb-5.dll +0 -0
  45. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/osql +388 -0
  46. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/tdspool.exe +0 -0
  47. data/ports/x64-mingw-ucrt/freetds/1.1.24/bin/tsql.exe +0 -0
  48. data/ports/x64-mingw-ucrt/freetds/1.1.24/lib/libct.dll.a +0 -0
  49. data/ports/x64-mingw-ucrt/freetds/1.1.24/lib/libct.la +41 -0
  50. data/ports/x64-mingw-ucrt/freetds/1.1.24/lib/libsybdb.dll.a +0 -0
  51. data/ports/x64-mingw-ucrt/freetds/1.1.24/lib/libsybdb.la +41 -0
  52. data/ports/x64-mingw-ucrt/libiconv/1.15/bin/iconv.exe +0 -0
  53. data/ports/x64-mingw-ucrt/libiconv/1.15/bin/libcharset-1.dll +0 -0
  54. data/ports/x64-mingw-ucrt/libiconv/1.15/bin/libiconv-2.dll +0 -0
  55. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/charset.alias +4 -0
  56. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/libcharset.dll.a +0 -0
  57. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/libcharset.la +41 -0
  58. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/libiconv.dll.a +0 -0
  59. data/ports/x64-mingw-ucrt/libiconv/1.15/lib/libiconv.la +41 -0
  60. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/c_rehash +251 -0
  61. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/libcrypto-1_1-x64.dll +0 -0
  62. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/libssl-1_1-x64.dll +0 -0
  63. data/ports/x64-mingw-ucrt/openssl/1.1.1s/bin/openssl.exe +0 -0
  64. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libcrypto.a +0 -0
  65. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libcrypto.dll.a +0 -0
  66. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libssl.a +0 -0
  67. data/ports/x64-mingw-ucrt/openssl/1.1.1s/lib/libssl.dll.a +0 -0
  68. data/setup_cimgruby_dev.sh +25 -0
  69. data/start_dev.sh +21 -0
  70. data/tasks/native_gem.rake +23 -0
  71. data/tasks/package.rake +8 -0
  72. data/tasks/ports/freetds.rb +37 -0
  73. data/tasks/ports/libiconv.rb +26 -0
  74. data/tasks/ports/openssl.rb +62 -0
  75. data/tasks/ports/recipe.rb +64 -0
  76. data/tasks/ports.rake +108 -0
  77. data/tasks/test.rake +9 -0
  78. data/test/benchmark/query.rb +77 -0
  79. data/test/benchmark/query_odbc.rb +106 -0
  80. data/test/benchmark/query_tinytds.rb +126 -0
  81. data/test/bin/install-freetds.sh +20 -0
  82. data/test/bin/install-mssql.ps1 +31 -0
  83. data/test/bin/install-mssqltools.sh +9 -0
  84. data/test/bin/install-openssl.sh +18 -0
  85. data/test/bin/setup_tinytds_db.sh +7 -0
  86. data/test/bin/setup_volume_permissions.sh +10 -0
  87. data/test/client_test.rb +275 -0
  88. data/test/gem_test.rb +177 -0
  89. data/test/result_test.rb +814 -0
  90. data/test/schema/1px.gif +0 -0
  91. data/test/schema/sqlserver_2000.sql +140 -0
  92. data/test/schema/sqlserver_2005.sql +140 -0
  93. data/test/schema/sqlserver_2008.sql +140 -0
  94. data/test/schema/sqlserver_2014.sql +140 -0
  95. data/test/schema/sqlserver_2016.sql +140 -0
  96. data/test/schema/sqlserver_azure.sql +140 -0
  97. data/test/schema/sybase_ase.sql +138 -0
  98. data/test/schema_test.rb +443 -0
  99. data/test/sql/db-create.sql +18 -0
  100. data/test/sql/db-login.sql +38 -0
  101. data/test/test_helper.rb +280 -0
  102. data/test/thread_test.rb +98 -0
  103. data/tiny_tds.gemspec +31 -0
  104. metadata +267 -0
@@ -0,0 +1,104 @@
1
+ require_relative './version'
2
+ require_relative './gem'
3
+ require 'shellwords'
4
+
5
+ module TinyTds
6
+ class Bin
7
+
8
+ attr_reader :name
9
+
10
+ class << self
11
+ def exe(name, *args)
12
+ bin = new(name)
13
+ puts bin.info unless args.any? { |x| x == '-q' }
14
+ bin.run(*args)
15
+ end
16
+ end
17
+
18
+ def initialize(name)
19
+ @root = Gem.root_path
20
+ @exts = (ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']) | ['.exe']
21
+
22
+ @name = name
23
+ @binstub = find_bin
24
+ @exefile = find_exe
25
+ end
26
+
27
+ def run(*args)
28
+ with_ports_paths do
29
+ return nil unless path
30
+ Kernel.system Shellwords.join(args.unshift(path))
31
+ $CHILD_STATUS.to_i
32
+ end
33
+ end
34
+
35
+ def path
36
+ @path ||= @exefile && File.exist?(@exefile) ? @exefile : which
37
+ end
38
+
39
+ def info
40
+ "[TinyTds][v#{TinyTds::VERSION}][#{name}]: #{path}"
41
+ end
42
+
43
+ private
44
+
45
+ def search_paths
46
+ ENV['PATH'].split File::PATH_SEPARATOR
47
+ end
48
+
49
+ def with_ports_paths
50
+ old_path = ENV['PATH']
51
+
52
+ begin
53
+ ENV['PATH'] = [
54
+ Gem.ports_bin_paths,
55
+ old_path
56
+ ].flatten.join File::PATH_SEPARATOR
57
+
58
+ yield if block_given?
59
+ ensure
60
+ ENV['PATH'] = old_path
61
+ end
62
+ end
63
+
64
+ def find_bin
65
+ File.join @root, 'bin', name
66
+ end
67
+
68
+ def find_exe
69
+ Gem.ports_bin_paths.each do |bin|
70
+ @exts.each do |ext|
71
+ f = File.join bin, "#{name}#{ext}"
72
+ return f if File.exist?(f)
73
+ end
74
+ end
75
+ nil
76
+ end
77
+
78
+ def which
79
+ search_paths.each do |path|
80
+ @exts.each do |ext|
81
+ exe = File.expand_path File.join(path, "#{name}#{ext}"), @root
82
+ next if exe == @binstub
83
+ next unless File.executable?(exe)
84
+ next unless binary?(exe)
85
+ return exe
86
+ end
87
+ end
88
+ nil
89
+ 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
+ end
104
+ end
@@ -0,0 +1,136 @@
1
+ module TinyTds
2
+ class Client
3
+
4
+ @default_query_options = {
5
+ as: :hash,
6
+ symbolize_keys: false,
7
+ cache_rows: true,
8
+ timezone: :local,
9
+ empty_sets: true
10
+ }
11
+
12
+ attr_reader :query_options
13
+ attr_reader :message_handler
14
+
15
+ class << self
16
+
17
+ attr_reader :default_query_options
18
+
19
+ # Most, if not all, iconv encoding names can be found by ruby. Just in case, you can
20
+ # overide this method to return a string name that Encoding.find would work with. Default
21
+ # is to return the passed encoding.
22
+ #
23
+ def transpose_iconv_encoding(encoding)
24
+ encoding
25
+ end
26
+
27
+ def local_offset
28
+ ::Time.local(2010).utc_offset.to_r / 86_400
29
+ end
30
+
31
+ end
32
+
33
+ # rubocop:disable Metrics/AbcSize
34
+ # rubocop:disable Metrics/MethodLength
35
+ # rubocop:disable Metrics/CyclomaticComplexity
36
+ # rubocop:disable Metrics/PerceivedComplexity
37
+ def initialize(opts = {})
38
+ if opts[:dataserver].to_s.empty? && opts[:host].to_s.empty?
39
+ raise ArgumentError, 'missing :host option if no :dataserver given'
40
+ end
41
+
42
+ @message_handler = opts[:message_handler]
43
+ if @message_handler && !@message_handler.respond_to?(:call)
44
+ raise ArgumentError, ':message_handler must implement `call` (eg, a Proc or a Method)'
45
+ end
46
+
47
+ opts[:username] = parse_username(opts)
48
+ @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] ||= 'TinyTds'
51
+ opts[:tds_version] = tds_versions_setter(opts)
52
+ opts[:use_utf16] = opts[:use_utf16].nil? || ["true", "1", "yes"].include?(opts[:use_utf16].to_s)
53
+ opts[:login_timeout] ||= 60
54
+ opts[:timeout] ||= 5
55
+ opts[:encoding] = opts[:encoding].nil? || opts[:encoding].casecmp('utf8').zero? ? 'UTF-8' : opts[:encoding].upcase
56
+ opts[:port] ||= 1433
57
+ opts[:dataserver] = "#{opts[:host]}:#{opts[:port]}" if opts[:dataserver].to_s.empty?
58
+ forced_integer_keys = [:login_timeout, :port, :timeout]
59
+ forced_integer_keys.each { |k| opts[k] = opts[k].to_i if opts[k] }
60
+ connect(opts)
61
+ end
62
+
63
+ def tds_73?
64
+ tds_version >= 11
65
+ end
66
+
67
+ def tds_version_info
68
+ info = TDS_VERSIONS_GETTERS[tds_version]
69
+ "#{info[:name]} - #{info[:description]}" if info
70
+ end
71
+
72
+ def active?
73
+ !closed? && !dead?
74
+ end
75
+
76
+ private
77
+
78
+ def parse_username(opts)
79
+ host = opts[:host]
80
+ username = opts[:username]
81
+ return username if username.nil? || !opts[:azure]
82
+ return username if username.include?('@') && !username.include?('database.windows.net')
83
+ user, domain = username.split('@')
84
+ domain ||= host
85
+ "#{user}@#{domain.split('.').first}"
86
+ end
87
+
88
+ def tds_versions_setter(opts = {})
89
+ v = opts[:tds_version] || ENV['TDSVER'] || '7.3'
90
+ TDS_VERSIONS_SETTERS[v.to_s]
91
+ end
92
+
93
+ # From sybdb.h comments:
94
+ # DBVERSION_xxx are used with dbsetversion()
95
+ #
96
+ TDS_VERSIONS_SETTERS = {
97
+ 'unknown' => 0,
98
+ '46' => 1,
99
+ '100' => 2,
100
+ '42' => 3,
101
+ '70' => 4,
102
+ '7.0' => 4,
103
+ '71' => 5,
104
+ '7.1' => 5,
105
+ '80' => 5,
106
+ '8.0' => 5,
107
+ '72' => 6,
108
+ '7.2' => 6,
109
+ '90' => 6,
110
+ '9.0' => 6,
111
+ '73' => 7,
112
+ '7.3' => 7
113
+ }.freeze
114
+
115
+ # From sybdb.h comments:
116
+ # DBTDS_xxx are returned by DBTDS()
117
+ # The integer values of the constants are poorly chosen.
118
+ #
119
+ TDS_VERSIONS_GETTERS = {
120
+ 0 => { name: 'DBTDS_UNKNOWN', description: 'Unknown' },
121
+ 1 => { name: 'DBTDS_2_0', description: 'Pre 4.0 SQL Server' },
122
+ 2 => { name: 'DBTDS_3_4', description: 'Microsoft SQL Server (3.0)' },
123
+ 3 => { name: 'DBTDS_4_0', description: '4.0 SQL Server' },
124
+ 4 => { name: 'DBTDS_4_2', description: '4.2 SQL Server' },
125
+ 5 => { name: 'DBTDS_4_6', description: '2.0 OpenServer and 4.6 SQL Server.' },
126
+ 6 => { name: 'DBTDS_4_9_5', description: '4.9.5 (NCR) SQL Server' },
127
+ 7 => { name: 'DBTDS_5_0', description: '5.0 SQL Server' },
128
+ 8 => { name: 'DBTDS_7_0', description: 'Microsoft SQL Server 7.0' },
129
+ 9 => { name: 'DBTDS_7_1/DBTDS_8_0', description: 'Microsoft SQL Server 2000' },
130
+ 10 => { name: 'DBTDS_7_2/DBTDS_9_0', description: 'Microsoft SQL Server 2005' },
131
+ 11 => { name: 'DBTDS_7_3', description: 'Microsoft SQL Server 2008' },
132
+ 12 => { name: 'DBTDS_7_4', description: 'Microsoft SQL Server 2012/2014' }
133
+ }.freeze
134
+
135
+ end
136
+ end
@@ -0,0 +1,14 @@
1
+ module TinyTds
2
+ class Error < StandardError
3
+
4
+ attr_accessor :source, :severity, :db_error_number, :os_error_number
5
+
6
+ def initialize(message)
7
+ super
8
+ @severity = nil
9
+ @db_error_number = nil
10
+ @os_error_number = nil
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ require 'rbconfig'
2
+
3
+ module TinyTds
4
+ module Gem
5
+ class << self
6
+ def root_path
7
+ File.expand_path '../../..', __FILE__
8
+ end
9
+
10
+ def ports_root_path
11
+ File.join(root_path,'ports')
12
+ end
13
+
14
+ def ports_bin_paths
15
+ Dir.glob(File.join(ports_root_path,ports_host,'**','bin'))
16
+ end
17
+
18
+ def ports_lib_paths
19
+ Dir.glob(File.join(ports_root_path,ports_host,'**','lib'))
20
+ end
21
+
22
+ def ports_host
23
+ RbConfig::CONFIG["arch"]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ module TinyTds
2
+ class Result
3
+
4
+ include Enumerable
5
+
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module TinyTds
2
+ VERSION = File.read(File.expand_path('../../../VERSION', __FILE__)).chomp
3
+ end
data/lib/tiny_tds.rb ADDED
@@ -0,0 +1,61 @@
1
+ # encoding: UTF-8
2
+ require 'date'
3
+ require 'bigdecimal'
4
+ require 'rational'
5
+
6
+ require 'tiny_tds/version'
7
+ require 'tiny_tds/error'
8
+ require 'tiny_tds/client'
9
+ require 'tiny_tds/result'
10
+ require 'tiny_tds/gem'
11
+
12
+ # Support multiple ruby versions, fat binaries under Windows.
13
+ if RUBY_PLATFORM =~ /mingw|mswin/ && RUBY_VERSION =~ /(\d+.\d+)/
14
+ ver = Regexp.last_match(1)
15
+
16
+ add_dll_path = proc do |path, &block|
17
+ begin
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}"
23
+ begin
24
+ block.call
25
+ ensure
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)
35
+ end
36
+ else
37
+ block.call
38
+ end
39
+ end
40
+
41
+ # Temporary add bin directories for DLL search, so that freetds DLLs can be found.
42
+ add_dll_paths.call( TinyTds::Gem.ports_bin_paths ) do
43
+ begin
44
+ require "tiny_tds/#{ver}/tiny_tds"
45
+ rescue LoadError
46
+ require 'tiny_tds/tiny_tds'
47
+ end
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)
58
+ end
59
+
60
+ require 'tiny_tds/tiny_tds'
61
+ end
@@ -0,0 +1,34 @@
1
+ diff --git a/src/tds/tls.c b/src/tds/tls.c
2
+ index 09e7fa0..1da18f6 100644
3
+ --- a/src/tds/tls.c
4
+ +++ b/src/tds/tls.c
5
+ @@ -101,6 +101,29 @@
6
+ #define SSL_PTR BIO_get_data(bio)
7
+ #endif
8
+
9
+ +/*
10
+ + * Add a workaround for older Mingw versions without inet_pton().
11
+ + * This means RubyInstallers DevKit-4.7.2 in particular.
12
+ + */
13
+ +#if defined(__MINGW32__) && !defined(InetPtonA)
14
+ + #include <windows.h>
15
+ +
16
+ + static HMODULE ws2_32 = NULL;
17
+ + typedef INT (WINAPI * __inet_pton)(INT Family, LPCWSTR pStringBuf, PVOID pAddr);
18
+ + static __inet_pton _inet_pton = NULL;
19
+ +
20
+ + INT WINAPI inet_pton(INT Family, LPCWSTR pStringBuf, PVOID pAddr)
21
+ + {
22
+ + if (_inet_pton == NULL) {
23
+ + ws2_32 = LoadLibraryEx("Ws2_32.dll", NULL, 0);
24
+ +
25
+ + _inet_pton = (__inet_pton)GetProcAddress(ws2_32, "inet_pton");
26
+ + }
27
+ +
28
+ + return (_inet_pton)(Family, pStringBuf, pAddr);
29
+ + }
30
+ +#endif
31
+ +
32
+ static SSL_RET
33
+ tds_pull_func_login(SSL_PULL_ARGS)
34
+ {
@@ -0,0 +1,28 @@
1
+ From 56e8972f66c3e948e2ad6885595c58fd23dcdb37 Mon Sep 17 00:00:00 2001
2
+ From: Lars Kanis <kanis@comcard.de>
3
+ Date: Thu, 6 Jul 2017 17:09:40 +0200
4
+ Subject: [PATCH] Don't use MSYS2 file libws2_32.a for MINGW build
5
+
6
+ This file is intended for MSYS2/cygwin builds and blocks OpenSSL
7
+ detection of freetds on i686.
8
+ ---
9
+ configure | 2 --
10
+ configure.ac | 2 --
11
+ 2 files changed, 4 deletions(-)
12
+
13
+ diff --git a/configure b/configure
14
+ index 9495a49..31eb01d 100644
15
+ --- a/configure
16
+ +++ b/configure
17
+ @@ -15915,8 +15915,6 @@ case $host in
18
+ tds_mingw=yes
19
+ if test "$host_cpu" = "x86_64"; then
20
+ LIBS="-lws2_32"
21
+ - elif test -r /usr/lib/w32api/libws2_32.a; then
22
+ - LIBS="-L/usr/lib/w32api -lws2_32"
23
+ else
24
+ LIBS="-lws2_32"
25
+ fi
26
+ --
27
+ 2.6.2.windows.1
28
+
@@ -0,0 +1,17 @@
1
+ --- a/srclib/stdio.in.h 2017-01-22 01:23:00.000000000 -0400
2
+ +++ b/srclib/stdio.in.h 2017-01-22 01:24:00.000000000 -0400
3
+ @@ -695,8 +695,14 @@
4
+ /* It is very rare that the developer ever has full control of stdin,
5
+ so any use of gets warrants an unconditional warning. Assume it is
6
+ always declared, since it is required by C89. */
7
+ +#if defined(__GLIBC__) && !defined(__UCLIBC__)
8
+ +# ifdef __GLIBC_PREREQ
9
+ +# if !__GLIBC_PREREQ(2, 16)
10
+ _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
11
+ +# endif
12
+ +# endif
13
+ +#endif
14
+ #endif
15
+
16
+
17
+ #if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@