On Mon, Sep 03, 2007 at 07:20:42PM +0200, Peter J. Holzer wrote: > On 2007-09-03 13:03:37 +0100, Tim Bunce wrote: > > Oh the joys of Oracle character set support. > > > > See the dbd_rebind_ph() code in dbdimp.c. Especially from the line > > "csform = phs->csform;" onwards. > > > > You can explicitly set the csform and csid using bind_param(..., { ... }) > > > > Have fun! > > I had :-). You gave me a push into the right direction, and I think I > found the problem: > > 1375 csform = phs->csform; > 1376 > 1377 if (!csform && SvUTF8(phs->sv)) { > 1378 /* try to default csform to avoid translation through > non-unicode */ > 1379 if (CSFORM_IMPLIES_UTF8(SQLCS_NCHAR)) /* prefer > NCHAR */ > 1380 csform = SQLCS_NCHAR; > 1381 else if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT)) > 1382 csform = SQLCS_IMPLICIT; > 1383 /* else leave csform == 0 */ > 1384 if (trace_level) > 1385 PerlIO_printf(DBILOGFP, " rebinding %s with UTF8 > value %s", phs->name, > 1386 (csform == SQLCS_NCHAR) ? "so setting > csform=SQLCS_IMPLICIT" : > 1387 (csform == SQLCS_IMPLICIT) ? "so setting > csform=SQLCS_NCHAR" : > 1388 "but neither CHAR nor NCHAR are unicode\n"); > 1389 } > > The first thing to notice is that the trace message is backwards: It > prints setting csform=SQLCS_IMPLICIT if the csform is set to SQLCS_NCHAR > and vice versa. So that explains why I didn't notice anything strange in > the trace output. While it claimed to set csform=SQLCS_IMPLICIT, it was > actually setting it to SQLCS_NCHAR, and I guess that was what prevented > the use of the index on the varchar2 column. Sure enough, if I > explicitely set ora_csform to 1, it's fast. It is also fast, if I set > NLS_NCHAR to US7ASCII, so that it isn't used. > > Maybe the tests in line 1379 and 1381 should be reversed so that > SQLCS_IMPLICIT is preferred over SQLCS_NCHAR?
Sounds very plausible. > I guess there was some good reason to prefer SQLCS_NCHAR, but it seems > to me that SQLCS_IMPLICIT is usually what you would want It was probably just the way the code evolved. > (but then I'm probably biased from my absolute failure to use nvarchar > or nclob columns with Oracle 8.0 from Java or Perl many moons ago). > > > But do please write up what you find as a patch the the Oracle docs. > > It's entirely possible that the code is doing the wrong thing. > > Like this? That's great, but why stop there? Now you seem to have identified the problem, how about patching the code instead ;-) Tim. > Index: Oracle.pm > =================================================================== > --- Oracle.pm (revision 9909) > +++ Oracle.pm (working copy) > @@ -1462,7 +1462,14 @@ > > Specify the OCI_ATTR_CHARSET_FORM for the bind value. Valid values > are SQLCS_IMPLICIT (1) and SQLCS_NCHAR (2). Both those constants can > -be imported from the DBD::Oracle module. Rarely needed. > +be imported from the DBD::Oracle module. > +This should be rarely needed, but at least some versions of Oracle > +(e.g., 10.2) don't use an index if this is set wrong, which can happen > +if both the character set and the national character set are UTF-8 and > +the placeholder value has the utf8 flag set. In this case you can either > +choose ora_csform to match your column or (if you don't have any NCHAR, > +NVARCHAR2 or NCLOB columns) you can set NLS_NCHAR to US7ASCII to prevent > +its use. > > =item ora_csid > > > hp > > -- > _ | Peter J. Holzer | If I wanted to be "academically correct", > |_|_) | Sysadmin WSR | I'd be programming in Java. > | | | [EMAIL PROTECTED] | I don't, and I'm not. > __/ | http://www.hjp.at/ | -- Jesse Erlbaum on dbi-users