blob: c1b575490ee84b6c05a29fb75b4d70b08248ac55 [file] [log] [blame]
/**
* Copyright (c) 2004 - 2011 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
* Stefan Winkler - bug 259402
* Stefan Winkler - redesign (prepared statements)
* Stefan Winkler - bug 276926
*/
package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.server.db.IDBStore;
import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
import org.eclipse.emf.cdo.server.db.IIDHandler;
import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBType;
import org.eclipse.net4j.db.DBUtil;
import org.eclipse.net4j.db.IDBAdapter;
import org.eclipse.net4j.db.ddl.IDBField;
import org.eclipse.net4j.db.ddl.IDBIndex;
import org.eclipse.net4j.db.ddl.IDBSchema;
import org.eclipse.net4j.db.ddl.IDBTable;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.emf.ecore.EClass;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* @author Eike Stepper
* @since 4.0
*/
public class ObjectTypeTable extends AbstractObjectTypeMapper
{
private IDBTable table;
private IDBField idField;
private IDBField typeField;
private IDBField timeField;
private String sqlDelete;
private String sqlInsert;
private String sqlSelect;
public ObjectTypeTable()
{
}
public final CDOClassifierRef getObjectType(IDBStoreAccessor accessor, CDOID id)
{
IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
IPreparedStatementCache statementCache = accessor.getStatementCache();
PreparedStatement stmt = null;
try
{
stmt = statementCache.getPreparedStatement(sqlSelect, ReuseProbability.MAX);
idHandler.setCDOID(stmt, 1, id);
DBUtil.trace(stmt.toString());
ResultSet resultSet = stmt.executeQuery();
if (!resultSet.next())
{
DBUtil.trace("ClassID for CDOID " + id + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
return null;
}
CDOID classID = idHandler.getCDOID(resultSet, 1);
EClass eClass = (EClass)getMetaDataManager().getMetaInstance(classID);
return new CDOClassifierRef(eClass);
}
catch (SQLException ex)
{
throw new DBException(ex);
}
finally
{
statementCache.releasePreparedStatement(stmt);
}
}
public final void putObjectType(IDBStoreAccessor accessor, long timeStamp, CDOID id, EClass type)
{
IDBStore store = getMappingStrategy().getStore();
IIDHandler idHandler = store.getIDHandler();
IPreparedStatementCache statementCache = accessor.getStatementCache();
PreparedStatement stmt = null;
try
{
stmt = statementCache.getPreparedStatement(sqlInsert, ReuseProbability.MAX);
idHandler.setCDOID(stmt, 1, id);
idHandler.setCDOID(stmt, 2, getMetaDataManager().getMetaID(type, timeStamp));
stmt.setLong(3, timeStamp);
DBUtil.trace(stmt.toString());
int result = stmt.executeUpdate();
if (result != 1)
{
throw new DBException("Object type could not be inserted: " + id); //$NON-NLS-1$
}
}
catch (SQLException ex)
{
// Unique key violation can occur in rare cases (merging new objects from other branches)
if (!store.getDBAdapter().isDuplicateKeyException(ex))
{
throw new DBException(ex);
}
}
finally
{
statementCache.releasePreparedStatement(stmt);
}
}
public final void removeObjectType(IDBStoreAccessor accessor, CDOID id)
{
IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
IPreparedStatementCache statementCache = accessor.getStatementCache();
PreparedStatement stmt = null;
try
{
stmt = statementCache.getPreparedStatement(sqlDelete, ReuseProbability.MAX);
idHandler.setCDOID(stmt, 1, id);
DBUtil.trace(stmt.toString());
int result = stmt.executeUpdate();
if (result != 1)
{
throw new DBException("Object type could not be deleted: " + id); //$NON-NLS-1$
}
}
catch (SQLException ex)
{
throw new DBException(ex);
}
finally
{
statementCache.releasePreparedStatement(stmt);
}
}
public CDOID getMaxID(Connection connection, IIDHandler idHandler)
{
Statement stmt = null;
ResultSet resultSet = null;
try
{
stmt = connection.createStatement();
resultSet = stmt.executeQuery("SELECT MAX(" + idField + ") FROM " + table);
if (resultSet.next())
{
return idHandler.getCDOID(resultSet, 1);
}
return null;
}
catch (SQLException ex)
{
throw new DBException(ex);
}
finally
{
DBUtil.close(resultSet);
DBUtil.close(stmt);
}
}
public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)
throws IOException
{
String where = " WHERE " + timeField + " BETWEEN " + fromCommitTime + " AND " + toCommitTime;
DBUtil.serializeTable(out, connection, table, null, where);
}
public void rawImport(Connection connection, CDODataInput in, OMMonitor monitor) throws IOException
{
DBUtil.deserializeTable(in, connection, table, monitor);
}
@Override
protected void doActivate() throws Exception
{
super.doActivate();
IDBStore store = getMappingStrategy().getStore();
IDBSchema schema = store.getDBSchema();
DBType dbType = store.getIDHandler().getDBType();
table = schema.addTable(CDODBSchema.CDO_OBJECTS);
idField = table.addField(CDODBSchema.ATTRIBUTES_ID, dbType);
typeField = table.addField(CDODBSchema.ATTRIBUTES_CLASS, dbType);
timeField = table.addField(CDODBSchema.ATTRIBUTES_CREATED, DBType.BIGINT);
table.addIndex(IDBIndex.Type.UNIQUE, idField);
IDBAdapter dbAdapter = store.getDBAdapter();
IDBStoreAccessor writer = store.getWriter(null);
Connection connection = writer.getConnection();
Statement statement = null;
try
{
statement = connection.createStatement();
dbAdapter.createTable(table, statement);
connection.commit();
}
catch (SQLException ex)
{
connection.rollback();
throw new DBException(ex);
}
finally
{
DBUtil.close(statement);
writer.release();
}
sqlSelect = "SELECT " + typeField + " FROM " + table + " WHERE " + idField + "=?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
sqlInsert = "INSERT INTO " + table + "(" + idField + "," + typeField + "," + timeField + ") VALUES (?, ?, ?)";
sqlDelete = "DELETE FROM " + table + " WHERE " + idField + "=?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@Override
protected void doDeactivate() throws Exception
{
table = null;
idField = null;
typeField = null;
super.doDeactivate();
}
}