[ 
https://issues.apache.org/jira/browse/DBCP-157?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13720903#comment-13720903
 ] 

Mark Thomas commented on DBCP-157:
----------------------------------

This wouldn't be too hard to do for DelegatingResultSet as all construction is 
through a couple of static methods. Those could be moved to factory and that 
factory could itself be configurable to allow custom factories that returned 
custom implementations (that I think would have to extend the existing 
implementation - switching to interfaces would be a step too far).

DelegatingPreparedStatement is a little more work (there are no static methods 
used for construction) but that could follow a similar pattern.

That immediately leads to thinking that instances of all the Delegating* 
classes should be created this way.

This is now looking to be a fairly invasive change for a problem that a) is 
caused by a 3rd party not following the relevant specs (and that always makes 
me less inclined to make a change) and b) doesn't appear to occur that often 
based on the lack of comments on this issue that has been open rather a while.

Overall, I am leaning towards resolving this as WONTFIX but keeping the idea in 
mind in case other use cases emerge that could benefit from the ability to use 
custom Delegating* classes.

I won't resolve this issue just yet to give other folks a chance to comment.
                
> [dbcp] allow to register a wrapper extending DelegatingPreparedStatement to 
> enhance setString for compatibility ("schema not null" issue)
> -----------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: DBCP-157
>                 URL: https://issues.apache.org/jira/browse/DBCP-157
>             Project: Commons Dbcp
>          Issue Type: Improvement
>         Environment: Operating System: All
> Platform: Other
>            Reporter: Ralf Hauser
>            Priority: Minor
>             Fix For: 2.0
>
>
> It would be great to be able to register a wrapper enhancing
> org.apache.commons.dbcp.DelegatingPreparedStatement. One purpose of this could
> be to enhance its setString() method to cope with portability issues between
> databases and their jdbc drivers: 
> - mysql considers "" as a non-null string
> - oracle complains that an attempt to insert a null string was made with "".
> A little test case to illustrate will be appended at the end of this 
> description.
> So, to create portability, dbcp users have the advantage that their 
> applications
> don't use the jdbc.jar's setString and getString methods directly anyway.
> Therefore, the proposed wrapper's setString() method should
> 1) detect whether ojdbc_14.jar or alike is used 
> 2) if getting "", change this to a never used string such as
> "eCoUnTeReDsTrInGoFlEnGtHzErO"
> Similarly, the DelegatingResultSet's getString() would have to be wrapped
> accordingly, therefore
> 3) the DelegatingResultSet's wrapper's getString() would do the same in 
> reverse.
> Anyway, even if either oracle or mysql breaks the standard, it is unlikely to
> have them quickly converge to the same behaviour, thus such an enhancement 
> could
> allow programmers to elegantly fix this and gain easy portability not 
> requiring
> them make their applications/db schemes aware of such idiosyncrasies.
> -------------
> In the below code, the mysql jdbc complains at the third attempt to insert 
> while
> recent oracle jdbc already refuses to execute variant 2:
>                 stmt = this.conn.createStatement(
>                         java.sql.ResultSet.TYPE_FORWARD_ONLY,
>                         java.sql.ResultSet.CONCUR_UPDATABLE);
>                 stmt.executeUpdate("DROP TABLE IF EXISTS schmNotNull");
>                 stmt
>                         .executeUpdate("CREATE TABLE schmNotNull ("
>                                 + "msg_id         INT NOT NULL AUTO_INCREMENT
> UNIQUE, "
>                                 + "subject        CHAR(255) NOT NULL, PRIMARY
> KEY (msg_id))");
>                 PreparedStatement insSenderStmt = null;
>                 
>                 //attempt 1
>                 insSenderStmt = this.conn
>                         .prepareStatement("INSERT INTO schmNotNull (  
> subject) "
>                                 + " VALUES (?);");
>                 insSenderStmt.setString(1, "testSubj"); // subject
>                 log.debug("insSenderStmt: "
>                         + ((DelegatingPreparedStatement) insSenderStmt)
>                                 .getDelegate().toString());
>                 int retVal = insSenderStmt.executeUpdate();
>                 log.debug("retVal1: " + retVal);
>                 
>                 //attempt 2
>                 insSenderStmt.setString(1, "");
>                 log.debug("insSenderStmt: "
>                         + ((DelegatingPreparedStatement) insSenderStmt)
>                                 .getDelegate().toString());
>                 retVal = insSenderStmt.executeUpdate();
>                 log.debug("retVal2: " + retVal);
>                 
>                 //attempt 3
>                 insSenderStmt.setString(1, null);
>                 log.debug("insSenderStmt: "
>                         + ((DelegatingPreparedStatement) insSenderStmt)
>                                 .getDelegate().toString());
>                 retVal = insSenderStmt.executeUpdate();
>                 log.debug("retVal3: " + retVal);
> so, the output of mysql looks like:
> <<DEBUG [main] (DBTest.java:590) - insSenderStmt:
> com.mysql.jdbc.PreparedStatement@82d603: INSERT INTO schmNotNull (  subject) 
> VALUES ('testSubj');
> DEBUG [main] (DBTest.java:594) - retVal1: 1
> DEBUG [main] (DBTest.java:596) - insSenderStmt:
> com.mysql.jdbc.PreparedStatement@82d603: INSERT INTO schmNotNull (  subject) 
> VALUES ('');
> DEBUG [main] (DBTest.java:600) - retVal2: 1
> DEBUG [main] (DBTest.java:602) - insSenderStmt:
> com.mysql.jdbc.PreparedStatement@82d603: INSERT INTO schmNotNull (  subject) 
> VALUES (null);
> java.sql.SQLException: Column 'subject' cannot be null
>       at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2847)
>       at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1531)
>       at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1622)
>       at com.mysql.jdbc.Connection.execSQL(Connection.java:2376)
>       at com.mysql.jdbc.Connection.execSQL(Connection.java:2297)
>       at 
> com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1860)
>       at 
> com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1957)
>       at 
> com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1880)
>       at 
> com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1741)
>       at
> org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:101)
>       at 
> com.privasphere.privalope.test.DBTest.testSchemaNotNull(DBTest.java:605)
> ...>>

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to