tiny_tds 0.7.0-x86-mingw32 → 0.9.5.beta.1-x86-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.
data/exe/.keep ADDED
File without changes
@@ -24,7 +24,8 @@ VALUE opt_escape_regex, opt_escape_dblquote;
24
24
 
25
25
  // Lib Backend (Helpers)
26
26
 
27
- VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, char *error, char *source, int severity, int dberr, int oserr) {
27
+ VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, const char *error, const char *source, int severity, int dberr, int oserr) {
28
+ VALUE e;
28
29
  GET_CLIENT_USERDATA(dbproc);
29
30
  if (cancel && !dbdead(dbproc) && userdata && !userdata->closed) {
30
31
  userdata->dbsqlok_sent = 1;
@@ -32,7 +33,7 @@ VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, char *error, char *s
32
33
  userdata->dbcancel_sent = 1;
33
34
  dbcancel(dbproc);
34
35
  }
35
- VALUE e = rb_exc_new2(cTinyTdsError, error);
36
+ e = rb_exc_new2(cTinyTdsError, error);
36
37
  rb_funcall(e, intern_source_eql, 1, rb_str_new2(source));
37
38
  if (severity)
38
39
  rb_funcall(e, intern_severity_eql, 1, INT2FIX(severity));
@@ -48,13 +49,13 @@ VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, char *error, char *s
48
49
  // Lib Backend (Memory Management & Handlers)
49
50
 
50
51
  int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr) {
51
- static char *source = "error";
52
- GET_CLIENT_USERDATA(dbproc);
53
-
52
+ static const char *source = "error";
54
53
  /* Everything should cancel by default */
55
54
  int return_value = INT_CANCEL;
56
55
  int cancel = 0;
57
56
 
57
+ GET_CLIENT_USERDATA(dbproc);
58
+
58
59
  /* These error codes are documented in include/sybdb.h in FreeTDS */
59
60
  switch(dberr) {
60
61
 
@@ -67,7 +68,7 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
67
68
 
68
69
  case SYBEICONVO:
69
70
  dbfreebuf(dbproc);
70
- break;
71
+ return return_value;
71
72
 
72
73
  case SYBETIME:
73
74
  /*
@@ -125,7 +126,7 @@ int tinytds_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, c
125
126
  }
126
127
 
127
128
  int tinytds_msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line) {
128
- static char *source = "message";
129
+ static const char *source = "message";
129
130
  GET_CLIENT_USERDATA(dbproc);
130
131
  if (severity > 10) {
131
132
  // See tinytds_err_handler() for info about why we do this
@@ -230,6 +231,8 @@ static VALUE rb_tinytds_sqlsent(VALUE self) {
230
231
  }
231
232
 
232
233
  static VALUE rb_tinytds_execute(VALUE self, VALUE sql) {
234
+ VALUE result;
235
+
233
236
  GET_CLIENT_WRAPPER(self);
234
237
  rb_tinytds_client_reset_userdata(cwrap->userdata);
235
238
  REQUIRE_OPEN_CLIENT(cwrap);
@@ -239,12 +242,14 @@ static VALUE rb_tinytds_execute(VALUE self, VALUE sql) {
239
242
  return Qfalse;
240
243
  }
241
244
  cwrap->userdata->dbsql_sent = 1;
242
- VALUE result = rb_tinytds_new_result_obj(cwrap);
245
+ result = rb_tinytds_new_result_obj(cwrap);
243
246
  rb_iv_set(result, "@query_options", rb_funcall(rb_iv_get(self, "@query_options"), intern_dup, 0));
244
- GET_RESULT_WRAPPER(result);
245
- rwrap->local_offset = rb_funcall(cTinyTdsClient, intern_local_offset, 0);
246
- rwrap->encoding = cwrap->encoding;
247
- return result;
247
+ {
248
+ GET_RESULT_WRAPPER(result);
249
+ rwrap->local_offset = rb_funcall(cTinyTdsClient, intern_local_offset, 0);
250
+ rwrap->encoding = cwrap->encoding;
251
+ return result;
252
+ }
248
253
  }
249
254
 
250
255
  static VALUE rb_tinytds_charset(VALUE self) {
@@ -258,9 +263,11 @@ static VALUE rb_tinytds_encoding(VALUE self) {
258
263
  }
259
264
 
260
265
  static VALUE rb_tinytds_escape(VALUE self, VALUE string) {
261
- Check_Type(string, T_STRING);
266
+ VALUE new_string;
262
267
  GET_CLIENT_WRAPPER(self);
263
- VALUE new_string = rb_funcall(string, intern_gsub, 2, opt_escape_regex, opt_escape_dblquote);
268
+
269
+ Check_Type(string, T_STRING);
270
+ new_string = rb_funcall(string, intern_gsub, 2, opt_escape_regex, opt_escape_dblquote);
264
271
  rb_enc_associate(new_string, cwrap->encoding);
265
272
  return new_string;
266
273
  }
@@ -280,13 +287,6 @@ static VALUE rb_tinytds_identity_sql(VALUE self) {
280
287
  return rb_str_new2(cwrap->identity_insert_sql);
281
288
  }
282
289
 
283
- static VALUE rb_tinytds_freetds_nine_one_or_higher(VALUE self) {
284
- #ifdef DBSETLDBNAME
285
- return Qtrue;
286
- #else
287
- return Qfalse;
288
- #endif
289
- }
290
290
 
291
291
 
292
292
  // TinyTds::Client (protected)
@@ -294,6 +294,8 @@ static VALUE rb_tinytds_freetds_nine_one_or_higher(VALUE self) {
294
294
  static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
295
295
  /* Parsing options hash to local vars. */
296
296
  VALUE user, pass, dataserver, database, app, version, ltimeout, timeout, charset, azure;
297
+ GET_CLIENT_WRAPPER(self);
298
+
297
299
  user = rb_hash_aref(opts, sym_username);
298
300
  pass = rb_hash_aref(opts, sym_password);
299
301
  dataserver = rb_hash_aref(opts, sym_dataserver);
@@ -311,7 +313,6 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
311
313
  }
312
314
  dberrhandle(tinytds_err_handler);
313
315
  dbmsghandle(tinytds_msg_handler);
314
- GET_CLIENT_WRAPPER(self);
315
316
  cwrap->login = dblogin();
316
317
  if (!NIL_P(version))
317
318
  dbsetlversion(cwrap->login, NUM2INT(version));
@@ -336,6 +337,8 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
336
337
  }
