### Eclipse Workspace Patch 1.0 #P org.eclipse.emf.cdo.server.db Index: src/org/eclipse/emf/cdo/server/internal/db/jdbc/PreparedStatementJDBCWrapper.java =================================================================== RCS file: src/org/eclipse/emf/cdo/server/internal/db/jdbc/PreparedStatementJDBCWrapper.java diff -N src/org/eclipse/emf/cdo/server/internal/db/jdbc/PreparedStatementJDBCWrapper.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/emf/cdo/server/internal/db/jdbc/PreparedStatementJDBCWrapper.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,245 @@ +/*************************************************************************** + * Copyright (c) 2004 - 2008 Eike Stepper, Germany. + * 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.emf.cdo.server.internal.db.jdbc; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.server.db.IAttributeMapping; +import org.eclipse.emf.cdo.server.internal.db.CDODBSchema; +import org.eclipse.emf.cdo.server.internal.db.ServerInfo; +import org.eclipse.emf.cdo.server.internal.db.bundle.OM; +import org.eclipse.emf.cdo.spi.common.InternalCDORevision; + +import org.eclipse.net4j.db.DBException; +import org.eclipse.net4j.db.DBUtil; +import org.eclipse.net4j.util.om.trace.ContextTracer; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; + +/** + * @author Stefan WInkler + * @since 2.0 + */ +public class PreparedStatementJDBCWrapper extends AbstractJDBCDelegate +{ + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, PreparedStatementJDBCWrapper.class); + + private static final String SQL_UPDATE_REVISE_VERSION = " SET " + CDODBSchema.ATTRIBUTES_REVISED + " = ? WHERE " + + CDODBSchema.ATTRIBUTES_ID + " = ? AND " + CDODBSchema.ATTRIBUTES_VERSION + " = ?"; + + private static final String SQL_UPDATE_REVISE_UNREVISED = " SET " + CDODBSchema.ATTRIBUTES_REVISED + " = ? WHERE " + + CDODBSchema.ATTRIBUTES_ID + " = ? AND " + CDODBSchema.ATTRIBUTES_REVISED + " = 0"; + + private static final String SQL_INSERT_REFERENCE_WITH_DBID = " VALUES (?, ?, ?, ?, ?)"; + + private static final String SQL_INSERT_REFERENCE = " VALUES (?, ?, ?, ?)"; + + @Override + protected void doInsertAttributes(Connection connection, String tableName, InternalCDORevision revision, + List attributeMappings, boolean withFullRevisionInfo) + { + PreparedStatement stmt = null; + StringBuilder sql = new StringBuilder(); + + if (attributeMappings == null) + { + attributeMappings = Collections.emptyList(); + } + + sql.append("INSERT INTO "); + sql.append(tableName); + sql.append(" VALUES (?, ?, "); + if (withFullRevisionInfo) + { + sql.append("?, ?, ?, ?, ?, ?"); + } + for (int i = 0; i < attributeMappings.size(); i++) + { + sql.append(", ?"); + } + sql.append(")"); + + int col = 1; + + try + { + if (TRACER.isEnabled()) + { + TRACER.format("{0} ({1})", sql.toString(), revision.toString()); + } + stmt = connection.prepareStatement(sql.toString()); + stmt.setLong(col++, CDOIDUtil.getLong(revision.getID())); + stmt.setInt(col++, revision.getVersion()); + + if (withFullRevisionInfo) + { + stmt.setInt(col++, ServerInfo.getDBID(revision.getCDOClass())); + stmt.setLong(col++, revision.getCreated()); + stmt.setLong(col++, revision.getRevised()); + stmt.setLong(col++, CDOIDUtil.getLong(revision.getResourceID())); + stmt.setLong(col++, CDOIDUtil.getLong((CDOID)revision.getContainerID())); + stmt.setInt(col++, revision.getContainingFeatureID()); + } + + for (IAttributeMapping attributeMapping : attributeMappings) + { + Object value = attributeMapping.getRevisionValue(revision); + stmt.setObject(col++, value); + } + stmt.execute(); + } + catch (SQLException e) + { + throw new DBException(e); + } + finally + { + DBUtil.close(stmt); + } + } + + @Override + protected void doInsertReference(Connection connection, String tableName, long source, int version, int i, long target) + { + PreparedStatement stmt = null; + + try + { + StringBuilder sql = new StringBuilder("INSERT INTO "); + sql.append(tableName); + sql.append(SQL_INSERT_REFERENCE); + + stmt = connection.prepareStatement(sql.toString()); + stmt.setLong(1, source); + stmt.setInt(2, version); + stmt.setInt(3, i); + stmt.setLong(4, target); + if (TRACER.isEnabled()) + { + TRACER.format("{0} ({1},{2},{3},{4})", sql.toString(), source, version, i, target); + } + stmt.execute(); + } + catch (SQLException e) + { + throw new DBException(e); + } + finally + { + DBUtil.close(stmt); + } + } + + @Override + protected void doInsertReference(Connection connection, String tableName, int dbId, long source, int version, int i, + long target) + { + PreparedStatement stmt = null; + + try + { + StringBuilder sql = new StringBuilder("INSERT INTO "); + sql.append(tableName); + sql.append(SQL_INSERT_REFERENCE_WITH_DBID); + + stmt = connection.prepareStatement(sql.toString()); + stmt.setInt(1, dbId); + stmt.setLong(2, source); + stmt.setInt(3, version); + stmt.setInt(4, i); + stmt.setLong(5, target); + + if (TRACER.isEnabled()) + { + TRACER.format("{0} ({1},{2},{3},{4},{5})", sql.toString(), dbId, source, version, i, target); + } + + stmt.execute(); + } + catch (SQLException e) + { + throw new DBException(e); + } + finally + { + DBUtil.close(stmt); + } + } + + @Override + protected void doUpdateRevised(Connection connection, String tableName, long revisedStamp, long cdoid, int version) + { + PreparedStatement stmt = null; + + try + { + StringBuilder sql = new StringBuilder("UPDATE "); + sql.append(tableName); + sql.append(SQL_UPDATE_REVISE_VERSION); + + stmt = connection.prepareStatement(sql.toString()); + stmt.setLong(1, revisedStamp); + stmt.setLong(2, cdoid); + stmt.setInt(3, version); + + if (TRACER.isEnabled()) + { + TRACER.format("{0} ({1},{2},{3})", sql.toString(), revisedStamp, cdoid, version); + } + + stmt.execute(); + } + catch (SQLException e) + { + throw new DBException(e); + } + finally + { + DBUtil.close(stmt); + } + } + + @Override + protected void doUpdateRevised(Connection connection, String tableName, long revisedStamp, long cdoid) + { + PreparedStatement stmt = null; + + try + { + StringBuilder sql = new StringBuilder("UPDATE "); + sql.append(tableName); + sql.append(SQL_UPDATE_REVISE_UNREVISED); + + stmt = connection.prepareStatement(sql.toString()); + stmt.setLong(1, revisedStamp); + stmt.setLong(2, cdoid); + + if (TRACER.isEnabled()) + { + TRACER.format("{0} ({1},{2})", sql.toString(), revisedStamp, cdoid); + } + + stmt.execute(); + } + catch (SQLException e) + { + throw new DBException(e); + } + finally + { + DBUtil.close(stmt); + } + } +} Index: src/org/eclipse/emf/cdo/server/internal/db/jdbc/JDBCPerformanceMeasurementWrapper.java =================================================================== RCS file: src/org/eclipse/emf/cdo/server/internal/db/jdbc/JDBCPerformanceMeasurementWrapper.java diff -N src/org/eclipse/emf/cdo/server/internal/db/jdbc/JDBCPerformanceMeasurementWrapper.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/emf/cdo/server/internal/db/jdbc/JDBCPerformanceMeasurementWrapper.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,145 @@ +/*************************************************************************** + * Copyright (c) 2004 - 2008 Eike Stepper, Germany. + * 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.emf.cdo.server.internal.db.jdbc; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.server.db.IAttributeMapping; +import org.eclipse.emf.cdo.server.db.IJDBCDelegate; +import org.eclipse.emf.cdo.server.internal.db.bundle.OM; +import org.eclipse.emf.cdo.spi.common.InternalCDORevision; + +import org.eclipse.net4j.util.om.trace.ContextTracer; + +import java.sql.Connection; +import java.util.HashMap; +import java.util.List; + +/** + * @author Stefan Winkler + * @since 2.0 + */ +public class JDBCPerformanceMeasurementWrapper implements IJDBCDelegate +{ + + private class TimeData + { + private String method; + + private long timeMin = Integer.MAX_VALUE; + + private long timeMax = Integer.MIN_VALUE; + + private long timeTotal = 0; + + private long numberOfCalls = 0; + + public TimeData(String method) + { + this.method = method; + } + + public void registerCall(long time) + { + if (timeMin > time) + { + timeMin = time; + } + if (timeMax < time) + { + timeMax = time; + } + + numberOfCalls++; + timeTotal += time; + } + + public void report(ContextTracer tracer) + { + tracer.format("{0}: {1} calls, {2} avg, {3} min, {4} max", method, numberOfCalls, timeTotal / numberOfCalls, + timeMin, timeMax); + } + } + + public JDBCPerformanceMeasurementWrapper(IJDBCDelegate delegate) + { + this.delegate = delegate; + } + + private IJDBCDelegate delegate; + + private HashMap timeData = new HashMap(); + + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, NonPreparedStatementJDBCWrapper.class); + + public final void insertAttributes(Connection dbConnection, String tableName, InternalCDORevision revision, + List attributeMappings, boolean withFullRevisionInfo) + { + long time = System.currentTimeMillis(); + delegate.insertAttributes(dbConnection, tableName, revision, attributeMappings, withFullRevisionInfo); + time = System.currentTimeMillis() - time; + + registerCall("insertAttributes", time); + } + + public final void insertReference(Connection dbConnection, String tableName, int dbId, CDORevision sourceRevision, + int idx, CDOID targetId) + { + long time = System.currentTimeMillis(); + delegate.insertReference(dbConnection, tableName, dbId, sourceRevision, idx, targetId); + time = System.currentTimeMillis() - time; + registerCall("insertReferenceDbId", time); + } + + public final void insertReference(Connection dbConnection, String tableName, CDORevision sourceRevision, int idx, + CDOID targetId) + { + long time = System.currentTimeMillis(); + delegate.insertReference(dbConnection, tableName, sourceRevision, idx, targetId); + time = System.currentTimeMillis() - time; + registerCall("insertReference", time); + } + + public final void updateRevised(Connection dbConnection, String tableName, CDORevision revision) + { + long time = System.currentTimeMillis(); + delegate.updateRevised(dbConnection, tableName, revision); + time = System.currentTimeMillis() - time; + registerCall("updateRevisedRevision", time); + } + + public final void updateRevised(Connection dbConnection, String tableName, long revised, CDOID cdoid) + { + long time = System.currentTimeMillis(); + delegate.updateRevised(dbConnection, tableName, revised, cdoid); + time = System.currentTimeMillis() - time; + registerCall("updateRevisedID", time); + } + + private void registerCall(String method, long time) + { + TimeData data = timeData.get(method); + if (data == null) + { + data = new TimeData(method); + timeData.put(method, data); + } + data.registerCall(time); + } + + public void report() + { + for (TimeData td : timeData.values()) + { + td.report(TRACER); + } + } +} Index: src/org/eclipse/emf/cdo/server/internal/db/jdbc/AbstractJDBCDelegate.java =================================================================== RCS file: src/org/eclipse/emf/cdo/server/internal/db/jdbc/AbstractJDBCDelegate.java diff -N src/org/eclipse/emf/cdo/server/internal/db/jdbc/AbstractJDBCDelegate.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/emf/cdo/server/internal/db/jdbc/AbstractJDBCDelegate.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (c) 2004 - 2008 Eike Stepper, Germany. + * 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.emf.cdo.server.internal.db.jdbc; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.server.db.IAttributeMapping; +import org.eclipse.emf.cdo.server.db.IJDBCDelegate; +import org.eclipse.emf.cdo.server.internal.db.bundle.OM; +import org.eclipse.emf.cdo.spi.common.InternalCDORevision; + +import org.eclipse.net4j.util.om.trace.ContextTracer; + +import java.sql.Connection; +import java.util.List; + +/** + * @author Eike Stepper + */ +public abstract class AbstractJDBCDelegate implements IJDBCDelegate +{ + protected static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AbstractJDBCDelegate.class); + + protected abstract void doInsertAttributes(Connection dbConnection, String tableName, InternalCDORevision revision, + List attributeMappings, boolean withFullRevisionInfo); + + protected abstract void doInsertReference(Connection dbConnection, String tableName, int dbId, long source, + int version, int i, long target); + + protected abstract void doInsertReference(Connection dbConnection, String tableName, long source, int version, int i, + long target); + + protected abstract void doUpdateRevised(Connection dbConnection, String tableName, long revised, long cdoid); + + protected abstract void doUpdateRevised(Connection dbConnection, String tableName, long revisedStamp, long cdoid, + int version); + + public final void insertAttributes(Connection dbConnection, String tableName, InternalCDORevision revision, + List attributeMappings, boolean withFullRevisionInfo) + { + doInsertAttributes(dbConnection, tableName, revision, attributeMappings, withFullRevisionInfo); + } + + public final void insertReference(Connection dbConnection, String tableName, CDORevision sourceRevision, int idx, + CDOID targetId) + { + doInsertReference(dbConnection, tableName, CDOIDUtil.getLong(sourceRevision.getID()), sourceRevision.getVersion(), + idx, CDOIDUtil.getLong(targetId)); + } + + public final void insertReference(Connection dbConnection, String tableName, int dbId, CDORevision sourceRevision, + int idx, CDOID targetId) + { + doInsertReference(dbConnection, tableName, dbId, CDOIDUtil.getLong(sourceRevision.getID()), sourceRevision + .getVersion(), idx, CDOIDUtil.getLong(targetId)); + } + + public final void updateRevised(Connection dbConnection, String tableName, CDORevision revision) + { + doUpdateRevised(dbConnection, tableName, revision.getCreated() - 1, CDOIDUtil.getLong(revision.getID()), revision + .getVersion() - 1); + } + + public final void updateRevised(Connection dbConnection, String tableName, long revised, CDOID id) + { + doUpdateRevised(dbConnection, tableName, revised, CDOIDUtil.getLong(id)); + } + +} Index: src/org/eclipse/emf/cdo/server/internal/db/jdbc/NonPreparedStatementJDBCWrapper.java =================================================================== RCS file: src/org/eclipse/emf/cdo/server/internal/db/jdbc/NonPreparedStatementJDBCWrapper.java diff -N src/org/eclipse/emf/cdo/server/internal/db/jdbc/NonPreparedStatementJDBCWrapper.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/emf/cdo/server/internal/db/jdbc/NonPreparedStatementJDBCWrapper.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,190 @@ +/*************************************************************************** + * Copyright (c) 2004 - 2008 Eike Stepper, Germany. + * 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.emf.cdo.server.internal.db.jdbc; + +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.server.db.IAttributeMapping; +import org.eclipse.emf.cdo.server.internal.db.CDODBSchema; +import org.eclipse.emf.cdo.server.internal.db.ServerInfo; +import org.eclipse.emf.cdo.spi.common.InternalCDORevision; + +import org.eclipse.net4j.db.DBException; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; + +/** + * @author Stefan Winkler + * @since 2.0 + */ +public class NonPreparedStatementJDBCWrapper extends AbstractJDBCDelegate +{ + + @Override + protected void doInsertAttributes(Connection dbConnection, String table, InternalCDORevision revision, + List attributeMappings, boolean withFullRevisionInfo) + { + StringBuilder builder = new StringBuilder(); + builder.append("INSERT INTO "); + builder.append(table); + builder.append(" VALUES ("); + + builder.append(CDOIDUtil.getLong(revision.getID())); + builder.append(", "); + builder.append(revision.getVersion()); + + if (withFullRevisionInfo) + { + builder.append(", "); + builder.append(ServerInfo.getDBID(revision.getCDOClass())); + builder.append(", "); + builder.append(revision.getCreated()); + builder.append(", "); + builder.append(revision.getRevised()); + builder.append(", "); + builder.append(CDOIDUtil.getLong(revision.getResourceID())); + builder.append(", "); + builder.append(CDOIDUtil.getLong((CDOID)revision.getContainerID())); + builder.append(", "); + builder.append(revision.getContainingFeatureID()); + } + + if (attributeMappings != null) + { + for (IAttributeMapping attributeMapping : attributeMappings) + { + builder.append(", "); + Object value = attributeMapping.getRevisionValue(revision); + attributeMapping.getField().appendValue(builder, value); + } + } + + builder.append(")"); + sqlUpdate(dbConnection, builder.toString()); + } + + @Override + protected void doUpdateRevised(Connection dbConnection, String table, long revisedStamp, long cdoid, int version) + { + StringBuilder builder = new StringBuilder(); + builder.append("UPDATE "); + builder.append(table); + builder.append(" SET "); + builder.append(CDODBSchema.ATTRIBUTES_REVISED); + builder.append("="); + builder.append(revisedStamp); + builder.append(" WHERE "); + builder.append(CDODBSchema.ATTRIBUTES_ID); + builder.append("="); + builder.append(cdoid); + builder.append(" AND "); + builder.append(CDODBSchema.ATTRIBUTES_VERSION); + builder.append("="); + builder.append(version); + sqlUpdate(dbConnection, builder.toString()); + } + + @Override + protected void doUpdateRevised(Connection dbConnection, String table, long revisedStamp, long cdoid) + { + StringBuilder builder = new StringBuilder(); + builder.append("UPDATE "); + builder.append(table); + builder.append(" SET "); + builder.append(CDODBSchema.ATTRIBUTES_REVISED); + builder.append("="); + builder.append(revisedStamp); + builder.append(" WHERE "); + builder.append(CDODBSchema.ATTRIBUTES_ID); + builder.append("="); + builder.append(cdoid); + builder.append(" AND "); + builder.append(CDODBSchema.ATTRIBUTES_REVISED); + builder.append("=0"); + sqlUpdate(dbConnection, builder.toString()); + } + + @Override + protected void doInsertReference(Connection dbConnection, String table, long source, int version, int i, long target) + { + StringBuilder builder = new StringBuilder(); + builder.append("INSERT INTO "); + builder.append(table); + builder.append(" VALUES ("); + builder.append(source); + builder.append(", "); + builder.append(version); + builder.append(", "); + builder.append(i); + builder.append(", "); + builder.append(target); + builder.append(")"); + sqlUpdate(dbConnection, builder.toString()); + } + + @Override + protected void doInsertReference(Connection dbConnection, String table, int dbId, long source, int version, int i, + long target) + { + StringBuilder builder = new StringBuilder(); + builder.append("INSERT INTO "); + builder.append(table); + builder.append(" VALUES ("); + builder.append(dbId); + builder.append(", "); + builder.append(source); + builder.append(", "); + builder.append(version); + builder.append(", "); + builder.append(i); + builder.append(", "); + builder.append(target); + builder.append(")"); + sqlUpdate(dbConnection, builder.toString()); + } + + private int sqlUpdate(Connection dbConnection, String sql) throws DBException + { + if (TRACER.isEnabled()) + { + TRACER.trace(sql); + } + + Statement statement = null; + try + { + statement = dbConnection.createStatement(); + return statement.executeUpdate(sql); + } + catch (SQLException ex) + { + throw new DBException(ex); + } + finally + { + try + { + statement.close(); + } + catch (SQLException e) + { + if (TRACER.isEnabled()) + { + TRACER.trace(e); + } + } + } + } + +}