[ruby-oci8-commit] [389] trunk/ruby-oci8: * ext/oci8/encoding.c: add new methods OCI8. nls_ratio

nobody at rubyforge.org nobody at rubyforge.org
Tue Apr 27 08:50:43 EDT 2010


Revision: 389
Author:   kubo
Date:     2010-04-27 08:50:42 -0400 (Tue, 27 Apr 2010)

Log Message:
-----------
* ext/oci8/encoding.c: add new methods OCI8.nls_ratio
    and OCI8.nls_ratio=. Comments for rdoc are added and
    revised for OCI8#charset_name2id, OCI8#charset_name2id=,
    OCI8.encoding and OCI8.encoding=.
* lib/oci8.rb.in, lib/oci8/encoding-init.rb: set
    OCI8.nls_ratio on initialization.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/encoding.c
    trunk/ruby-oci8/lib/oci8/encoding-init.rb
    trunk/ruby-oci8/lib/oci8.rb.in

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2010-04-23 13:32:46 UTC (rev 388)
+++ trunk/ruby-oci8/ChangeLog	2010-04-27 12:50:42 UTC (rev 389)
@@ -1,3 +1,11 @@
+2010-04-27  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/encoding.c: add new methods OCI8.nls_ratio
+	    and OCI8.nls_ratio=. Comments for rdoc are added and
+	    revised for OCI8#charset_name2id, OCI8#charset_name2id=,
+	    OCI8.encoding and OCI8.encoding=.
+	* lib/oci8.rb.in, lib/oci8/encoding-init.rb: set
+	    OCI8.nls_ratio on initialization.
+
 2010-04-23  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/oranumber_util.c, test/test_oranumber.rb:
 	    add limitted support for OraNumber's positive and negative
@@ -16,7 +24,7 @@
 
 2010-02-28  KUBO Takehiro  <kubo at jiubao.org>
 	* NEWS: add changes between 2.0.3 and 2.0.4.
-	* VERSION: change the version to 2.0.3.
+	* VERSION: change the version to 2.0.4.
 	* ext/oci8/stmt.c: fix segmentation fault when OCI8::Cursor#fetch
 	    is called prior to OCI8::Cursor#exec.
 	* ext/oci8/oci8.c: minor fix in rdoc comment.

Modified: trunk/ruby-oci8/ext/oci8/encoding.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/encoding.c	2010-04-23 13:32:46 UTC (rev 388)
+++ trunk/ruby-oci8/ext/oci8/encoding.c	2010-04-27 12:50:42 UTC (rev 389)
@@ -2,7 +2,7 @@
 /*
  * encoding.c - part of ruby-oci8
  *
- * Copyright (C) 2008 KUBO Takehiro <kubo at jiubao.org>
+ * Copyright (C) 2008-2010 KUBO Takehiro <kubo at jiubao.org>
  *
  */
 #include "oci8.h"
@@ -21,6 +21,9 @@
     } u;
 } cb_arg_t;
 
+/* NLS ratio, maximum number of bytes per one chracter */
+int oci8_nls_ratio = 1;
+
 /* Oracle charset id -> Oracle charset name */
 static VALUE csid2name;
 
@@ -32,6 +35,30 @@
 rb_encoding *oci8_encoding;
 #endif
 
+
+/*
+ * call-seq:
+ *   charset_id2name(charset_id) -> charset_name
+ *
+ * <b>(new in 2.0.0)</b>
+ *
+ * Returns the Oracle character set name from the specified
+ * character set ID if it is valid. Otherwise, +nil+ is returned.
+ *
+ * === Oracle 9iR2 client or upper
+ *
+ * It is done by using the mapping table stored in the client side.
+ *
+ * === Oracle 9iR1 client or lower
+ *
+ * It executes the following PL/SQL block internally to use
+ * the mapping table stored in the server side.
+ *
+ *   BEGIN
+ *     :name := nls_charset_name(:csid);
+ *   END;
+ *
+ */
 VALUE oci8_charset_id2name(VALUE svc, VALUE csid)
 {
     VALUE name = rb_hash_aref(csid2name, csid);
@@ -83,6 +110,29 @@
     return name;
 }
 
