/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* 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.jkiss.dbeaver.model.impl.sql.edit.struct;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.DBPEvaluationContext;
import org.jkiss.dbeaver.model.DBPObject;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.edit.DBEPersistAction;
import org.jkiss.dbeaver.model.edit.DBERegistry;
import org.jkiss.dbeaver.model.impl.DBObjectNameCaseTransformer;
import org.jkiss.dbeaver.model.impl.edit.SQLDatabasePersistAction;
import org.jkiss.dbeaver.model.impl.jdbc.struct.JDBCTable;
import org.jkiss.dbeaver.model.impl.sql.edit.SQLObjectEditor;
import org.jkiss.dbeaver.model.impl.sql.edit.SQLStructEditor;
import org.jkiss.dbeaver.model.messages.ModelMessages;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.struct.*;
import org.jkiss.dbeaver.model.struct.rdb.DBSTableConstraint;
import org.jkiss.dbeaver.model.struct.rdb.DBSTableForeignKey;
import org.jkiss.dbeaver.model.struct.rdb.DBSTableIndex;
import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.utils.CommonUtils;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* JDBC table manager
*/
public abstract class SQLTableManager<OBJECT_TYPE extends JDBCTable, CONTAINER_TYPE extends DBSObjectContainer>
extends SQLStructEditor<OBJECT_TYPE, CONTAINER_TYPE>
{
private static final String BASE_TABLE_NAME = "NewTable"; //$NON-NLS-1$
@Override
public long getMakerOptions()
{
return FEATURE_EDITOR_ON_CREATE;
}
@Override
protected final void addObjectCreateActions(List<DBEPersistAction> actions, ObjectCreateCommand objectChangeCommand)
{
throw new IllegalStateException("addObjectCreateActions should never be called in struct editor");
}
@Override
protected void addStructObjectCreateActions(List<DBEPersistAction> actions, StructCreateCommand command)
{
final OBJECT_TYPE table = command.getObject();
final NestedObjectCommand tableProps = command.getObjectCommands().get(table);
if (tableProps == null) {
log.warn("Object change command not found"); //$NON-NLS-1$
return;
}
final String tableName = table.getFullyQualifiedName(DBPEvaluationContext.DDL);
final String lineSeparator = GeneralUtils.getDefaultLineSeparator();
StringBuilder createQuery = new StringBuilder(100);
createQuery.append("CREATE TABLE ").append(tableName).append(" (").append(lineSeparator); //$NON-NLS-1$ //$NON-NLS-2$
boolean hasNestedDeclarations = false;
final Collection<NestedObjectCommand> orderedCommands = getNestedOrderedCommands(command);
for (NestedObjectCommand nestedCommand : orderedCommands) {
if (nestedCommand.getObject() == table) {
continue;
}
if (excludeFromDDL(nestedCommand, orderedCommands)) {
continue;
}
final String nestedDeclaration = nestedCommand.getNestedDeclaration(table);
if (!CommonUtils.isEmpty(nestedDeclaration)) {
// Insert nested declaration
if (hasNestedDeclarations) {
createQuery.append(",").append(lineSeparator); //$NON-NLS-1$
}
createQuery.append("\t").append(nestedDeclaration); //$NON-NLS-1$
hasNestedDeclarations = true;
} else {
// This command should be executed separately
final DBEPersistAction[] nestedActions = nestedCommand.getPersistActions();
if (nestedActions != null) {
Collections.addAll(actions, nestedActions);
}
}
}
createQuery.append(lineSeparator).append(")"); //$NON-NLS-1$
appendTableModifiers(table, tableProps, createQuery);
actions.add( 0, new SQLDatabasePersistAction(ModelMessages.model_jdbc_create_new_table, createQuery.toString()) );
}
protected boolean excludeFromDDL(NestedObjectCommand command, Collection<NestedObjectCommand> orderedCommands) {
return false;
}
@Override
protected void addObjectDeleteActions(List<DBEPersistAction> actions, ObjectDeleteCommand command)
{
actions.add(
new SQLDatabasePersistAction(
ModelMessages.model_jdbc_drop_table,
"DROP " + (command.getObject().isView() ? "VIEW" : "TABLE") +
" " + command.getObject().getFullyQualifiedName(DBPEvaluationContext.DDL)) //$NON-NLS-2$
);
}
protected void appendTableModifiers(OBJECT_TYPE table, NestedObjectCommand tableProps, StringBuilder ddl)
{
}
protected void setTableName(DBRProgressMonitor monitor, CONTAINER_TYPE container, OBJECT_TYPE table) throws DBException {
table.setName(getTableName(monitor, container));
}
protected String getTableName(DBRProgressMonitor monitor, CONTAINER_TYPE container) throws DBException {
return getTableName(monitor, container, BASE_TABLE_NAME);
}
protected String getTableName(DBRProgressMonitor monitor, CONTAINER_TYPE container, String baseName) throws DBException {
for (int i = 0; ; i++) {
String tableName = DBObjectNameCaseTransformer.transformName(container.getDataSource(), i == 0 ? baseName : (baseName + "_" + i));
DBSObject child = container.getChild(monitor, tableName);
if (child == null) {
return tableName;
}
}
}
public DBEPersistAction[] getTableDDL(DBRProgressMonitor monitor, OBJECT_TYPE table) throws DBException
{
final DBERegistry editorsRegistry = table.getDataSource().getContainer().getPlatform().getEditorsRegistry();
SQLObjectEditor<DBSEntityAttribute, OBJECT_TYPE> tcm = getObjectEditor(editorsRegistry, DBSEntityAttribute.class);
SQLObjectEditor<DBSTableConstraint, OBJECT_TYPE> pkm = getObjectEditor(editorsRegistry, DBSTableConstraint.class);
SQLObjectEditor<DBSTableForeignKey, OBJECT_TYPE> fkm = getObjectEditor(editorsRegistry, DBSTableForeignKey.class);
SQLObjectEditor<DBSTableIndex, OBJECT_TYPE> im = getObjectEditor(editorsRegistry, DBSTableIndex.class);
StructCreateCommand command = makeCreateCommand(table);
if (tcm != null) {
// Aggregate nested column, constraint and index commands
for (DBSEntityAttribute column : CommonUtils.safeCollection(table.getAttributes(monitor))) {
if (DBUtils.isHiddenObject(column)) {
continue;
}
command.aggregateCommand(tcm.makeCreateCommand(column));
}
}
if (pkm != null) {
try {
for (DBSTableConstraint constraint : CommonUtils.safeCollection(table.getConstraints(monitor))) {
if (DBUtils.isHiddenObject(constraint)) {
continue;
}
command.aggregateCommand(pkm.makeCreateCommand(constraint));
}
} catch (DBException e) {
// Ignore primary keys
log.debug(e);
}
}
if (fkm != null) {
try {
for (DBSEntityAssociation foreignKey : CommonUtils.safeCollection(table.getAssociations(monitor))) {
if (!(foreignKey instanceof DBSTableForeignKey) || DBUtils.isHiddenObject(foreignKey)) {
continue;
}
command.aggregateCommand(fkm.makeCreateCommand((DBSTableForeignKey) foreignKey));
}
} catch (DBException e) {
// Ignore primary keys
log.debug(e);
}
}
if (im != null) {
try {
for (DBSTableIndex index : CommonUtils.safeCollection(table.getIndexes(monitor))) {
if (DBUtils.isHiddenObject(index)) {
continue;
}
command.aggregateCommand(im.makeCreateCommand(index));
}
} catch (DBException e) {
// Ignore indexes
log.debug(e);
}
}
return command.getPersistActions();
}
}