/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * 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: * Florent Guillaume */ package org.eclipse.ecr.core.storage.sql.jdbc.dialect; import java.io.Serializable; import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.ecr.core.storage.StorageException; import org.eclipse.ecr.core.storage.sql.BinaryManager; import org.eclipse.ecr.core.storage.sql.ColumnType; import org.eclipse.ecr.core.storage.sql.Model; import org.eclipse.ecr.core.storage.sql.RepositoryDescriptor; import org.eclipse.ecr.core.storage.sql.jdbc.db.Column; import org.eclipse.ecr.core.storage.sql.jdbc.db.Database; import org.eclipse.ecr.core.storage.sql.jdbc.db.Table; /** * HSQLDB-specific dialect. * <p> * Not used for VCS, only for directories, so many features don't matter. */ public class DialectHSQLDB extends Dialect { public DialectHSQLDB(DatabaseMetaData metadata, BinaryManager binaryManager, RepositoryDescriptor repositoryDescriptor) throws StorageException { super(metadata, binaryManager, repositoryDescriptor); } @Override public boolean supportsIfExistsAfterTableName() { return true; } @Override public JDBCInfo getJDBCTypeAndString(ColumnType type) { switch (type.spec) { case STRING: if (type.isUnconstrained()) { return jdbcInfo("VARCHAR", Types.VARCHAR); } else if (type.isClob()) { return jdbcInfo("CLOB", Types.CLOB); } else { return jdbcInfo("VARCHAR(%d)", type.length, Types.VARCHAR); } case BOOLEAN: return jdbcInfo("BOOLEAN", Types.BOOLEAN); case LONG: return jdbcInfo("BIGINT", Types.BIGINT); case DOUBLE: return jdbcInfo("DOUBLE", Types.DOUBLE); case TIMESTAMP: return jdbcInfo("TIMESTAMP", Types.TIMESTAMP); case BLOBID: return jdbcInfo("VARCHAR(40)", Types.VARCHAR); // ----- case NODEID: case NODEIDFK: case NODEIDFKNP: case NODEIDFKMUL: case NODEIDFKNULL: case NODEIDPK: case NODEVAL: return jdbcInfo("VARCHAR(36)", Types.VARCHAR); case SYSNAME: case SYSNAMEARRAY: return jdbcInfo("VARCHAR(250)", Types.VARCHAR); case TINYINT: return jdbcInfo("TINYINT", Types.TINYINT); case INTEGER: return jdbcInfo("INTEGER", Types.INTEGER); case FTINDEXED: throw new AssertionError(type); case FTSTORED: return jdbcInfo("CLOB", Types.CLOB); case CLUSTERNODE: return jdbcInfo("INTEGER", Types.INTEGER); case CLUSTERFRAGS: return jdbcInfo("VARCHAR", Types.VARCHAR); } throw new AssertionError(type); } @Override public boolean isAllowedConversion(int expected, int actual, String actualName, int actualSize) { // CLOB vs VARCHAR compatibility if (expected == Types.VARCHAR && actual == Types.CLOB) { return true; } if (expected == Types.CLOB && actual == Types.VARCHAR) { return true; } // INTEGER vs BIGINT compatibility if (expected == Types.BIGINT && actual == Types.INTEGER) { return true; } if (expected == Types.INTEGER && actual == Types.BIGINT) { return true; } return false; } @Override public void setToPreparedStatement(PreparedStatement ps, int index, Serializable value, Column column) throws SQLException { switch (column.getJdbcType()) { case Types.VARCHAR: case Types.CLOB: setToPreparedStatementString(ps, index, value, column); return; case Types.BOOLEAN: ps.setBoolean(index, ((Boolean) value).booleanValue()); return; case Types.TINYINT: case Types.INTEGER: case Types.BIGINT: ps.setLong(index, ((Long) value).longValue()); return; case Types.DOUBLE: ps.setDouble(index, ((Double) value).doubleValue()); return; case Types.TIMESTAMP: setToPreparedStatementTimestamp(ps, index, value, column); return; default: throw new SQLException("Unhandled JDBC type: " + column.getJdbcType()); } } @Override @SuppressWarnings("boxing") public Serializable getFromResultSet(ResultSet rs, int index, Column column) throws SQLException { switch (column.getJdbcType()) { case Types.VARCHAR: case Types.CLOB: return getFromResultSetString(rs, index, column); case Types.BOOLEAN: return rs.getBoolean(index); case Types.TINYINT: case Types.INTEGER: case Types.BIGINT: return rs.getLong(index); case Types.DOUBLE: return rs.getDouble(index); case Types.TIMESTAMP: return getFromResultSetTimestamp(rs, index, column); } throw new SQLException("Unhandled JDBC type: " + column.getJdbcType()); } @Override public String getCreateFulltextIndexSql(String indexName, String quotedIndexName, Table table, List<Column> columns, Model model) { throw new UnsupportedOperationException(); } @Override public String getDialectFulltextQuery(String query) { throw new UnsupportedOperationException(); } @Override public FulltextMatchInfo getFulltextScoredMatchInfo(String fulltextQuery, String indexName, int nthMatch, Column mainColumn, Model model, Database database) { throw new UnsupportedOperationException(); } @Override public boolean getMaterializeFulltextSyntheticColumn() { return false; } @Override public int getFulltextIndexedColumns() { return 2; } @Override public boolean supportsUpdateFrom() { return false; } @Override public boolean doesUpdateFromRepeatSelf() { return true; } @Override public boolean supportsReadAcl() { return false; } @Override public String getReadAclsCheckSql(String idColumnName) { throw new UnsupportedOperationException(); } @Override public String getUpdateReadAclsSql() { throw new UnsupportedOperationException(); } @Override public String getRebuildReadAclsSql() { throw new UnsupportedOperationException(); } @Override public String getClobCast(boolean inOrderBy) { if (!inOrderBy) { return "CAST(%s AS VARCHAR)"; } return null; } @Override public String getSecurityCheckSql(String idColumnName) { throw new UnsupportedOperationException(); } @Override public String getInTreeSql(String idColumnName) { throw new UnsupportedOperationException(); } @Override public boolean supportsArrays() { return false; } @Override public String getSQLStatementsFilename() { return "resources/nuxeovcs/hsqldb.sql.txt"; // TODO VCS } @Override public String getTestSQLStatementsFilename() { return "resources/nuxeovcs/hsqldb.test.sql.txt"; // TODO VCS } @Override public Map<String, Serializable> getSQLStatementsProperties(Model model, Database database) { return new HashMap<String, Serializable>(); } @Override public boolean isClusteringSupported() { return false; } @Override public String getClusterInsertInvalidations() { throw new UnsupportedOperationException(); } @Override public String getClusterGetInvalidations() { throw new UnsupportedOperationException(); } @Override public boolean supportsPaging() { return true; } @SuppressWarnings("boxing") @Override public String getPagingClause(long limit, long offset) { return String.format("LIMIT %d OFFSET %d", limit, offset); } }