org.batoo.jpa.jdbc.adapter.HsqlAdaptor.java Source code

Java tutorial

Introduction

Here is the source code for org.batoo.jpa.jdbc.adapter.HsqlAdaptor.java

Source

/*
 * Copyright (c) 2012-2013, Batu Alp Ceylan
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.batoo.jpa.jdbc.adapter;

import java.sql.SQLException;
import java.sql.Types;
import java.util.Collection;
import java.util.List;

import javax.persistence.GenerationType;
import javax.persistence.LockModeType;
import javax.persistence.criteria.CriteriaBuilder.Trimspec;
import javax.sql.DataSource;

import org.apache.commons.lang.StringUtils;
import org.batoo.jpa.jdbc.AbstractColumn;
import org.batoo.jpa.jdbc.AbstractTable;
import org.batoo.jpa.jdbc.BasicColumn;
import org.batoo.jpa.jdbc.IdType;
import org.batoo.jpa.jdbc.dbutils.QueryRunner;
import org.batoo.jpa.jdbc.dbutils.SingleValueHandler;
import org.batoo.jpa.jdbc.generator.SequenceGenerator;

import com.google.common.base.Joiner;

/**
 * JDBC Adapter for HSQLDB.
 * 
 * @author hceylan
 * @since 2.0.0
 */
public class HsqlAdaptor extends JdbcAdaptor {

    private static final String[] PRODUCT_NAMES = new String[] { "HSQL Database Engine" };

    /**
     * 
     * @since 2.0.0
     */
    public HsqlAdaptor() {
        super();
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public String applyConcat(List<String> arguments) {
        return Joiner.on(" || ").join(arguments);
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public String applyLikeEscape(String escapePattern) {
        return " {ESCAPE " + escapePattern + "}";

    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public String applyLock(String sql, LockModeType lockMode) {
        switch (lockMode) {
        case PESSIMISTIC_FORCE_INCREMENT:
        case PESSIMISTIC_READ:
            return sql + "\nFOR READ ONLY";
        case PESSIMISTIC_WRITE:
            return sql + "\nFOR UPDATE";
        default:
            break;
        }

        return sql;
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public String applyPagination(String sql, int startPosition, int maxResult) {
        if ((startPosition != 0) || (maxResult != Integer.MAX_VALUE)) {
            sql = sql + "\nLIMIT " + maxResult;

            if (startPosition != 0) {
                sql = sql + "OFFSET " + startPosition;
            }
        }

        return sql;
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public String applyTrim(Trimspec trimspec, String trimChar, String argument) {
        final StringBuilder builder = new StringBuilder("TRIM(");

        if (trimspec != null) {
            builder.append(trimspec.toString()).append(" ");
        }

        if (trimChar != null) {
            builder.append(trimChar).append(" ");
        }

        return builder.append("FROM ").append(argument).append(")").toString();
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public String createColumnDDL(AbstractColumn column) {
        final boolean identity = column.getIdType() == IdType.IDENTITY;

        return column.getName() + " " // name part
                + this.getColumnType(column, column.getSqlType()) // data type part
                + (!column.isNullable() ? " NOT NULL" : "") // not null part
                + (identity ? " GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1)" : ""); // auto increment part
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public String createCreateTableStatement(AbstractTable table, Collection<String> ddlColumns,
            List<String> pkColumns, List<String> uniqueColumns) {
        // HSQL handles the unique columns as constraints only
        final String columns = Joiner.on(",\n\t").join(ddlColumns);
        final String keys = Joiner.on(", ").join(pkColumns);
        final String uniques = Joiner.on(", ").join(uniqueColumns);

        final StringBuilder statement = new StringBuilder();
        statement.append("CREATE TABLE ").append(table.getQName()).append(" (\n\t"); // table part
        statement.append(columns); // columns part

        if (StringUtils.isNotBlank(uniques)) {
            statement.append(",");
            statement.append("\nUNIQUE(").append(uniques).append(")");
        }

        if (StringUtils.isNotBlank(keys)) {
            statement.append(",");
            statement.append("\nPRIMARY KEY(").append(keys).append(")");
        }

        statement.append(")");

        return statement.toString();
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public void createSequenceIfNecessary(DataSource datasource, SequenceGenerator sequence) {
        final String sql = "CREATE SEQUENCE " //
                + sequence.getQName() + " AS BIGINT"// ;
                + " START WITH " + sequence.getInitialValue() //
                + " INCREMENT BY " + sequence.getAllocationSize();

        try {
            new QueryRunner(datasource).update(sql);
        } catch (final SQLException e) {
            this.logRelaxed(e, "Cannot create sequence " + sequence.getName());
        }
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    protected String getColumnType(AbstractColumn cd, int sqlType) {
        switch (sqlType) {
        case Types.BLOB:
        case Types.CLOB:
            return "VARBINARY(" + cd.getLength() + ")";
        case Types.VARCHAR:
            return "VARCHAR(" + cd.getLength() + ")";
        case Types.TIME:
            return "TIME";
        case Types.DATE:
            return "DATE";
        case Types.TIMESTAMP:
            return "TIMESTAMP";
        case Types.CHAR:
            return "CHAR";
        case Types.BOOLEAN:
            return "BOOLEAN";
        case Types.TINYINT:
        case Types.SMALLINT:
            return "SMALLINT";
        case Types.INTEGER:
            return "INTEGER";
        case Types.BIGINT:
            return "BIGINT";
        case Types.FLOAT:
            return "FLOAT" + (cd.getPrecision() > 0 ? "(" + cd.getPrecision() + ")" : "");
        case Types.DOUBLE:
            return "DOUBLE" + (cd.getPrecision() > 0 ? "(" + cd.getPrecision() + ")" : "");
        case Types.DECIMAL:
            return "DECIMAL" + (cd.getPrecision() > 0
                    ? "(" + cd.getPrecision() + (cd.getScale() > 0 ? "," + cd.getScale() : "") + ")"
                    : "");
        }

        throw new IllegalArgumentException("Unhandled sql type: " + sqlType);
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    protected String getDatabaseName() {
        return "HSqlDb";
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    protected String getDropForeignKeySql(String schema, String table, String foreignKey) {
        final String qualifiedName = Joiner.on(".").skipNulls().join(schema, table);

        return "ALTER TABLE " + qualifiedName + " DROP CONSTRAINT " + foreignKey;
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public int getInsertBatchSize() {
        return 1;
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public long getNextSequence(DataSource datasource, String sequenceName) throws SQLException {
        return new QueryRunner(datasource) //
                .query("CALL NEXT VALUE FOR " + sequenceName, new SingleValueHandler<Number>()).longValue();
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public PaginationParamsOrder getPaginationParamsOrder() {
        return PaginationParamsOrder.SQL_MAX_START;
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    protected String[] getProductNames() {
        return HsqlAdaptor.PRODUCT_NAMES;
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public String getSelectLastIdentitySql(BasicColumn identityColumn) {
        return "CALL IDENTITY()";
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    protected boolean isForeignKeyHasDefaultIndex() {
        return true;
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public boolean paginationNeedsMaxResultsAlways() {
        return true;
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public boolean paginationNeedsStartAlways() {
        return false;
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public boolean parameterizedPagination() {
        return false;
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public IdType supports(GenerationType type) {
        if (type == null) {
            return IdType.SEQUENCE;
        }

        switch (type) {
        case IDENTITY:
            return IdType.IDENTITY;
        case SEQUENCE:
            return IdType.SEQUENCE;
        case TABLE:
            return IdType.TABLE;
        default:
            return IdType.SEQUENCE;
        }
    }

    /**
     * {@inheritDoc}
     * 
     */
    @Override
    public boolean supportsOrdinalParams() {
        return false;
    }
}