Navigation Menu

Skip to content

Commit

Permalink
0001334: The issue with jConnect JDBC, SQL Anywhere and decimal value.
Browse files Browse the repository at this point in the history
Fixing unit test errors on ASE and mapping issues on ASA.
  • Loading branch information
abrougher committed Aug 13, 2013
1 parent d2e091f commit 714b157
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 18 deletions.
Expand Up @@ -27,7 +27,7 @@
import org.apache.commons.lang.StringUtils;
import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform;
import org.jumpmind.db.platform.DatabaseNamesConstants;
import org.jumpmind.db.platform.ase.AseDdlBuilder;
import org.jumpmind.db.sql.JdbcUtils;
import org.jumpmind.db.sql.SqlTemplateSettings;

/*
Expand Down Expand Up @@ -68,7 +68,7 @@ protected AseDdlReader createDdlReader() {

@Override
protected AseJdbcSqlTemplate createSqlTemplate() {
return new AseJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo());
return new AseJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo(), JdbcUtils.getNativeJdbcExtractory());
}

public String getName() {
Expand Down
Expand Up @@ -20,19 +20,35 @@
*/
package org.jumpmind.db.platform.ase;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.jumpmind.db.platform.DatabaseInfo;
import org.jumpmind.db.platform.sqlanywhere.SqlAnywhereJdbcSqlTemplate;
import org.jumpmind.db.sql.ISqlTemplate;
import org.jumpmind.db.sql.ISqlTransaction;
import org.jumpmind.db.sql.JdbcSqlTemplate;
import org.jumpmind.db.sql.SqlTemplateSettings;
import org.jumpmind.db.sql.SymmetricLobHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.SqlTypeValue;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;

