ruby-odbc 0.99999 → 0.999991

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ebe50088f7b79d16a5dc300d6b07890b808a57c6
4
- data.tar.gz: 5bfa7a5595c786bcf6125b4bb43f5e0c1312b9cd
2
+ SHA256:
3
+ metadata.gz: 860fc0eb5595959ec764079118f528b5b0afa5d49e919ab0f8c46e971bd7dbc0
4
+ data.tar.gz: 843b2f2427d1378489cbc6eea0cb3e3ce5daff17f42ac3a040a0a979f04dddae
5
5
  SHA512:
6
- metadata.gz: f5ab42fe5a650e2d88cda3106ec3beea1e53bdc651ef6b9ca8848d61904c5b7a4b86e89373e3f392c971ad5cdc8cf3b0423d4163349fa62b337dc2a6cb502c6d
7
- data.tar.gz: 3f0fd86fce0f7a08cb59913483a4f494a24dcbc4cfb00eceffeb822a63eb7fdee644a6e13ba5e0a83e7375ed3e9c5f88c4f2f36e778e8e52fc643a797aa4bb56
6
+ metadata.gz: 600c7ef68780fa4f3eae56dddd7ca01fa1cbd425b58a0c50663688bcefddc6b2471b79e0a51e044d95c570e531a91e4b883c5aa9b813c84c1997498e93024f5e
7
+ data.tar.gz: 020cd8f08ffce0d846262d839db86b8741db74eeb0ce774ce69aa99d09a56a5b9cd70abf36b06d27f9216118aff945d3ace3778c93f914794c30420c8a43dfab
data/COPYING CHANGED
@@ -1,4 +1,4 @@
1
- Ruby/ODBC is copyrighted free software by Christian Werner <chw@ch-werner.de>
1
+ Ruby/ODBC is copyrighted free software by Christian Werner chw at ch-werner.de
2
2
  You can redistribute it and/or modify it under either the terms of the GPL
3
3
  (see the file GPL), or the conditions below:
4
4
 
data/ChangeLog CHANGED
@@ -1,6 +1,11 @@
1
1
  ODBC binding for Ruby
2
2
  ---------------------
3
3
 
4
+ Sat Dec 26 2020 version 0.999991 released
5
+
6
+ * update to compile with newer Ruby releases
7
+ * report larger width for SQL_(DECIMAL|NUMERIC) columns
8
+
4
9
  Wed Feb 28 2018 version 0.99999 released
5
10
 
6
11
  * update to compile with newer Ruby releases, thanks
data/README CHANGED
@@ -1,6 +1,6 @@
1
- # $Id: README,v 1.46 2018/02/28 15:08:50 chw Exp chw $
1
+ # $Id: README,v 1.47 2020/12/25 21:47:43 chw Exp chw $
2
2
 
3
- ruby-odbc-0.99999
3
+ ruby-odbc-0.999991
4
4
 
5
5
  This is an ODBC binding for Ruby. So far it has been tested with
6
6
 
@@ -20,11 +20,11 @@ This is an ODBC binding for Ruby. So far it has been tested with
20
20
 
21
21
  - Ruby 2.0.0, SQLite/ODBC >= 0.93, unixODBC 2.2.14 on Ubuntu 12.04 x86
22
22
 
23
- - Ruby 2.4
23
+ - Ruby >= 2.4
24
24
 
25
- Michael Neumann <neumann@s-direktnet.de> and
26
- Will Merrell <wmerrell@catalystcorp.com> reported successful compilation
27
- with Cygwin on Win32.
25
+ Michael Neumann <neumann @nospam@ s-direktnet.de> and
26
+ Will Merrell <wmerrell @nospam@ catalystcorp.com> reported successful
27
+ compilation with Cygwin on Win32.
28
28
 
29
29
  Requirements:
30
30
 
@@ -110,5 +110,5 @@ TODO:
110
110
  Author:
111
111
 
112
112
  Christian Werner
113
- mailto:chw@ch-werner.de
113
+ mailto:chw @nospam@ ch-werner.de
114
114
  http://www.ch-werner.de/rubyodbc
@@ -20,6 +20,7 @@ end
20
20
 
