org.jumpmind.db.platform.AbstractDatabasePlatform Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of symmetric-db Show documentation
Show all versions of symmetric-db Show documentation
This library is a fork of Apache DdlUtils. DdlUtils is a small, easy-to-use component for working with Database Definition (DDL) files.
package org.jumpmind.db.platform;
/*
* 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.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Array;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.jumpmind.db.io.DatabaseXmlUtil;
import org.jumpmind.db.model.Column;
import org.jumpmind.db.model.ColumnTypes;
import org.jumpmind.db.model.Database;
import org.jumpmind.db.model.ForeignKey;
import org.jumpmind.db.model.IIndex;
import org.jumpmind.db.model.IndexColumn;
import org.jumpmind.db.model.Reference;
import org.jumpmind.db.model.Table;
import org.jumpmind.db.model.TypeMap;
import org.jumpmind.db.sql.DmlStatement;
import org.jumpmind.db.sql.DmlStatement.DmlType;
import org.jumpmind.db.sql.ISqlTemplate;
import org.jumpmind.db.sql.Row;
import org.jumpmind.db.sql.SqlScript;
import org.jumpmind.db.util.BinaryEncoding;
import org.jumpmind.exception.IoException;
import org.jumpmind.util.FormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
* Base class for platform implementations.
*/
public abstract class AbstractDatabasePlatform implements IDatabasePlatform {
/* The log for this platform. */
protected final Logger log = LoggerFactory.getLogger(getClass());
public static final String REQUIRED_FIELD_NULL_SUBSTITUTE = " ";
/* The default name for models read from the database, if no name as given. */
protected static final String MODEL_DEFAULT_NAME = "default";
/* The model reader for this platform. */
protected IDdlReader ddlReader;
protected IDdlBuilder ddlBuilder;
protected Map tableCache = new HashMap();
private long lastTimeCachedModelClearedInMs = System.currentTimeMillis();
protected long clearCacheModelTimeoutInMs = DateUtils.MILLIS_PER_HOUR;
protected String defaultSchema;
protected String defaultCatalog;
protected Boolean storesUpperCaseIdentifiers;
protected Boolean storesLowerCaseIdentifiers;
protected Boolean storesMixedCaseIdentifiers;
protected boolean metadataIgnoreCase = true;
public AbstractDatabasePlatform() {
}
public DatabaseInfo getDatabaseInfo() {
return getDdlBuilder().getDatabaseInfo();
}
abstract public ISqlTemplate getSqlTemplate();
public DmlStatement createDmlStatement(DmlType dmlType, Table table) {
return createDmlStatement(dmlType, table.getCatalog(), table.getSchema(), table.getName(),
table.getPrimaryKeyColumns(), table.getColumns(), null);
}
public DmlStatement createDmlStatement(DmlType dmlType, String catalogName, String schemaName,
String tableName, Column[] keys, Column[] columns, boolean[] nullKeyValues) {
return DmlStatementFactory.createDmlStatement(getName(), dmlType, catalogName, schemaName,
tableName, keys, columns, nullKeyValues, getDdlBuilder());
}
public IDdlReader getDdlReader() {
return ddlReader;
}
public IDdlBuilder getDdlBuilder() {
return ddlBuilder;
}
public void setClearCacheModelTimeoutInMs(long clearCacheModelTimeoutInMs) {
this.clearCacheModelTimeoutInMs = clearCacheModelTimeoutInMs;
}
public long getClearCacheModelTimeoutInMs() {
return clearCacheModelTimeoutInMs;
}
public void dropTables(boolean continueOnError, Table...tables) {
Database db = new Database();
for (Table table : tables) {
db.addTable(table);
}
dropDatabase(db, continueOnError);
}
public void dropDatabase(Database database, boolean continueOnError) {
String sql = ddlBuilder.dropTables(database);
new SqlScript(sql, getSqlTemplate(), !continueOnError, null).execute(true);
}
public void createTables(boolean dropTablesFirst, boolean continueOnError, Table... tables) {
Database database = new Database();
database.addTables(tables);
createDatabase(database, dropTablesFirst, continueOnError);
}
public void createDatabase(Database targetDatabase, boolean dropTablesFirst,
boolean continueOnError) {
if (dropTablesFirst) {
dropDatabase(targetDatabase, true);
}
String createSql = ddlBuilder.createTables(targetDatabase, false);
if (log.isDebugEnabled()) {
log.debug("Generated create sql: \n{}", createSql);
}
String delimiter = getDdlBuilder().getDatabaseInfo().getSqlCommandDelimiter();
new SqlScript(createSql, getSqlTemplate(), !continueOnError, false, false, delimiter, null).execute();
}
public void alterDatabase(Database desiredDatabase, boolean continueOnError) {
alterTables(continueOnError, desiredDatabase.getTables());
}
public void alterTables(boolean continueOnError, Table... desiredTables) {
Database currentDatabase = new Database();
Database desiredDatabase = new Database();
StringBuilder tablesProcessed = new StringBuilder();
for (Table table : desiredTables) {
tablesProcessed.append(table.getFullyQualifiedTableName());
tablesProcessed.append(", ");
desiredDatabase.addTable(table);
Table currentTable = ddlReader.readTable(table.getCatalog(), table.getSchema(),
table.getName());
if (currentTable != null) {
currentDatabase.addTable(currentTable);
}
}
if (tablesProcessed.length() > 1) {
tablesProcessed.replace(tablesProcessed.length() - 2, tablesProcessed.length(), "");
}
String alterSql = ddlBuilder.alterDatabase(currentDatabase, desiredDatabase);
if (StringUtils.isNotBlank(alterSql.trim())) {
log.info("Running alter sql:\n{}", alterSql);
String delimiter = getDdlBuilder().getDatabaseInfo().getSqlCommandDelimiter();
new SqlScript(alterSql, getSqlTemplate(), !continueOnError, false, false, delimiter, null).execute(getDatabaseInfo().isRequiresAutoCommitForDdl());
} else {
log.info("Tables up to date. No alters found for {}", tablesProcessed);
}
}
public Database readDatabase(String catalog, String schema, String[] tableTypes) {
Database model = ddlReader.readTables(catalog, schema, tableTypes);
if ((model.getName() == null) || (model.getName().length() == 0)) {
model.setName(MODEL_DEFAULT_NAME);
}
return model;
}
public Database readFromDatabase(Table... tables) {
Database fromDb = new Database();
for (Table tableFromXml : tables) {
Table tableFromDatabase = getTableFromCache(getDefaultCatalog(),
getDefaultSchema(), tableFromXml.getName(), true);
if (tableFromDatabase != null) {
fromDb.addTable(tableFromDatabase);
}
}
return fromDb;
}
public Table readTableFromDatabase(String catalogName, String schemaName, String tableName) {
String originalFullyQualifiedName = Table.getFullyQualifiedTableName(catalogName,
schemaName, tableName);
catalogName = catalogName == null ? getDefaultCatalog() : catalogName;
schemaName = schemaName == null ? getDefaultSchema() : schemaName;
Table table = ddlReader.readTable(catalogName, schemaName, tableName);
if (table == null && metadataIgnoreCase) {
if (isStoresUpperCaseIdentifiers()) {
catalogName = StringUtils.upperCase(catalogName);
schemaName = StringUtils.upperCase(schemaName);
tableName = StringUtils.upperCase(tableName);
// if we didn't find the table, the database stores upper case,
// and the catalog, schema or table were not in upper case
// already then it is probably stored in uppercase
if (!originalFullyQualifiedName.equals(Table.getFullyQualifiedTableName(
catalogName, schemaName, tableName))) {
table = ddlReader.readTable(catalogName, schemaName, tableName);
}
} else if (isStoresLowerCaseIdentifiers()) {
catalogName = StringUtils.lowerCase(catalogName);
schemaName = StringUtils.lowerCase(schemaName);
tableName = StringUtils.lowerCase(tableName);
// if we didn't find the table, the database stores lower case,
// and the catalog, schema or table were not in lower case
// already then it is probably stored in uppercase
if (!originalFullyQualifiedName.equals(Table.getFullyQualifiedTableName(
catalogName, schemaName, tableName))) {
table = ddlReader.readTable(catalogName, schemaName, tableName);
}
} else {
tableName = StringUtils.lowerCase(tableName);
// Last ditch lower case effort. This case applied to
// symmetricds tables stored in a mixed case schema or catalog
// whose default case is different on the source system than on
// the target system.
if (!originalFullyQualifiedName.equals(Table.getFullyQualifiedTableName(
catalogName, schemaName, tableName))) {
table = ddlReader.readTable(catalogName, schemaName, tableName);
}
}
if (table == null) {
// Last ditch upper case effort. This case applied to
// symmetricds tables stored in a mixed case schema or catalog
// whose default case is different on the source system than on
// the target system.
tableName = StringUtils.upperCase(tableName);
if (!originalFullyQualifiedName.equals(Table.getFullyQualifiedTableName(
catalogName, schemaName, tableName))) {
table = ddlReader.readTable(catalogName, schemaName, tableName);
}
}
}
if (table != null && log.isDebugEnabled()) {
log.debug("Just read table: \n{}", table.toVerboseString());
}
return table;
}
public void resetCachedTableModel() {
synchronized (this.getClass()) {
this.tableCache = new HashMap();
lastTimeCachedModelClearedInMs = System.currentTimeMillis();
}
}
public Table getTableFromCache(String tableName, boolean forceReread) {
return getTableFromCache(null, null, tableName, forceReread);
}
public Table getTableFromCache(String catalogName, String schemaName, String tableName,
boolean forceReread) {
if (System.currentTimeMillis() - lastTimeCachedModelClearedInMs > clearCacheModelTimeoutInMs) {
resetCachedTableModel();
}
catalogName = catalogName == null ? getDefaultCatalog() : catalogName;
schemaName = schemaName == null ? getDefaultSchema() : schemaName;
Map model = tableCache;
String key = Table.getFullyQualifiedTableName(catalogName, schemaName, tableName);
Table retTable = model != null ? model.get(key) : null;
if (retTable == null || forceReread) {
synchronized (this.getClass()) {
try {
Table table = readTableFromDatabase(catalogName, schemaName, tableName);
tableCache.put(key, table);
retTable = table;
} catch (RuntimeException ex) {
throw ex;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
return retTable;
}
public Object[] getObjectValues(BinaryEncoding encoding, Table table, String[] columnNames,
String[] values) {
Column[] metaData = Table.orderColumns(columnNames, table);
return getObjectValues(encoding, values, metaData);
}
public Object[] getObjectValues(BinaryEncoding encoding, Table table, String[] columnNames,
String[] values, boolean useVariableDates) {
Column[] metaData = Table.orderColumns(columnNames, table);
return getObjectValues(encoding, values, metaData, useVariableDates);
}
public Object[] getObjectValues(BinaryEncoding encoding, String[] values,
Column[] orderedMetaData) {
return getObjectValues(encoding, values, orderedMetaData, false);
}
public Object[] getObjectValues(BinaryEncoding encoding, String[] values,
Column[] orderedMetaData, boolean useVariableDates) {
if (values != null) {
List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy