Thread: \0 and IllegalArgumentException
Hi, I'm using postgres 7.4 with the latest JDBC driver, and had an insert statement to insert data as follows try { ... ps.setCharacterStream(1, myStream, myStreamLength); ps.executeUpdate(); } catch (SQLException e) { ... } With this I was hoping to catch invalid inserts (with an SQLException), however I'm getting: java.lang.IllegalArgumentException: \0 not allowed which is an UNCHECKED runtime exception, that in no way indicates (programatically) that the insert failed. I think very few people would expect a runtime exception on what essentially amounts to a failed insert. Futhermore, it is very hard to discover the SOURCE of the runtime exception (lots of things might throw an IllegalArgumentException) and to programatically do something sensible with this. Thus in my opinion, an SQLException would be better here for at least three reasons: 1) It's a checked exception (I'm counting on it happening)... 2) I will know where it came from (postgres)... 3) Now I'm totally unsure of what other kind of runtime exceptions the postgres driver may throw for some reason or other, nor do I know how to handle a runtime exception properly if one does occur... I want runtime exceptions basically only on PROGRAMMATIC errors, errors that I as the developer made and can fix. User data CAN in fact contain \0, and the fact that postgres cannot handle this is an issue of the backend, which (in the case of postgres, but certainly not in the case of all databases) does not consider these kind of strings as valid. As the developer (oblivious to what kind of backend database is used) I cannot take any programmatic steps to avoid this problem (other than string scanning caught IllegalArgumentExceptions for this specific problem). In conclusion, I REALLY think that this is the wrong exception to be thrown. Greetings, Sebastiaan van Erk
Sebastiaan van Erk wrote: > I'm using postgres 7.4 with the latest JDBC driver, [...] > java.lang.IllegalArgumentException: \0 not allowed Please check your driver version. The latest development driver throws SQLException in this case: >> throw new PSQLException(GT.tr("Zero bytes may not occur in string parameters."), PSQLState.INVALID_PARAMETER_VALUE); -O
On Friday 29 October 2004 05:55, Sebastiaan van Erk wrote: [...] > however I'm getting: > > java.lang.IllegalArgumentException: \0 not allowed [...] > 2) I will know where it came from (postgres)... [...] > User data CAN in fact contain \0, and the fact that postgres cannot > handle this is an issue of the backend Funny you should mention this. Just yesterday a coworker of mine was bitching about the PostgreSQL JDBC driver's refusal to allow \0 in strings. As he pointed out, it's not totally clear if the blame rests entirely with the backend. Consider these examples: | test=> create table dropme (str varchar(100)); | CREATE TABLE | test=> insert into dropme values ('Hello' || chr(0) || 'world'); | INSERT 160829 1 | test=> select str, length(str) as length from dropme; | str | length | -------+-------- | Hello | 5 | (1 row) | | test=> select str, length(str) as length from dropme where str like '%world'; | str | length | -------+-------- | Hello | 5 | (1 row) | | test=> select str, length(str) as length from dropme where str like '%Welt'; | str | length | -----+-------- | (0 rows) This is with a fairly old version of PosgreSQL: | test=> select substring(version(), 1, 20) as version; | version | ---------------------- | PostgreSQL 7.3.4-RH | (1 row) Not sure how the latest version behaves. I think you do have a point though when you say that \0 should be allowed (and handled properly). Vadim
Vadim Nasardinov <vadimn@redhat.com> writes: > I think you do have a point though when you say that \0 should be > allowed (and handled properly). Don't hold your breath. Moving away from the zero-terminated-string approach would require protocol changes (IIRC, the v3 protocol still depends on that in places), a massive rewrite effort to change every datatype's I/O functions, plus writing our own locale library because we couldn't use strcoll() anymore. And that's just the impacts I can think of before having had any coffee ;-) While the private locale library might eventually happen anyway, the other two things are still daunting, mainly because they break a ton of user code not only the backend. Basically, the bang for the buck doesn't seem to be there... regards, tom lane
I just tested pg74.215.jdbc3.jar which I just downloaded from the jdbc.postgresql.org site, and it still gives me the IllegalArgumentException. Happy to know it has been fixed in the latest development version. Greetings, Sebastiaan van Erk Oliver Jowett wrote: > Sebastiaan van Erk wrote: > > >I'm using postgres 7.4 with the latest JDBC driver, [...] > > >java.lang.IllegalArgumentException: \0 not allowed > > Please check your driver version. The latest development driver throws > SQLException in this case: > > >>throw new PSQLException(GT.tr("Zero bytes may not occur in string > >>parameters."), PSQLState.INVALID_PARAMETER_VALUE); > > -O > > ---------------------------(end of broadcast)--------------------------- > TIP 2: you can get off all lists at once with the unregister command > (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
On Fri, 2004-10-29 at 10:24 -0400, Vadim Nasardinov wrote: > | test=> select str, length(str) as length from dropme; > | str | length > | -------+-------- > | Hello | 5 > | (1 row) > | > | test=> select str, length(str) as length from dropme where str like '%world'; > | str | length > | -------+-------- > | Hello | 5 > | (1 row) > | > | test=> select str, length(str) as length from dropme where str like '%Welt'; > | str | length > | -----+-------- > | (0 rows) > Not sure how the latest version behaves. I get slightly different results from 7.4.5. The string is still truncated, but the length is correct: jorris=# select str, length(str) as length from dropme; str | length -------+-------- Hello | 11 (1 row) jorris=# select str, length(str) as length from dropme where str like '% world'; str | length -------+-------- Hello | 11 (1 row) jorris=# select substring(version(), 1, 20) as version; version ---------------------- PostgreSQL 7.4.5 on (1 row)