21
21
  dir_config("odbc")
22
22
  have_header("version.h")
23
+ have_header("ruby/version.h")
23
24
  have_header("sql.h") || begin
24
25
  puts "ERROR: sql.h not found"
25
26
  exit 1
data/ext/odbc.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * ODBC-Ruby binding
3
- * Copyright (c) 2001-2015 Christian Werner <chw@ch-werner.de>
3
+ * Copyright (c) 2001-2020 Christian Werner <chw@ch-werner.de>
4
4
  * Portions copyright (c) 2004 Ryszard Niewisiewicz <micz@fibernet.pl>
5
5
  * Portions copyright (c) 2006 Carl Blakeley <cblakeley@openlinksw.co.uk>
6
6
  *
@@ -8,7 +8,7 @@
8
8
  * and redistribution of this file and for a
9
9
  * DISCLAIMER OF ALL WARRANTIES.
10
10
  *
11
- * $Id: odbc.c,v 1.79 2018/02/28 15:15:24 chw Exp chw $
11
+ * $Id: odbc.c,v 1.80 2020/12/25 21:45:42 chw Exp chw $
12
12
  */
13
13
 
14
14
  #undef ODBCVER
@@ -22,6 +22,9 @@
22
22
  #ifdef HAVE_VERSION_H
23
23
  #include "version.h"
24
24
  #endif
25
+ #ifdef HAVE_RUBY_VERSION_H
26
+ #include "ruby/version.h"
27
+ #endif
25
28
  #ifdef HAVE_SQL_H
26
29
  #include <sql.h>
27
30
  #else
@@ -65,6 +68,12 @@ typedef SQLCHAR SQLTCHAR;
65
68
  #define TIME_USE_USEC 1
66
69
  #endif
67
70
 
71
+ #if (RUBY_API_VERSION_CODE >= 20500)
72
+ #define FUNCALL_NOARGS(o, m) rb_funcall((o), (m), 0)
73
+ #else
74
+ #define FUNCALL_NOARGS(o, m) rb_funcall((o), (m), 0, NULL)
75
+ #endif
76
+
68
77
  #ifdef HAVE_RUBY_THREAD_H
69
78
  #include "ruby/thread.h"
70
79
  #endif
@@ -1824,7 +1833,7 @@ free_stmt(STMT *q)
1824
1833
  static void
1825
1834
  start_gc()
1826
1835
  {
1827
- rb_funcall(rb_mGC, IDstart, 0, NULL);
1836
+ FUNCALL_NOARGS(rb_mGC, IDstart);
1828
1837
  }
1829
1838
 
1830
1839
  static void
@@ -1899,6 +1908,7 @@ get_err_or_info(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt, int isinfo)
1899
1908
  msg[SQL_MAX_MESSAGE_LENGTH - 1] = '\0';