+/*
+ * call-seq:
+ *   charset_name2id(charset_name) -> charset_id
+ *
+ * <b>(new in 2.0.0)</b>
+ *
+ * Returns the Oracle character set ID for the specified Oracle
+ * character set name if it is valid. Othewise, +nil+ is returned.
+ *
+ * === Oracle 9iR2 client or upper
+ *
+ * It is done by using the mapping table stored in the client side.
+ *
+ * === Oracle 9iR1 client or lower
+ *
+ * It executes the following PL/SQL block internally to use
+ * the mapping table stored in the server side.
+ *
+ *   BEGIN
+ *     :csid := nls_charset_id(:name);
+ *   END;
+ *
+ */
 static VALUE oci8_charset_name2id(VALUE svc, VALUE name)
 {
     VALUE csid;
@@ -132,27 +182,72 @@
     return csid;
 }
 
+/*
+ * call-seq:
+ *   OCI8.nls_ratio -> integer
+ *
+ * <b>(new in 2.0.5)</b>
+ *
+ * Gets NLS ratio, maximum number of bytes per one character of the
+ * current NLS chracter set. It is a factor to calculate the
+ * internal buffer size of a string bind variable whose nls length
+ * semantics is char.
+ */
+static VALUE oci8_get_nls_ratio(VALUE klass)
+{
+    return INT2NUM(oci8_nls_ratio);
+}
+
+/*
+ * call-seq:
+ *   OCI8.nls_ratio = integer
+ *
+ * <b>(new in 2.0.5)</b>
+ *
+ * Sets NLS ratio, maximum number of bytes per one character of the
+ * current NLS chracter set. It is initialized in 'oci8/encoding-init.rb'
+ * when oci8 is required. You have no need to set it explicitly.
+ */
+static VALUE oci8_set_nls_ratio(VALUE klass, VALUE val)
+{
+    int v = NUM2INT(val);
+    if (v <= 0) {
+        rb_raise(rb_eRangeError, "expected a positive integer but %d", v);
+    }
+    oci8_nls_ratio = v;
+    return val;
+}
+
 #ifdef HAVE_TYPE_RB_ENCODING
 
 /*
  * call-seq:
- *   OCI8.encoding -> enc
+ *    OCI8.encoding -> enc
  *
- * (new in ruby 1.9)
+ * <b>(new in 2.0.0 and ruby 1.9)</b>
  *
- * Returns Oracle client encoding.
+ * Returns the Oracle client encoding.
  *
- * String values passed to Oracle, such as SQL statements,
- * bind values etc., are converted from their encoding to
- * the Oracle client encoding.
+ * When string data, such as SQL statements and bind variables,
+ * are passed to Oracle, they are converted to +OCI8.encoding+
+ * in advance.
  *
- * If <code>Encoding.default_internal</code> is nil,
- * string values got from Oracle are tagged by
- * <code>OCI8.encoding</code>. If not nil, they are
- * converted from <code>OCI8.encoding</code> to
- * <code>Encoding.default_internal</code> by default.
+ *   # When OCI8.encoding is ISO-8859-1,
+ *   conn.exec('insert into country_code values(:1, :2, :3)',
+ *             'AT', 'Austria', "\u00d6sterreichs")
+ *   # "\u00d6sterreichs" is 'Österreichs' encoded by UTF-8.
+ *   # It is converted to ISO-8859-1 before it is passed to
+ *   # the Oracle C API.
  *
- * If it is 'ASCII-8BIT', no encoding conversions are done.
+ *
+ * When string data, such as fetched values and bind variable
+ * for output, are retrieved from Oracle, they are encoded
+ * by +OCI8.encoding+ if +Encoding.default_internal+ is +nil+.
+ * If it isn't +nil+, they are converted from +OCI8.encoding+
+ * to +Encoding.default_internal+.
+ *
+ * If +OCI8.encoding+ is ASCII-8BIT, no encoding conversions
+ * are done.
  */
 static VALUE oci8_get_encoding(VALUE klass)
 {
@@ -163,9 +258,11 @@
  * call-seq:
  *   OCI8.encoding = enc or nil
  *
- * (new in ruby 1.9)
+ * <b>(new in 2.0.0 and ruby 1.9)</b>
  *
- * Sets Oracle client encoding.
+ * Sets Oracle client encoding. You must not use this method.
+ * You should set the environment variable NLS_LANG properly to
+ * change +OCI8.encoding+.
  */
 static VALUE oci8_set_encoding(VALUE klass, VALUE encoding)
 {
@@ -180,6 +277,10 @@
 
 void Init_oci8_encoding(VALUE cOCI8)
 {
+#if 0
+    oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject);
+    cOCI8 = rb_define_class("OCI8", oci8_cOCIHandle);
+#endif
     csid2name = rb_hash_new();
     rb_global_variable(&csid2name);
 
@@ -189,6 +290,8 @@
 
     rb_define_method(cOCI8, "charset_name2id", oci8_charset_name2id, 1);
     rb_define_method(cOCI8, "charset_id2name", oci8_charset_id2name, 1);
+    rb_define_singleton_method(cOCI8, "nls_ratio", oci8_get_nls_ratio, 0);
+    rb_define_singleton_method(cOCI8, "nls_ratio=", oci8_set_nls_ratio, 1);
 #ifdef HAVE_TYPE_RB_ENCODING
     rb_define_singleton_method(cOCI8, "encoding", oci8_get_encoding, 0);
     rb_define_singleton_method(cOCI8, "encoding=", oci8_set_encoding, 1);

Modified: trunk/ruby-oci8/lib/oci8/encoding-init.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/encoding-init.rb	2010-04-23 13:32:46 UTC (rev 388)
+++ trunk/ruby-oci8/lib/oci8/encoding-init.rb	2010-04-27 12:50:42 UTC (rev 389)
@@ -2,10 +2,11 @@
 # setup default OCI encoding from NLS_LANG.
 #
 
-# try to get NLS_LANG.
+# get the environment variable NLS_LANG.
 nls_lang = ENV['NLS_LANG']
 
-if defined? OCI8::Win32Util
+# if NLS_LANG is not set, get it from the Windows registry.
+if nls_lang.nil? and defined? OCI8::Win32Util
   dll_path = OCI8::Win32Util.dll_path.upcase
   if dll_path =~ %r{\\BIN\\OCI.DLL}
     oracle_home = $`
@@ -18,23 +19,48 @@
   end
 end
 
+# extract the charset name.
 if nls_lang
-  # Extract character set name from NLS_LANG.
   if nls_lang =~ /\.([[:alnum:]]+)$/
     charset = $1.upcase
   else
     raise "Invalid NLS_LANG format: #{nls_lang}"
   end
+else
+  warn "Warning: NLS_LANG is not set. fallback to US7ASCII."
+  charset = 'US7ASCII'
+end
 
-  # Convert the Oracle character set name to Ruby encoding name by
-  # querying the yaml data.
-  require 'yaml'
-  enc = YAML::load_file(File.dirname(__FILE__) + '/encoding.yml')[charset]
-  if enc.nil?
-    raise "Ruby encoding name is not found in encoding.yml for NLS_LANG #{nls_lang}."
-  end
+# NLS ratio, maximum number of bytes per one chracter
+case charset
+when 'UTF8'
+  OCI8.nls_ratio = 3
+when 'AL16UTF16'
+  OCI8.nls_ratio = 4
+when /^\w+(\d+)/
+  # convert maximum number of bits per one chracter to NLS ratio.
+  #   charset name  max bits  max bytes
+  #   ------------  --------  ---------
+  #   US7ASCII          7         1
+  #   WE8ISO8859P1      8         1
+  #   JA16SJIS         16         2
+  #   AL32UTF8         32         4
+  #   ...
+  OCI8.nls_ratio = (($1.to_i + 7) >> 3)
 else
-  warn "Warning: NLS_LANG is not set. fallback to US-ASCII."
-  enc = 'US-ASCII'
+  raise "Unknown NLS character set name format: #{charset}"
 end
-OCI8.encoding = enc
+
+# Ruby encoding name for ruby 1.9.
+if OCI8.respond_to? :encoding
+  if defined? DEFAULT_OCI8_ENCODING
+    enc = DEFAULT_OCI8_ENCODING
+  else
+    require 'yaml'
+    enc = YAML::load_file(File.dirname(__FILE__) + '/encoding.yml')[charset]
+    if enc.nil?
+      raise "Ruby encoding name is not found in encoding.yml for NLS_LANG #{nls_lang}."
+    end
+  end
+  OCI8.encoding = enc
+end

Modified: trunk/ruby-oci8/lib/oci8.rb.in
===================================================================
--- trunk/ruby-oci8/lib/oci8.rb.in	2010-04-23 13:32:46 UTC (rev 388)
+++ trunk/ruby-oci8/lib/oci8.rb.in	2010-04-27 12:50:42 UTC (rev 389)
@@ -27,14 +27,7 @@
   raise 'unsupported ruby version: ' + RUBY_VERSION
 end
 
-if OCI8.respond_to? :encoding
-  if defined? DEFAULT_OCI8_ENCODING
-    OCI8.encoding = DEFAULT_OCI8_ENCODING
-  else
-    load 'oci8/encoding-init.rb'
-  end
-end
-
+require 'oci8/encoding-init.rb'
 require 'oci8/oracle_version.rb'
 
 class OCI8




More information about the ruby-oci8-commit mailing list