/* * Copyright 2007 - 2017 the original author or authors. * * 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 net.sf.jailer.api; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.sql.SQLException; import java.util.Map; import javax.sql.DataSource; import org.xml.sax.SAXException; import net.sf.jailer.ExecutionContext; import net.sf.jailer.configuration.DBMS; import net.sf.jailer.database.BasicDataSource; import net.sf.jailer.database.WorkingTableScope; import net.sf.jailer.subsetting.ScriptFormat; import net.sf.jailer.subsetting.SubsettingEngine; /** * Generates a subset of a relational database that respects foreign key constraints. <br> * * @author Ralf Wisser */ public class Subsetter { /** * Default constructor. */ public Subsetter() { executionContext = new ExecutionContext(); } /** * Copy constructor. */ public Subsetter(Subsetter other) { this.dataSource = other.dataSource; this.modelPoolSize = other.modelPoolSize; this.dbms = other.dbms; this.executionContext = new ExecutionContext(other.executionContext); this.extractionModelURL = other.extractionModelURL; } /** * Creates a new Subsetter with all mandatory attributes. * * @param dataSource the data-source to connect with the source database * @param dbms the DBMS of the source database * @param dataModel URL of the current data model (the datamodel's base folder) * @param extractionModel URL of the extraction model * @param scriptFormat script format */ public Subsetter( DataSource dataSource, DBMS dbms, URL dataModel, URL extractionModel, ScriptFormat scriptFormat) { executionContext = new ExecutionContext(); setDataSource(dataSource); setDbms(dbms); setDataModelURL(dataModel); setExtractionModelURL(extractionModel); setScriptFormat(scriptFormat); } /** * Creates a new Subsetter with all mandatory attributes. * * @param dataSource the data-source to connect with the source database * @param dbms the DBMS of the source database * @param dataModel the current data model (the datamodel's base folder) * @param extractionModel the extraction model * @param scriptFormat script format */ public Subsetter( DataSource dataSource, DBMS dbms, File dataModel, File extractionModel, ScriptFormat scriptFormat) { executionContext = new ExecutionContext(); setDataSource(dataSource); setDbms(dbms); try { setDataModelURL(dataModel.toURI().toURL()); setExtractionModelURL(extractionModel.toURI().toURL()); } catch (MalformedURLException e) { throw new RuntimeException(e); } setScriptFormat(scriptFormat); } /** * Generates the export-script. * @param whereClause if not <code>null</code>, overrides the extraction model's subject condition * * @param exportScriptFile the export-script file (compressed if it ends with '.zip' or '.gz') */ public void execute(String whereClause, File exportScriptFile) throws SQLException, IOException { execute(whereClause, exportScriptFile, null); } /** * Generates the export- and/or delete-script. * * @param whereClause if not <code>null</code>, overrides the extraction model's subject condition * @param exportScriptFile the export-script file (compressed if it ends with '.zip' or '.gz'), optional * @param deleteScriptFile the delete-script file (compressed if it ends with '.zip' or '.gz'), optional */ public void execute(String whereClause, File exportScriptFile, File deleteScriptFile) throws SQLException, IOException { try { if (getDataModelURL() == null) { throw new IllegalStateException("missing DataModelURL"); } if (getExtractionModelURL() == null) { throw new IllegalStateException("missing ExtractionModelURL"); } if (getDataSource() == null) { throw new IllegalStateException("missing DataSource"); } if (getScriptFormat() == null) { throw new IllegalStateException("missing ScriptFormat"); } DBMS sourceDBMS = getDbms(); if (sourceDBMS == null) { if (getDataSource() instanceof BasicDataSource) { sourceDBMS = ((BasicDataSource) getDataSource()).dbms; } else { throw new IllegalStateException("no DBMS set but data-source is not net.sf.jailer.database.BasicDataSource"); } } new SubsettingEngine(executionContext).export( whereClause, getExtractionModelURL(), exportScriptFile == null? null : exportScriptFile.getAbsolutePath(), deleteScriptFile == null? null : deleteScriptFile.getAbsolutePath(), getDataSource(), sourceDBMS, false, getScriptFormat(), getModelPoolSize()); } catch (SAXException e) { throw new RuntimeException(e); } } /** * Gets the data-source to connect with the database. * * @return the data-source to connect with the database */ public DataSource getDataSource() { return dataSource; } /** * Sets the data-source to connect with the database. * * @param dataSource the data-source to connect with the database */ public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } /** * Gets the DBMS of the database. * * @return the DBMS */ public DBMS getDbms() { return dbms; } /** * Sets the DBMS of the database. <br> * Note that it's not necessary to set the DBMS if {@link BasicDataSource} is used. * * @param dbms the DBMS */ public void setDbms(DBMS dbms) { this.dbms = dbms; } /** * Gets URL of the current data model (the datamodel's base folder) */ public URL getDataModelURL() { return executionContext.getDataModelURL(); } /** * Sets URL of the current data model (the datamodel's base folder) */ public void setDataModelURL(URL datamodelURL) { executionContext.setDataModelURL(datamodelURL); } /** * Sets the current data model as {@link File} * * @param datamodelBaseFolder represents the folder. Will be converted to an URL an set as datamodel URL * * @see #setDataModelURL(URL) */ public void setDataModelBaseFolder(File datamodelBaseFolder) { try { setDataModelURL(datamodelBaseFolder.toURI().toURL()); } catch (MalformedURLException e) { throw new RuntimeException(e); } } /** * Gets the URL of the extraction model. * * @return the URL of the extraction model */ public URL getExtractionModelURL() { return extractionModelURL; } /** * Sets the URL of the extraction model. * * @param extractionModelURL the URL of the extraction model */ public void setExtractionModelURL(URL extractionModelURL) { this.extractionModelURL = extractionModelURL; } /** * Gets the script format. * * @return the script format */ public ScriptFormat getScriptFormat() { return executionContext.getScriptFormat(); } /** * Sets the script format. * * @return the script format */ public void setScriptFormat(ScriptFormat scriptFormat) { executionContext.setScriptFormat(scriptFormat); } /** * If <code>true</code>, Use uTF-8 encoding * * @return <code>true</code> if use UTF-8 encoding */ public boolean getUTF8() { return executionContext.getUTF8(); } /** * If <code>true</code>, use UTF-8 encoding * * @param uTF8 * <code>true</code> if use UTF-8 encoding */ public void setUTF8(boolean uTF8) { executionContext.setUTF8(uTF8); } /** * Gets target-DBMS. * * @return target-DBMS */ public DBMS getTargetDBMS() { return executionContext.getTargetDBMS(); } /** * Sets target-DBMS. * * @param targetDBMS target-DBMS. If it's <code>null</code>, target DBMS is assumed to be the same as {@link #getDbms()} */ public void setTargetDBMS(DBMS targetDBMS) { executionContext.setTargetDBMS(targetDBMS); } /** * Gets root tag of XML export file * * @return root tag of XML export file */ public String getXmlRootTag() { return executionContext.getXmlRootTag(); } /** * Sets root tag of XML export file * * @param xmlRootTag * root tag of XML export file */ public void setXmlRootTag(String xmlRootTag) { executionContext.setXmlRootTag(xmlRootTag); } /** * Gets pattern for dates in XML and LIQUIBASE_XML export file * * @return pattern for dates in XML and LIQUIBASE_XML export file */ public String getXmlDatePattern() { return executionContext.getXmlDatePattern(); } /** * Sets pattern for dates in XML and LIQUIBASE_XML export file * * @param xmlDatePattern * pattern for dates in XML and LIQUIBASE_XML export file */ public void setXmlDatePattern(String xmlDatePattern) { executionContext.setXmlDatePattern(xmlDatePattern); } /** * Gets pattern for times in XML and LIQUIBASE_XML export file * * @return pattern for times in XML and LIQUIBASE_XML export file */ public String getXmlTimePattern() { return executionContext.getXmlTimePattern(); } /** * Sets pattern for times in XML and LIQUIBASE_XML export file * * @param xmlTimePattern * pattern for times in XML and LIQUIBASE_XML export file */ public void setXmlTimePattern(String xmlTimePattern) { executionContext.setXmlTimePattern(xmlTimePattern); } /** * Gets pattern for time-stamps in XML and LIQUIBASE_XML export file * * @return pattern for time-stamps in XML and LIQUIBASE_XML export file */ public String getXmlTimeStampPattern() { return executionContext.getXmlTimeStampPattern(); } /** * Sets pattern for time-stamps in XML and LIQUIBASE_XML export file * * @param xmlTimeStampPattern * pattern for time-stamps in XML and LIQUIBASE_XML export file */ public void setXmlTimeStampPattern(String xmlTimeStampPattern) { executionContext.setXmlTimeStampPattern(xmlTimeStampPattern); } /** * Gets number of parallel threads (default is 1) to be used. * * @return number of threads (default is 1) */ public int getNumberOfThreads() { return executionContext.getNumberOfThreads(); } /** * Sets number of parallel threads (default is 1) to be used * * @param numberOfThreads * number of threads */ public void setNumberOfThreads(int numberOfThreads) { executionContext.setNumberOfThreads(numberOfThreads); } /** * Gets maximum number of entities per insert-statement (in export-file, * default is 10) * * @return maximum number of entities per insert-statement (in export-file, * default is 10) */ public int getNumberOfEntities() { return executionContext.getNumberOfEntities(); } /** * Sets maximum number of entities per insert-statement (in export-file, * default is 10) * * @param numberOfEntities * maximum number of entities per insert-statement (in * export-file, default is 10) */ public void setNumberOfEntities(int numberOfEntities) { executionContext.setNumberOfEntities(numberOfEntities); } /** * If <code>true</code>, Generate 'upsert'-statements for all entities (in * export-file) * * @return <code>true</code> if Generate 'upsert'-statements for all * entities (in export-file) */ public boolean getUpsertOnly() { return executionContext.getUpsertOnly(); } /** * If <code>true</code>, Generate 'upsert'-statements for all entities (in * export-file) * * @param upsertOnly * <code>true</code> if Generate 'upsert'-statements for all * entities (in export-file) */ public void setUpsertOnly(boolean upsertOnly) { executionContext.setUpsertOnly(upsertOnly); } /** * Gets scope of working tables, GLOBAL, SESSION_LOCAL or LOCAL_DATABASE <br> * Default is GLOBAL. * * @return scope of working tables, GLOBAL, SESSION_LOCAL or LOCAL_DATABASE */ public WorkingTableScope getScope() { return executionContext.getScope(); } /** * Sets scope of working tables, GLOBAL, SESSION_LOCAL or LOCAL_DATABASE * * @param scope * scope of working tables, GLOBAL, SESSION_LOCAL or * LOCAL_DATABASE */ public void setScope(WorkingTableScope scope) { executionContext.setScope(scope); } /** * Gets schema in which the working tables will be created * * @return schema in which the working tables will be created */ public String getWorkingTableSchema() { return executionContext.getWorkingTableSchema(); } /** * Sets schema in which the working tables will be created * * @param workingTableSchema * schema in which the working tables will be created */ public void setWorkingTableSchema(String workingTableSchema) { executionContext.setWorkingTableSchema(workingTableSchema); } /** * If <code>true</code>, The exported rows will not be sorted according to * foreign key constraints * * @return <code>true</code> if The exported rows will not be sorted * according to foreign key constraints */ public boolean getNoSorting() { return executionContext.getNoSorting(); } /** * If <code>true</code>, The exported rows will not be sorted according to * foreign key constraints * * @param noSorting * <code>true</code> if The exported rows will not be sorted * according to foreign key constraints */ public void setNoSorting(boolean noSorting) { executionContext.setNoSorting(noSorting); } /** * If <code>true</code>, Use primary keys to determine row identity (instead * of rowid-column) * * @return <code>true</code> if Use primary keys to determine row identity * (instead of rowid-column) */ public boolean getNoRowid() { return executionContext.getNoRowid(); } /** * If <code>true</code>, Use primary keys to determine row identity (instead * of rowid-column) * * @param noRowid * <code>true</code> if Use primary keys to determine row * identity (instead of rowid-column) */ public void setNoRowid(boolean noRowid) { executionContext.setNoRowid(noRowid); } /** * Gets schema in which the import-filter mapping tables will be created * * @return schema in which the import-filter mapping tables will be created */ public String getImportFilterMappingTableSchema() { return executionContext.getImportFilterMappingTableSchema(); } /** * Sets schema in which the import-filter mapping tables will be created * * @param importFilterMappingTableSchema * schema in which the import-filter mapping tables will be * created */ public void setImportFilterMappingTableSchema(String importFilterMappingTableSchema) { executionContext.setImportFilterMappingTableSchema(importFilterMappingTableSchema); } /** * Gets parameters * TODO * @return parameters */ public Map<String, String> getParameters() { return executionContext.getParameters(); } /** * Sets a parameter. * * @param name parameter name * @param value value */ public void setParameter(String name, String value) { executionContext.setParameter(name, value); } public Map<String, String> getSchemaMapping() { return executionContext.getSchemaMapping(); } /** * Sets source schema map * TODO * @param rawsourceschemamapping * source schema map */ public void setSchemaMapping(Map<String, String> schemaMapping) { executionContext.setSchemaMapping(schemaMapping); } /** * TODO * * @param sourceSchemaMapping the sourceSchemaMapping to set */ public void setSourceSchemaMapping(Map<String, String> sourceSchemaMapping) { executionContext.setSourceSchemaMapping(sourceSchemaMapping); } public Map<String, String> getSourceSchemaMapping() { return executionContext.getSourceSchemaMapping(); } /** * @return the size of extraction-model pool (default is 10) */ public int getModelPoolSize() { return modelPoolSize; } /** * @param modelPoolSize size of extraction-model pool (default is 10) */ public void setModelPoolSize(int modelPoolSize) { this.modelPoolSize = modelPoolSize; } private final ExecutionContext executionContext; private int modelPoolSize = 10; private URL extractionModelURL; private DataSource dataSource; private DBMS dbms; }