ruby-oci8 2.1.8 → 2.2.0.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.
@@ -4,7 +4,6 @@
4
4
  *
5
5
  * Copyright (C) 2011 KUBO Takehiro <kubo@jiubao.org>
6
6
  */
7
- #ifdef USE_THREAD_LOCAL_ERRHP
8
7
 
9
8
  /*
10
9
  * Prepare to execute thread-related functions.
@@ -17,14 +16,3 @@ void Init_oci8_thread_util(void);
17
16
  * The return value is errno.
18
17
  */
19
18
  int oci8_run_native_thread(void *(*func)(void *), void *arg);
20
-
21
- #else
22
-
23
- /*
24
- * For ruby 1.8 configured without --enable-pthread on Unix.
25
- */
26
-
27
- #define Init_oci8_thread_util() do {} while (0)
28
- #define oci8_run_native_thread(func, arg) ((func)(arg), 0)
29
-
30
- #endif
@@ -0,0 +1,71 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ util.c - part of ruby-oci8
4
+
5
+ Copyright (C) 2015 Kubo Takehiro <kubo@jiubao.org>
6
+ */
7
+ #if defined __linux && !defined(_GNU_SOURCE)
8
+ #define _GNU_SOURCE 1
9
+ #endif
10
+ #include "oci8.h"
11
+ #ifdef HAVE_DLADDR
12
+ #include <dlfcn.h>
13
+ #endif
14
+ #ifdef __CYGWIN__
15
+ #undef boolean
16
+ #include <windows.h>
17
+ #endif
18
+
19
+ const char *oci8_dll_path(void)
20
+ {
21
+ #if defined _WIN32 || defined __CYGWIN__
22
+ HMODULE hMod = GetModuleHandleA("OCI.DLL");
23
+ static char buf[MAX_PATH];
24
+ if (hMod != NULL) {
25
+ if (GetModuleFileName(hMod, buf, sizeof(buf))) {
26
+ return buf;
27
+ }
28
+ }
29
+ #elif defined HAVE_DLADDR && defined RTLD_DEFAULT
30
+ void *addr = dlsym(RTLD_DEFAULT, "OCIEnvCreate");
31
+ Dl_info info;
32
+ if (addr != NULL && dladdr(addr, &info)) {
33
+ return info.dli_fname;
34
+ }
35
+ #elif defined HAVE_DLMODINFO && defined HAVE_DLGETNAME && defined RTLD_DEFAULT
36
+ void *addr = dlsym(RTLD_DEFAULT, "OCIEnvCreate");
37
+ if (addr != NULL) {
38
+ struct load_module_desc desc;
39
+ if (dlmodinfo((uint64_t)addr, &desc, sizeof(desc), NULL, 0, 0) != 0) {
40
+ return dlgetname(&desc, sizeof(desc), NULL, 0, 0);
41
+ }
42
+ }
43
+ #endif
44
+ return NULL;
45
+ }
46
+
47
+ /*
48
+ * Returns the full path of Oracle client library used by the current process.
49
+ *
50
+ * @return [String]
51
+ */
52
+ static VALUE dll_path(VALUE module)
53
+ {
54
+ const char *path = oci8_dll_path();
55
+ if (path == NULL) {
56
+ return Qnil;
57
+ }
58
+ return rb_external_str_new_with_enc(path, strlen(path), rb_filesystem_encoding());
59
+ }
60
+
61
+ void Init_oci8_util(VALUE cOCI8)
62
+ {
63
+ #if 0
64
+ /* for yard */
65
+ cOCIHandle = rb_define_class("OCIHandle", rb_cObject);
66
+ cOCI8 = rb_define_class("OCI8", cOCIHandle);
67
+ #endif
68
+ VALUE mUtil = rb_define_module_under(cOCI8, "Util");
69
+
70
+ rb_define_module_function(mUtil, "dll_path", dll_path, 0);
71
+ }
@@ -2,7 +2,7 @@
2
2
  /*
3
3
  win32.c - part of ruby-oci8
4
4
 
5
- Copyright (C) 2009-2010 KUBO Takehiro <kubo@jiubao.org>
5
+ Copyright (C) 2009-2015 Kubo Takehiro <kubo@jiubao.org>
6
6
  */
7
7
  #include "oci8.h"
8
8
  #ifdef __CYGWIN__