public class AseJdbcSqlTemplate extends JdbcSqlTemplate implements ISqlTemplate {

static final Logger log = LoggerFactory.getLogger(AseJdbcSqlTemplate.class);

public class AseJdbcSqlTemplate extends JdbcSqlTemplate {
private NativeJdbcExtractor nativeJdbcExtractor;

public AseJdbcSqlTemplate(DataSource dataSource, SqlTemplateSettings settings,
SymmetricLobHandler lobHandler, DatabaseInfo databaseInfo) {
SymmetricLobHandler lobHandler, DatabaseInfo databaseInfo, NativeJdbcExtractor nativeJdbcExtractor) {
super(dataSource, settings, lobHandler, databaseInfo);
this.nativeJdbcExtractor = nativeJdbcExtractor;
primaryKeyViolationCodes = new int[] {423,511,515,530,547,2601,2615,2714};
}

Expand All @@ -46,4 +62,52 @@ protected boolean allowsNullForIdentityColumn() {
return false;
}

protected void setDecimalValue(PreparedStatement ps, int i, Object arg, int argType)
throws SQLException {
PreparedStatement nativeStatement = getNativeStmt(ps);
if (nativeStatement != null
&& "com.sybase.jdbc4.jdbc.SybPreparedStatement".equals(nativeStatement.getClass()
.getName())) {
Class<?> clazz = nativeStatement.getClass();
Class<?>[] parameterTypes = new Class[] { int.class, BigDecimal.class, int.class,
int.class };
Method method = null;
try {
method = clazz.getMethod("setBigDecimal", parameterTypes);
BigDecimal value = (BigDecimal) arg;
Object[] params = new Object[] { new Integer(i), value,
new Integer(value.precision()), new Integer(value.scale()) };
method.invoke(nativeStatement, params);
} catch (Exception e) {
log.info("Can't find stmt.setBigDecimal(int,BigDecimal,int,int) method: "
+ e.getMessage());
return;
}
}
}

private PreparedStatement getNativeStmt(PreparedStatement ps) {
PreparedStatement stmt = ps;
try {
stmt = nativeJdbcExtractor.getNativePreparedStatement(ps);
} catch (SQLException ex) {
log.debug("Could not find a native preparedstatement using {}", nativeJdbcExtractor
.getClass().getName());
}
return stmt;
}

@Override
public void setValues(PreparedStatement ps, Object[] args)
throws SQLException {
super.setValues(ps, args);
if (args != null && args.length > 0) {
int[] argTypes = new int[args.length];
for (int i = 0; i < argTypes.length; i++) {
argTypes[i] = SqlTypeValue.TYPE_UNKNOWN;
}
setValues(ps, args, argTypes, getLobHandler().getDefaultHandler());
}
}

}
Expand Up @@ -27,6 +27,7 @@
import org.apache.commons.lang.StringUtils;
import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform;
import org.jumpmind.db.platform.DatabaseNamesConstants;
import org.jumpmind.db.sql.JdbcUtils;
import org.jumpmind.db.sql.SqlTemplateSettings;

/*
Expand Down Expand Up @@ -67,7 +68,7 @@ protected SqlAnywhereDdlReader createDdlReader() {

@Override
protected SqlAnywhereJdbcSqlTemplate createSqlTemplate() {
return new SqlAnywhereJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo());
return new SqlAnywhereJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo(), JdbcUtils.getNativeJdbcExtractory());
}

public String getName() {
Expand Down
Expand Up @@ -88,11 +88,6 @@ protected Column readColumn(DatabaseMetaDataWrapper metaData, Map<String,Object>
&& (column.getScale() == 0)) {
// Back-mapping to BIGINT
column.setMappedTypeCode(Types.BIGINT);
} else if (column.getMappedTypeCode() == Types.NUMERIC
|| column.getMappedTypeCode() == Types.DECIMAL) {
// ASA truncates everything to the right of the decimal point unless
// we map to DOUBLE.
column.setMappedTypeCode(Types.DOUBLE);
} else if (column.getDefaultValue() != null) {
if (column.getMappedTypeCode() == Types.TIMESTAMP) {
// Sybase maintains the default values for DATE/TIME jdbc types,
Expand Down
Expand Up @@ -20,19 +20,33 @@
*/
package org.jumpmind.db.platform.sqlanywhere;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.jumpmind.db.platform.DatabaseInfo;
import org.jumpmind.db.sql.ISqlTemplate;
import org.jumpmind.db.sql.JdbcSqlTemplate;
import org.jumpmind.db.sql.SqlTemplateSettings;
import org.jumpmind.db.sql.SymmetricLobHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.SqlTypeValue;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;

public class SqlAnywhereJdbcSqlTemplate extends JdbcSqlTemplate implements ISqlTemplate {

static final Logger log = LoggerFactory.getLogger(SqlAnywhereJdbcSqlTemplate.class);

private NativeJdbcExtractor nativeJdbcExtractor;

public SqlAnywhereJdbcSqlTemplate(DataSource dataSource, SqlTemplateSettings settings,
SymmetricLobHandler lobHandler, DatabaseInfo databaseInfo) {
SymmetricLobHandler lobHandler, DatabaseInfo databaseInfo, NativeJdbcExtractor nativeJdbcExtractor) {
super(dataSource, settings, lobHandler, databaseInfo);
this.nativeJdbcExtractor = nativeJdbcExtractor;
primaryKeyViolationCodes = new int[] {423,511,515,530,547,2601,2615,2714};
}

Expand All @@ -41,5 +55,54 @@ protected boolean allowsNullForIdentityColumn() {
return false;
}

protected void setDecimalValue(PreparedStatement ps, int i, Object arg, int argType)
throws SQLException {
PreparedStatement nativeStatement = getNativeStmt(ps);
if (nativeStatement != null
&& "com.sybase.jdbc4.jdbc.SybPreparedStatement".equals(nativeStatement.getClass()
.getName())) {
Class<?> clazz = nativeStatement.getClass();
Class<?>[] parameterTypes = new Class[] { int.class, BigDecimal.class, int.class,
int.class };
Method method = null;

try {
method = clazz.getMethod("setBigDecimal", parameterTypes);
BigDecimal value = (BigDecimal) arg;
Object[] params = new Object[] { new Integer(i), value,
new Integer(value.precision()),
new Integer(value.scale()) };
method.invoke(nativeStatement, params);
} catch (Exception e) {
log.info("Can't find stmt.setBigDecimal(int,BigDecimal,int,int) method: "
+ e.getMessage());
return;
}
}
}

private PreparedStatement getNativeStmt(PreparedStatement ps) {
PreparedStatement stmt = ps;
try {
stmt = nativeJdbcExtractor.getNativePreparedStatement(ps);
} catch (SQLException ex) {
log.debug("Could not find a native preparedstatement using {}", nativeJdbcExtractor
.getClass().getName());
}
return stmt;
}

@Override
public void setValues(PreparedStatement ps, Object[] args)
throws SQLException {
super.setValues(ps, args);
if (args != null && args.length > 0) {
int[] argTypes = new int[args.length];
for (int i = 0; i < argTypes.length; i++) {
argTypes[i] = SqlTypeValue.TYPE_UNKNOWN;
}
setValues(ps, args, argTypes, getLobHandler().getDefaultHandler());
}
}

}
Expand Up @@ -875,12 +875,18 @@ public void setValues(PreparedStatement ps, Object[] args, int[] argTypes,
lobHandler.getLobCreator().setBlobAsBytes(ps, i, arg.toString().getBytes());
} else if (argType == Types.CLOB && lobHandler != null) {
lobHandler.getLobCreator().setClobAsString(ps, i, (String) arg);
} else if (argType == Types.DECIMAL && arg != null) {
setDecimalValue(ps, i, arg, argType);
} else {
StatementCreatorUtils.setParameterValue(ps, i, verifyArgType(arg, argType), arg);
}
}
}

