Open Source Repository

Home /hibernate/hibernate-3.2.7.ga | Repository Home


org/hibernate/dialect/InformixDialect.java
//$Id: InformixDialect.java 15897 2009-02-04 23:14:05Z [email protected] $
package org.hibernate.dialect;

import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.MappingException;
import org.hibernate.Hibernate;
import org.hibernate.dialect.function.VarArgsSQLFunction;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.exception.TemplatedViolatedConstraintNameExtracter;
import org.hibernate.exception.ViolatedConstraintNameExtracter;
import org.hibernate.util.StringHelper;

/**
 * Informix dialect.<br>
 <br>
 * Seems to work with Informix Dynamic Server Version 7.31.UD3,
 * Informix JDBC driver version 2.21JC3.
 @author Steve Molitor
 */
public class InformixDialect extends Dialect {

  /**
   * Creates new <code>InformixDialect</code> instance. Sets up the JDBC /
   * Informix type mappings.
   */
  public InformixDialect() {
    super();

    registerColumnType(Types.BIGINT, "int8");
    registerColumnType(Types.BINARY, "byte");
    registerColumnType(Types.BIT, "smallint")// Informix doesn't have a bit type
    registerColumnType(Types.CHAR, "char($l)");
    registerColumnType(Types.DATE, "date");
    registerColumnType(Types.DECIMAL, "decimal");
        registerColumnType(Types.DOUBLE, "float");
        registerColumnType(Types.FLOAT, "smallfloat");
    registerColumnType(Types.INTEGER, "integer");
    registerColumnType(Types.LONGVARBINARY, "blob")// or BYTE
    registerColumnType(Types.LONGVARCHAR, "clob")// or TEXT?
    registerColumnType(Types.NUMERIC, "decimal")// or MONEY
    registerColumnType(Types.REAL, "smallfloat");
    registerColumnType(Types.SMALLINT, "smallint");
    registerColumnType(Types.TIMESTAMP, "datetime year to fraction(5)");
    registerColumnType(Types.TIME, "datetime hour to second");
    registerColumnType(Types.TINYINT, "smallint");
    registerColumnType(Types.VARBINARY, "byte");
    registerColumnType(Types.VARCHAR, "varchar($l)");
    registerColumnType(Types.VARCHAR, 255"varchar($l)");
    registerColumnType(Types.VARCHAR, 32739"lvarchar($l)");

    registerFunction"concat"new VarArgsSQLFunctionHibernate.STRING, "(""||"")" ) );
  }

  public String getAddColumnString() {
    return "add";
  }

  public boolean supportsIdentityColumns() {
    return true;
  }

  public String getIdentitySelectString(String table, String column, int type
  throws MappingException {
    return type==Types.BIGINT ?
      "select dbinfo('serial8') from systables where tabid=1" :
      "select dbinfo('sqlca.sqlerrd1') from systables where tabid=1";
  }

  public String getIdentityColumnString(int typethrows MappingException {
    return type==Types.BIGINT ?
      "serial8 not null" :
      "serial not null";
  }

  public boolean hasDataTypeInIdentityColumn() {
    return false;
  }

  /**
   * The syntax used to add a foreign key constraint to a table.
   * Informix constraint name must be at the end.
   @return String
   */
  public String getAddForeignKeyConstraintString(
      String constraintName,
      String[] foreignKey,
      String referencedTable,
      String[] primaryKey,
      boolean referencesPrimaryKey) {
    StringBuffer result = new StringBuffer30 )
        .append" add constraint " )
        .append" foreign key (" )
        .appendStringHelper.join", ", foreignKey ) )
        .append") references " )
        .appendreferencedTable );

    if !referencesPrimaryKey ) {
      result.append" (" )
          .appendStringHelper.join", ", primaryKey ) )
          .append')' );
    }

    result.append" constraint " ).appendconstraintName );

    return result.toString();
  }

  /**
   * The syntax used to add a primary key constraint to a table.
   * Informix constraint name must be at the end.
   @return String
   */
  public String getAddPrimaryKeyConstraintString(String constraintName) {
    return " add constraint primary key constraint " + constraintName + " ";
  }

  public String getCreateSequenceString(String sequenceName) {
    return "create sequence " + sequenceName;
  }
  public String getDropSequenceString(String sequenceName) {
    return "drop sequence " + sequenceName + " restrict";
  }

  public String getSequenceNextValString(String sequenceName) {
    return "select " + getSelectSequenceNextValStringsequenceName " from systables where tabid=1";
  }

  public String getSelectSequenceNextValString(String sequenceName) {
    return sequenceName + ".nextval";
  }

  public boolean supportsSequences() {
    return true;
  }

  public boolean supportsLimit() {
    return true;
  }

  public boolean useMaxForLimit() {
    return true;
  }

  public boolean supportsLimitOffset() {
    return false;
  }

  public String getLimitString(String querySelect, int offset, int limit) {
    if offset > ) {
      throw new UnsupportedOperationException"query result offset is not supported" );
    }
    return new StringBufferquerySelect.length() )
        .appendquerySelect )
        .insertquerySelect.toLowerCase().indexOf"select" 6" first " + limit )
        .toString();
  }

  public boolean supportsVariableLimit() {
    return false;
  }

  public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
        return EXTRACTER;
  }

  private static ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {

    /**
     * Extract the name of the violated constraint from the given SQLException.
     *
     @param sqle The exception that was the result of the constraint violation.
     @return The extracted constraint name.
     */
    public String extractConstraintName(SQLException sqle) {
      String constraintName = null;
      
      int errorCode = JDBCExceptionHelper.extractErrorCode(sqle);
      if errorCode == -268 ) {
        constraintName = extractUsingTemplate"Unique constraint ("") violated.", sqle.getMessage() );
      }
      else if errorCode == -691 ) {
        constraintName = extractUsingTemplate"Missing key in referenced table for referential constraint ("").", sqle.getMessage() );
      }
      else if errorCode == -692 ) {
        constraintName = extractUsingTemplate"Key value for constraint ("") is still being referenced.", sqle.getMessage() );
      }
      
      if (constraintName != null) {
        // strip table-owner because Informix always returns constraint names as "<table-owner>.<constraint-name>"
        int i = constraintName.indexOf('.');
        if (i != -1) {
          constraintName = constraintName.substring(i + 1);
        }
      }

      return constraintName;
    }

  };

  public boolean supportsCurrentTimestampSelection() {
    return true;
  }

  public boolean isCurrentTimestampSelectStringCallable() {
    return false;
  }

  public String getCurrentTimestampSelectString() {
    return "select distinct current timestamp from informix.systables";
  }
}