/* * 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.tools.transfer.database; import org.jkiss.dbeaver.Log; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.core.CoreMessages; import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.DBUtils; import org.jkiss.dbeaver.model.data.DBDDataFilter; import org.jkiss.dbeaver.model.exec.*; import org.jkiss.dbeaver.model.impl.AbstractExecutionSource; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.struct.DBSDataContainer; import org.jkiss.dbeaver.tools.transfer.IDataTransferConsumer; import org.jkiss.dbeaver.tools.transfer.IDataTransferProducer; /** * Data container transfer producer */ public class DatabaseTransferProducer implements IDataTransferProducer<DatabaseProducerSettings> { private static final Log log = Log.getLog(DatabaseTransferProducer.class); @NotNull private DBSDataContainer dataContainer; @Nullable private DBDDataFilter dataFilter; public DatabaseTransferProducer(@NotNull DBSDataContainer dataContainer) { this.dataContainer = dataContainer; } public DatabaseTransferProducer(@NotNull DBSDataContainer dataContainer, @Nullable DBDDataFilter dataFilter) { this.dataContainer = dataContainer; this.dataFilter = dataFilter; } @Override public DBSDataContainer getSourceObject() { return dataContainer; } @Override public void transferData( DBRProgressMonitor monitor, IDataTransferConsumer consumer, DatabaseProducerSettings settings) throws DBException { String contextTask = CoreMessages.data_transfer_wizard_job_task_export; DBPDataSource dataSource = getSourceObject().getDataSource(); assert (dataSource != null); boolean newConnection = settings.isOpenNewConnections(); DBCExecutionContext context = newConnection ? dataSource.openIsolatedContext(monitor, "Data transfer producer") : dataSource.getDefaultContext(false); try (DBCSession session = context.openSession(monitor, DBCExecutionPurpose.UTIL, contextTask)) { try { AbstractExecutionSource transferSource = new AbstractExecutionSource(dataContainer, context, consumer); session.enableLogging(false); if (newConnection) { // Turn off auto-commit in source DB // Auto-commit has to be turned off because some drivers allows to read LOBs and // other complex structures only in transactional mode try { DBCTransactionManager txnManager = DBUtils.getTransactionManager(context); if (txnManager != null) { txnManager.setAutoCommit(monitor, false); } } catch (DBCException e) { log.warn("Can't change auto-commit", e); } } long totalRows = 0; if (settings.isQueryRowCount() && (dataContainer.getSupportedFeatures() & DBSDataContainer.DATA_COUNT) != 0) { monitor.beginTask(CoreMessages.data_transfer_wizard_job_task_retrieve, 1); try { totalRows = dataContainer.countData(transferSource, session, dataFilter); } catch (Throwable e) { log.warn("Can't retrieve row count from '" + dataContainer.getName() + "'", e); try { DBCTransactionManager txnManager = DBUtils.getTransactionManager(session.getExecutionContext()); if (txnManager != null && !txnManager.isAutoCommit()) { txnManager.rollback(session, null); } } catch (Throwable e1) { log.warn("Error rolling back transaction", e1); } } finally { monitor.done(); } } monitor.beginTask(CoreMessages.data_transfer_wizard_job_task_export_table_data, (int) totalRows); try { // Perform export if (settings.getExtractType() == DatabaseProducerSettings.ExtractType.SINGLE_QUERY) { // Just do it in single query dataContainer.readData(transferSource, session, consumer, dataFilter, -1, -1, DBSDataContainer.FLAG_NONE); } else { // Read all data by segments long offset = 0; int segmentSize = settings.getSegmentSize(); for (; ; ) { DBCStatistics statistics = dataContainer.readData( transferSource, session, consumer, dataFilter, offset, segmentSize, DBSDataContainer.FLAG_NONE); if (statistics == null || statistics.getRowsFetched() < segmentSize) { // Done break; } offset += statistics.getRowsFetched(); } } } finally { monitor.done(); } //dataContainer.readData(context, consumer, dataFilter, -1, -1); } finally { if (newConnection) { DBCTransactionManager txnManager = DBUtils.getTransactionManager(context); if (txnManager != null) { try { txnManager.commit(session); } catch (DBCException e) { log.error("Can't finish transaction in data producer connection", e); } } } if (newConnection) { context.close(); } } } } }