| /** |
| * 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(); |
| } |
| } |