ruby-oci8 2.0.4 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,7 +3,7 @@
3
3
  * oradate.c
4
4
  *
5
5
  * $Author: kubo $
6
- * $Date: 2009-01-04 01:58:01 +0900 (Sun, 04 Jan 2009) $
6
+ * $Date: 2010-09-05 22:07:21 +0900 (日, 05 9月 2010) $
7
7
  *
8
8
  * Copyright (C) 2002-2008 KUBO Takehiro <kubo@jiubao.org>
9
9
  *
@@ -146,7 +146,7 @@ static VALUE ora_date_initialize_copy(VALUE lhs, VALUE rhs)
146
146
  {
147
147
  ora_date_t *l, *r;
148
148
 
149
- rb_obj_init_copy(lhs, rhs);
149
+ rb_call_super(1, &rhs);
150
150
  Data_Get_Struct(lhs, ora_date_t, l);
151
151
  Data_Get_Struct(rhs, ora_date_t, r);
152
152
  memcpy(l, r, sizeof(ora_date_t));
@@ -37,9 +37,24 @@ int oranumber_to_str(const OCINumber *on, char *buf, int buflen)
37
37
  PUTEND();
38
38
  return 1;
39
39
  }
40
+ if (on->OCINumberPart[1] == 0) {
41
+ /* negative infinity */
42
+ PUTC('-');
43
+ PUTC('~');
44
+ PUTEND();
45
+ return 2;
46
+ }
40
47
  /* unexpected format */
41
48
  return -1;
42
49
  }
50
+ if (datalen == 2) {
51
+ if (on->OCINumberPart[1] == 255 && on->OCINumberPart[2] == 101) {
52
+ /* positive infinity */
53
+ PUTC('~');
54
+ PUTEND();
55
+ return 1;
56
+ }
57
+ }
43
58
  if (datalen > 21) {
44
59
  /* too long */
45
60
  return -1;
@@ -137,6 +152,28 @@ int oranumber_from_str(OCINumber *on, const char *buf, int buflen)
137
152
  buf++;
138
153
  is_positive = 0;
139
154
  }
155
+ if (*buf == '~') {
156
+ buf ++;
157
+ /* skip trailing spaces */
158
+ while (buf < end && *buf == ' ') {
159
+ buf++;
160
+ }
161
+ if (buf != end) {
162
+ return ORANUMBER_INVALID_NUMBER;
163
+ }
164
+ if (is_positive) {
165
+ /* positive infinity */
166
+ on->OCINumberPart[0] = 2;
167
+ on->OCINumberPart[1] = 255;
168
+ on->OCINumberPart[2] = 101;
169
+ } else {
170
+ /* negative infinity */
171
+ on->OCINumberPart[0] = 1;
172
+ on->OCINumberPart[1] = 0;
173
+ }
174
+ return ORANUMBER_SUCCESS;
175
+ }
176
+
140
177
  /* next should be number or a dot */
141
178
  if ((*buf < '0' || '9' < *buf) && *buf != '.') {
142
179
  return ORANUMBER_INVALID_NUMBER;
@@ -308,7 +345,7 @@ int oranumber_dump(const OCINumber *on, char *buf)
308
345
  len = 21;
309
346
  }
310
347
  for (idx = 1; idx <= len; idx++) {
311
- offset += sprintf(buf + offset, "%hhu,", on->OCINumberPart[idx]);
348
+ offset += sprintf(buf + offset, "%u,", (ub4)on->OCINumberPart[idx]);
312
349
  }
313
350
  buf[--offset] = '\0';
314
351
  return offset;
@@ -3,7 +3,7 @@
3
3
  * stmt.c - part of ruby-oci8
4
4
  * implement the methods of OCIStmt.
5
5
  *
6
- * Copyright (C) 2002-2007 KUBO Takehiro <kubo@jiubao.org>
6
+ * Copyright (C) 2002-2010 KUBO Takehiro <kubo@jiubao.org>
7
7
  *
8
8
  */
9
9
  #include "oci8.h"
@@ -28,6 +28,8 @@ static ID id_clear;
28
28
 
29
29
  VALUE cOCIStmt;
30
30
 
