You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ddlutils-dev@db.apache.org by to...@apache.org on 2006/02/25 21:16:52 UTC
svn commit: r380979 - in /db/ddlutils/trunk/src/java/org/apache/ddlutils:
platform/PlatformImplBase.java platform/SqlBuilder.java
platform/sybase/SybaseBuilder.java platform/sybase/SybasePlatform.java
util/JdbcSupport.java
Author: tomdz
Date: Sat Feb 25 12:16:50 2006
New Revision: 380979
URL: http://svn.apache.org/viewcvs?rev=380979&view=rev
Log:
Fixed/enhanced Sybase (ASE) implementation
Modified:
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sybase/SybaseBuilder.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sybase/SybasePlatform.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/util/JdbcSupport.java
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java?rev=380979&r1=380978&r2=380979&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java Sat Feb 25 12:16:50 2006
@@ -854,7 +854,7 @@
finally
{
// the iterator should return the connection automatically
- // so this is usuallynot necessary (but just in case)
+ // so this is usually not necessary (but just in case)
closeStatement(statement);
returnConnection(connection);
}
@@ -1655,7 +1655,23 @@
int typeCode = property.getColumn().getTypeCode();
Object value = dynaBean.get(property.getName());
- if (value == null)
+ setStatementParameterValue(statement, sqlIndex, typeCode, value);
+ }
+
+ /**
+ * This is the core method to set the parameter of a prepared statement to a given value.
+ * The primary purpose of this method is to call the appropriate method on the statement,
+ * and to give database-specific implementations the ability to change this behavior.
+ *
+ * @param statement The statement
+ * @param sqlIndex The parameter index
+ * @param typeCode The JDBC type code
+ * @param value The value
+ * @throws SQLException If an error occurred while setting the parameter value
+ */
+ protected void setStatementParameterValue(PreparedStatement statement, int sqlIndex, int typeCode, Object value) throws SQLException
+ {
+ if (value == null)
{
statement.setNull(sqlIndex, typeCode);
}
@@ -1704,7 +1720,7 @@
{
statement.setObject(sqlIndex, value, typeCode);
}
- }
+ }
/**
* Helper method esp. for the {@link ModelBasedResultSetIterator} class that retrieves
@@ -1742,92 +1758,7 @@
// we should not use the Clob interface if the database doesn't map to this type
jdbcType = targetJdbcType;
}
- switch (jdbcType)
- {
- case Types.CHAR:
- case Types.VARCHAR:
- case Types.LONGVARCHAR:
- value = resultSet.getString(columnName);
- break;
- case Types.NUMERIC:
- case Types.DECIMAL:
- value = resultSet.getBigDecimal(columnName);
- break;
- case Types.BIT:
- value = new Boolean(resultSet.getBoolean(columnName));
- break;
- case Types.TINYINT:
- case Types.SMALLINT:
- case Types.INTEGER:
- value = new Integer(resultSet.getInt(columnName));
- break;
- case Types.BIGINT:
- value = new Long(resultSet.getLong(columnName));
- break;
- case Types.REAL:
- value = new Float(resultSet.getFloat(columnName));
- break;
- case Types.FLOAT:
- case Types.DOUBLE:
- value = new Double(resultSet.getDouble(columnName));
- break;
- case Types.BINARY:
- case Types.VARBINARY:
- case Types.LONGVARBINARY:
- value = resultSet.getBytes(columnName);
- break;
- case Types.DATE:
- value = resultSet.getDate(columnName);
- break;
- case Types.TIME:
- value = resultSet.getTime(columnName);
- break;
- case Types.TIMESTAMP:
- value = resultSet.getTimestamp(columnName);
- break;
- case Types.CLOB:
- Clob clob = resultSet.getClob(columnName);
-
- if ((clob == null) || (clob.length() > Integer.MAX_VALUE))
- {
- value = clob;
- }
- else
- {
- value = clob.getSubString(1l, (int)clob.length());
- }
- break;
- case Types.BLOB:
- Blob blob = resultSet.getBlob(columnName);
-
- if ((blob == null) || (blob.length() > Integer.MAX_VALUE))
- {
- value = blob;
- }
- else
- {
- value = blob.getBytes(1l, (int)blob.length());
- }
- break;
- case Types.ARRAY:
- value = resultSet.getArray(columnName);
- break;
- case Types.REF:
- value = resultSet.getRef(columnName);
- break;
- default:
- // special handling for Java 1.4/JDBC 3 types
- if (Jdbc3Utils.supportsJava14JdbcTypes() &&
- (jdbcType == Jdbc3Utils.determineBooleanTypeCode()))
- {
- value = new Boolean(resultSet.getBoolean(columnName));
- }
- else
- {
- value = resultSet.getObject(columnName);
- }
- break;
- }
+ value = extractColumnValue(resultSet, columnName, jdbcType);
}
else
{
@@ -1835,6 +1766,110 @@
}
return value;
}
+
+ /**
+ * This is the core method to retrieve a value for a column from a result set. Its primary
+ * purpose is to call the appropriate method on the result set, and to provide an extension
+ * point where database-specific implementations can change this behavior.
+ *
+ * @param resultSet The result set to extract the value from
+ * @param columnName The name of the column
+ * @param jdbcType The jdbc type to extract
+ * @return The value
+ * @throws SQLException If an error occurred while accessing the result set
+ */
+ protected Object extractColumnValue(ResultSet resultSet, String columnName, int jdbcType) throws SQLException
+ {
+ Object value;
+
+ switch (jdbcType)
+ {
+ case Types.CHAR:
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR:
+ value = resultSet.getString(columnName);
+ break;
+ case Types.NUMERIC:
+ case Types.DECIMAL:
+ value = resultSet.getBigDecimal(columnName);
+ break;
+ case Types.BIT:
+ value = new Boolean(resultSet.getBoolean(columnName));
+ break;
+ case Types.TINYINT:
+ case Types.SMALLINT:
+ case Types.INTEGER:
+ value = new Integer(resultSet.getInt(columnName));
+ break;
+ case Types.BIGINT:
+ value = new Long(resultSet.getLong(columnName));
+ break;
+ case Types.REAL:
+ value = new Float(resultSet.getFloat(columnName));
+ break;
+ case Types.FLOAT:
+ case Types.DOUBLE:
+ value = new Double(resultSet.getDouble(columnName));
+ break;
+ case Types.BINARY:
+ case Types.VARBINARY:
+ case Types.LONGVARBINARY:
+ value = resultSet.getBytes(columnName);
+ break;
+ case Types.DATE:
+ value = resultSet.getDate(columnName);
+ break;
+ case Types.TIME:
+ value = resultSet.getTime(columnName);
+ break;
+ case Types.TIMESTAMP:
+ value = resultSet.getTimestamp(columnName);
+ break;
+ case Types.CLOB:
+ Clob clob = resultSet.getClob(columnName);
+
+ if ((clob == null) || (clob.length() > Integer.MAX_VALUE))
+ {
+ value = clob;
+ }
+ else
+ {
+ value = clob.getSubString(1l, (int)clob.length());
+ }
+ break;
+ case Types.BLOB:
+ Blob blob = resultSet.getBlob(columnName);
+
+ if ((blob == null) || (blob.length() > Integer.MAX_VALUE))
+ {
+ value = blob;
+ }
+ else
+ {
+ value = blob.getBytes(1l, (int)blob.length());
+ }
+ break;
+ case Types.ARRAY:
+ value = resultSet.getArray(columnName);
+ break;
+ case Types.REF:
+ value = resultSet.getRef(columnName);
+ break;
+ default:
+ // special handling for Java 1.4/JDBC 3 types
+ if (Jdbc3Utils.supportsJava14JdbcTypes() &&
+ (jdbcType == Jdbc3Utils.determineBooleanTypeCode()))
+ {
+ value = new Boolean(resultSet.getBoolean(columnName));
+ }
+ else
+ {
+ value = resultSet.getObject(columnName);
+ }
+ break;
+ }
+ return value;
+ }
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java?rev=380979&r1=380978&r2=380979&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java Sat Feb 25 12:16:50 2006
@@ -1121,7 +1121,7 @@
return shortenName(column.getName(), getPlatformInfo().getMaxIdentifierLength());
}
- /**
+ /**
* Outputs the DDL for the specified column.
*
* @param table The table containing the column
@@ -1301,7 +1301,12 @@
}
else
{
- print(getNativeDefaultValue(column).toString());
+ Object nativeDefault = getNativeDefaultValue(column);
+
+ if (nativeDefault != null)
+ {
+ print(nativeDefault.toString());
+ }
}
}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sybase/SybaseBuilder.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sybase/SybaseBuilder.java?rev=380979&r1=380978&r2=380979&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sybase/SybaseBuilder.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sybase/SybaseBuilder.java Sat Feb 25 12:16:50 2006
@@ -17,13 +17,19 @@
*/
import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.sql.Types;
import java.util.Map;
+import org.apache.ddlutils.DynaSqlException;
import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.ForeignKey;
import org.apache.ddlutils.model.Table;
import org.apache.ddlutils.platform.SqlBuilder;
+import org.apache.ddlutils.util.Jdbc3Utils;
/**
* The SQL Builder for Sybase.
@@ -54,13 +60,77 @@
super.createTable(database, table, parameters);
}
- /**
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeColumn(Table table, Column column) throws IOException
+ {
+ printIdentifier(getColumnName(column));
+ print(" ");
+ print(getSqlType(column));
+
+ if (column.getDefaultValue() != null)
+ {
+ if (!getPlatformInfo().isSupportingDefaultValuesForLongTypes() &&
+ ((column.getTypeCode() == Types.LONGVARBINARY) || (column.getTypeCode() == Types.LONGVARCHAR)))
+ {
+ throw new DynaSqlException("The platform does not support default values for LONGVARCHAR or LONGVARBINARY columns");
+ }
+ print(" DEFAULT ");
+ writeColumnDefaultValue(table, column);
+ }
+ // Sybase does not like NOT NULL and IDENTITY together
+ if (column.isRequired() && !column.isAutoIncrement())
+ {
+ print(" ");
+ writeColumnNotNullableStmt();
+ }
+ if (column.isAutoIncrement())
+ {
+ print(" ");
+ writeColumnAutoIncrementStmt(table, column);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getNativeDefaultValue(Column column)
+ {
+ if ((column.getTypeCode() == Types.BIT) ||
+ (Jdbc3Utils.supportsJava14JdbcTypes() && (column.getTypeCode() == Jdbc3Utils.determineBooleanTypeCode())))
+ {
+ return getDefaultValueHelper().convert(column.getDefaultValue(), column.getTypeCode(), Types.SMALLINT).toString();
+ }
+ else
+ {
+ return super.getNativeDefaultValue(column);
+ }
+ }
+
+ /**
* {@inheritDoc}
*/
protected void alterTable(Database currentModel, Table currentTable, Database desiredModel, Table desiredTable, boolean doDrops, boolean modifyColumns) throws IOException
{
- writeQuotationOnStatement();
+ // we only want to generate the quotation start statement if there is something to write
+ // thus we write the alteration commands into a temporary writer
+ // and only if something was written, write the quotation start statement and the
+ // alteration commands to the original writer
+ Writer originalWriter = getWriter();
+ StringWriter tempWriter = new StringWriter();
+
+ setWriter(tempWriter);
super.alterTable(currentModel, currentTable, desiredModel, desiredTable, doDrops, modifyColumns);
+ setWriter(originalWriter);
+
+ String alterationCommands = tempWriter.toString();
+
+ if (alterationCommands.trim().length() > 0)
+ {
+ writeQuotationOnStatement();
+ getWriter().write(alterationCommands);
+ }
}
/**
@@ -116,47 +186,6 @@
{
print("SET quoted_identifier on");
printEndOfStatement();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public String getDeleteSql(Table table, Map pkValues, boolean genPlaceholders)
- {
- return getQuotationOnStatement() + super.getDeleteSql(table, pkValues, genPlaceholders);
- }
-
- /**
- * {@inheritDoc}
- */
- public String getInsertSql(Table table, Map columnValues, boolean genPlaceholders)
- {
- return getQuotationOnStatement() + super.getInsertSql(table, columnValues, genPlaceholders);
- }
-
- /**
- * {@inheritDoc}
- */
- public String getUpdateSql(Table table, Map columnValues, boolean genPlaceholders)
- {
- return getQuotationOnStatement() + super.getUpdateSql(table, columnValues, genPlaceholders);
- }
-
- /**
- * Returns the statement that turns on the ability to write delimited identifiers.
- *
- * @return The quotation-on statement
- */
- private String getQuotationOnStatement()
- {
- if (getPlatformInfo().isUseDelimitedIdentifiers())
- {
- return "SET quoted_identifier on" + getPlatformInfo().getSqlCommandDelimiter() + "\n";
- }
- else
- {
- return "";
}
}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sybase/SybasePlatform.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sybase/SybasePlatform.java?rev=380979&r1=380978&r2=380979&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sybase/SybasePlatform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sybase/SybasePlatform.java Sat Feb 25 12:16:50 2006
@@ -16,9 +16,24 @@
* limitations under the License.
*/
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
import java.sql.Types;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ddlutils.DynaSqlException;
import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.model.Database;
+import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.model.TypeMap;
import org.apache.ddlutils.platform.PlatformImplBase;
/**
@@ -38,6 +53,9 @@
/** The subprotocol used by the standard Sybase driver. */
public static final String JDBC_SUBPROTOCOL = "sybase:Tds";
+ /** The maximum size that text and binary columns can have. */
+ public static final long MAX_TEXT_SIZE = 2147483647;
+
/**
* Creates a new platform instance.
*/
@@ -45,7 +63,7 @@
{
PlatformInfo info = new PlatformInfo();
- info.setMaxIdentifierLength(30);
+ info.setMaxIdentifierLength(28);
info.setRequiringNullAsDefaultValue(false);
info.setPrimaryKeyEmbedded(true);
info.setForeignKeysEmbedded(false);
@@ -54,13 +72,15 @@
info.setCommentSuffix("*/");
info.addNativeTypeMapping(Types.ARRAY, "IMAGE");
+ // we're not using the native BIT type because it is rather limited (cannot be NULL, cannot be indexed)
+ info.addNativeTypeMapping(Types.BIT, "SMALLINT", Types.SMALLINT);
info.addNativeTypeMapping(Types.BIGINT, "DECIMAL(19,0)");
info.addNativeTypeMapping(Types.BLOB, "IMAGE");
info.addNativeTypeMapping(Types.CLOB, "TEXT");
- info.addNativeTypeMapping(Types.DATE, "DATETIME");
+ info.addNativeTypeMapping(Types.DATE, "DATETIME", Types.TIMESTAMP);
info.addNativeTypeMapping(Types.DISTINCT, "IMAGE");
info.addNativeTypeMapping(Types.DOUBLE, "DOUBLE PRECISION");
- info.addNativeTypeMapping(Types.FLOAT, "DOUBLE PRECISION");
+ info.addNativeTypeMapping(Types.FLOAT, "DOUBLE PRECISION", Types.DOUBLE);
info.addNativeTypeMapping(Types.INTEGER, "INT");
info.addNativeTypeMapping(Types.JAVA_OBJECT, "IMAGE");
info.addNativeTypeMapping(Types.LONGVARBINARY, "IMAGE");
@@ -69,13 +89,19 @@
info.addNativeTypeMapping(Types.OTHER, "IMAGE");
info.addNativeTypeMapping(Types.REF, "IMAGE");
info.addNativeTypeMapping(Types.STRUCT, "IMAGE");
- info.addNativeTypeMapping(Types.TIME, "DATETIME");
- info.addNativeTypeMapping(Types.TIMESTAMP, "DATETIME");
- info.addNativeTypeMapping(Types.TINYINT, "SMALLINT");
- info.addNativeTypeMapping("BOOLEAN", "BIT");
+ info.addNativeTypeMapping(Types.TIME, "DATETIME", Types.TIMESTAMP);
+ info.addNativeTypeMapping(Types.TIMESTAMP, "DATETIME", Types.TIMESTAMP);
+ info.addNativeTypeMapping(Types.TINYINT, "SMALLINT", Types.SMALLINT);
+ info.addNativeTypeMapping("BOOLEAN", "SMALLINT", "SMALLINT");
info.addNativeTypeMapping("DATALINK", "IMAGE");
+ info.addDefaultSize(Types.BINARY, 254);
+ info.addDefaultSize(Types.VARBINARY, 254);
+ info.addDefaultSize(Types.CHAR, 254);
+ info.addDefaultSize(Types.VARCHAR, 254);
+
setSqlBuilder(new SybaseBuilder(info));
+ setModelReader(new SybaseModelReader(info));
}
/**
@@ -85,4 +111,136 @@
{
return DATABASENAME;
}
+
+ /**
+ * Sets the text size which is the maximum amount of bytes that Sybase returns in a SELECT statement
+ * for binary/text columns (e.g. blob, longvarchar etc.).
+ *
+ * @param size The size to set
+ */
+ private void setTextSize(long size)
+ {
+ Connection connection = borrowConnection();
+ Statement stmt = null;
+
+ try
+ {
+ stmt = connection.createStatement();
+
+ stmt.execute("SET textsize "+size);
+ }
+ catch (SQLException ex)
+ {
+ throw new DynaSqlException(ex);
+ }
+ finally
+ {
+ closeStatement(stmt);
+ returnConnection(connection);
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Object extractColumnValue(ResultSet resultSet, String columnName, int jdbcType) throws SQLException
+ {
+ if (jdbcType == Types.LONGVARBINARY)
+ {
+ InputStream stream = resultSet.getBinaryStream(columnName);
+
+ if (stream == null)
+ {
+ return null;
+ }
+ else
+ {
+ byte[] buf = new byte[65536];
+ byte[] result = new byte[0];
+ int len;
+
+ try
+ {
+ do
+ {
+ len = stream.read(buf);
+ if (len > 0)
+ {
+ byte[] newResult = new byte[result.length + len];
+
+ System.arraycopy(result, 0, newResult, 0, result.length);
+ System.arraycopy(buf, 0, newResult, result.length, len);
+ result = newResult;
+ }
+ }
+ while (len > 0);
+ stream.close();
+ return result;
+ }
+ catch (IOException ex)
+ {
+ throw new DynaSqlException("Error while extracting the value of column " + columnName + " of type " +
+ TypeMap.getJdbcTypeName(jdbcType) + " from a result set", ex);
+ }
+ }
+ }
+ else
+ {
+ return super.extractColumnValue(resultSet, columnName, jdbcType);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void setStatementParameterValue(PreparedStatement statement, int sqlIndex, int typeCode, Object value) throws SQLException
+ {
+ if ((value instanceof byte[]) && (typeCode == Types.LONGVARBINARY))
+ {
+ byte[] data = (byte[])value;
+
+ statement.setBinaryStream(sqlIndex, new ByteArrayInputStream(data), data.length);
+ }
+ else
+ {
+ super.setStatementParameterValue(statement, sqlIndex, typeCode, value);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List fetch(Database model, String sql, Collection parameters, Table[] queryHints, int start, int end) throws DynaSqlException
+ {
+ setTextSize(MAX_TEXT_SIZE);
+ return super.fetch(model, sql, parameters, queryHints, start, end);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List fetch(Database model, String sql, Table[] queryHints, int start, int end) throws DynaSqlException
+ {
+ setTextSize(MAX_TEXT_SIZE);
+ return super.fetch(model, sql, queryHints, start, end);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator query(Database model, String sql, Collection parameters, Table[] queryHints) throws DynaSqlException
+ {
+ setTextSize(MAX_TEXT_SIZE);
+ return super.query(model, sql, parameters, queryHints);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator query(Database model, String sql, Table[] queryHints) throws DynaSqlException
+ {
+ setTextSize(MAX_TEXT_SIZE);
+ return super.query(model, sql, queryHints);
+ }
}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/util/JdbcSupport.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/util/JdbcSupport.java?rev=380979&r1=380978&r2=380979&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/util/JdbcSupport.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/util/JdbcSupport.java Sat Feb 25 12:16:50 2006
@@ -211,7 +211,7 @@
}
catch (Exception e)
{
- _log.warn("Ignoring exception closing statement", e);
+ _log.debug("Ignoring exception that occurred while closing statement", e);
}
}
}