Skip to content

Commit

Permalink
MySQL and Oracle actually throw an exception when asked the parameter…
Browse files Browse the repository at this point in the history
… type from the metadata, and not the metadata from the statement. Catch the SQLException in the DefaultBinderConfiguration to return the default binder.
  • Loading branch information
jnizet committed May 21, 2014
1 parent 0fc84d2 commit aab52c2
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ public interface BinderConfiguration {

/**
* Returns the appropriate {@link Binder} for the given parameter, based on the given metadata.
* @param metadata the metadata allowing to decide which Binder to return. <code>null</code> if the database
* doesn't support parameter metadata, or if the Insert has been configured to not use metadata.
* @param metadata the metadata allowing to decide which Binder to return. <code>null</code> if the Insert has been
* configured to not use metadata, or if the JDBC driver returned null metadata, or the JDBC driver threw a
* SQLException when asked for the metadata
* @param param the param for which a binder is requested
* @return the binder for the given param and its metadata
* @throws SQLException if a SQLException occurs while using the metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected DefaultBinderConfiguration() {
* Uses the parameter type of the given parameter and returns the following Binders depending on the type
* got from the metadata.
* <ul>
* <li>null metadata (i.e. metadata not supported): {@link Binders#defaultBinder()}</li>
* <li>null metadata (i.e. metadata not used or not returned): {@link Binders#defaultBinder()}</li>
* <li>VARCHAR, CHAR, LONGNVARCHAR, LONGVARCHAR, NCHAR, NVARCHAR :
* {@link Binders#stringBinder()}</li>
* <li>DATE : {@link Binders#dateBinder()}</li>
Expand All @@ -61,44 +61,53 @@ protected DefaultBinderConfiguration() {
* <li>INTEGER, BIGINT, SMALLINT, TINYINT : {@link Binders#integerBinder()}</li>
* <li>DECIMAL, DOUBLE, FLOAT, NUMERIC, REAL : {@link Binders#decimalBinder()}</li>
* <li>other : {@link Binders#defaultBinder()}</li>
* </ul>
*
* If the parameter type can't be obtained from the metadata, the default binder is returned.
*/
@Override
public Binder getBinder(ParameterMetaData metadata, int param) throws SQLException {
if (metadata == null) {
return Binders.defaultBinder();
}
int sqlType = metadata.getParameterType(param);
if (sqlType == Types.DATE) {
return Binders.dateBinder();
}
if (sqlType == Types.TIME) {
return Binders.timeBinder();
}
if (sqlType == Types.TIMESTAMP) {
return Binders.timestampBinder();
}
if (sqlType == Types.BIGINT
|| sqlType == Types.INTEGER
|| sqlType == Types.SMALLINT
|| sqlType == Types.TINYINT) {
return Binders.integerBinder();
}
if (sqlType == Types.DECIMAL
|| sqlType == Types.DOUBLE
|| sqlType == Types.FLOAT
|| sqlType == Types.NUMERIC
|| sqlType == Types.REAL) {
return Binders.decimalBinder();
try {
int sqlType = metadata.getParameterType(param);
if (sqlType == Types.DATE) {
return Binders.dateBinder();
}
if (sqlType == Types.TIME) {
return Binders.timeBinder();
}
if (sqlType == Types.TIMESTAMP) {
return Binders.timestampBinder();
}
if (sqlType == Types.BIGINT
|| sqlType == Types.INTEGER
|| sqlType == Types.SMALLINT
|| sqlType == Types.TINYINT) {
return Binders.integerBinder();
}
if (sqlType == Types.DECIMAL
|| sqlType == Types.DOUBLE
|| sqlType == Types.FLOAT
|| sqlType == Types.NUMERIC
|| sqlType == Types.REAL) {
return Binders.decimalBinder();
}
if (sqlType == Types.VARCHAR
|| sqlType == Types.CHAR
|| sqlType == Types.LONGNVARCHAR
|| sqlType == Types.LONGVARCHAR
|| sqlType == Types.NCHAR
|| sqlType == Types.NVARCHAR) {
return Binders.stringBinder();
}
return Binders.defaultBinder();
}
if (sqlType == Types.VARCHAR
|| sqlType == Types.CHAR
|| sqlType == Types.LONGNVARCHAR
|| sqlType == Types.LONGVARCHAR
|| sqlType == Types.NCHAR
|| sqlType == Types.NVARCHAR) {
return Binders.stringBinder();
catch (SQLException e) {
// the database can't return types from parameters. Fall back to default binder.
return Binders.defaultBinder();
}
return Binders.defaultBinder();
}

@Override
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/com/ninja_squad/dbsetup/operation/Insert.java
Original file line number Diff line number Diff line change
Expand Up @@ -529,9 +529,8 @@ public Builder withGeneratedValue(@Nonnull String column, @Nonnull ValueGenerato
* a Binder.<br/>
* Before version 1.3.0, a SQLException was thrown if the database doesn't support parameter metadata and
* <code>useMetadata(false)</code> wasn't called. Since version 1.3.0, if <code>useMetadata</code> is true
* (the default) but the database doesn't support metadata, then the BinderConfiguration is asked for a binder
* with a null metadata. And the default binder configuration returns the default binder in this case. Using
* this method is thus normally unnecessary as of 1.3.0.
* (the default) but the database doesn't support metadata, then the default binder configuration returns the
* default binder. Using this method is thus normally unnecessary as of 1.3.0.
* @return this Builder instance, for chaining.
* @throws IllegalStateException if the Insert has already been built.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@

import org.junit.Test;

import java.sql.ParameterMetaData;
import java.sql.SQLException;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

public class DefaultBinderConfigurationTest {

@Test
public void shouldReturnDefaultBinderIfNoParameterMetadata() throws SQLException {
assertEquals(Binders.defaultBinder(), DefaultBinderConfiguration.INSTANCE.getBinder(null, 1));
}

@Test
public void shouldReturnDefaultBinderIfParameterTypeCantBeObtained() throws SQLException {
ParameterMetaData mockMetaData = mock(ParameterMetaData.class);
when(mockMetaData.getParameterType(1)).thenThrow(new SQLException());
assertEquals(Binders.defaultBinder(), DefaultBinderConfiguration.INSTANCE.getBinder(mockMetaData, 1));
}
}

0 comments on commit aab52c2

Please sign in to comment.