// 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.schema.sql;

import com.google.gwtorm.schema.ColumnModel;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.StatementExecutor;

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

/** Dialect for <a href="http://www.h2database.com/">H2</a> */
public class DialectH2 extends SqlDialect {
  @Override
  public boolean handles(String url, Connection c) {
    return url.startsWith("jdbc:h2:");
  }

  @Override
  public OrmException convertError(final String op, final String entity,
      final SQLException err) {
    switch (getSQLStateInt(err)) {
      case 23001: // UNIQUE CONSTRAINT VIOLATION
      case 23505: // DUPLICATE_KEY_1
        return new OrmDuplicateKeyException(entity, err);

      default:
        return super.convertError(op, entity, err);
    }
  }

  @Override
  protected String getNextSequenceValueSql(final String seqname) {
    return "SELECT NEXT VALUE FOR " + seqname;
  }

  @Override
  public Set<String> listSequences(Connection db) throws SQLException {
    Statement s = db.createStatement();
    try {
      ResultSet rs =
          s.executeQuery("SELECT SEQUENCE_NAME"
              + " FROM INFORMATION_SCHEMA.SEQUENCES"
              + " WHERE SEQUENCE_SCHEMA = 'PUBLIC'");
      try {
        HashSet<String> sequences = new HashSet<>();
        while (rs.next()) {
          sequences.add(rs.getString(1).toLowerCase());
        }
        return sequences;
      } finally {
        rs.close();
      }
    } finally {
      s.close();
    }
  }

  @Override
  public void addColumn(StatementExecutor stmt, String tableName,
      ColumnModel col) throws OrmException {
    final StringBuilder r = new StringBuilder();
    r.append("ALTER TABLE ");
    r.append(tableName);
    r.append(" ADD ");
    r.append(col.getColumnName());
    r.append(" ");
    r.append(getSqlTypeInfo(col).getSqlType(col, this));
    stmt.execute(r.toString());

    String check = getSqlTypeInfo(col).getCheckConstraint(col, this);
    if (check != null) {
      r.setLength(0);
      r.append("ALTER TABLE ");
      r.append(tableName);
      r.append(" ADD CONSTRAINT ");
      r.append(col.getColumnName() + "_check");
      r.append(' ');
      r.append(check);
      stmt.execute(r.toString());
    }
  }

  @Override
  public void renameColumn(StatementExecutor stmt, String tableName,
      String fromColumn, ColumnModel col) throws OrmException {
    final StringBuilder r = new StringBuilder();
    r.append("ALTER TABLE ");
    r.append(tableName);
    r.append(" ALTER COLUMN ");
    r.append(fromColumn);
    r.append(" RENAME TO ");
    r.append(col.getColumnName());
    stmt.execute(r.toString());
  }
}

@@ -2899,32 +2899,50 @@
 %0A      r.append(
+tableName + %22_%22 + 
 col.getColumnNam

Incorporate table into H2 column constraint name