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 mv...@apache.org on 2006/01/17 22:43:32 UTC
svn commit: r369928 - in
/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird:
FirebirdBuilder.java FirebirdModelReader.java FirebirdPlatform.java
Author: mvdb
Date: Tue Jan 17 13:43:27 2006
New Revision: 369928
URL: http://svn.apache.org/viewcvs?rev=369928&view=rev
Log:
First start of firebird database. Not all tests pass currently, but I've come a long way..
Added:
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdBuilder.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdModelReader.java
Modified:
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdPlatform.java
Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdBuilder.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdBuilder.java?rev=369928&view=auto
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdBuilder.java (added)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdBuilder.java Tue Jan 17 13:43:27 2006
@@ -0,0 +1,152 @@
+package org.apache.ddlutils.platform.firebird;
+
+/*
+ * Copyright 1999-2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.sql.Types;
+import java.util.Map;
+
+import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.model.Column;
+import org.apache.ddlutils.model.Database;
+import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.platform.SqlBuilder;
+
+/**
+ * The SQL Builder for the FireBird database.
+ *
+ * @author Martin van den Bemt
+ * @version $Revision: 231306 $
+ */
+public class FirebirdBuilder extends SqlBuilder
+{
+ /**
+ * Creates a new builder instance.
+ *
+ * @param info The platform info
+ */
+ public FirebirdBuilder(PlatformInfo info)
+ {
+ super(info);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void createTable(Database database, Table table, Map parameters) throws IOException
+ {
+ super.createTable(database, table, parameters);
+
+ // creating generator and trigger for auto-increment
+ Column[] columns = table.getAutoIncrementColumns();
+
+ for (int idx = 0; idx < columns.length; idx++)
+ {
+ print("CREATE GENERATOR ");
+ printIdentifier(getConstraintName("gen", table, columns[idx].getName(), null));
+ printEndOfStatement();
+ print("--TERM--");
+ printEndOfStatement();
+ print("CREATE TRIGGER ");
+ printIdentifier(getConstraintName("trg", table, columns[idx].getName(), null));
+ print(" FOR ");
+ printlnIdentifier(getTableName(table));
+ println("ACTIVE BEFORE INSERT POSITION 0 AS");
+ println("BEGIN");
+ print("IF (NEW.");
+ printIdentifier(getColumnName(columns[idx]));
+ println(" IS NULL) THEN");
+ print("NEW.");
+ printIdentifier(getColumnName(columns[idx]));
+ print(" = GEN_ID(");
+ printIdentifier(getConstraintName("gen", table, columns[idx].getName(), null));
+ println(", 1);");
+ println("END;");
+ print("--TERM--;");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dropTable(Table table) throws IOException
+ {
+ super.dropTable(table);
+ // dropping generators for auto-increment
+ Column[] columns = table.getAutoIncrementColumns();
+
+ for (int idx = 0; idx < columns.length; idx++)
+ {
+ print("DROP GENERATOR ");
+ printIdentifier(getConstraintName("gen", table, columns[idx].getName(), null));
+ printEndOfStatement();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeColumnAutoIncrementStmt(Table table, Column column) throws IOException
+ {
+ // we're using a generator
+ }
+
+ /**
+ * {@inheritDoc}
+ * @todo : we are kinf of stuck here, since last insert id needs the database name..
+ */
+ public String getSelectLastInsertId(Table table)
+ {
+ Column[] columns = table.getAutoIncrementColumns();
+
+ if (columns.length == 0)
+ {
+ return null;
+ }
+ else
+ {
+ StringBuffer result = new StringBuffer();
+
+ for (int idx = 0; idx < columns.length; idx++)
+ {
+ result.append("SELECT GEN_ID (");
+ result.append(getConstraintName("gen", table, columns[idx].getName(), null));
+ result.append(",0 ) FROM RDB$DATABASE");
+ result.append(table.getName());
+ result.append(getDelimitedIdentifier(columns[idx].getName()));
+ }
+ return result.toString();
+ }
+ }
+
+ /**
+ * Returns the native default value for the column.
+ *
+ * @param column The column
+ * @return The native default value
+ */
+ protected String getNativeDefaultValue(Column column)
+ {
+ String defaultValue = column.getDefaultValue();
+ if (column.getTypeCode() == Types.BIT || column.getTypeCode() == Types.BOOLEAN)
+ {
+ defaultValue = getDefaultValueHelper().convert(column.getDefaultValue(), column.getTypeCode(), Types.SMALLINT).toString();
+ }
+ return defaultValue;
+ }
+
+}
Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdModelReader.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdModelReader.java?rev=369928&view=auto
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdModelReader.java (added)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdModelReader.java Tue Jan 17 13:43:27 2006
@@ -0,0 +1,143 @@
+/*
+ * Copyright 1999-2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ddlutils.platform.firebird;
+
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.model.Column;
+import org.apache.ddlutils.model.ForeignKey;
+import org.apache.ddlutils.model.Index;
+import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.platform.DatabaseMetaDataWrapper;
+import org.apache.ddlutils.platform.JdbcModelReader;
+
+/**
+ * The Jdbc Model Reader for FireBird.
+ *
+ * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
+ * @version $Revision: $
+ */
+public class FirebirdModelReader extends JdbcModelReader {
+
+ /**
+ * @param platformInfo the platformInfo
+ */
+ public FirebirdModelReader(PlatformInfo platformInfo) {
+ super(platformInfo);
+ }
+
+ /**
+ * (@inheritDoc)
+ */
+ protected void readIndex(DatabaseMetaDataWrapper metaData, Map values, Map knownIndices) throws SQLException {
+ super.readIndex(metaData, values, knownIndices);
+ Iterator indexNames = knownIndices.keySet().iterator();
+// printIdentifier(getConstraintName(null, table, "PK", null));
+
+ while (indexNames.hasNext())
+ {
+ String indexName = (String) indexNames.next();
+ if (indexName.indexOf("PRIMARY") != -1)
+ {
+ // we have hit a primary key, remove it..
+ indexNames.remove();
+ }
+ }
+ }
+ /**
+ * {@inheritDoc}
+ * @todo This needs some more work, since table names can be case sensitive or lowercase
+ * depending on the platform (really cute).
+ * See http://dev.mysql.com/doc/refman/4.1/en/name-case-sensitivity.html for more info.
+ */
+ protected Table readTable(DatabaseMetaDataWrapper metaData, Map values) throws SQLException
+ {
+ Table table = super.readTable(metaData, values);
+
+ determineAutoIncrementFromResultSetMetaData(table, table.getColumns());
+ // fix the indexes.
+ fixIndexes(table);
+
+ return table;
+ }
+
+ /**
+ * Helper method that determines the auto increment status for the given columns via the
+ * {@link ResultSetMetaData#isAutoIncrement(int)} method.<br>
+ *
+ * @param table The table
+ * @param columnsToCheck The columns to check (e.g. the primary key columns)
+ */
+ protected void determineAutoIncrementFromResultSetMetaData(Table table, Column[] columnsToCheck) throws SQLException
+ {
+ StringBuffer query = new StringBuffer();
+
+ String prefix = ("gen_"+table.getName()+"_").toUpperCase();
+
+ query.append("SELECT RDB$GENERATOR_NAME FROM RDB$GENERATORS WHERE RDB$GENERATOR_NAME STARTING WITH '");
+ query.append(prefix);
+ query.append("'");
+ Statement stmt = getConnection().createStatement();
+ ResultSet rs = stmt.executeQuery(query.toString());
+
+
+ while(rs.next())
+ {
+ String generatorName = rs.getString(1).substring(prefix.length()).trim();
+ Column column = table.findColumn(generatorName, false);
+ if (column != null)
+ {
+ column.setAutoIncrement(true);
+ }
+ }
+ stmt.close();
+ }
+
+ /**
+ * Firebird als returns indexes for foreignkeys and we need to strip
+ * them from the model.
+ *
+ * @param table the table to fix.
+ */
+ private void fixIndexes(Table table)
+ {
+ if (table.getIndexCount() == 0 || table.getForeignKeyCount() == 0)
+ {
+ // we don't do anything when there are no indexes or foreignkeys.
+ return;
+ }
+ for (int i = 0; i < table.getForeignKeyCount(); i++)
+ {
+ ForeignKey fk = table.getForeignKey(i);
+ Index index = table.findIndex(fk.getName());
+ if (index != null)
+ {
+ // remove it from the indexes..
+ table.removeIndex(index);
+ }
+ }
+ // filter
+ }
+
+
+}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdPlatform.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdPlatform.java?rev=369928&r1=369927&r2=369928&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdPlatform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/firebird/FirebirdPlatform.java Tue Jan 17 13:43:27 2006
@@ -16,16 +16,32 @@
* limitations under the License.
*/
-import org.apache.ddlutils.platform.interbase.InterbasePlatform;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.StringTokenizer;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ddlutils.DynaSqlException;
+import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.model.Database;
+import org.apache.ddlutils.platform.PlatformImplBase;
/**
* The platform implementation for the Firebird database.
+ * It is assumed that the database is configured with sql dialect 3!
*
* @author Thomas Dudziak
+ * @author Martin van den Bemt
* @version $Revision: 231306 $
*/
-public class FirebirdPlatform extends InterbasePlatform
+public class FirebirdPlatform extends PlatformImplBase
{
+ /** The log for this platform. */
+ private final Log _log = LogFactory.getLog(getClass());
/** Database name of this platform. */
public static final String DATABASENAME = "Firebird";
/** The standard Firebird jdbc driver. */
@@ -33,6 +49,52 @@
/** The subprotocol used by the standard Firebird driver. */
public static final String JDBC_SUBPROTOCOL = "firebirdsql";
+ public FirebirdPlatform() {
+ PlatformInfo info = new PlatformInfo();
+
+ info.setMaxIdentifierLength(31);
+ info.setRequiringNullAsDefaultValue(false);
+ info.setPrimaryKeyEmbedded(true);
+ info.setForeignKeysEmbedded(false);
+ info.setIndicesEmbedded(false);
+ info.setCommentPrefix("/*");
+ info.setCommentSuffix("*/");
+ info.setSupportingDelimitedIdentifiers(false);
+
+ // BINARY and VARBINARY are also handled by the InterbaseBuilder.getSqlType method
+ info.addNativeTypeMapping(Types.ARRAY, "BLOB");
+ info.addNativeTypeMapping(Types.BINARY, "BLOB", Types.LONGVARBINARY);
+ info.addNativeTypeMapping(Types.BIT, "SMALLINT", Types.BIT);
+ info.addNativeTypeMapping(Types.CLOB, "BLOB SUB_TYPE TEXT", Types.LONGVARCHAR);
+ info.addNativeTypeMapping(Types.DISTINCT, "BLOB", Types.LONGVARBINARY);
+ info.addNativeTypeMapping(Types.BLOB, "BLOB", Types.LONGVARBINARY);
+ info.addNativeTypeMapping(Types.DOUBLE, "DOUBLE PRECISION");
+ info.addNativeTypeMapping(Types.FLOAT, "DOUBLE PRECISION");
+ info.addNativeTypeMapping(Types.JAVA_OBJECT, "BLOB", Types.LONGVARBINARY);
+ info.addNativeTypeMapping(Types.LONGVARBINARY, "BLOB", Types.LONGVARBINARY);
+ info.addNativeTypeMapping(Types.LONGVARCHAR, "BLOB SUB_TYPE TEXT");
+ info.addNativeTypeMapping(Types.NULL, "BLOB");
+ info.addNativeTypeMapping(Types.OTHER, "BLOB");
+ info.addNativeTypeMapping(Types.REAL, "FLOAT");
+ info.addNativeTypeMapping(Types.TINYINT, "SMALLINT");
+ info.addNativeTypeMapping(Types.REF, "BLOB");
+ info.addNativeTypeMapping(Types.STRUCT, "BLOB");
+ info.addNativeTypeMapping(Types.VARBINARY, "BLOB", Types.LONGVARBINARY);
+ info.addNativeTypeMapping(Types.BOOLEAN, "SMALLINT");
+ info.addNativeTypeMapping("DATALINK", "BLOB");
+
+ /**
+ * This value is set to 128, to give multiple column index a chance
+ * to stay below the maximum key size of 256.
+ * If you use different encodings, you most likely need to decrease this value.
+ */
+ info.addDefaultSize(Types.VARCHAR, 128);
+ info.addDefaultSize(Types.CHAR, 128);
+ info.addDefaultSize(Types.SMALLINT, 5);
+
+ setSqlBuilder(new FirebirdBuilder(info));
+ setModelReader(new FirebirdModelReader(info));
+ }
/**
* {@inheritDoc}
*/
@@ -40,4 +102,110 @@
{
return DATABASENAME;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void createTables(Connection connection, Database model, boolean dropTablesFirst, boolean continueOnError) throws DynaSqlException
+ {
+ String sql = getCreateTablesSql(model, dropTablesFirst, continueOnError);
+ runBatch(connection, sql, continueOnError);
+ }
+
+ /**
+ * Runbatch is a replacement for evaluateBatch.
+ * Especially the <code>SET TERM !!;</code> blocks need to be executed in one go.
+ *
+ * @param connection the connection to use
+ * @param sql the sql to process
+ * @param continueOnError needs to continue when an error occurs.
+ */
+ public int runBatch(Connection connection, String sql, boolean continueOnError) throws DynaSqlException
+ {
+ int errors = 0;
+ Statement statement = null;
+ int commandCount = 0;
+
+ try {
+ statement = connection.createStatement();
+ StringTokenizer tokenizer = new StringTokenizer(sql, ";");
+
+ while (tokenizer.hasMoreTokens())
+ {
+ String command = tokenizer.nextToken().trim();
+ if (command.equals("--TERM--"))
+ {
+ command = "";
+ while(tokenizer.hasMoreTokens())
+ {
+ String termSql = tokenizer.nextToken().trim();
+ if(termSql.equals("--TERM--"))
+ {
+ break;
+ }
+ if (termSql.length() > 0)
+ {
+ command+=termSql+";";
+ }
+
+ }
+ }
+ if (command.length() == 0)
+ {
+ continue;
+ }
+
+ System.err.println("SQL Command :\n" + command);
+ commandCount++;
+
+ if (_log.isDebugEnabled())
+ {
+ _log.debug("About to execute SQL " + command);
+ }
+ try
+ {
+ int results = statement.executeUpdate(command);
+
+ if (_log.isDebugEnabled())
+ {
+ _log.debug("After execution, " + results + " row(s) have been changed");
+ }
+ }
+ catch (SQLException ex)
+ {
+ if (continueOnError)
+ {
+ System.err.println("SQL Command " + command + " failed with " + ex.getMessage());
+ errors++;
+ }
+ else
+ {
+ throw new DynaSqlException("Error while executing SQL "+command, ex);
+ }
+ }
+
+ // lets display any warnings
+ SQLWarning warning = connection.getWarnings();
+
+ while (warning != null)
+ {
+ _log.warn(warning.toString());
+ warning = warning.getNextWarning();
+ }
+ connection.clearWarnings();
+ }
+ _log.info("Executed "+ commandCount + " SQL command(s) with " + errors + " error(s)");
+ }
+ catch (SQLException ex)
+ {
+ throw new DynaSqlException("Error while executing SQL", ex);
+ }
+ finally
+ {
+ closeStatement(statement);
+ }
+
+ return errors;
+ }
+
}