blob: 4bb34c2778029bb13a884c5ec449b3d1f8279930 [file] [log] [blame]
/*
* Copyright (c) 2008, 2013, 2015 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.net4j.internal.db.ddl;
import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBUtil;
import org.eclipse.net4j.db.IDBAdapter;
import org.eclipse.net4j.db.IDBConnectionProvider;
import org.eclipse.net4j.db.IDBRowHandler;
import org.eclipse.net4j.db.ddl.IDBField;
import org.eclipse.net4j.db.ddl.IDBIndex;
import org.eclipse.net4j.db.ddl.IDBIndexField;
import org.eclipse.net4j.db.ddl.IDBSchema;
import org.eclipse.net4j.db.ddl.IDBSchemaElement;
import org.eclipse.net4j.db.ddl.IDBSchemaVisitor;
import org.eclipse.net4j.db.ddl.IDBTable;
import org.eclipse.net4j.db.ddl.SchemaElementNotFoundException;
import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta;
import org.eclipse.net4j.internal.db.ddl.delta.DBSchemaDelta;
import org.eclipse.net4j.spi.db.ddl.InternalDBSchema;
import javax.sql.DataSource;
import java.io.PrintStream;
import java.sql.Connection;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Eike Stepper
*/
public class DBSchema extends DBSchemaElement implements InternalDBSchema
{
private static final long serialVersionUID = 1L;
private static int indexCounter;
private Map<String, IDBTable> tables = new HashMap<String, IDBTable>();
private transient boolean locked;
public DBSchema(String name)
{
super(name);
}
/**
* @since 4.2
*/
public DBSchema(IDBSchema source)
{
super(source.getName());
for (IDBTable sourceTable : source.getTables())
{
IDBTable table = addTable(sourceTable.getName());
for (IDBField sourceField : sourceTable.getFields())
{
table.addField(sourceField.getName(), sourceField.getType(), sourceField.getPrecision(), sourceField.getScale(),
sourceField.isNotNull());
}
for (IDBIndex sourceIndex : sourceTable.getIndices())
{
IDBIndex index = table.addIndexEmpty(sourceIndex.getName(), sourceIndex.getType());
for (IDBField sourceField : sourceIndex.getFields())
{
IDBField field = table.getField(sourceField.getPosition());
index.addIndexField(field);
}
}
}
}
/**
* Constructor for deserialization.
*
* @since 4.2
*/
protected DBSchema()
{
}
@Override
public IDBSchema getWrapper()
{
return (IDBSchema)super.getWrapper();
}
/**
* @since 4.2
*/
public SchemaElementType getSchemaElementType()
{
return SchemaElementType.SCHEMA;
}
public IDBSchema getSchema()
{
return this;
}
/**
* @since 4.2
*/
public final IDBSchemaElement getParent()
{
return null;
}
public String getFullName()
{
return getName();
}
/**
* @since 4.2
*/
@SuppressWarnings("unchecked")
public final <T extends IDBSchemaElement> T findElement(IDBSchemaElement prototype)
{
SchemaElementType schemaElementType = prototype.getSchemaElementType();
switch (schemaElementType)
{
case SCHEMA:
return (T)(prototype.equals(this) ? this : null);
case TABLE:
return (T)getElement(IDBTable.class, prototype.getName());
case FIELD:
{
IDBTable table = getElement(IDBTable.class, prototype.getParent().getName());
if (table == null)
{
return null;
}
return (T)table.getElement(IDBField.class, prototype.getName());
}
case INDEX:
{
IDBTable table = getElement(IDBTable.class, prototype.getParent().getName());
if (table == null)
{
return null;
}
return (T)table.getElement(IDBIndex.class, prototype.getName());
}
case INDEX_FIELD:
{
IDBTable table = getElement(IDBTable.class, prototype.getParent().getParent().getName());
if (table == null)
{
return null;
}
IDBIndex index = table.getElement(IDBIndex.class, prototype.getParent().getName());
if (index == null)
{
return null;
}
return (T)index.getElement(IDBIndexField.class, prototype.getName());
}
default:
throw new IllegalStateException("Illegal schema element type: " + schemaElementType);
}
}
/**
* @since 2.0
*/
public IDBTable addTable(String name) throws DBException
{
assertUnlocked();
if (tables.containsKey(name))
{
throw new DBException("IDBTable exists: " + name); //$NON-NLS-1$
}
IDBTable table = new DBTable(this, name);
tables.put(table.getName(), table);
resetElements();
return table;
}
/**
* @since 4.0
*/
public IDBTable removeTable(String name)
{
assertUnlocked();
name = name(name);
IDBTable table = tables.remove(name);
resetElements();
return table;
}
/**
* @since 4.2
*/
public final IDBTable getTableSafe(String name) throws SchemaElementNotFoundException
{
IDBTable table = getTable(name);
if (table == null)
{
throw new SchemaElementNotFoundException(this, SchemaElementType.TABLE, name);
}
return table;
}
/**
* @since 2.0
*/
public IDBTable getTable(String name)
{
name = name(name);
return tables.get(name);
}
/**
* @since 2.0
*/
public IDBTable[] getTables()
{
return tables.values().toArray(new IDBTable[tables.size()]);
}
/**
* @since 4.2
*/
public void remove()
{
assertUnlocked();
tables.clear();
}
public boolean isLocked()
{
return locked;
}
public boolean lock()
{
return locked = true;
}
/**
* @since 4.2
*/
public boolean unlock()
{
return locked = false;
}
public void assertUnlocked() throws DBException
{
if (locked)
{
throw new DBException("Schema locked: " + this); //$NON-NLS-1$
}
}
public Set<IDBTable> create(IDBAdapter dbAdapter, Connection connection) throws DBException
{
return dbAdapter.createTables(tables.values(), connection);
}
public Set<IDBTable> create(IDBAdapter dbAdapter, DataSource dataSource) throws DBException
{
return create(dbAdapter, dbAdapter.createConnectionProvider(dataSource));
}
public Set<IDBTable> create(IDBAdapter dbAdapter, IDBConnectionProvider connectionProvider) throws DBException
{
Connection connection = null;
try
{
connection = connectionProvider.getConnection();
if (connection == null)
{
throw new DBException("No connection available from " + connectionProvider); //$NON-NLS-1$
}
return create(dbAdapter, connection);
}
finally
{
DBUtil.close(connection);
}
}
public void drop(IDBAdapter dbAdapter, Connection connection) throws DBException
{
dbAdapter.dropTables(tables.values(), connection);
}
public void drop(IDBAdapter dbAdapter, DataSource dataSource) throws DBException
{
drop(dbAdapter, dbAdapter.createConnectionProvider(dataSource));
}
public void drop(IDBAdapter dbAdapter, IDBConnectionProvider connectionProvider) throws DBException
{
Connection connection = null;
try
{
connection = connectionProvider.getConnection();
drop(dbAdapter, connection);
}
finally
{
DBUtil.close(connection);
}
}
public void export(Connection connection, PrintStream out) throws DBException
{
for (IDBTable table : getTables())
{
export(table, connection, out);
}
}
private void export(final IDBTable table, Connection connection, final PrintStream out)
{
if (DBUtil.select(connection, new IDBRowHandler()
{
public boolean handle(int row, Object... values)
{
if (row == 0)
{
String tableName = table.getName();
out.println(tableName);
for (int i = 0; i < tableName.length(); i++)
{
out.print("="); //$NON-NLS-1$
}
out.println();
}
out.println(Arrays.asList(values));
return true;
}
}, table.getFields()) > 0)
{
out.println();
}
}
public void export(DataSource dataSource, PrintStream out) throws DBException
{
export(DBUtil.createConnectionProvider(dataSource), out);
}
public void export(IDBConnectionProvider connectionProvider, PrintStream out) throws DBException
{
Connection connection = null;
try
{
connection = connectionProvider.getConnection();
export(connection, out);
}
finally
{
DBUtil.close(connection);
}
}
/**
* @since 4.2
*/
public IDBSchemaDelta compare(IDBSchema oldSchema)
{
return new DBSchemaDelta(this, oldSchema);
}
/**
* @since 4.2
*/
public String createIndexName(IDBTable table, IDBIndex.Type type, IDBField[] fields, int position)
{
return "I" + System.currentTimeMillis() + "_" + ++indexCounter;
}
/**
* @since 4.2
*/
@Override
protected void collectElements(List<IDBSchemaElement> elements)
{
elements.addAll(tables.values());
}
/**
* @since 4.2
*/
@Override
protected void doAccept(IDBSchemaVisitor visitor)
{
visitor.visit(this);
}
}