[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