Oracle knows nothing about Java
Posted by Mike Haller
on Saturday, March 24. 2007
at 14:53
Let's pretend Oracle makes some good database stuff. What they apparently do really bad: Java drivers. The Oracle Thin JDBC Drivers are so bad, that there is a whole bunch of vendors implementing their own drivers. Commercial drivers.(We are not talking about some opensource guys trying to circumvent a license agreement by implementing a free version, so they can put drivers into a free tool. No we're talking about high-quality and sometimes high-priced replacement products.)
I didn't believe what I was hearing from friends, but this week, i trapped into it on my own. Let's suppose you've got some code which inserts a large numeric value like 12 Million Euro into your companies database...
BigDecimal value = BigDecimal.valueOf(12300000.0); // value.toString is "1.23E+7" oracleDB.insert(value);
As you can see, BigDecimal uses the exponent notation to represent the value internally in this case. The Oracle driver uses BigDecimal.toString() to get exactly this representation on Java 1.5.
The driver also checks for the existence of "E" in the value toString(). After decompiling the current thin driver 10.2.0.3, I found that in oracle.jdbc.driver.BigDecimalBinder:
public void testOracleDriver() throws Exception {
// Input Variables
int eIndex = 0;
String sval = "1.23E+7";
// Oracle code from BigDecimalBinder
if((eIndex = sval.indexOf("E")) != -
{
String s = "";
int zeros = 0;
BigDecimal val2 = null;
String eValue = sval.substring(eIndex + 1);
String intVal = sval.substring(0, eIndex);
val2 = new BigDecimal(intVal);
boolean isNegative = eValue.charAt(0) == '-';
eValue = eValue.substring(1);
zeros = Integer.parseInt(eValue);
int dotIndex = val2.toString().indexOf(".");
if(dotIndex != -1)
{
double pow = Math.pow(10D, dotIndex);
val2 = val2.multiply(new BigDecimal(pow));
zeros -= dotIndex;
} else
if(isNegative)
zeros--;
String sval2 = val2.toString();
sval2 = sval2.substring(0, sval2.length()
- (dotIndex + 1));
s = isNegative ? "0." : sval2;
for(int i = 0; i < zeros; i++)
s = s + "0";
if(isNegative)
s = s + sval2;
sval = s;
}
// Oracle code from BigDecimalBinder
// Succeeds incorrectly:
assertEquals("12.000000",sval);
// Fails
assertEquals("12300000",sval);
}
In the end, you end up with the value
12 in your database -- you just lost 12299988 bucks without any notice - no error message, no exception, nothing.What I do like most: Even so, their driver 10.2.0.3 is Java5 certified! Yes, it is officially certified. I wonder who certified this piece of crap and whether they got further than the usual Hello-World example.
In their support forum, there seem to be announces to a fixed version 10.2.0.4, which won't be released publicly for the next few months. Is there any reason to hold back a driver update that long which has a really serious flaw?
Thanks Oracle!
John had the same problem and asks for people who suffer from the same issue. Let him know. There is a discussion on the Oracle Forum where the lead developer replies.
