[rt-devel] Who would have guessed that VARCHAR2 and CLOB are so different (Was: SearchBuilder/Oracle inconsistencies)

Brook Schofield b.schofield at griffith.edu.au
Wed May 14 01:48:19 EDT 2003


Brook Schofield wrote on 14/05/2003 12:38:39 AM:
> 
> Well - I now know why the [crit] lines appear in the Oracle 
> initialize-database output. This is because the SQL SELECT to load 
> columns from the Groups table doesn't work.
> 
> Oracle SQL:
> ===========
> SimpleQuery: SELECT  * FROM Groups WHERE lower(Domain) = ? AND 
> lower(Name) = ? AND lower(Type) = ? AND lower(Instance) = ?^M
>          systeminternal^M
>          ^M
>          everyone^M
>          ^M

I modified the Oracle SQL query to force either = '' or IS NULL - but I 
still ran into strange problems. The issue appears to be with the 
difference between VARCHAR2 and CLOB types in Oracle 9i. From the Oracle 
9i manual:

IS NULL Semantic Discrepancy 
In the SQL 92 standard, a character string of length zero is distinct from 
a null string. 
For an initialized LOB of length 0, you should expect `IS NULL' to return 
zero (FALSE), since it is the correct and standard compliant behavior. In 
contrast, a VARCHAR2 of length 0 returns TRUE on 'IS NULL`. 
In addition, for the LENGTH() function:
If the input is a character string of zero length, LENGTH() returns NULL.
For a CLOB of zero length, an EMPTY_CLOB(), zero is returned by LENGTH and 
DBMS_LOB.GETLENGTH() in SQL and PL/SQL.
This can be misleading. Note this semantic discrepancy.
This last line is actually from the Oracle 9i manual - not my own addition 
;-)
So I'll be left with changing the query from:
SimpleQuery: SELECT  * FROM Groups WHERE lower(Domain) = ? AND lower(Name) 
= ? AND lower(Type) = ? AND lower(Instance) = ?^M
          systeminternal^M
          ^M
          everyone^M
          ^M
to:

SELECT  * FROM Groups WHERE lower(Domain) = ? AND (Name = '' OR Name IS 
NULL) AND lower(Type) = ? AND (Instance = '' OR Instance IS NULL)
          systeminternal^M
          everyone^M

to satisfy the issue with VARCHAR2 and CLOB. My DBAs tell me that Oracle 
recommends the use of VARCHAR2 over VARCHAR because the behaviour of 
VARCHAR may change over time - hopefully they'll change VARCHAR to have 
the same behaviour as their CLOB type in some future edition - which will 
allow SearchBuilder to be simplified.

Now the only issue is whether the change should be within LoadByCols or 
whether it should be abstracted out to an Oracle specific change?

> sub LoadByCols  {
>      my $self = shift;
>      my %hash  = (@_);
>      my (@bind, @phrases);
>      foreach my $key (keys %hash) {
-          if (defined $hash{$key}) {
+          if (defined $hash{$key} && $hash{$key} ne '') {
>                  push @phrases, "$key = ?";
>                  push @bind, $hash{$key};
>          }
>          else {
-                  push @phrases, "$key is null";
+                  push @phrases, "($key IS NULL or $key = '')";
>          }
>      }
> 
>      my $QueryString = "SELECT  * FROM ".$self->Table." WHERE ".
>      join(' AND ', @phrases) ;
>      return ($self->_LoadFromSQL($QueryString, @bind));
> }

NB:- The change for adding/removing the lower() tag should be made in 
SearchBuilder.pm.

I know I always say this, but "Oracle support for RT is one step closer" 
;-)

-Brook 



More information about the Rt-devel mailing list