All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwtorm.jdbc.JdbcSchema Maven / Gradle / Ivy

There is a newer version: 1.20
Show newest version
// Copyright 2008 Google Inc.
//
// Licensed 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.

package com.google.gwtorm.jdbc;

import com.google.common.base.Preconditions;
import com.google.gwtorm.schema.ColumnModel;
import com.google.gwtorm.schema.RelationModel;
import com.google.gwtorm.schema.SchemaModel;
import com.google.gwtorm.schema.SequenceModel;
import com.google.gwtorm.schema.sql.SqlDialect;
import com.google.gwtorm.server.AbstractSchema;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.Schema;
import com.google.gwtorm.server.StatementExecutor;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;

/** Internal base class for implementations of {@link Schema}. */
public abstract class JdbcSchema extends AbstractSchema {
  private final Database dbDef;
  private Connection conn;

  protected JdbcSchema(final Database d) throws OrmException {
    dbDef = d;
    conn = dbDef.newConnection();
  }

  public final Connection getConnection() {
    return conn;
  }

  public final SqlDialect getDialect() {
    return dbDef.getDialect();
  }

  @Override
  public void commit() throws OrmException {
    try {
      if (!conn.getAutoCommit()) {
        conn.commit();
      }
    } catch (SQLException err) {
      throw new OrmException("Cannot commit transaction", err);
    } finally {
      try {
        conn.setAutoCommit(true);
      } catch (SQLException err) {
        throw new OrmException("Cannot set auto commit mode", err);
      }
    }
  }

  @Override
  public void rollback() throws OrmException {
    try {
      if (!conn.getAutoCommit()) {
        conn.rollback();
      }
    } catch (SQLException err) {
      throw new OrmException("Cannot rollback transaction", err);
    } finally {
      try {
        conn.setAutoCommit(true);
      } catch (SQLException err) {
        throw new OrmException("Cannot set auto commit mode", err);
      }
    }
  }

  @Override
  public void updateSchema(final StatementExecutor e) throws OrmException {
    try {
      createSequences(e);
      createRelations(e);

      for (final RelationModel rel : dbDef.getSchemaModel().getRelations()) {
        addColumns(e, rel);
      }
    } catch (SQLException err) {
      throw new OrmException("Cannot update schema", err);
    }
  }

  private void createSequences(final StatementExecutor e) throws OrmException,
      SQLException {
    final SqlDialect dialect = dbDef.getDialect();
    final SchemaModel model = dbDef.getSchemaModel();

    Set have = dialect.listSequences(getConnection());
    for (final SequenceModel s : model.getSequences()) {
      if (!have.contains(s.getSequenceName().toLowerCase())) {
        e.execute(s.getCreateSequenceSql(dialect));
      }
    }
  }

  private void createRelations(final StatementExecutor e) throws SQLException,
      OrmException {
    final SqlDialect dialect = dbDef.getDialect();
    final SchemaModel model = dbDef.getSchemaModel();
    Set have = dialect.listTables(getConnection());
    for (final RelationModel r : model.getRelations()) {
      if (!have.contains(r.getRelationName().toLowerCase())) {
        e.execute(r.getCreateTableSql(dialect));
      }
    }
  }

  private void addColumns(final StatementExecutor e, final RelationModel rel)
      throws SQLException, OrmException {
    final SqlDialect dialect = dbDef.getDialect();
    Set have = dialect.listColumns( //
        getConnection(), rel.getRelationName().toLowerCase());
    for (final ColumnModel c : rel.getColumns()) {
      if (!have.contains(c.getColumnName().toLowerCase())) {
        dialect.addColumn(e, rel.getRelationName(), c);
      }
    }
  }

  public void renameTable(final StatementExecutor e, String from, String to)
      throws OrmException {
    Preconditions.checkNotNull(e);
    Preconditions.checkNotNull(from);
    Preconditions.checkNotNull(to);
    getDialect().renameTable(e, from, to);
  }

  public void renameField(final StatementExecutor e, String table, String from,
      String to) throws OrmException {
    final RelationModel rel = findRelationModel(table);
    if (rel == null) {
      throw new OrmException("Relation " + table + " not defined");
    }
    final ColumnModel col = rel.getField(to);
    if (col == null) {
      throw new OrmException("Relation " + table + " does not have " + to);
    }
    getDialect().renameColumn(e, table, from, col);
  }

  public void renameColumn(final StatementExecutor e, String table, String from,
      String to) throws OrmException {
    final RelationModel rel = findRelationModel(table);
    if (rel == null) {
      throw new OrmException("Relation " + table + " not defined");
    }
    final ColumnModel col = rel.getColumn(to);
    if (col == null) {
      throw new OrmException("Relation " + table + " does not have " + to);
    }
    getDialect().renameColumn(e, table, from, col);
  }

  private RelationModel findRelationModel(String table) {
    for (final RelationModel rel : dbDef.getSchemaModel().getRelations()) {
      if (table.equalsIgnoreCase(rel.getRelationName())) {
        return rel;
      }
    }
    return null;
  }

  @Override
  public void pruneSchema(final StatementExecutor e) throws OrmException {
    try {
      pruneSequences(e);
      pruneRelations(e);

      for (final RelationModel rel : dbDef.getSchemaModel().getRelations()) {
        pruneColumns(e, rel);
      }
    } catch (SQLException err) {
      throw new OrmException("Schema prune failure", err);
    }
  }

  private void pruneSequences(final StatementExecutor e) throws SQLException,
      OrmException {
    final SqlDialect dialect = dbDef.getDialect();
    final SchemaModel model = dbDef.getSchemaModel();
    HashSet want = new HashSet<>();
    for (final SequenceModel s : model.getSequences()) {
      want.add(s.getSequenceName().toLowerCase());
    }
    for (final String sequence : dialect.listSequences(getConnection())) {
      if (!want.contains(sequence)) {
        e.execute(dialect.getDropSequenceSql(sequence));
      }
    }
  }

  private void pruneRelations(final StatementExecutor e) throws SQLException,
      OrmException {
    final SqlDialect dialect = dbDef.getDialect();
    final SchemaModel model = dbDef.getSchemaModel();
    HashSet want = new HashSet<>();
    for (final RelationModel r : model.getRelations()) {
      want.add(r.getRelationName().toLowerCase());
    }
    for (final String table : dialect.listTables(getConnection())) {
      if (!want.contains(table)) {
        e.execute("DROP TABLE " + table);
      }
    }
  }

  private void pruneColumns(final StatementExecutor e, final RelationModel rel)
      throws SQLException, OrmException {
    final SqlDialect dialect = dbDef.getDialect();
    HashSet want = new HashSet<>();
    for (final ColumnModel c : rel.getColumns()) {
      want.add(c.getColumnName().toLowerCase());
    }
    for (String column : dialect.listColumns( //
        getConnection(), rel.getRelationName().toLowerCase())) {
      if (!want.contains(column)) {
        dialect.dropColumn(e, rel.getRelationName(), column);
      }
    }
  }

  @Override
  protected long nextLong(final String poolName) throws OrmException {
    return getDialect().nextLong(getConnection(), poolName);
  }

  @Override
  public void close() {
    if (conn != null) {
      try {
        conn.close();
      } catch (SQLException err) {
        // TODO Handle an exception while closing a connection
      }
      conn = null;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy