/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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;
import java.io.IOException;
import java.sql.DatabaseMetaData;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.apache.ddlutils.Platform;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.ForeignKey;
import org.apache.ddlutils.model.Table;
import org.apache.ddlutils.platform.CreationParameters;
import org.apache.ddlutils.platform.SqlBuilder;
/**
* SqlBuilder enhanced through cglib modifying ddlutils 1.0 behavior at runtime for
* https://issues.apache.org/jira/browse/DDLUTILS-75 which is fixed in ddlutils 1.1 but hasn't been released yet.
*
* @version $Id: EnhancedSqlBuilder.java 1079014 2011-03-07 23:05:12Z ate $
*/
public class EnhancedSqlBuilder extends SqlBuilder
{
private SqlBuilder internal;
private class SqlBuilderEnhancer implements MethodInterceptor
{
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable
{
if (method.getName().equals("writeEmbeddedForeignKeysStmt"))
{
EnhancedSqlBuilder.this.writeEmbeddedForeignKeysStmt((Database)args[0], (Table)args[1]);
return null;
}
else if (method.getName().equals("writeExternalForeignKeyCreateStmt"))
{
EnhancedSqlBuilder.this.writeExternalForeignKeyCreateStmt((Database)args[0], (Table)args[1], (ForeignKey)args[2]);
return null;
}
else
{
return proxy.invokeSuper(obj, args);
}
}
}
public EnhancedSqlBuilder(SqlBuilder sqlBuilder)
{
super(null);
Enhancer e = new Enhancer();
e.setSuperclass(sqlBuilder.getClass());
e.setCallback(new SqlBuilderEnhancer());
internal = (SqlBuilder)e.create(new Class[]{Platform.class}, new Object[]{sqlBuilder.getPlatform()});
internal.setIndent(sqlBuilder.getIndent());
internal.setValueLocale(sqlBuilder.getValueLocale());
internal.setWriter(sqlBuilder.getWriter());
}
public void createTables(Database database, CreationParameters params,
boolean dropTables) throws IOException
{
internal.createTables(database, params, dropTables);
}
/**
* {@inheritDoc}
*/
protected String getOnDeleteClauseForCode(int deleteRuleCode)
{
String platform = internal.getPlatform().getName();
if ( platform.equals("Firebird") ||
platform.equals("SapDB") ||
platform.equals("PostgreSql") ||
platform.equals("Derby") ||
platform.startsWith("MySQL") ||
platform.startsWith("DB2"))
{
switch (deleteRuleCode)
{
case DatabaseMetaData.importedKeyCascade:
return "ON DELETE CASCADE";
case DatabaseMetaData.importedKeyRestrict:
return "ON DELETE RESTRICT";
case DatabaseMetaData.importedKeySetNull:
return "ON DELETE SET NULL";
default:
return ""; // No action case
}
}
else if (platform.startsWith("HsqlDb") || platform.startsWith("Oracle"))
{
switch (deleteRuleCode)
{
case DatabaseMetaData.importedKeyCascade:
return "ON DELETE CASCADE";
case DatabaseMetaData.importedKeyRestrict:
return ""; // not supported
case DatabaseMetaData.importedKeySetNull:
return "ON DELETE SET NULL";
default:
return ""; // No action case
}
}
else if (platform.equals("MsSql"))
{
switch (deleteRuleCode)
{
case DatabaseMetaData.importedKeyCascade:
return "ON DELETE CASCADE";
case DatabaseMetaData.importedKeyRestrict:
return ""; // not supported
case DatabaseMetaData.importedKeySetNull:
return "ON DELETE SET NULL";
default:
return "ON DELETE NO ACTION"; // No action case
}
}
return "";
}
/**
* Writes the foreign key constraints inside a create table () clause.
*
* @param database The database model
* @param table The table
*/
protected void writeEmbeddedForeignKeysStmt(Database database, Table table) throws IOException
{
for (int idx = 0; idx < table.getForeignKeyCount(); idx++)
{
ForeignKey key = table.getForeignKey(idx);
if (key.getForeignTableName() == null)
{
internal._log.warn("Foreign key table is null for key " + key);
}
else
{
internal.printStartOfEmbeddedStatement();
if (internal.getPlatformInfo().isEmbeddedForeignKeysNamed())
{
internal.print("CONSTRAINT ");
internal.printIdentifier(internal.getForeignKeyName(table, key));
internal.print(" ");
}
internal.print("FOREIGN KEY (");
internal.writeLocalReferences(key);
internal.print(") REFERENCES ");
internal.printIdentifier(internal.getTableName(database.findTable(key.getForeignTableName())));
internal.print(" (");
internal.writeForeignReferences(key);
internal.print(")");
String onDeleteClause = getOnDeleteClauseForCode(((org.apache.jetspeed.maven.plugins.db.ddlutils.model.ForeignKey)key).getDeleteRuleCode());
if (onDeleteClause.trim().length() > 0)
{
internal.print(' ' + onDeleteClause);
}
}
}
}
/**
* Writes a single foreign key constraint using a alter table statement.
*
* @param database The database model
* @param table The table
* @param key The foreign key
*/
protected void writeExternalForeignKeyCreateStmt(Database database, Table table, ForeignKey key) throws IOException
{
if (key.getForeignTableName() == null)
{
internal._log.warn("Foreign key table is null for key " + key);
}
else
{
internal.writeTableAlterStmt(table);
String platform = internal.getPlatform().getName();
if (platform.equals("SapDB") || platform.equals("MaxDB"))
{
internal.print(" ADD FOREIGN KEY ");
internal.printIdentifier(internal.getForeignKeyName(table, key));
internal.print(" (");
}
else
{
internal.print("ADD CONSTRAINT ");
internal.printIdentifier(internal.getForeignKeyName(table, key));
internal.print(" FOREIGN KEY (");
}
internal.writeLocalReferences(key);
internal.print(") REFERENCES ");
internal.printIdentifier(internal.getTableName(database.findTable(key.getForeignTableName())));
internal.print(" (");
internal.writeForeignReferences(key);
internal.print(")");
String onDeleteClause = getOnDeleteClauseForCode(((org.apache.jetspeed.maven.plugins.db.ddlutils.model.ForeignKey)key).getDeleteRuleCode());
if (onDeleteClause.trim().length() > 0)
{
internal.print(' ' + onDeleteClause);
}
internal.printEndOfStatement();
}
}
}