1900
1909
  switch (err) {
1901
1910
  case SQL_SUCCESS:
1911
+ case SQL_SUCCESS_WITH_INFO:
1902
1912
  #ifdef UNICODE
1903
1913
  v = uc_str_new2(state);
1904
1914
  #else
@@ -2513,7 +2523,7 @@ conf_dsn(int argc, VALUE *argv, VALUE self, int op)
2513
2523
  if (rb_obj_is_kind_of(attr, rb_cHash) == Qtrue) {
2514
2524
  VALUE a, x;
2515
2525
 
2516
- a = rb_funcall(attr, IDkeys, 0, NULL);
2526
+ a = FUNCALL_NOARGS(attr, IDkeys);
2517
2527
  while ((x = rb_ary_shift(a)) != Qnil) {
2518
2528
  VALUE v = rb_hash_aref(attr, x);
2519
2529
 
@@ -3018,7 +3028,7 @@ dbc_drvconnect(VALUE self, VALUE drv)
3018
3028
  VALUE d, a, x;
3019
3029
 
3020
3030
  d = rb_str_new2("");
3021
- a = rb_funcall(rb_iv_get(drv, "@attrs"), IDkeys, 0, NULL);
3031
+ a = FUNCALL_NOARGS(rb_iv_get(drv, "@attrs"), IDkeys);
3022
3032
  while ((x = rb_ary_shift(a)) != Qnil) {
3023
3033
  VALUE v = rb_hash_aref(rb_iv_get(drv, "@attrs"), x);
3024
3034
 
@@ -4238,6 +4248,22 @@ make_coltypes(SQLHSTMT hstmt, int ncols, char **msgp)
4238
4248
  }
4239
4249
  break;
4240
4250
  #endif
4251
+ case SQL_DECIMAL:
4252
+ case SQL_NUMERIC:
4253
+ if ((size == 0) || (size > SEGSIZE)) {
4254
+ size = SQL_NO_TOTAL;
4255
+ }
4256
+ if (size != SQL_NO_TOTAL) {
4257
+ size += 2; /* sign and decimal point */
4258
+ size += 1; /* NUL terminator */
4259
+ }
4260
+ #ifdef UNICODE
4261
+ type = SQL_C_WCHAR;
4262
+ size *= sizeof (SQLWCHAR);
4263
+ #else
4264
+ type = SQL_C_CHAR;
4265
+ #endif
4266
+ break;
4241
4267
  default:
4242
4268
  if ((size == 0) || (size > SEGSIZE)) {
4243
4269
  size = SQL_NO_TOTAL;
@@ -5095,7 +5121,7 @@ dbc_transaction(VALUE self)
5095
5121
  }
5096
5122
  ret = rb_ary_entry(a, 1);
5097
5123
  rb_exc_raise(rb_exc_new3(rb_obj_class(ret),
5098
- rb_funcall(ret, IDto_s, 0, 0)));
5124
+ FUNCALL_NOARGS(ret, IDto_s)));
5099
5125
  return Qnil;
5100
5126
  }
5101
5127
 
@@ -5660,16 +5686,16 @@ date_init(int argc, VALUE *argv, VALUE self)
5660
5686
  if (argc > 1) {
5661
5687
  rb_raise(rb_eArgError, "wrong # arguments");
5662
5688
  }