337
338
  cwrap->client = dbopen(cwrap->login, StringValueCStr(dataserver));
338
339
  if (cwrap->client) {
340
+ VALUE transposed_encoding;
341
+
339
342
  cwrap->closed = 0;
340
343
  cwrap->charset = charset;
341
344
  if (!NIL_P(version))
@@ -345,7 +348,7 @@ static VALUE rb_tinytds_connect(VALUE self, VALUE opts) {
345
348
  if (!NIL_P(database) && (azure != Qtrue)) {
346
349
  dbuse(cwrap->client, StringValueCStr(database));
347
350
  }
348
- VALUE transposed_encoding = rb_funcall(cTinyTdsClient, intern_transpose_iconv_encoding, 1, charset);
351
+ transposed_encoding = rb_funcall(cTinyTdsClient, intern_transpose_iconv_encoding, 1, charset);
349
352
  cwrap->encoding = rb_enc_find(StringValueCStr(transposed_encoding));
350
353
  if (dbtds(cwrap->client) <= 7) {
351
354
  cwrap->identity_insert_sql = "SELECT CAST(@@IDENTITY AS bigint) AS Ident";
@@ -375,7 +378,6 @@ void init_tinytds_client() {
375
378
  rb_define_method(cTinyTdsClient, "escape", rb_tinytds_escape, 1);
376
379
  rb_define_method(cTinyTdsClient, "return_code", rb_tinytds_return_code, 0);
377
380
  rb_define_method(cTinyTdsClient, "identity_sql", rb_tinytds_identity_sql, 0);
378
- rb_define_method(cTinyTdsClient, "freetds_091_or_higer?", rb_tinytds_freetds_nine_one_or_higher, 0);
379
381
  /* Define TinyTds::Client Protected Methods */
380
382
  rb_define_protected_method(cTinyTdsClient, "connect", rb_tinytds_connect, 1);
381
383
  /* Symbols For Connect */
@@ -36,6 +36,7 @@ typedef struct {
36
36
  rb_encoding *encoding;
37
37
  } tinytds_client_wrapper;
38
38
 
39
+ VALUE rb_tinytds_raise_error(DBPROCESS *dbproc, int cancel, const char *error, const char *source, int severity, int dberr, int oserr);
39
40
 
40
41
  // Lib Macros
41
42
 
@@ -3,27 +3,13 @@ ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
3
3
  # :stopdoc:
4
4
 
5
5
  require 'mkmf'
6
- require 'mini_portile'
7
6
  require 'fileutils'
8
7
 
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
- "0.92" => {:files => "ftp://ftp.freetds.org/pub/freetds/stable/freetds-0.92.405.tar.gz"},
24
- "current" => {:files => "ftp://ftp.freetds.org/pub/freetds/current/freetds-current.tar.gz"}
25
- })
26
- FREETDS_SOURCE_URI = FREETDS_VERSION_INFO[FREETDS_VERSION][:files]
8
+ # The gem version constraint in the gemspec is not respected at install time.
9
+ # Keep this version in sync with the one in the gemspec !
10
+ gem 'mini_portile2', '~> 2.0'
11
+ require 'mini_portile2'
12
+ require_relative './extconsts'
27
13
 
28
14
  # Shamelessly copied from nokogiri
29
15
  #
@@ -44,6 +30,12 @@ usage: ruby #{$0} [options]
44
30
  --enable-lookup
45
31
  Search for freetds through all paths in the PATH environment variable.
46
32
 
33
+ --disable-openssl
34
+ Disable OpenSSL for freetds build. No effect on system-freetds.
35
+
36
+ --enable-gnutls
37
+ Use GnuTLS instead of OpenSSL for freetds build.
38
+
47
39
  --enable-cross-build
48
40
  Do cross-build.
49
41
  HELP
@@ -90,17 +82,13 @@ class BuildRecipe < MiniPortile
90
82
  super(name, version)
91
83
  self.files = files
92
84
  self.target = File.expand_path('../../../ports', __FILE__)
93
- # Prefer host_alias over host in order to use i586-mingw32msvc as
94
- # correct compiler prefix for cross build, but use host if not set.
95
- self.host = consolidated_host(RbConfig::CONFIG["host_alias"].empty? ? RbConfig::CONFIG["host"] : RbConfig::CONFIG["host_alias"])
85
+ self.host = consolidated_host(RbConfig::CONFIG["host"])
96
86
  self.patch_files = Dir[File.join(self.target, "patches", self.name, self.version, "*.diff")].sort
97
87
  end
98
88
 
99
89
  def consolidated_host(name)
100
- # For ruby-1.9.3 we use newer mingw-w64 (i686-w64-mingw32) to build the shared libraries
101
- # and mingw32 (i586-mingw32msvc) to build the extension.
102
- name.gsub('i586-mingw32msvc', 'i686-w64-mingw32').
103
- gsub('i686-pc-mingw32', 'i686-w64-mingw32')
90
+ # Host name and prefix of build tools are different on Windows 32 bit.
91
+ name.gsub('i686-pc-mingw32', 'i686-w64-mingw32')
104
92
  end
105
93
 
106
94
  def configure_defaults
@@ -111,10 +99,16 @@ class BuildRecipe < MiniPortile
111
99
  ]
112
100
  end
113
101
 
102
+ # Use the same path for all recipes, so that only one include/lib path is required.
114
103
  def port_path
115
104
  "#{target}/#{host}"
116
105
  end
117
106
 
107
+ # We use the same port_path for all recipes. That breaks the standard installed? method.
108
+ def installed?
109
+ false
110
+ end
111
+
118
112
  # When using rake-compiler-dock on Windows, the underlying Virtualbox shared
119
113
  # folders don't support symlinks, but libiconv expects it for a build on
120
114
  # Linux. We work around this limitation by using the temp dir for cooking.
@@ -195,21 +189,24 @@ def define_libssl_recipe(host)
195
189
  end
196
190
 
197
191
  def define_libiconv_recipe(host)
198
- BuildRecipe.new("libiconv", ICONV_VERSION, [ICONV_SOURCE_URI])
199
- .tap do |recipe|
192
+ BuildRecipe.new("libiconv", ICONV_VERSION, [ICONV_SOURCE_URI]).tap do |recipe|
200
193
  # always produce position independent code
201
194
  recipe.configure_options << "CFLAGS=-fPIC"
202
195
  end
203
196
  end
204
197
 
205
- def define_freetds_recipe(host, libiconv, libssl)
206
- BuildRecipe.new("freetds", FREETDS_VERSION, [FREETDS_SOURCE_URI])
207
- .tap do |recipe|
208
- with_tdsver = FREETDS_VERSION =~ /0\.8/ ? "--with-tdsver=8.0" : "--with-tdsver=7.1"
198
+ def define_freetds_recipe(host, libiconv, libssl, gnutls)
199
+ BuildRecipe.new("freetds", FREETDS_VERSION, [FREETDS_SOURCE_URI]).tap do |recipe|
200
+ with_tdsver = FREETDS_VERSION =~ /0\.91/ ? "--with-tdsver=7.1" : "--with-tdsver=7.3"
209
201
  for_windows = recipe.host =~ /mswin|mingw/i
210
202
  recipe.configure_options << '--with-pic'
211
203
  recipe.configure_options << "--with-libiconv-prefix=#{libiconv.path}" if libiconv
212
- recipe.configure_options << "--with-openssl=#{libssl.path}" if libssl
204
+ if true == libssl
205
+ recipe.configure_options << "--with-openssl"
206
+ elsif libssl
207
+ recipe.configure_options << "--with-openssl=#{libssl.path}"
208
+ end
209
+ recipe.configure_options << "--with-gnutls" if gnutls
213
210
  recipe.configure_options << '--sysconfdir=C:/Sites' if for_windows
214
211
  recipe.configure_options << '--enable-sspi' if for_windows
215
212
  recipe.configure_options << "--disable-odbc"
@@ -217,9 +214,31 @@ def define_freetds_recipe(host, libiconv, libssl)
217
214
  if libiconv
218
215
  # For some reason freetds doesn't honor --with-libiconv-prefix
219
216
  # so we have do add it by hand:
220
- recipe.configure_options << "\"CFLAGS=-I#{libiconv.path}/include\""
221
- recipe.configure_options << "\"LDFLAGS=-L#{libiconv.path}/lib -liconv\""
217
+ recipe.configure_options << "CFLAGS=-I#{libiconv.path}/include"
218
+ recipe.configure_options << "LDFLAGS=-L#{libiconv.path}/lib -liconv"
219
+ end
220
+
221
+ class << recipe
222
+
223
+ def install
224
+ super_value = super
225
+ # Install binstub target binaries.
226
+ if super_value
227
+ bin_path = File.expand_path File.join(path, 'bin')
228
+ exe_path = File.expand_path File.join(target, '..', 'exe')
229
+ return unless File.directory?(bin_path)
230
+ ENV['PATH'] = "#{bin_path}#{File::PATH_SEPARATOR}#{ENV['PATH']}" unless ENV['PATH'].include?(bin_path)
231
+ ['tsql'].each do |bin|
232
+ path = which(bin)
233
+ next unless path.include?(bin_path)
234
+ FileUtils.cp path, exe_path
235
+ end
236
+ end
237
+ super_value
238
+ end
239
+
222
240
  end
241
+
223
242
  end
224
243
  end
225
244
 
@@ -285,11 +304,13 @@ system_freetds = enable_config('system-freetds', ENV['TINYTDS_SKIP_PORTS'] || fr
285
304
  host = RbConfig::CONFIG["host"]
286
305
  system_iconv = enable_config('system-iconv', host =~ /mingw|mswin/ ? false : true)
287
306
  system_openssl = enable_config('system-openssl', host =~ /mingw|mswin/ ? false : true )
307
+ enable_gnutls = enable_config('gnutls', false )
308
+ enable_openssl = enable_config('openssl', !enable_gnutls )
288
309
 
289
310
  unless system_freetds
290
311
  libssl = define_libssl_recipe(host).cook_and_activate unless system_openssl
291
312
  libiconv = define_libiconv_recipe(host).cook_and_activate unless system_iconv
292
- freetds = define_freetds_recipe(host, libiconv, libssl).cook_and_activate
313
+ freetds = define_freetds_recipe(host, libiconv, libssl || enable_openssl, enable_gnutls).cook_and_activate
293
314
  dir_config('freetds', freetds.path + "/include", freetds.path + "/lib")
294
315
  end
295
316
 
@@ -0,0 +1,14 @@
1
+
2
+ ICONV_VERSION = ENV['TINYTDS_ICONV_VERSION'] || "1.14"
3
+ ICONV_SOURCE_URI = "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-#{ICONV_VERSION}.tar.gz"
4
+
5
+ OPENSSL_VERSION = ENV['TINYTDS_OPENSSL_VERSION'] || '1.0.2e'
6
+ OPENSSL_SOURCE_URI = "http://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz"
7
+
8
+ FREETDS_VERSION = ENV['TINYTDS_FREETDS_VERSION'] || "0.95.75"
9
+ FREETDS_VERSION_INFO = Hash.new { |h,k|
10
+ h[k] = {files: "ftp://ftp.freetds.org/pub/freetds/stable/freetds-#{k}.tar.bz2"}
11
+ }
12
+ FREETDS_VERSION_INFO['0.99'] = {files: 'ftp://ftp.freetds.org/pub/freetds/current/freetds-dev.0.99.479.tar.bz2'}
13
+ FREETDS_VERSION_INFO['current'] = {files: 'https://github.com/FreeTDS/freetds/archive/master.zip'}
14
+ FREETDS_SOURCE_URI = FREETDS_VERSION_INFO[FREETDS_VERSION][:files]
@@ -7,9 +7,9 @@
7
7
  VALUE cTinyTdsResult;
8
8
  extern VALUE mTinyTds, cTinyTdsClient, cTinyTdsError;
9
9
  VALUE cBigDecimal, cDate;
10
- VALUE opt_decimal_zero, opt_float_zero, opt_one, opt_zero, opt_four, opt_19hdr, opt_tenk, opt_onemil;
10
+ VALUE opt_decimal_zero, opt_float_zero, opt_one, opt_zero, opt_four, opt_19hdr, opt_onek, opt_tenk, opt_onemil, opt_onebil;
11
11
  static ID intern_new, intern_utc, intern_local, intern_localtime, intern_merge,
12
- intern_civil, intern_new_offset, intern_plus, intern_divide, intern_Rational;
12
+ intern_civil, intern_new_offset, intern_plus, intern_divide;
13
13
  static ID sym_symbolize_keys, sym_as, sym_array, sym_cache_rows, sym_first, sym_timezone, sym_local, sym_utc, sym_empty_sets;
14
14
 
15
15
 
@@ -27,6 +27,12 @@ rb_encoding *binaryEncoding;
27
27
  _val; \
28
28
  })