protected void setDecimalValue(PreparedStatement ps, int i, Object arg, int argType) throws SQLException {
StatementCreatorUtils.setParameterValue(ps, i, verifyArgType(arg, argType), arg);
}

protected int verifyArgType(Object arg, int argType) {
if (argType == -101 || argType == Types.OTHER) {
return SqlTypeValue.TYPE_UNKNOWN;
Expand Down
24 changes: 17 additions & 7 deletions symmetric-jdbc/src/test/resources/db-test.properties
Expand Up @@ -18,10 +18,20 @@
# specific language governing permissions and limitations
# under the License.
#
#
#test.server=h2
#test.root=h2
#test.client=h2

test.server=sqlanywhere
test.root=sqlanywhere
test.client=sqlanywhere

#test.server=ase
#test.root=ase
#test.client=ase


test.server=h2
test.root=h2
test.client=h2

mysql.db.driver=com.mysql.jdbc.Driver
mysql.db.user=root
Expand Down Expand Up @@ -132,10 +142,10 @@ informix.client.db.url=jdbc:informix-sqli://dbdev1:30277/symmetricclient:INFORMI

ase.db.driver=com.sybase.jdbc4.jdbc.SybDriver
ase.db.user=sa
ase.db.password=admin123
ase.root.db.url=jdbc:sybase:Tds:dbdev1:5000/symmetricroot
ase.server.db.url=jdbc:sybase:Tds:dbdev1:5000/symmetricroot
ase.client.db.url=jdbc:sybase:Tds:dbdev1:5000/symmetricclient
ase.db.password=
ase.root.db.url=jdbc:sybase:Tds:localhost:7100/symmetricroot
ase.server.db.url=jdbc:sybase:Tds:localhost:7100/symmetricroot
ase.client.db.url=jdbc:sybase:Tds:localhost:7100/symmetricclient

ase12.db.driver=com.sybase.jdbc4.jdbc.SybDriver
ase12.db.user=sa
Expand Down

0 comments on commit 714b157

Please sign in to comment.