5663
- d = rb_funcall(y, IDday, 0, NULL);
5664
- m = rb_funcall(y, IDmonth, 0, NULL);
5665
- y = rb_funcall(y, IDyear, 0, NULL);
5689
+ d = FUNCALL_NOARGS(y, IDday);
5690
+ m = FUNCALL_NOARGS(y, IDmonth);
5691
+ y = FUNCALL_NOARGS(y, IDyear);
5666
5692
  } else if (rb_obj_is_kind_of(y, rb_cDate) == Qtrue) {
5667
5693
  if (argc > 1) {
5668
5694
  rb_raise(rb_eArgError, "wrong # arguments");
5669
5695
  }
5670
- d = rb_funcall(y, IDmday, 0, NULL);
5671
- m = rb_funcall(y, IDmonth, 0, NULL);
5672
- y = rb_funcall(y, IDyear, 0, NULL);
5696
+ d = FUNCALL_NOARGS(y, IDmday);
5697
+ m = FUNCALL_NOARGS(y, IDmonth);
5698
+ y = FUNCALL_NOARGS(y, IDyear);
5673
5699
  } else if ((argc == 1) && (rb_obj_is_kind_of(y, rb_cString) == Qtrue)) {
5674
5700
  if (date_load1(self, y, 0) != Qnil) {
5675
5701
  return self;
@@ -5895,9 +5921,9 @@ time_init(int argc, VALUE *argv, VALUE self)
5895
5921
  if (argc > 1) {
5896
5922
  rb_raise(rb_eArgError, "wrong # arguments");
5897
5923
  }
5898
- s = rb_funcall(h, IDsec, 0, NULL);
5899
- m = rb_funcall(h, IDmin, 0, NULL);
5900
- h = rb_funcall(h, IDhour, 0, NULL);
5924
+ s = FUNCALL_NOARGS(h, IDsec);
5925
+ m = FUNCALL_NOARGS(h, IDmin);
5926
+ h = FUNCALL_NOARGS(h, IDhour);
5901
5927
  } else if ((argc == 1) && (rb_obj_is_kind_of(h, rb_cString) == Qtrue)) {
5902
5928
  if (time_load1(self, h, 0) != Qnil) {
5903
5929
  return self;
@@ -6135,13 +6161,13 @@ timestamp_init(int argc, VALUE *argv, VALUE self)
6135
6161
  if (argc > 1) {
6136
6162
  rb_raise(rb_eArgError, "wrong # arguments");
6137
6163
  }
6138
- f = rb_funcall(y, IDusec, 0, NULL);
6139
- ss = rb_funcall(y, IDsec, 0, NULL);
6140
- mm = rb_funcall(y, IDmin, 0, NULL);
6141
- hh = rb_funcall(y, IDhour, 0, NULL);
6142
- d = rb_funcall(y, IDday, 0, NULL);
6143
- m = rb_funcall(y, IDmonth, 0, NULL);
6144
- y = rb_funcall(y, IDyear, 0, NULL);
6164
+ f = FUNCALL_NOARGS(y, IDusec);
6165
+ ss = FUNCALL_NOARGS(y, IDsec);
6166
+ mm = FUNCALL_NOARGS(y, IDmin);
6167
+ hh = FUNCALL_NOARGS(y, IDhour);
6168
+ d = FUNCALL_NOARGS(y, IDday);
6169
+ m = FUNCALL_NOARGS(y, IDmonth);
6170
+ y = FUNCALL_NOARGS(y, IDyear);
6145
6171
  f = INT2NUM(NUM2INT(f) * 1000);
6146
6172
  } else if (rb_obj_is_kind_of(y, rb_cDate) == Qtrue) {
6147
6173
  if (argc > 1) {
@@ -6151,9 +6177,9 @@ timestamp_init(int argc, VALUE *argv, VALUE self)
6151
6177
  ss = INT2FIX(0);
6152
6178
  mm = INT2FIX(0);
6153
6179
  hh = INT2FIX(0);
6154
- d = rb_funcall(y, IDmday, 0, NULL);
6155
- m = rb_funcall(y, IDmonth, 0, NULL);
6156
- y = rb_funcall(y, IDyear, 0, NULL);
6180
+ d = FUNCALL_NOARGS(y, IDmday);
6181
+ m = FUNCALL_NOARGS(y, IDmonth);
6182
+ y = FUNCALL_NOARGS(y, IDyear);
6157
6183
  } else if ((argc == 1) && (rb_obj_is_kind_of(y, rb_cString) == Qtrue)) {
6158
6184
  if (timestamp_load1(self, y, 0) != Qnil) {
6159
6185
  return self;
@@ -6628,13 +6654,13 @@ stmt_param_output_value(int argc, VALUE *argv, VALUE self)
6628
6654
 
6629
6655
  time = (TIME_STRUCT *) q->paraminfo[vnum].outbuf;
6630
6656
  frac = rb_float_new(0.0);
6631
- now = rb_funcall(rb_cTime, IDnow, 0, NULL);
6657
+ now = FUNCALL_NOARGS(rb_cTime, IDnow);
6632
6658
  v = rb_funcall(rb_cTime,
6633
6659
  (q->dbcp->gmtime == Qtrue) ? IDutc : IDlocal,
6634
6660
  7,
6635
- rb_funcall(now, IDyear, 0, NULL),
6636
- rb_funcall(now, IDmonth, 0, NULL),
6637
- rb_funcall(now, IDday, 0, NULL),
6661
+ FUNCALL_NOARGS(now, IDyear),
6662
+ FUNCALL_NOARGS(now, IDmonth),
6663
+ FUNCALL_NOARGS(now, IDday),
6638
6664
  INT2NUM(time->hour),
6639
6665
  INT2NUM(time->minute),
6640
6666
  INT2NUM(time->second),
@@ -7285,14 +7311,14 @@ do_fetch(STMT *q, int mode)
7285
7311
 
7286
7312
  time = (TIME_STRUCT *) valp;
7287
7313
  frac = rb_float_new(0.0);
7288
- now = rb_funcall(rb_cTime, IDnow, 0, NULL);
7314
+ now = FUNCALL_NOARGS(rb_cTime, IDnow);
7289
7315
  v = rb_funcall(rb_cTime,
7290
7316
  (q->dbcp->gmtime == Qtrue) ?
7291
7317
  IDutc : IDlocal,
7292
7318
  7,
7293
- rb_funcall(now, IDyear, 0, NULL),
7294
- rb_funcall(now, IDmonth, 0, NULL),
7295
- rb_funcall(now, IDday, 0, NULL),
7319
+ FUNCALL_NOARGS(now, IDyear),
7320
+ FUNCALL_NOARGS(now, IDmonth),
7321
+ FUNCALL_NOARGS(now, IDday),
7296
7322
  INT2NUM(time->hour),
7297
7323
  INT2NUM(time->minute),
7298
7324
  INT2NUM(time->second),
@@ -8148,9 +8174,9 @@ bind_one_param(int pnum, VALUE arg, STMT *q, char **msgp, int *outpp)
8148
8174
  ctype = SQL_C_TIME;
8149
8175
  time = (TIME_STRUCT *) valp;
8150
8176
  memset(time, 0, sizeof (TIME_STRUCT));
8151
- time->hour = rb_funcall(arg, IDhour, 0, NULL);
8152
- time->minute = rb_funcall(arg, IDmin, 0, NULL);
8153
- time->second = rb_funcall(arg, IDsec, 0, NULL);
8177
+ time->hour = FUNCALL_NOARGS(arg, IDhour);
8178
+ time->minute = FUNCALL_NOARGS(arg, IDmin);
8179
+ time->second = FUNCALL_NOARGS(arg, IDsec);
8154
8180
  rlen = 1;
8155
8181
  vlen = sizeof (TIME_STRUCT);
8156
8182
  } else if (q->paraminfo[pnum].type == SQL_DATE) {
@@ -8159,9 +8185,9 @@ bind_one_param(int pnum, VALUE arg, STMT *q, char **msgp, int *outpp)
8159
8185
  ctype = SQL_C_DATE;
8160
8186
  date = (DATE_STRUCT *) valp;
8161
8187
  memset(date, 0, sizeof (DATE_STRUCT));
8162
- date->year = rb_funcall(arg, IDyear, 0, NULL);
8163
- date->month = rb_funcall(arg, IDmonth, 0, NULL);
8164
- date->day = rb_funcall(arg, IDday, 0, NULL);
8188
+ date->year = FUNCALL_NOARGS(arg, IDyear);
8189
+ date->month = FUNCALL_NOARGS(arg, IDmonth);
8190
+ date->day = FUNCALL_NOARGS(arg, IDday);
8165
8191
  rlen = 1;
8166
8192
  vlen = sizeof (TIMESTAMP_STRUCT);
8167
8193
  } else {
@@ -8170,16 +8196,16 @@ bind_one_param(int pnum, VALUE arg, STMT *q, char **msgp, int *outpp)
8170
8196
  ctype = SQL_C_TIMESTAMP;
8171
8197
  ts = (TIMESTAMP_STRUCT *) valp;
8172
8198
  memset(ts, 0, sizeof (TIMESTAMP_STRUCT));
8173
- ts->year = rb_funcall(arg, IDyear, 0, NULL);
8174
- ts->month = rb_funcall(arg, IDmonth, 0, NULL);
8175
- ts->day = rb_funcall(arg, IDday, 0, NULL);
8176
- ts->hour = rb_funcall(arg, IDhour, 0, NULL);
8177
- ts->minute = rb_funcall(arg, IDmin, 0, NULL);
8178
- ts->second = rb_funcall(arg, IDsec, 0, NULL);
8199
+ ts->year = FUNCALL_NOARGS(arg, IDyear);
8200
+ ts->month = FUNCALL_NOARGS(arg, IDmonth);
8201
+ ts->day = FUNCALL_NOARGS(arg, IDday);
8202
+ ts->hour = FUNCALL_NOARGS(arg, IDhour);
8203
+ ts->minute = FUNCALL_NOARGS(arg, IDmin);
8204
+ ts->second = FUNCALL_NOARGS(arg, IDsec);
8179
8205
  #ifdef TIME_USE_USEC
8180
- ts->fraction = rb_funcall(arg, IDusec, 0, NULL) * 1000;
8206
+ ts->fraction = FUNCALL_NOARGS(arg, IDusec) * 1000;
8181
8207
  #else
8182
- ts->fraction = rb_funcall(arg, IDnsec, 0, NULL);
8208
+ ts->fraction = FUNCALL_NOARGS(arg, IDnsec);
8183
8209
  #endif
8184
8210
  rlen = 1;
8185
8211
  vlen = sizeof (TIMESTAMP_STRUCT);
@@ -8192,9 +8218,9 @@ bind_one_param(int pnum, VALUE arg, STMT *q, char **msgp, int *outpp)
8192
8218
  ctype = SQL_C_DATE;
8193
8219
  date = (DATE_STRUCT *) valp;
8194
8220
  memset(date, 0, sizeof (DATE_STRUCT));
8195
- date->year = rb_funcall(arg, IDyear, 0, NULL);
8196
- date->month = rb_funcall(arg, IDmonth, 0, NULL);
8197
- date->day = rb_funcall(arg, IDmday, 0, NULL);
8221
+ date->year = FUNCALL_NOARGS(arg, IDyear);
8222
+ date->month = FUNCALL_NOARGS(arg, IDmonth);
8223
+ date->day = FUNCALL_NOARGS(arg, IDmday);
8198
8224
  rlen = 1;
8199
8225
  vlen = sizeof (DATE_STRUCT);
8200
8226
  break;
@@ -8708,7 +8734,7 @@ again:
8708
8734
  rb_raise(rb_eTypeError, "expecting ODBC::Date");
8709
8735
  }
8710
8736
  } else {
8711
- VALUE now = rb_funcall(rb_cTime, IDnow, 0, NULL);
8737
+ VALUE now = FUNCALL_NOARGS(rb_cTime, IDnow);
8712
8738
 
8713
8739
  y = rb_funcall(rb_cTime, IDyear, 1, now);
8714
8740
  m = rb_funcall(rb_cTime, IDmonth, 1, now);
@@ -9298,7 +9324,7 @@ Init_odbc()
9298
9324
  rb_define_method(Cstmt, "fetch_scroll!", stmt_fetch_scroll_bang, -1);
9299
9325
  rb_define_method(Cstmt, "fetch_hash", stmt_fetch_hash, -1);
9300
9326
  rb_define_method(Cstmt, "fetch_hash!", stmt_fetch_hash_bang, -1);
9301
- rb_define_method(Cstmt, "fetch_first_hash", stmt_fetch_first_hash, 0);
9327
+ rb_define_method(Cstmt, "fetch_first_hash", stmt_fetch_first_hash, -1);
9302
9328
  rb_define_method(Cstmt, "fetch_many", stmt_fetch_many, 1);
9303
9329
  rb_define_method(Cstmt, "fetch_all", stmt_fetch_all, 0);
9304
9330
  rb_define_method(Cstmt, "each", stmt_each, 0);
@@ -40,6 +40,8 @@ def have_func_nolink(func, headers = nil, &b)
40
40
  end
41
41
 
42
42
  dir_config("odbc")
43
+ have_header("version.h")
44
+ have_header("ruby/version.h")
43
45
  have_header("sql.h") || begin
44
46
  puts "ERROR: sql.h not found"
45
47
  exit 1
@@ -1,7 +1,7 @@
1
1
  require 'date'
2
2
  spec = Gem::Specification.new do |s|
3
3
  s.name = "ruby-odbc"
4
- s.version = "0.99999"
4
+ s.version = "0.999991"
5
5
  s.date = Date.today.to_s
6
6
  s.author = "Christian Werner"
7
7
  s.email = "chw @nospam@ ch-werner.de"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-odbc
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.99999'
4
+ version: '0.999991'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Werner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-28 00:00:00.000000000 Z
11
+ date: 2020-12-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: chw @nospam@ ch-werner.de
@@ -66,8 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0'
68
68
  requirements: []
69
- rubyforge_project:
70
- rubygems_version: 2.4.5
69
+ rubygems_version: 3.1.4
71
70
  signing_key:
72
71
  specification_version: 4
73
72
  summary: ODBC binding for Ruby