29
29
 
30
+ #ifdef _WIN32
31
+ #define LONG_LONG_FORMAT "I64d"
32
+ #else
33
+ #define LONG_LONG_FORMAT "lld"
34
+ #endif
35
+
30
36
 
31
37
  // Lib Backend (Memory Management)
32
38
 
@@ -42,7 +48,6 @@ static void rb_tinytds_result_mark(void *ptr) {
42
48
  }
43
49
 
44
50
  static void rb_tinytds_result_free(void *ptr) {
45
- tinytds_result_wrapper *rwrap = (tinytds_result_wrapper *)ptr;
46
51
  xfree(ptr);
47
52
  }
48
53
 
@@ -67,8 +72,8 @@ VALUE rb_tinytds_new_result_obj(tinytds_client_wrapper *cwrap) {
67
72
  // No GVL Helpers
68
73
 
69
74
  #define NOGVL_DBCALL(_dbfunction, _client) ( \
70
- (RETCODE)rb_thread_call_without_gvl( \
71
- (rb_blocking_function_t*)_dbfunction, _client, \
75
+ (RETCODE)(intptr_t)rb_thread_call_without_gvl( \
76
+ (void *(*)(void *))_dbfunction, _client, \
72
77
  (rb_unblock_function_t*)dbcancel_ubf, _client ) \
73
78
  )
74
79
 
@@ -94,8 +99,8 @@ static void nogvl_cleanup(DBPROCESS *client) {
94
99
  userdata->nonblocking_error.is_set = 0;
95
100
  rb_tinytds_raise_error(client,
96
101
  userdata->nonblocking_error.cancel,
97
- &userdata->nonblocking_error.error,
98
- &userdata->nonblocking_error.source,
102
+ userdata->nonblocking_error.error,
103
+ userdata->nonblocking_error.source,
99
104
  userdata->nonblocking_error.severity,
100
105
  userdata->nonblocking_error.dberr,
101
106
  userdata->nonblocking_error.oserr);
@@ -139,9 +144,9 @@ static RETCODE nogvl_dbnextrow(DBPROCESS * client) {
139
144
  // Lib Backend (Helpers)
140
145
 
141
146
  static RETCODE rb_tinytds_result_dbresults_retcode(VALUE self) {
142
- GET_RESULT_WRAPPER(self);
143
147
  VALUE ruby_rc;
144
148
  RETCODE db_rc;
149
+ GET_RESULT_WRAPPER(self);
145
150
  ruby_rc = rb_ary_entry(rwrap->dbresults_retcodes, rwrap->number_of_results);
146
151
  if (NIL_P(ruby_rc)) {
147
152
  db_rc = nogvl_dbresults(rwrap->client);
@@ -162,8 +167,8 @@ static RETCODE rb_tinytds_result_ok_helper(DBPROCESS *client) {
162
167
  }
163
168
 
164
169
  static void rb_tinytds_result_exec_helper(DBPROCESS *client) {
165
- GET_CLIENT_USERDATA(client);
166
170
  RETCODE dbsqlok_rc = rb_tinytds_result_ok_helper(client);
171
+ GET_CLIENT_USERDATA(client);
167
172
  if (dbsqlok_rc == SUCCEED) {
168
173
  /*
169
174
  This is to just process each result set. Commands such as backup and
@@ -185,12 +190,13 @@ static void rb_tinytds_result_exec_helper(DBPROCESS *client) {
185
190
  }
186
191
 
187
192
  static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_keys, int as_array) {
193
+ VALUE row;
194
+ /* Storing Values */
195
+ unsigned int i;
188
196
  /* Wrapper And Local Vars */
189
197
  GET_RESULT_WRAPPER(self);
190
198
  /* Create Empty Row */
191
- VALUE row = as_array ? rb_ary_new2(rwrap->number_of_fields) : rb_hash_new();
192
- /* Storing Values */
193
- unsigned int i = 0;
199
+ row = as_array ? rb_ary_new2(rwrap->number_of_fields) : rb_hash_new();
194
200
  for (i = 0; i < rwrap->number_of_fields; i++) {
195
201
  VALUE val = Qnil;
196
202
  int col = i+1;
@@ -238,7 +244,7 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
238
244
  DBMONEY *money = (DBMONEY *)data;
239
245
  char converted_money[25];
240
246
  long long money_value = ((long long)money->mnyhigh << 32) | money->mnylow;
241
- sprintf(converted_money, "%lld", money_value);
247
+ sprintf(converted_money, "%" LONG_LONG_FORMAT, money_value);
242
248
  val = rb_funcall(cBigDecimal, intern_new, 2, rb_str_new2(converted_money), opt_four);
243
249
  val = rb_funcall(val, intern_divide, 1, opt_tenk);
244
250
  break;
@@ -270,22 +276,50 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
270
276
  data_len = sizeof(new_data);
271
277
  }
272
278
  case SYBDATETIME: {
273
- DBDATEREC date_rec;
274
- dbdatecrack(rwrap->client, &date_rec, (DBDATETIME *)data);
275
- int year = date_rec.dateyear,
276
- month = date_rec.datemonth+1,
277
- day = date_rec.datedmonth,
278
- hour = date_rec.datehour,
279
- min = date_rec.dateminute,
280
- sec = date_rec.datesecond,
281
- msec = date_rec.datemsecond;
282
- if (year+month+day+hour+min+sec+msec != 0) {
283
- VALUE offset = (timezone == intern_local) ? rwrap->local_offset : opt_zero;
284
- uint64_t seconds = (year*31557600ULL) + (month*2592000ULL) + (day*86400ULL) + (hour*3600ULL) + (min*60ULL) + sec;
285
- val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec), INT2NUM(msec*1000));
279
+ DBDATEREC dr;
280
+ dbdatecrack(rwrap->client, &dr, (DBDATETIME *)data);
281
+ if (dr.year + dr.month + dr.day + dr.hour + dr.minute + dr.second + dr.millisecond != 0) {
282
+ val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(dr.year), INT2NUM(dr.month), INT2NUM(dr.day), INT2NUM(dr.hour), INT2NUM(dr.minute), INT2NUM(dr.second), INT2NUM(dr.millisecond*1000));
286
283
  }
287
284
  break;
288
285
  }
286
+ case 40: // SYBMSDATE
287
+ case 41: // SYBMSTIME
288
+ case 42: // SYBMSDATETIME2
289
+ case 43: { // SYBMSDATETIMEOFFSET
290
+ #ifdef DBVERSION_73
291
+ if (dbtds(rwrap->client) >= DBTDS_7_3) {
292
+ DBDATEREC2 dr2;
293
+ dbanydatecrack(rwrap->client, &dr2, coltype, data);
294
+ switch(coltype) {
295
+ case 40: { // SYBMSDATE
296
+ val = rb_funcall(cDate, intern_new, 3, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day));
297
+ break;
298
+ }
299
+ case 41: { // SYBMSTIME
300
+ VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
301
+ val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(1900), INT2NUM(1), INT2NUM(1), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
302
+ break;
303
+ }
304
+ case 42: { // SYBMSDATETIME2
305
+ VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
306
+ 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);
307
+ break;
308
+ }
309
+ case 43: { // SYBMSDATETIMEOFFSET
310
+ VALUE rational_sec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onebil);
311
+ 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));
312
+ break;
313
+ }
314
+ }
315
+ } else {
316
+ val = ENCODED_STR_NEW(data, data_len);
317
+ }
318
+ #else
319
+ val = ENCODED_STR_NEW(data, data_len);
320
+ #endif
321
+ break;
322
+ }
289
323
  case SYBCHAR:
290
324
  case SYBTEXT:
291
325
  val = ENCODED_STR_NEW(data, data_len);
@@ -314,10 +348,12 @@ static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_
314
348
  // TinyTds::Client (public)
315
349
 
316
350
  static VALUE rb_tinytds_result_fields(VALUE self) {
351
+ RETCODE dbsqlok_rc, dbresults_rc;
352
+ VALUE fields_processed;
317
353
  GET_RESULT_WRAPPER(self);
318
- RETCODE dbsqlok_rc = rb_tinytds_result_ok_helper(rwrap->client);
319
- RETCODE dbresults_rc = rb_tinytds_result_dbresults_retcode(self);
320
- VALUE fields_processed = rb_ary_entry(rwrap->fields_processed, rwrap->number_of_results);
354
+ dbsqlok_rc = rb_tinytds_result_ok_helper(rwrap->client);
355
+ dbresults_rc = rb_tinytds_result_dbresults_retcode(self);
356
+ fields_processed = rb_ary_entry(rwrap->fields_processed, rwrap->number_of_results);
321
357
  if ((dbsqlok_rc == SUCCEED) && (dbresults_rc == SUCCEED) && (fields_processed == Qnil)) {
322
358
  /* Default query options. */
323
359
  int symbolize_keys = 0;
@@ -353,12 +389,13 @@ static VALUE rb_tinytds_result_fields(VALUE self) {
353
389
  }
354
390
 
355
391
  static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
356
- GET_RESULT_WRAPPER(self);
357
- GET_CLIENT_USERDATA(rwrap->client);
358
392
  /* Local Vars */
359
393
  VALUE qopts, opts, block;
360
394
  ID timezone;
361
395
  int symbolize_keys = 0, as_array = 0, cache_rows = 0, first = 0, empty_sets = 0;
396
+ tinytds_client_userdata *userdata;
397
+ GET_RESULT_WRAPPER(self);
398
+ userdata = (tinytds_client_userdata *)dbgetuserdata(rwrap->client);
362
399
  /* Merge Options Hash To Query Options. Populate Opts & Block Var. */
363
400
  qopts = rb_iv_get(self, "@query_options");
364
401
  if (rb_scan_args(argc, argv, "01&", &opts, &block) == 1)
@@ -385,9 +422,10 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
385
422
  empty_sets = 1;
386
423
  /* Make The Results Or Yield Existing */
387
424
  if (NIL_P(rwrap->results)) {
425
+ RETCODE dbsqlok_rc, dbresults_rc;
388
426
  rwrap->results = rb_ary_new();
389
- RETCODE dbsqlok_rc = rb_tinytds_result_ok_helper(rwrap->client);
390
- RETCODE dbresults_rc = rb_tinytds_result_dbresults_retcode(self);
427
+ dbsqlok_rc = rb_tinytds_result_ok_helper(rwrap->client);
428
+ dbresults_rc = rb_tinytds_result_dbresults_retcode(self);
391
429
  while ((dbsqlok_rc == SUCCEED) && (dbresults_rc == SUCCEED)) {
392
430
  int has_rows = (DBROWS(rwrap->client) == SUCCEED) ? 1 : 0;
393
431
  if (has_rows || empty_sets || (rwrap->number_of_results == 0))
@@ -447,8 +485,9 @@ static VALUE rb_tinytds_result_each(int argc, VALUE * argv, VALUE self) {
447
485
  }
448
486
 
449
487
  static VALUE rb_tinytds_result_cancel(VALUE self) {
488
+ tinytds_client_userdata *userdata;
450
489
  GET_RESULT_WRAPPER(self);
451
- GET_CLIENT_USERDATA(rwrap->client);
490
+ userdata = (tinytds_client_userdata *)dbgetuserdata(rwrap->client);
452
491
  if (rwrap->client && !userdata->dbcancel_sent) {
453
492
  RETCODE dbsqlok_rc = rb_tinytds_result_ok_helper(rwrap->client);
454
493
  dbcancel(rwrap->client);
@@ -490,8 +529,8 @@ static VALUE rb_tinytds_result_return_code(VALUE self) {
490
529
  static VALUE rb_tinytds_result_insert(VALUE self) {
491
530
  GET_RESULT_WRAPPER(self);
492
531
  if (rwrap->client) {
493
- rb_tinytds_result_exec_helper(rwrap->client);
494
532
  VALUE identity = Qnil;
533
+ rb_tinytds_result_exec_helper(rwrap->client);
495
534
  dbcmd(rwrap->client, rwrap->cwrap->identity_insert_sql);
496
535
  if (nogvl_dbsqlexec(rwrap->client) != FAIL
497
536
  && nogvl_dbresults(rwrap->client) != FAIL
@@ -538,7 +577,6 @@ void init_tinytds_result() {
538
577
  intern_new_offset = rb_intern("new_offset");
539
578
  intern_plus = rb_intern("+");
540
579
  intern_divide = rb_intern("/");
541
- intern_Rational = rb_intern("Rational");
542
580
  /* Symbol Helpers */
543
581
  sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
544
582
  sym_as = ID2SYM(rb_intern("as"));
@@ -558,8 +596,10 @@ void init_tinytds_result() {
558
596
  opt_zero = INT2NUM(0);
559
597
  opt_four = INT2NUM(4);
560
598
  opt_19hdr = INT2NUM(1900);
599
+ opt_onek = INT2NUM(1000);
561
600
  opt_tenk = INT2NUM(10000);
562
601
  opt_onemil = INT2NUM(1000000);
602
+ opt_onebil = INT2NUM(1000000000);
563
603
  /* Encoding */
564
604
  #ifdef HAVE_RUBY_ENCODING_H
565
605
  binaryEncoding = rb_enc_find("binary");