提交 3cda85ec 编写于 作者: N Nikita Akilov

#11047 fix numerous code review remarks


Former-commit-id: 605d998e
上级 09f42026
......@@ -43,7 +43,8 @@ public class DTUIMessages extends NLS {
public static String database_consumer_wizard_truncate_checkbox_label;
public static String database_consumer_wizard_truncate_checkbox_description;
public static String database_consumer_wizard_disable_referential_integrity_label;
public static String database_consumer_wizard_disable_referential_integrity_tip;
public static String database_consumer_wizard_disable_referential_integrity_tip_no_caveats;
public static String database_consumer_wizard_disable_referential_integrity_tip_with_caveats;
public static String database_consumer_wizard_performance_group_label;
public static String database_consumer_wizard_transactions_checkbox_label;
public static String database_consumer_wizard_commit_spinner_label;
......
......@@ -25,7 +25,8 @@ database_consumer_wizard_truncate_checkbox_label = Truncate target table(s) befo
database_consumer_wizard_truncate_checkbox_description = Truncate target table(s) before load. This will remove ALL data from target table(s)
database_consumer_wizard_truncate_checkbox_question = "Truncate target table" option is enabled.\nThis will remove ALL data from target table(s) ({0}).\nit will not be possible to revert this.\nAre you absolutely sure you want to proceed?
database_consumer_wizard_disable_referential_integrity_label = Disable referential integrity checks during the transfer
database_consumer_wizard_disable_referential_integrity_tip = Disables referential integrity checks during the transfer. Be warned that it can lead to all sorts of problems!
database_consumer_wizard_disable_referential_integrity_tip_no_caveats = Disables referential integrity checks during the transfer. Be warned that potentially it can lead to all sorts of problems!
database_consumer_wizard_disable_referential_integrity_tip_with_caveats = Disables referential integrity checks during the transfer. Be warned that potentially it can lead to all sorts of problems, including (but not limited to):
database_consumer_wizard_truncate_checkbox_title = Data truncate attention
database_consumer_wizard_disable_import_batches_label = Disable batches
database_consumer_wizard_disable_import_batches_description = Disable the use of batch imports. Import row by row.\nEnabling this function will show all import errors, but make the import process slower.
......
......@@ -22,14 +22,17 @@ import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.DBPReferentialIntegrityController;
import org.jkiss.dbeaver.model.sql.registry.SQLDialectDescriptor;
import org.jkiss.dbeaver.model.sql.registry.SQLDialectRegistry;
import org.jkiss.dbeaver.model.sql.registry.SQLInsertReplaceMethodDescriptor;
import org.jkiss.dbeaver.model.struct.DBSDataManipulator;
import org.jkiss.dbeaver.tools.transfer.DataTransferPipe;
import org.jkiss.dbeaver.tools.transfer.IDataTransferConsumer;
import org.jkiss.dbeaver.tools.transfer.IDataTransferConsumerExtension;
import org.jkiss.dbeaver.tools.transfer.database.DatabaseConsumerSettings;
import org.jkiss.dbeaver.tools.transfer.internal.DTMessages;
import org.jkiss.dbeaver.tools.transfer.ui.internal.DTUIMessages;
......@@ -38,12 +41,17 @@ import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.dialogs.ActiveWizardPage;
import org.jkiss.dbeaver.utils.HelpUtils;
import org.jkiss.utils.CommonUtils;
import org.jkiss.utils.Pair;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
public class DatabaseConsumerPageLoadSettings extends ActiveWizardPage<DataTransferWizard> {
private static final Log log = Log.getLog(DatabaseConsumerPageLoadSettings.class);
private final String HELP_TOPIC_REPLACE_METHOD = "Data-Import-and-Replace";
private Button transferAutoGeneratedColumns;
......@@ -94,10 +102,11 @@ public class DatabaseConsumerPageLoadSettings extends ActiveWizardPage<DataTrans
}
});
Pair<Boolean, String> pair = getDisableReferentialIntegrityCheckboxEnableSettingAndTooltip();
disableReferentialIntegrity = UIUtils.createCheckbox(
loadSettings,
DTUIMessages.database_consumer_wizard_disable_referential_integrity_label,
DTUIMessages.database_consumer_wizard_disable_referential_integrity_tip,
pair.getSecond(),
settings.isDisableReferentialIntegrity(),
2
);
......@@ -107,7 +116,7 @@ public class DatabaseConsumerPageLoadSettings extends ActiveWizardPage<DataTrans
settings.setDisableReferentialIntegrity(disableReferentialIntegrity.getSelection());
}
});
disableReferentialIntegrity.setEnabled(isDisablingReferentialIntegritySupported());
disableReferentialIntegrity.setEnabled(pair.getFirst());
UIUtils.createControlLabel(loadSettings, DTUIMessages.database_consumer_wizard_on_duplicate_key_insert_method_text);
onDuplicateKeyInsertMethods = new Combo(loadSettings, SWT.DROP_DOWN | SWT.READ_ONLY);
......@@ -186,22 +195,46 @@ public class DatabaseConsumerPageLoadSettings extends ActiveWizardPage<DataTrans
setControl(composite);
}
private boolean isDisablingReferentialIntegritySupported() {
boolean[] answer = new boolean[1];
@NotNull
private Pair<Boolean, String> getDisableReferentialIntegrityCheckboxEnableSettingAndTooltip() {
Collection<String> caveats = new HashSet<>();
boolean[] enableArray = new boolean[]{false};
try {
getWizard().getRunnableContext().run(false, false, monitor -> {
for (DataTransferPipe pipe: getWizard().getSettings().getDataPipes()) {
IDataTransferConsumer<?, ?> consumer = pipe.getConsumer();
if (consumer instanceof IDataTransferConsumerExtension && ((IDataTransferConsumerExtension) consumer).supportsDisablingReferentialIntegrity(monitor)) {
answer[0] = true;
return;
if (consumer instanceof DBPReferentialIntegrityController) {
DBPReferentialIntegrityController controller = (DBPReferentialIntegrityController) consumer;
try {
if (controller.supportsChangingReferentialIntegrity(monitor)) {
enableArray[0] = true;
caveats.add(controller.getCaveatsDescription(monitor));
}
} catch (DBException e) {
log.warn("Unexpected DBException when calculating UI options for disableReferentialIntegrity checkbox");
}
}
}
});
} catch (InvocationTargetException | InterruptedException e) {
} catch (InvocationTargetException e) {
log.warn("Unexpected InvocationTargetException when calculating UI options for disableReferentialIntegrity checkbox");
return new Pair<>(false, "");
} catch (InterruptedException e) {
//ignore
}
return answer[0];
boolean enable = enableArray[0];
if (!enable) {
return new Pair<>(false, "");
}
if (caveats.isEmpty() || caveats.size() == 1 && caveats.contains("")) {
return new Pair<>(true, DTUIMessages.database_consumer_wizard_disable_referential_integrity_tip_no_caveats);
}
StringBuilder tooltip = new StringBuilder(DTUIMessages.database_consumer_wizard_disable_referential_integrity_tip_with_caveats);
tooltip.append("\n");
for (String caveat: caveats) {
tooltip.append(caveat);
}
return new Pair<>(true, tooltip.toString());
}
private DatabaseConsumerSettings getSettings() {
......
......@@ -17,7 +17,6 @@
package org.jkiss.dbeaver.tools.transfer;
import org.eclipse.osgi.util.NLS;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.DBRRunnableWithProgress;
......@@ -28,13 +27,11 @@ import org.jkiss.utils.CommonUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
/**
* Data transfer job
*/
public class DataTransferJob implements DBRRunnableWithProgress {
private final CountDownLatch countDownLatch;
private DataTransferSettings settings;
private DBTTask task;
private long elapsedTime;
......@@ -44,13 +41,12 @@ public class DataTransferJob implements DBRRunnableWithProgress {
private Log log;
private DBTTaskExecutionListener listener;
public DataTransferJob(DataTransferSettings settings, DBTTask task, Locale locale, Log log, DBTTaskExecutionListener listener, @NotNull CountDownLatch countDownLatch) {
public DataTransferJob(DataTransferSettings settings, DBTTask task, Locale locale, Log log, DBTTaskExecutionListener listener) {
this.settings = settings;
this.task = task;
this.locale = locale;
this.log = log;
this.listener = listener;
this.countDownLatch = countDownLatch;
}
public DataTransferSettings getSettings() {
......@@ -67,14 +63,6 @@ public class DataTransferJob implements DBRRunnableWithProgress {
@Override
public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
runJob(monitor);
} finally {
countDownLatch.countDown();
}
}
private void runJob(@NotNull DBRProgressMonitor monitor) throws InvocationTargetException {
monitor.beginTask("Perform data transfer", 1);
hasErrors = false;
long startTime = System.currentTimeMillis();
......@@ -132,7 +120,5 @@ public class DataTransferJob implements DBRRunnableWithProgress {
} finally {
monitor.done();
}
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2021 DBeaver Corp and others
*
* 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.tools.transfer;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
public interface IDataTransferConsumerExtension {
void preTransfer(@NotNull DBRProgressMonitor monitor) throws DBException;
void postTransfer(@NotNull DBRProgressMonitor monitor) throws DBException;
boolean supportsDisablingReferentialIntegrity(@NotNull DBRProgressMonitor monitor);
}
......@@ -40,7 +40,6 @@ import org.jkiss.dbeaver.model.struct.rdb.DBSManipulationType;
import org.jkiss.dbeaver.model.struct.rdb.DBSSchema;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.tools.transfer.IDataTransferConsumer;
import org.jkiss.dbeaver.tools.transfer.IDataTransferConsumerExtension;
import org.jkiss.dbeaver.tools.transfer.IDataTransferNodePrimary;
import org.jkiss.dbeaver.tools.transfer.IDataTransferProcessor;
import org.jkiss.dbeaver.tools.transfer.internal.DTMessages;
......@@ -52,7 +51,8 @@ import java.util.*;
* Stream transfer consumer
*/
@DBSerializable("databaseTransferConsumer")
public class DatabaseTransferConsumer implements IDataTransferConsumer<DatabaseConsumerSettings, IDataTransferProcessor>, IDataTransferNodePrimary, IDataTransferConsumerExtension {
public class DatabaseTransferConsumer implements IDataTransferConsumer<DatabaseConsumerSettings, IDataTransferProcessor>,
IDataTransferNodePrimary, DBPReferentialIntegrityController {
private static final Log log = Log.getLog(DatabaseTransferConsumer.class);
private DatabaseConsumerSettings settings;
......@@ -703,29 +703,32 @@ public class DatabaseTransferConsumer implements IDataTransferConsumer<DatabaseC
CommonUtils.equalObjects(getTargetObject(), ((DatabaseTransferConsumer) obj).getTargetObject());
}
private void trySetReferentialIntegrity(@NotNull DBRProgressMonitor monitor, @Nullable DBSObject dbsObject, boolean enable) throws DBException {
if (settings.isDisableReferentialIntegrity() && dbsObject instanceof DBPReferentialIntegrityController) {
((DBPReferentialIntegrityController) dbsObject).setReferentialIntegrity(monitor, enable);
}
}
@Override
public void preTransfer(@NotNull DBRProgressMonitor monitor) throws DBException {
trySetReferentialIntegrity(monitor, checkTargetContainer(monitor), false);
public boolean supportsChangingReferentialIntegrity(@NotNull DBRProgressMonitor monitor) throws DBException {
return settings.isDisableReferentialIntegrity() && checkTargetContainer(monitor) instanceof DBPReferentialIntegrityController;
}
@Override
public void postTransfer(@NotNull DBRProgressMonitor monitor) throws DBException {
trySetReferentialIntegrity(monitor, checkTargetContainer(monitor), true);
public void setReferentialIntegrity(@NotNull DBRProgressMonitor monitor, boolean enable) throws DBException {
if (settings.isDisableReferentialIntegrity()) {
throw new DBException("Changing referential integrity is unsupported!");
}
DBSObject dbsObject = checkTargetContainer(monitor);
if (!(dbsObject instanceof DBPReferentialIntegrityController)) {
throw new DBException("Changing referential integrity is unsupported!");
}
DBPReferentialIntegrityController controller = (DBPReferentialIntegrityController) dbsObject;
controller.setReferentialIntegrity(monitor, enable);
}
@NotNull
@Override
public boolean supportsDisablingReferentialIntegrity(@NotNull DBRProgressMonitor monitor) {
try {
return checkTargetContainer(monitor) instanceof DBPReferentialIntegrityController;
} catch (DBException e) {
return false;
public String getCaveatsDescription(@NotNull DBRProgressMonitor monitor) throws DBException {
DBSObject dbsObject = checkTargetContainer(monitor);
if (dbsObject instanceof DBPReferentialIntegrityController) {
return ((DBPReferentialIntegrityController) dbsObject).getCaveatsDescription(monitor);
}
return "";
}
private class PreviewBatch implements DBSDataManipulator.ExecuteBatch {
......
......@@ -139,7 +139,10 @@ public class DTMessages extends NLS {
public static String stream_transfer_consumer_title_run_process;
public static String stream_transfer_consumer_message_error_running_process;
public static String data_transfer_task_handler_unexpected_error_title;
public static String data_transfer_task_handler_unexpected_error_message;
public static String data_transfer_task_handler_resoring_referential_integrity_unexpected_error_title;
public static String data_transfer_task_handler_resoring_referential_integrity_unexpected_error_message;
static {
// initialize resource bundle
......
......@@ -115,4 +115,9 @@ database_mapping_container_title_attributes_read_failed = Attributes read failed
database_mapping_container_message_get_attributes_from = Can't get attributes from {0}
database_transfer_consumer_task_error_occurred_during_data_load = Error occurred during data load
stream_transfer_consumer_title_run_process = Run process
stream_transfer_consumer_message_error_running_process = Error running process [{0}]
\ No newline at end of file
stream_transfer_consumer_message_error_running_process = Error running process [{0}]
data_transfer_task_handler_unexpected_error_title = Unexpected error during data transfer
data_transfer_task_handler_unexpected_error_message = Unable to finish data transfer properly due to unexpected error
data_transfer_task_handler_resoring_referential_integrity_unexpected_error_title = Unexpected error during data transfer
data_transfer_task_handler_resoring_referential_integrity_unexpected_error_message = Unable to restore referential integrity properly while performing data transfer due to unexpected error
......@@ -17,21 +17,21 @@
package org.jkiss.dbeaver.tools.transfer.task;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPReferentialIntegrityController;
import org.jkiss.dbeaver.model.runtime.DBRRunnableContext;
import org.jkiss.dbeaver.model.task.DBTTask;
import org.jkiss.dbeaver.model.task.DBTTaskExecutionListener;
import org.jkiss.dbeaver.model.task.DBTTaskHandler;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.tools.transfer.*;
import org.jkiss.dbeaver.tools.transfer.internal.DTMessages;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.*;
/**
* DTTaskHandlerTransfer
......@@ -60,54 +60,80 @@ public class DTTaskHandlerTransfer implements DBTTaskHandler {
executeWithSettings(runnableContext, task, locale, log, listener, settings[0]);
}
public void executeWithSettings(@NotNull DBRRunnableContext runnableContext, DBTTask task, @NotNull Locale locale, @NotNull Log log, @NotNull DBTTaskExecutionListener listener, DataTransferSettings settings) throws DBException {
// Start consumers
public void executeWithSettings(@NotNull DBRRunnableContext runnableContext, DBTTask task, @NotNull Locale locale,
@NotNull Log log, @NotNull DBTTaskExecutionListener listener,
DataTransferSettings settings) throws DBException {
listener.taskStarted(settings);
int indexOfLastPipeWithDisabledReferentialIntegrity = -1;
try {
indexOfLastPipeWithDisabledReferentialIntegrity = initializePipes(runnableContext, settings);
Throwable error = runDataTransferJobs(runnableContext, task, locale, log, listener, settings);
listener.taskFinished(settings, null, error);
} catch (InvocationTargetException e) {
DBWorkbench.getPlatformUI().showError(
DTMessages.data_transfer_task_handler_unexpected_error_title,
DTMessages.data_transfer_task_handler_unexpected_error_message,
e
);
throw new DBException("Error starting data transfer", e);
} catch (InterruptedException e) {
//ignore
} finally {
restoreReferentialIntegrity(
runnableContext,
settings.getDataPipes(),
indexOfLastPipeWithDisabledReferentialIntegrity
);
}
}
private int initializePipes(@NotNull DBRRunnableContext runnableContext, @NotNull DataTransferSettings settings)
throws InvocationTargetException, InterruptedException, DBException {
int[] indexOfLastPipeWithDisabledReferentialIntegrity = new int[]{-1};
DBException[] dbException = {null};
List<DataTransferPipe> dataPipes = settings.getDataPipes();
int[] lastPreTransferredPipeIndex = new int[1];
try {
runnableContext.run(true, false, monitor -> {
monitor.beginTask("Initialize pipes", dataPipes.size());
try {
for (int i = 0; i < dataPipes.size(); i++) {
DataTransferPipe pipe = dataPipes.get(i);
pipe.initPipe(settings, i, dataPipes.size());
IDataTransferConsumer<?, ?> consumer = pipe.getConsumer();
consumer.startTransfer(monitor);
if (consumer instanceof IDataTransferConsumerExtension) {
((IDataTransferConsumerExtension) consumer).preTransfer(monitor);
lastPreTransferredPipeIndex[0] = i;
runnableContext.run(true, false, monitor -> {
monitor.beginTask("Initialize pipes", dataPipes.size());
try {
for (int i = 0; i < dataPipes.size(); i++) {
DataTransferPipe pipe = dataPipes.get(i);
pipe.initPipe(settings, i, dataPipes.size());
IDataTransferConsumer<?, ?> consumer = pipe.getConsumer();
consumer.startTransfer(monitor);
if (consumer instanceof DBPReferentialIntegrityController) {
DBPReferentialIntegrityController controller = (DBPReferentialIntegrityController) consumer;
if (controller.supportsChangingReferentialIntegrity(monitor)) {
controller.setReferentialIntegrity(monitor, false);
indexOfLastPipeWithDisabledReferentialIntegrity[0] = i;
}
monitor.worked(1);
}
} catch (DBException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
monitor.worked(1);
}
});
} catch (InvocationTargetException e) {
try {
executePostTransfer(runnableContext, dataPipes.subList(0, lastPreTransferredPipeIndex[0] + 1));
} catch (DBException postTransferException) {
throw new DBException("Error starting data transfer and cleaning up after unsuccessful start!");
} catch (DBException e) {
dbException[0] = e;
} finally {
monitor.done();
}
throw new DBException("Error starting data transfer", e.getTargetException());
} catch (InterruptedException e) {
executePostTransfer(runnableContext, dataPipes);
return;
});
if (dbException[0] != null) {
throw dbException[0];
}
// Schedule jobs for data providers
return indexOfLastPipeWithDisabledReferentialIntegrity[0];
}
@Nullable
private Throwable runDataTransferJobs(@NotNull DBRRunnableContext runnableContext, DBTTask task, @NotNull Locale locale,
@NotNull Log log, @NotNull DBTTaskExecutionListener listener,
@NotNull DataTransferSettings settings) {
int totalJobs = settings.getDataPipes().size();
if (totalJobs > settings.getMaxJobCount()) {
totalJobs = settings.getMaxJobCount();
}
CountDownLatch countDownLatch = new CountDownLatch(totalJobs);
Throwable error = null;
for (int i = 0; i < totalJobs; i++) {
DataTransferJob job = new DataTransferJob(settings, task, locale, log, listener, countDownLatch);
DataTransferJob job = new DataTransferJob(settings, task, locale, log, listener);
try {
runnableContext.run(true, true, job);
} catch (InvocationTargetException e) {
......@@ -117,46 +143,47 @@ public class DTTaskHandlerTransfer implements DBTTaskHandler {
}
listener.subTaskFinished(error);
}
listener.taskFinished(settings, null, error);
try {
countDownLatch.await();
} catch (InterruptedException e) {
//ignore
} finally {
executePostTransfer(runnableContext, dataPipes);
}
return error;
}
private void executePostTransfer(@NotNull DBRRunnableContext runnableContext, @NotNull Collection<DataTransferPipe> pipes) throws DBException {
private void restoreReferentialIntegrity(@NotNull DBRRunnableContext runnableContext, @NotNull List<DataTransferPipe> pipes,
int toIndexInclusive) throws DBException {
List<DataTransferPipe> affectedPipes = pipes.subList(0, toIndexInclusive + 1);
boolean[] dbExceptionWasThrown = new boolean[]{false};
try {
runnableContext.run(true, false, monitor -> {
StringBuilder errorMessages = new StringBuilder();
monitor.beginTask("Post transfer work", pipes.size());
try {
for (DataTransferPipe pipe: pipes) {
if (pipe.getConsumer() instanceof IDataTransferConsumerExtension) {
try {
((IDataTransferConsumerExtension) pipe.getConsumer()).postTransfer(monitor);
} catch (DBException e) {
if (errorMessages.length() != 0) {
errorMessages.append("\n\n");
}
errorMessages.append(e.getMessage());
monitor.beginTask("Post transfer work", affectedPipes.size());
for (DataTransferPipe pipe: affectedPipes) {
IDataTransferConsumer<?, ?> consumer = pipe.getConsumer();
if (!(consumer instanceof DBPReferentialIntegrityController)) {
continue;
}
DBPReferentialIntegrityController controller = (DBPReferentialIntegrityController) consumer;
try {
if (controller.supportsChangingReferentialIntegrity(monitor)) {
controller.setReferentialIntegrity(monitor, true);
}
} catch (DBException e) {
dbExceptionWasThrown[0] = true;
}
monitor.worked(1);
}
} finally {
monitor.done();
}
if (errorMessages.length() != 0) {
throw new InvocationTargetException(new DBException("Possible data integrity problems! Unable to execute post transfer due to the following errors: \n" + errorMessages.toString()));
}
});
} catch (InterruptedException e) {
throw new DBException("Unable to finish post transfer properly. It means possible data integrity problems!");
//ignore
} catch (InvocationTargetException e) {
throw (DBException) e.getCause();
DBWorkbench.getPlatformUI().showError(
DTMessages.data_transfer_task_handler_resoring_referential_integrity_unexpected_error_title,
DTMessages.data_transfer_task_handler_resoring_referential_integrity_unexpected_error_message,
e
);
}
if (dbExceptionWasThrown[0]) {
throw new DBException("Unable to restore referential integrity properly");
}
}
}
......@@ -24,10 +24,7 @@ import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ext.postgresql.PostgreUtils;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreSchema;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableColumn;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableConstraint;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableRegular;
import org.jkiss.dbeaver.ext.postgresql.model.*;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
......@@ -47,8 +44,7 @@ import java.util.List;
/**
* GreenplumTable
*/
public class GreenplumTable extends PostgreTableRegular {
public class GreenplumTable extends PostgreForkTable {
private static final Log log = Log.getLog(GreenplumTable.class);
private int[] distributionColumns;
......@@ -207,5 +203,4 @@ public class GreenplumTable extends PostgreTableRegular {
}
}
}
}
......@@ -46,7 +46,8 @@ import java.util.*;
/**
* OracleTable
*/
public class OracleTable extends OracleTablePhysical implements DBPScriptObject, DBDPseudoAttributeContainer, DBPObjectStatistics, DBPImageProvider, DBPReferentialIntegrityController {
public class OracleTable extends OracleTablePhysical implements DBPScriptObject, DBDPseudoAttributeContainer,
DBPObjectStatistics, DBPImageProvider, DBPReferentialIntegrityController {
private static final Log log = Log.getLog(OracleTable.class);
private OracleDataType tableType;
......@@ -452,4 +453,15 @@ public class OracleTable extends OracleTablePhysical implements DBPScriptObject,
}
}
}
@Override
public boolean supportsChangingReferentialIntegrity(@NotNull DBRProgressMonitor monitor) {
return true;
}
@NotNull
@Override
public String getCaveatsDescription(@NotNull DBRProgressMonitor monitor) {
return "Oracle tables: all foreign key constraints will be either enabled or disabled";
}
}
package org.jkiss.dbeaver.ext.postgresql.model;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import java.sql.ResultSet;
public abstract class PostgreForkTable extends PostgreTableRegular {
public PostgreForkTable(PostgreSchema catalog) {
super(catalog);
}
public PostgreForkTable(PostgreSchema catalog, ResultSet dbResult) {
super(catalog, dbResult);
}
@Override
public boolean supportsChangingReferentialIntegrity(@NotNull DBRProgressMonitor monitor) {
return false;
}
@Override
public void setReferentialIntegrity(@NotNull DBRProgressMonitor monitor, boolean enable) throws DBException {
throw new DBException("Changing referential integrity is not supported");
}
@NotNull
@Override
public String getCaveatsDescription(@NotNull DBRProgressMonitor monitor) {
return "";
}
}
......@@ -16,16 +16,22 @@
*/
package org.jkiss.dbeaver.ext.postgresql.model;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.DBPEvaluationContext;
import org.jkiss.dbeaver.model.DBPReferentialIntegrityController;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* PostgreTableRegular
*/
public class PostgreTableRegular extends PostgreTable
{
public class PostgreTableRegular extends PostgreTable implements DBPReferentialIntegrityController {
public PostgreTableRegular(PostgreSchema catalog)
{
super(catalog);
......@@ -35,11 +41,37 @@ public class PostgreTableRegular extends PostgreTable
super(monitor, catalog, source, false);
}
public PostgreTableRegular(
PostgreSchema catalog,
ResultSet dbResult)
{
public PostgreTableRegular(PostgreSchema catalog, ResultSet dbResult) {
super(catalog, dbResult);
}
@Override
public boolean supportsChangingReferentialIntegrity(@NotNull DBRProgressMonitor monitor) {
return true;
}
@Override
public void setReferentialIntegrity(@NotNull DBRProgressMonitor monitor, boolean enable) throws DBException {
try (JDBCSession session = DBUtils.openMetaSession(monitor, this, "Disabling referential integrity")) {
try (JDBCStatement statement = session.createStatement()) {
StringBuilder sql = new StringBuilder("ALTER TABLE ");
sql.append(getFullyQualifiedName(DBPEvaluationContext.DDL)).append(" ");
if (enable) {
sql.append("ENABLE ");
} else {
sql.append("DISABLE ");
}
sql.append("TRIGGER ALL");
statement.execute(sql.toString());
} catch (SQLException e) {
throw new DBException("Unable to change referential integrity", e);
}
}
}
@NotNull
@Override
public String getCaveatsDescription(@NotNull DBRProgressMonitor monitor) {
return "PostgreSQL tables: all triggers will be either enabled or disabled";
}
}
......@@ -17,8 +17,8 @@
package org.jkiss.dbeaver.ext.postgresql.model.impls.redshift;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreForkTable;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreSchema;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableRegular;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCPreparedStatement;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
......@@ -29,8 +29,7 @@ import java.sql.SQLException;
/**
* RedshiftTable base
*/
public class RedshiftTable extends PostgreTableRegular
{
public class RedshiftTable extends PostgreForkTable {
private static final Log log = Log.getLog(RedshiftTable.class);
public RedshiftTable(PostgreSchema catalog) {
......@@ -59,5 +58,4 @@ public class RedshiftTable extends PostgreTableRegular
diskSpace = dbResult.getLong("size") * 1024 * 1024;
rowCountEstimate = rowCount = dbResult.getLong("tbl_rows");
}
}
......@@ -21,5 +21,20 @@ import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
public interface DBPReferentialIntegrityController {
boolean supportsChangingReferentialIntegrity(@NotNull DBRProgressMonitor monitor) throws DBException;
void setReferentialIntegrity(@NotNull DBRProgressMonitor monitor, boolean enable) throws DBException;
/**
* Returns description of things that may go wrong when changing referential integrity setting back and forth.
* When changing referential integrity is not supported, returns an empty string rather than null
* to avoid callers making redundant null checks
* (callers should check if controller supports changing referential integrity anyway).
*
* @param monitor monitor
* @return caveats description, never {@code null}
* @throws DBException if unable to retrieve caveats for any reason
*/
@NotNull
String getCaveatsDescription(@NotNull DBRProgressMonitor monitor) throws DBException;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册