Date: 2012-12-17 10:27
Sender: Per Grottum
Since there has been no development in this matter, I have
made a temporary hack to solve the problem.
When ruby-oci8 is loaded the procedure Init_oci8lib() in
oci8lib.c is called. It in turn calls oci8_make_envhp in
env.c which sets up the environment. Originally
oci8_make_envhp employed the Oracle OCI-routine
OCIEnvCreate to accomplish this. Oracle has another version
of the same routine, OCIEnvNlsCreate which makes it
possible to set the equivalent of NLS_LANG and NLS_NCHAR
for the current application. The problem is how to pass the
desired parameters to this routine. I have found no way to
pass a parameter in the call to Init_oci8lib(), so I ended
up defining a global parameter as the first line in the
actual Rails-application's config/environment.rb, e.g.:
$my_nls_lang = 'WE8ISO8859P1'
This variable can be picked up and processed in env.c by
e.g. the following modified code:
OCIEnv *oci8_make_envhp(void)
{
sword rv;
VALUE NLSL;
ub2 nlsid;
OCIEnv *envhp;
NLSL = rb_gv_get("my_nls_lang");
if (TYPE(NLSL) == T_STRING) {
rv = OCIEnvCreate(&envhp, oci8_env_mode, NULL,
NULL, NULL, NULL, 0, NULL);
nlsid = OCINlsCharSetNameToId(envhp, StringValuePtr
(NLSL));
OCIHandleFree(envhp, OCI_HTYPE_ENV);
}
else {
nlsid = 0;
}
rv = OCIEnvNlsCreate(&oci8_global_envhp, oci8_env_mode,
NULL, NULL, NULL, NULL, 0, NULL, nlsid, nlsid);
if (rv != OCI_SUCCESS) {
oci8_raise_init_error();
}
return oci8_global_envhp;
}
I have not experimented with different codes for NLS_LANG
and NLS_NCHAR, but only used the same for both. The default
0 means that the system NLS_LANG and NLS_NCHAR will be used.
I have tested this in a production of Rails running under
Apache/Passenger with two Rails-applications using
different databases and NLS_LANG, and it works.
Per
|