31
+ #define TO_STMT(obj) ((oci8_stmt_t *)oci8_get_handle((obj), cOCIStmt))
32
+
31
33
  typedef struct {
32
34
  oci8_base_t base;
33
35
  VALUE svc;
@@ -94,7 +96,7 @@ static VALUE oci8_stmt_initialize(int argc, VALUE *argv, VALUE self)
94
96
 
95
97
  static VALUE oci8_define_by_pos(VALUE self, VALUE vposition, VALUE vbindobj)
96
98
  {
97
- oci8_stmt_t *stmt = DATA_PTR(self);
99
+ oci8_stmt_t *stmt = TO_STMT(self);
98
100
  ub4 position;
99
101
  oci8_bind_t *obind;
100
102
  const oci8_bind_class_t *bind_class;
@@ -117,6 +119,10 @@ static VALUE oci8_define_by_pos(VALUE self, VALUE vposition, VALUE vbindobj)
117
119
  oci8_raise(oci8_errhp, status, stmt->base.hp.ptr);
118
120
  }
119
121
  obind->base.type = OCI_HTYPE_DEFINE;
122
+ /* link to the parent as soon as possible to preserve deallocation order. */
123
+ oci8_unlink_from_parent((oci8_base_t*)obind);
124
+ oci8_link_to_parent((oci8_base_t*)obind, (oci8_base_t*)stmt);
125
+
120
126
  if (NIL_P(obind->tdo) && obind->maxar_sz > 0) {
121
127
  oci_lc(OCIDefineArrayOfStruct(obind->base.hp.dfn, oci8_errhp, obind->alloc_sz, sizeof(sb2), 0, 0));
122
128
  }
@@ -135,14 +141,12 @@ static VALUE oci8_define_by_pos(VALUE self, VALUE vposition, VALUE vbindobj)
135
141
  oci_lc(OCIAttrSet(obind->base.hp.ptr, OCI_HTYPE_DEFINE, (void*)&bind_class->csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp));
136
142
  }
137
143
  rb_ary_store(stmt->defns, position - 1, obind->base.self);
138
- oci8_unlink_from_parent((oci8_base_t*)obind);
139
- oci8_link_to_parent((oci8_base_t*)obind, (oci8_base_t*)stmt);
140
144
  return obind->base.self;
141
145
  }
142
146
 
143
147
  static VALUE oci8_bind(VALUE self, VALUE vplaceholder, VALUE vbindobj)
144
148
  {
145
- oci8_stmt_t *stmt = DATA_PTR(self);
149
+ oci8_stmt_t *stmt = TO_STMT(self);
146
150
  char *placeholder_ptr = (char*)-1; /* initialize as an invalid value */
147
151
  ub4 placeholder_len = 0;
148
152
  ub4 position = 0;
@@ -197,6 +201,10 @@ static VALUE oci8_bind(VALUE self, VALUE vplaceholder, VALUE vbindobj)
197
201
  oci8_raise(oci8_errhp, status, stmt->base.hp.stmt);
198
202
  }
199
203
  obind->base.type = OCI_HTYPE_BIND;
204
+ /* link to the parent as soon as possible to preserve deallocation order. */
205
+ oci8_unlink_from_parent((oci8_base_t*)obind);
206
+ oci8_link_to_parent((oci8_base_t*)obind, (oci8_base_t*)stmt);
207
+
200
208
  if (NIL_P(obind->tdo) && obind->maxar_sz > 0) {
201
209
  oci_lc(OCIBindArrayOfStruct(obind->base.hp.bnd, oci8_errhp, obind->alloc_sz, sizeof(sb2), 0, 0));
202
210
  }
@@ -213,8 +221,6 @@ static VALUE oci8_bind(VALUE self, VALUE vplaceholder, VALUE vbindobj)
213
221
  oci8_base_free((oci8_base_t*)oci8_get_bind(old_value));
214
222
  }
215
223
  rb_hash_aset(stmt->binds, vplaceholder, obind->base.self);
216
- oci8_unlink_from_parent((oci8_base_t*)obind);
217
- oci8_link_to_parent((oci8_base_t*)obind, (oci8_base_t*)stmt);
218
224
  return obind->base.self;
219
225
  }