@@ -41,29 +41,6 @@ static void raise_error(void)
41
41
  rb_raise(rb_eRuntimeError, "%s", msg);
42
42
  }
43
43
 
44
- /*
45
- * Returns the full path of OCI.DLL used by the current process.
46
- *
47
- * @return [String]
48
- */
49
- static VALUE dll_path(VALUE module)
50
- {
51
- HMODULE hModule;
52
- DWORD len;
53
- char path[1024];
54
-
55
- hModule = GetModuleHandle("OCI.DLL");
56
- if (hModule == NULL) {
57
- raise_error();
58
- }
59
- len = GetModuleFileName(hModule, path, sizeof(path));
60
- if (len == 0) {
61
- raise_error();
62
- }
63
- return rb_external_str_new_with_enc(path, len, rb_filesystem_encoding());
64
- }
65
-
66
-
67
44
  typedef struct {
68
45
  HKEY hKey;
69
46
  HKEY hSubKey;
@@ -154,6 +131,5 @@ void Init_oci8_win32(VALUE cOCI8)
154
131
  {
155
132
  VALUE mWin32Util = rb_define_module_under(cOCI8, "Win32Util");
156
133
 
157
- rb_define_module_function(mWin32Util, "dll_path", dll_path, 0);
158
134
  rb_define_module_function(mWin32Util, "enum_homes", enum_homes, 0);
159
135
  }
@@ -67,12 +67,20 @@ when 'jruby'
67
67
  else
68
68
  raise 'unsupported ruby engine: ' + RUBY_ENGINE
69
69
  end
70
- require so_basename
71
70
 
72
- if OCI8::VERSION != '@@OCI8_MODULE_VERSION@@'
71
+ begin
72
+ require so_basename
73
+ rescue LoadError, OCIError
74
+ require 'oci8/check_load_error'
75
+ OCI8::Util::check_load_error($!)
76
+ raise
77
+ end
78
+
79
+ require 'oci8/version.rb'
80
+ if OCI8::VERSION != OCI8::LIB_VERSION
73
81
  require 'rbconfig'
74
82
  so_name = so_basename + "." + RbConfig::CONFIG['DLEXT']
75
- raise "VERSION MISMATCH! #{so_name} version is #{OCI8::VERSION}, but oci8.rb version is @@OCI8_MODULE_VERSION@@."
83
+ raise "VERSION MISMATCH! #{so_name} version is #{OCI8::LIB_VERSION}, but oci8.rb version is #{OCI8::VERSION}."
76
84
  end
77
85
 
78
86
  require 'oci8/encoding-init.rb'
@@ -115,18 +115,12 @@ class OCI8
115
115
  param[:length] = val.size
116
116
  else
117
117
  # byte semantics
118
- if OCI8.respond_to? :encoding and OCI8.encoding != val.encoding
118
+ if OCI8.encoding != val.encoding
119
119
  # If the string encoding is different with NLS_LANG character set,
120
120
  # convert it to get the length.
121
121
  val = val.encode(OCI8.encoding)
122
122
  end
123
- if val.respond_to? :bytesize
124
- # ruby 1.8.7 or upper
125
- param[:length] = val.bytesize
126
- else
127
- # ruby 1.8.6 or lower
128
- param[:length] = val.size
129
- end
123
+ param[:length] = val.bytesize
130
124
  end
131
125
  else
132
126
  param[:length] = @@minimum_bind_length
@@ -166,11 +160,7 @@ class OCI8
166
160
  unless param[:length]
167
161
  if val.respond_to? :to_str
168
162
  val = val.to_str
169
- if val.respond_to? :bytesize
170
- param[:length] = val.bytesize
171
- else
172
- param[:length] = val.size
173
- end
163
+ param[:length] = val.bytesize
174
164
  else
175
165
  param[:length] = 400
176
166
  end
@@ -0,0 +1,99 @@
1
+ # This file is loaded only on LoadError.
2
+
3
+ class OCI8
4
+ module Util
5
+
6
+ case RUBY_PLATFORM
7
+ when /mswin32|cygwin|mingw32|bccwin32/
8
+
9
+ require 'Win32API'
10
+ MAX_PATH = 260
11
+ GetModuleFileNameA = Win32API.new('kernel32', 'GetModuleFileNameA', 'PPL', 'L')
12
+ GetSystemDirectoryA = Win32API.new('kernel32', 'GetSystemDirectoryA', 'PL', 'L')
13
+ GetWindowsDirectoryA = Win32API.new('kernel32', 'GetWindowsDirectoryA', 'PL', 'L')
14
+
15
+ def self.check_os_specific_load_error(exc)
16
+ case exc.message
17
+ when /^193: / # "193: %1 is not a valid Win32 application." in English
18
+ check_win32_pe_arch(exc.message.split(' - ')[1], "ruby-oci8")
19
+ dll_load_path_list.each do |path|
20
+ check_win32_pe_arch(File.join(path, '\OCI.DLL'), "Oracle client")
21
+ end
22
+ end
23
+ end # self.check_os_specific_load_error
24
+
25
+ def self.dll_load_path_list
26
+ buf = "\0" * MAX_PATH
27
+ paths = []
28
+ paths << buf[0, GetModuleFileNameA.call(nil, buf, MAX_PATH)].force_encoding("locale").gsub(/\\[^\\]*$/, '')
29
+ paths << buf[0, GetSystemDirectoryA.call(buf, MAX_PATH)].force_encoding("locale")
30
+ paths << buf[0, GetWindowsDirectoryA.call(buf, MAX_PATH)].force_encoding("locale")
31
+ paths << "."
32
+ paths + ENV['PATH'].split(';')
33
+ end # self.dll_load_path_list
34
+
35
+ def self.check_win32_pe_arch(filename, package)
36
+ open(filename, 'rb') do |f|
37
+ # DOS header.
38
+ if f.read(2) == 'MZ'
39
+ f.seek(60, IO::SEEK_SET)
40
+ pe_offset = f.read(4).unpack('V')[0]
41
+ f.seek(pe_offset)
42
+ # PE header.
43
+ if f.read(4) == "PE\000\000"
44
+ case f.read(2).unpack('v')[0]
45
+ when 0x8664
46
+ if [nil].pack('P').size == 4
47
+ raise LoadError, "\"#{filename}\" is x64 DLL. Use 32-bit #{package} instead."
48
+ end
49
+ return true
50
+ when 0x014c
51
+ if [nil].pack('P').size == 8
52
+ raise LoadError, "\"#{filename}\" is 32-bit DLL. Use x64 #{package} instead."
53
+ end
54
+ return true
55
+ end
56
+ end
57
+ end
58
+ raise LoadError, "\"#{filename}\" is not a valid Win32 application."
59
+ end
60
+ nil
61
+ rescue
62
+ nil
63
+ end # self.check_win32_pe_arch
64
+
65
+ when /linux/
66
+
67
+ def self.check_os_specific_load_error(exc)
68
+ case exc.message
69
+ when /^libaio\.so\.1:/ # "libaio.so.1: cannot open shared object file: No such file or directory" in English
70
+ install_cmd = if File.executable? '/usr/bin/apt-get'
71
+ 'apt-get install libaio1'
72
+ elsif File.executable? '/usr/bin/yum'
73
+ 'yum install libaio'
74
+ end
75
+ if install_cmd
76
+ raise LoadError, "You need to install libaio.so.1. Run '#{install_cmd}'."
77
+ else
78
+ raise LoadError, "You need to install libaio.so.1."
79
+ end
80
+ end
81
+ end # self.check_os_specific_load_error
82
+
83
+ else
84
+
85
+ def self.check_os_specific_load_error(exc)
86
+ end
87
+
88
+ end # case RUBY_PLATFORM
89
+
90
+ def self.check_load_error(exc)
91
+ check_os_specific_load_error(exc)
92
+ case exc.message
93
+ when /^OCI Library Initialization Error/
94
+ # TODO
95
+ end
96
+ end
97
+
98
+ end # module Util
99
+ end
@@ -5,75 +5,41 @@
5
5
  #
6
6
  class OCI8
7
7
 
8
- # get the environment variable NLS_LANG.
9
- nls_lang = ENV['NLS_LANG']
8
+ @@client_charset_name = charset_id2name(@@environment_handle.send(:attr_get_ub2, 31))
9
+ # 31 is OCI_ATTR_ENV_CHARSET_ID.
10
10
 
11
- if nls_lang.is_a? String and nls_lang.length == 0
12
- nls_lang = nil
13
- end
14
-
15
- # if NLS_LANG is not set, get it from the Windows registry.
16
- if nls_lang.nil? and defined? OCI8::Win32Util
17
- dll_path = OCI8::Win32Util.dll_path.upcase
18
- if dll_path =~ %r{\\BIN\\OCI.DLL}
19
- oracle_home = $`
20
- OCI8::Win32Util.enum_homes do |home, lang|
21
- if oracle_home == home.upcase
22
- nls_lang = lang
23
- break
11
+ if @@client_charset_name == 'US7ASCII'
12
+ # Check whether US7ASCII is explicitly set by NLS_LANG or not.
13
+ nls_lang = ENV['NLS_LANG']
14
+ if nls_lang.nil? and defined? OCI8::Win32Util
15
+ if OCI8::Util::dll_path =~ /\\BIN\\OCI\.DLL$/i
16
+ oracle_home = $`
17
+ OCI8::Win32Util.enum_homes do |home, lang|
18
+ if oracle_home == home.upcase
19
+ nls_lang = lang
20
+ break
21
+ end
24
22
  end
25
23
  end
26
24
  end
27
- end
28
-
29
- # extract the charset name.
30
- if nls_lang
31
- if nls_lang =~ /\.([[:alnum:]]+)$/
32
- @@client_charset_name = $1.upcase
33
- else
34
- raise "Invalid NLS_LANG format: #{nls_lang}"
25
+ if nls_lang.nil?
26
+ warn "Warning: NLS_LANG is not set. fallback to US7ASCII."
35
27
  end
36
- else
37
- warn "Warning: NLS_LANG is not set. fallback to US7ASCII."
38
- # @private
39
- @@client_charset_name = 'US7ASCII'
40
28
  end
41
29
 
42
- # Ruby encoding name for ruby 1.9.
43
- if OCI8.respond_to? :encoding
44
- if defined? DEFAULT_OCI8_ENCODING
45
- enc = DEFAULT_OCI8_ENCODING
46
- else
47
- require 'yaml'
48
- enc = YAML::load_file(File.dirname(__FILE__) + '/encoding.yml')[@@client_charset_name]
49
- if enc.nil?
50
- raise "Ruby encoding name is not found in encoding.yml for NLS_LANG #{nls_lang}."
51
- end
52
- if enc.is_a? Array
53
- # Use the first available encoding in the array.
54
- enc = enc.find do |e| Encoding.find(e) rescue false; end
55
- end
56
- end
57
- OCI8.encoding = enc
30
+ if defined? DEFAULT_OCI8_ENCODING
31
+ enc = DEFAULT_OCI8_ENCODING
58
32
  else
59
- # NLS ratio, maximum number of bytes per one chracter
60
- case @@client_charset_name
61
- when 'UTF8'
62
- OCI8.nls_ratio = 3
63
- when 'AL16UTF16'
64
- OCI8.nls_ratio = 4
65
- when /^[[:alpha:]]+(\d+)/
66
- # convert maximum number of bits per one chracter to NLS ratio.
67
- # charset name max bits max bytes
68
- # ------------ -------- ---------
69
- # US7ASCII 7 1
70
- # WE8ISO8859P1 8 1
71
- # JA16SJIS 16 2
72
- # AL32UTF8 32 4
73
- # ...
74
- OCI8.nls_ratio = (($1.to_i + 7) >> 3)
75
- else
76
- raise "Unknown NLS character set name format: #{@@client_charset_name}"
33
+ require 'yaml'
34
+ yaml_file = File.dirname(__FILE__) + '/encoding.yml'
35
+ enc = YAML::load_file(yaml_file)[@@client_charset_name]
36
+ if enc.nil?
37
+ raise "Cannot convert Oracle charset name #{@@client_charset_name} to Ruby encoding name in #{yaml_file}."
38
+ end
39
+ if enc.is_a? Array
40
+ # Use the first available encoding in the array.
41
+ enc = enc.find do |e| Encoding.find(e) rescue false; end
77
42
  end
78
43
  end
44
+ OCI8.encoding = enc
79
45
  end
@@ -996,20 +996,14 @@ class OCI8
996
996
  __charset_form
997
997
  end
998
998
 
999
- if OCI8.oracle_client_version >= ORAVER_9_0
1000
- # The fractional seconds precision of a datetime or interval.
1001
- #
1002
- # (unavailable on Oracle 8.1 or lower)
1003
- def fsprecision
1004
- attr_get_ub1(OCI_ATTR_FSPRECISION)
1005
- end
999
+ # The fractional seconds precision of a datetime or interval.
1000
+ def fsprecision
1001
+ attr_get_ub1(OCI_ATTR_FSPRECISION)
1002
+ end
1006
1003
 
1007
- # The leading field precision of an interval
1008
- #
1009
- # (unavailable on Oracle 8.1 or lower)
1010
- def lfprecision
1011
- attr_get_ub1(OCI_ATTR_LFPRECISION)
1012
- end
1004
+ # The leading field precision of an interval
1005
+ def lfprecision
1006
+ attr_get_ub1(OCI_ATTR_LFPRECISION)
1013
1007
  end
1014
1008
 
1015
1009
  # character set name if the type attribute is of a string/character type.
@@ -1339,30 +1333,18 @@ class OCI8
1339
1333
 
1340
1334
  ## Table 6-13 Attributes Belonging to Columns of Tables or Views
1341
1335
 
1342
- if OCI8.oracle_client_version >= ORAVER_9_0
1343
- # returns the type of length semantics of the column.
1344
- # [<tt>:byte</tt>] byte-length semantics
1345
- # [<tt>:char</tt>] character-length semantics.
1346
- #
1347
- # (unavailable on Oracle 8.1 or lower)
1348
- def char_used?
1349
- attr_get_ub1(OCI_ATTR_CHAR_USED) != 0
1350
- end
1351
-
1352
- # returns the column character length which is the number of
1353
- # characters allowed in the column. It is the counterpart of
1354
- # OCI8::Metadata::Column#data_size which gets the byte length.
1355
- def char_size
1356
- attr_get_ub2(OCI_ATTR_CHAR_SIZE)
1357
- end
1358
- else
1359
- def char_used?
1360
- false
1361
- end
1336
+ # returns the type of length semantics of the column.
1337
+ # [<tt>:byte</tt>] byte-length semantics
1338
+ # [<tt>:char</tt>] character-length semantics.
1339
+ def char_used?
1340
+ attr_get_ub1(OCI_ATTR_CHAR_USED) != 0
1341
+ end
1362
1342
 
1363
- def char_size
1364
- data_size
1365
- end
1343
+ # returns the column character length which is the number of
1344
+ # characters allowed in the column. It is the counterpart of
1345
+ # OCI8::Metadata::Column#data_size which gets the byte length.
1346
+ def char_size
1347
+ attr_get_ub2(OCI_ATTR_CHAR_SIZE)
1366
1348
  end
1367
1349
 
1368
1350
  # The maximum size of the column. This length is
@@ -1445,20 +1427,14 @@ class OCI8
1445
1427
  ## Table 6-8 Attributes Belonging to Type Attributes
1446
1428
  ## But Column also have these.
1447
1429
 
1448
- if OCI8.oracle_client_version >= ORAVER_9_0
1449
- # The fractional seconds precision of a datetime or interval.
1450
- #
1451
- # (unavailable on Oracle 8.1 or lower)
1452
- def fsprecision
1453
- attr_get_ub1(OCI_ATTR_FSPRECISION)
1454
- end
1430
+ # The fractional seconds precision of a datetime or interval.
1431
+ def fsprecision
1432
+ attr_get_ub1(OCI_ATTR_FSPRECISION)
1433
+ end
1455
1434
 
1456
- # The leading field precision of an interval
1457
- #
1458
- # (unavailable on Oracle 8.1 or lower)
1459
- def lfprecision
1460
- attr_get_ub1(OCI_ATTR_LFPRECISION)
1461
- end
1435
+ # The leading field precision of an interval
1436
+ def lfprecision
1437
+ attr_get_ub1(OCI_ATTR_LFPRECISION)
1462
1438
  end
1463
1439
 
1464
1440
  # The character set name, if the column is of a string/character type
@@ -1677,14 +1653,8 @@ class OCI8
1677
1653
 
1678
1654
  ## Table 6-15 List Attributes
1679
1655
 
1680
- if OCI8::oracle_client_version < OCI8::ORAVER_8_1
1681
- def ltype
1682
- raise "This feature is unavailable on Oracle 8.0"
1683
- end
1684
- else
1685
- def ltype
1686
- attr_get_ub2(OCI_ATTR_LTYPE)
1687
- end
1656
+ def ltype
1657
+ attr_get_ub2(OCI_ATTR_LTYPE)
1688
1658
  end
1689
1659
 
1690
1660
  # convert to array