220
226
 
@@ -237,7 +243,7 @@ static sword oci8_call_stmt_execute(oci8_svcctx_t *svcctx, oci8_stmt_t *stmt, ub
237
243
 
238
244
  static VALUE oci8_stmt_execute(VALUE self, VALUE iteration_count)
239
245
  {
240
- oci8_stmt_t *stmt = DATA_PTR(self);
246
+ oci8_stmt_t *stmt = TO_STMT(self);
241
247
  oci8_svcctx_t *svcctx = oci8_get_svcctx(stmt->svc);
242
248
  ub4 iters;
243
249
  ub4 mode;
@@ -323,8 +329,8 @@ static VALUE clear_binds_iterator_proc(VALUE val, VALUE arg)
323
329
 
324
330
  static VALUE oci8_stmt_clear_binds(VALUE self)
325
331
  {
326
- oci8_stmt_t *stmt = DATA_PTR(self);
327
-
332
+ oci8_stmt_t *stmt = TO_STMT(self);
333
+
328
334
  if(!RTEST(rb_funcall(stmt->binds, id_empty_p, 0)))
329
335
  {
330
336
  rb_iterate(each_value, stmt->binds, clear_binds_iterator_proc, Qnil);
@@ -449,7 +455,7 @@ static VALUE oci8_stmt_do_fetch(oci8_stmt_t *stmt, oci8_svcctx_t *svcctx)
449
455
  */
450
456
  static VALUE oci8_stmt_fetch(VALUE self)
451
457
  {
452
- oci8_stmt_t *stmt = DATA_PTR(self);
458
+ oci8_stmt_t *stmt = TO_STMT(self);
453
459
  oci8_svcctx_t *svcctx = oci8_get_svcctx(stmt->svc);
454
460
 
455
461
  if (rb_block_given_p()) {
@@ -466,7 +472,7 @@ static VALUE oci8_stmt_fetch(VALUE self)
466
472
 
467
473
  static VALUE oci8_stmt_get_param(VALUE self, VALUE pos)
468
474
  {
469
- oci8_stmt_t *stmt = DATA_PTR(self);
475
+ oci8_stmt_t *stmt = TO_STMT(self);
470
476
  OCIParam *parmhp = NULL;
471
477
  sword rv;
472
478
 
@@ -498,7 +504,7 @@ static VALUE oci8_stmt_get_param(VALUE self, VALUE pos)
498
504
  */
499
505
  static VALUE oci8_stmt_get_stmt_type(VALUE self)
500
506
  {
501
- VALUE stmt_type = oci8_get_ub2_attr(DATA_PTR(self), OCI_ATTR_STMT_TYPE);
507
+ VALUE stmt_type = oci8_get_ub2_attr(oci8_get_handle(self, cOCIStmt), OCI_ATTR_STMT_TYPE);
502
508
  switch (FIX2INT(stmt_type)) {
503
509
  case OCI_STMT_SELECT:
504
510
  return oci8_sym_select_stmt;
@@ -528,7 +534,7 @@ static VALUE oci8_stmt_get_stmt_type(VALUE self)
528
534
  */
529
535
  static VALUE oci8_stmt_get_row_count(VALUE self)
530
536
  {
531
- return oci8_get_ub4_attr(DATA_PTR(self), OCI_ATTR_ROW_COUNT);
537
+ return oci8_get_ub4_attr(oci8_get_handle(self, cOCIStmt), OCI_ATTR_ROW_COUNT);
532
538
  }
533
539
 
534
540
  /*
@@ -547,12 +553,12 @@ static VALUE oci8_stmt_get_row_count(VALUE self)
547
553
  */
548
554
  static VALUE oci8_stmt_get_rowid(VALUE self)
549
555
  {
550
- return oci8_get_rowid_attr(DATA_PTR(self), OCI_ATTR_ROWID);
556
+ return oci8_get_rowid_attr(oci8_get_handle(self, cOCIStmt), OCI_ATTR_ROWID);
551
557
  }
552
558
 
553
559
  static VALUE oci8_stmt_get_param_count(VALUE self)
554
560
  {
555
- return oci8_get_ub4_attr(DATA_PTR(self), OCI_ATTR_PARAM_COUNT);
561
+ return oci8_get_ub4_attr(oci8_get_handle(self, cOCIStmt), OCI_ATTR_PARAM_COUNT);
556
562
  }
557
563
 
558
564
  /*
@@ -595,7 +601,7 @@ static VALUE oci8_stmt_get_param_count(VALUE self)
595
601
  */
596
602
  static VALUE oci8_stmt_aref(VALUE self, VALUE key)
597
603
  {
598
- oci8_stmt_t *stmt = DATA_PTR(self);
604
+ oci8_stmt_t *stmt = TO_STMT(self);
599
605
  VALUE obj = rb_hash_aref(stmt->binds, key);
600
606
  if (NIL_P(obj)) {
601
607
  return Qnil;
@@ -633,7 +639,7 @@ static VALUE oci8_stmt_aset(VALUE self, VALUE key, VALUE val)
633
639
  long actual_array_size;
634
640
  long bind_array_size;
635
641
 
636
- oci8_stmt_t *stmt = DATA_PTR(self);
642
+ oci8_stmt_t *stmt = TO_STMT(self);
637
643
  VALUE obj = rb_hash_aref(stmt->binds, key);
638
644
  if (NIL_P(obj)) {
639
645
  return Qnil; /* ?? MUST BE ERROR? */
@@ -650,7 +656,7 @@ static VALUE oci8_stmt_aset(VALUE self, VALUE key, VALUE val)
650
656
  if(bind_array_size <= max_array_size && actual_array_size == 0) {
651
657
  rb_ivar_set(self, id_at_actual_array_size, INT2NUM(bind_array_size));
652
658
  }
653
- }
659
+ }
654
660
  oci8_bind_set_data(obj, val);
655
661
  return val;
656
662
  }
@@ -663,13 +669,13 @@ static VALUE oci8_stmt_aset(VALUE self, VALUE key, VALUE val)
663
669
  */
664
670
  static VALUE oci8_stmt_keys(VALUE self)
665
671
  {
666
- oci8_stmt_t *stmt = DATA_PTR(self);
672
+ oci8_stmt_t *stmt = TO_STMT(self);
667
673
  return rb_funcall(stmt->binds, oci8_id_keys, 0);
668
674
  }
669
675
 
670
676
  static VALUE oci8_stmt_defined_p(VALUE self, VALUE pos)
671
677
  {
672
- oci8_stmt_t *stmt = DATA_PTR(self);
678
+ oci8_stmt_t *stmt = TO_STMT(self);
673
679
  long position = NUM2INT(pos);
674
680
 
675
681
  if (position - 1 < RARRAY_LEN(stmt->defns)) {
@@ -693,7 +699,7 @@ static VALUE oci8_stmt_defined_p(VALUE self, VALUE pos)
693
699
  */
694
700
  static VALUE oci8_stmt_set_prefetch_rows(VALUE self, VALUE rows)
695
701
  {
696
- oci8_stmt_t *stmt = DATA_PTR(self);
702
+ oci8_stmt_t *stmt = TO_STMT(self);
697
703
  ub4 num = NUM2UINT(rows);
698
704
 
699
705
  oci_lc(OCIAttrSet(stmt->base.hp.ptr, OCI_HTYPE_STMT, &num, 0, OCI_ATTR_PREFETCH_ROWS, oci8_errhp));
@@ -2,9 +2,15 @@
2
2
  /*
3
3
  win32.c - part of ruby-oci8
4
4
 
5
- Copyright (C) 2009 KUBO Takehiro <kubo@jiubao.org>
5
+ Copyright (C) 2009-2010 KUBO Takehiro <kubo@jiubao.org>
6
6
  */
7
7
  #include "oci8.h"
8
+ #ifdef __CYGWIN__
9
+ /* boolean is defined as a macro in oratypes.h.
10
+ * It conflicts with the definition in windows.h.
11
+ */
12
+ #undef boolean
13
+ #endif
8
14
  #include <windows.h>
9
15
 
10
16
  NORETURN(static void raise_error(void));
@@ -84,14 +90,14 @@ static VALUE enum_homes_real(enum_homes_arg_t *arg)
84
90
  }
85
91
  /* Get ORACLE_HOME */
86
92
  name_len = sizeof(name);
87
- rv = RegQueryValueEx(arg->hSubKey, "ORACLE_HOME", NULL, &type, name, &name_len);
93
+ rv = RegQueryValueEx(arg->hSubKey, "ORACLE_HOME", NULL, &type, TO_ORATEXT(name), &name_len);
88
94
  if (rv != ERROR_SUCCESS || type != REG_SZ) {
89
95
  continue;
90
96
  }
91
97
  oracle_home = rb_locale_str_new_cstr(name);
92
98
  /* Get NLS_LANG */
93
99
  name_len = sizeof(name);
94
- rv = RegQueryValueEx(arg->hSubKey, "NLS_LANG", NULL, &type, name, &name_len);
100
+ rv = RegQueryValueEx(arg->hSubKey, "NLS_LANG", NULL, &type, TO_ORATEXT(name), &name_len);
95
101
  if (rv != ERROR_SUCCESS || type != REG_SZ) {
96
102
  continue;
97
103
  }
@@ -18,14 +18,24 @@ if RUBY_PLATFORM =~ /cygwin/
18
18
  end
19
19
  end
20
20
 
21
+ so_basename = 'oci8lib_'
22
+ if defined? RUBY_ENGINE and RUBY_ENGINE != 'ruby'
23
+ so_basename += RUBY_ENGINE
24
+ end
25
+
26
+ # The suffix number indicates the ruby API version.
27
+ # 18 - ruby 1.8.x
28
+ # 191 - ruby 1.9.1 and 1.9.2
29
+ # 19x - ruby 1.9.x future version which will break the API compatibility
21
30
  case RUBY_VERSION
22
31
  when /^1\.9/
23
- require 'oci8lib_191'
32
+ so_basename += '191'
24
33
  when /^1\.8/
25
- require 'oci8lib_18'
34
+ so_basename += '18'
26
35
  else
27
36
  raise 'unsupported ruby version: ' + RUBY_VERSION
28
37
  end
38
+ require so_basename
29
39
 
30
40
  if OCI8.respond_to? :encoding
31
41
  if defined? DEFAULT_OCI8_ENCODING
@@ -75,6 +85,7 @@ require 'oci8/bindtype.rb'
75
85
  require 'oci8/metadata.rb'
76
86
  require 'oci8/compat.rb'
77
87
  require 'oci8/object.rb'
88
+ require 'oci8/properties.rb'
78
89
 
79
90
  class OCI8
80
91
  VERSION = '@@OCI8_MODULE_VERSION@@'
@@ -3,3 +3,4 @@ object.rb
3
3
  metadata.rb
4
4
  oracle_version.rb
5
5
  oci8.rb
6
+ properties.rb
@@ -1,7 +1,7 @@
1
1
  #--
2
2
  # bindtype.rb -- OCI8::BindType
3
3
  #
4
- # Copyright (C) 2009 KUBO Takehiro <kubo@jiubao.org>
4
+ # Copyright (C) 2009-2010 KUBO Takehiro <kubo@jiubao.org>
5
5
  #++
6
6
 
7
7
  class OCI8
@@ -46,6 +46,12 @@ class OCI8
46
46
  end
47
47
  end
48
48
 
49
+ class BasicNumberType < OCI8::BindType::OraNumber
50
+ def get()
51
+ (val = super()) && (val.has_decimal_part? ? val.to_f : val.to_i)
52
+ end
53
+ end
54
+
49
55
  # get/set Number (for OCI8::SQLT_NUM)
50
56
  class Number
51
57
  def self.create(con, val, param, max_array_size)
@@ -116,6 +122,8 @@ class OCI8
116
122
  length = val.size
117
123
  end
118
124
  end
125
+ # use the default value when :nchar is not set explicitly.
126
+ nchar = OCI8.properties[:bind_string_as_nchar] unless param.has_key?(:nchar)
119
127
  when OCI8::Metadata::Base
120
128
  case param.data_type
121
129
  when :char, :varchar2
@@ -124,13 +132,18 @@ class OCI8
124
132
  # The length of a Japanese half-width kana is one in Shift_JIS,
125
133
  # two in EUC-JP, three in UTF-8.
126
134
  length *= 3 unless param.char_used?
135
+ nchar = (param.charset_form == :nchar)
127
136
  when :raw
128
137
  # HEX needs twice space.
129
138
  length = param.data_size * 2
130
139
  end
131
140
  end
132
141
  length = @@minimum_bind_length if length.nil? or length < @@minimum_bind_length
133
- self.new(con, val, length, max_array_size)
142
+ if nchar
143
+ OCI8::BindType::NCHAR.new(con, val, length, max_array_size)
144
+ else
145
+ OCI8::BindType::CHAR.new(con, val, length, max_array_size)
146
+ end
134
147
  end
135
148
  end
136
149
 
@@ -153,7 +166,7 @@ class OCI8
153
166
 
154
167
  class Long < OCI8::BindType::String
155
168
  def self.create(con, val, param, max_array_size)
156
- self.new(con, val, con.long_read_len, max_array_size)
169
+ super(con, val, {:length => con.long_read_len}, max_array_size)
157
170
  end
158
171
  end
159
172
 
@@ -38,6 +38,14 @@ class OCI8
38
38
  @@time_new_accepts_timezone = false # prior to ruby 1.9.2
39
39
  end
40
40
 
41
+ begin
42
+ # 2001-01-01 00:00:59.999
43
+ ::DateTime.civil(2001, 1, 1, 0, 0, Rational(59_999, 1000), 0)
44
+ @@datetime_has_fractional_second_bug = false
45
+ rescue ArgumentError
46
+ @@datetime_has_fractional_second_bug = true
47
+ end
48
+
41
49
  def self.default_timezone
42
50
  @@default_timezone
43
51
  end
@@ -162,8 +170,8 @@ class OCI8
162
170
  return nil if ary.nil?
163
171
 
164
172
  year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
165
- if sec >= 59 and fsec != 0
166
- # convert to a DateTime via a String as a last resort.
173
+ if @@datetime_has_fractional_second_bug and sec >= 59 and fsec != 0
174
+ # convert to a DateTime via a String as a workaround
167
175
  if tz_hour >= 0 && tz_min >= 0
168
176
  sign = ?+
169
177
  else
@@ -245,7 +253,7 @@ class OCI8
245
253
  end
246
254
 
247
255
  if OCI8.oracle_client_version >= ORAVER_9_0
248
- class DateTimeViaOCITimestamp < OCI8::BindType::OCITimestamp # :nodoc:
256
+ class DateTimeViaOCITimestampTZ < OCI8::BindType::OCITimestampTZ # :nodoc:
249
257
  include OCI8::BindType::Util
250
258
 
251
259
  def set(val) # :nodoc:
@@ -257,7 +265,7 @@ class OCI8
257
265
  end
258
266
  end
259
267
 
260
- class TimeViaOCITimestamp < OCI8::BindType::OCITimestamp # :nodoc:
268
+ class TimeViaOCITimestampTZ < OCI8::BindType::OCITimestampTZ # :nodoc:
261
269
  include OCI8::BindType::Util
262
270
 
263
271
  def set(val) # :nodoc:
@@ -335,7 +343,7 @@ class OCI8
335
343
  if OCI8.oracle_client_version >= ORAVER_9_0
336
344
  def self.create(con, val, param, max_array_size) # :nodoc:
337
345
  if true # TODO: check Oracle server version
338
- DateTimeViaOCITimestamp.new(con, val, param, max_array_size)
346
+ DateTimeViaOCITimestampTZ.new(con, val, param, max_array_size)
339
347
  else
340
348
  DateTimeViaOCIDate.new(con, val, param, max_array_size)
341
349
  end
@@ -414,7 +422,7 @@ class OCI8
414
422
  if OCI8.oracle_client_version >= ORAVER_9_0
415
423
  def self.create(con, val, param, max_array_size) # :nodoc:
416
424
  if true # TODO: check Oracle server version
417
- TimeViaOCITimestamp.new(con, val, param, max_array_size)
425
+ TimeViaOCITimestampTZ.new(con, val, param, max_array_size)
418
426
  else
419
427
  TimeViaOCIDate.new(con, val, param, max_array_size)
420
428
  end