/* * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * 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. * * Contributors: * Florent Guillaume */ package org.nuxeo.ecm.core.storage.sql.jdbc.db; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Calendar; import org.nuxeo.ecm.core.storage.sql.ColumnType; import org.nuxeo.ecm.core.storage.sql.jdbc.dialect.Dialect; import org.nuxeo.ecm.core.storage.sql.jdbc.dialect.Dialect.JDBCInfo; /** * An SQL {@code column}. * * @author Florent Guillaume */ public class Column implements Serializable { private static final long serialVersionUID = 1L; protected final Table table; protected final Dialect dialect; protected final String physicalName; private final String quotedName; private final String freeVariableSetter; /** The abstract type. */ private final ColumnType type; /** * The JDBC {@link java.sql.Types} type. Used for: - comparison with database introspected type - switch() to get * from result set or set to prepared statement - setNull to prepared statement */ private int jdbcType; /** The JDBC type string. */ private final String jdbcTypeString; /* * {@see java.sql.Array.getBaseType() value is 0 if this is not an array column */ private int jdbcBaseType; /* * {@see java.sql.Array.getBaseTypeName() value is null if this is not an array column */ private final String jdbcBaseTypeString; private final String key; private boolean identity; private boolean primary; private boolean nullable = true; private String defaultValue; /** For foreign key reference. */ private Table foreignTable; private String foreignKey; /** * Creates a new column with the given name and type. * * @param table the column's table * @param physicalName the column physical name * @param type the column's type * @param key the associated field name */ public Column(Table table, String physicalName, ColumnType type, String key) { this.table = table; dialect = table.getDialect(); this.physicalName = physicalName; this.type = type; JDBCInfo jdbcInfo = dialect.getJDBCTypeAndString(type); jdbcType = jdbcInfo.jdbcType; jdbcTypeString = jdbcInfo.string; jdbcBaseType = jdbcInfo.jdbcBaseType; jdbcBaseTypeString = jdbcInfo.jdbcBaseTypeString; this.key = key; quotedName = dialect.openQuote() + physicalName + dialect.closeQuote(); freeVariableSetter = dialect.getFreeVariableSetterForType(type); } /** * Creates a column from an existing column and an aliased table. */ public Column(Column column, Table table) { this(table, column.physicalName, column.type, column.key); } public Table getTable() { return table; } public String getPhysicalName() { return physicalName; } public String getQuotedName() { return quotedName; } public String getFullQuotedName() { return table.getQuotedName() + '.' + quotedName; } public int getJdbcType() { return jdbcType; } public int getJdbcBaseType() { return jdbcBaseType; } public ColumnType getType() { return type; } public ColumnType getBaseType() { ColumnType baseType; if (type == ColumnType.ARRAY_BLOBID) { baseType = ColumnType.BLOBID; } else if (type == ColumnType.ARRAY_BOOLEAN) { baseType = ColumnType.BOOLEAN; } else if (type == ColumnType.ARRAY_CLOB) { baseType = ColumnType.CLOB; } else if (type == ColumnType.ARRAY_DOUBLE) { baseType = ColumnType.DOUBLE; } else if (type == ColumnType.ARRAY_INTEGER) { baseType = ColumnType.INTEGER; } else if (type == ColumnType.ARRAY_LONG) { baseType = ColumnType.LONG; } else if (type == ColumnType.ARRAY_STRING) { baseType = ColumnType.STRING; } else if (type == ColumnType.ARRAY_TIMESTAMP) { baseType = ColumnType.TIMESTAMP; } else { baseType = type; } return baseType; } public String getFreeVariableSetter() { return freeVariableSetter; } public boolean isArray() { return type.isArray(); } public boolean isOpaque() { return type == ColumnType.FTINDEXED || type == ColumnType.FTSTORED; } public boolean setJdbcType(int actual, String actualName, int actualSize) { int expected = jdbcType; if (actual == expected) { return true; } if (dialect.isAllowedConversion(expected, actual, actualName, actualSize)) { return true; } return false; } public String getKey() { return key; } public void setIdentity(boolean identity) { this.identity = identity; } public boolean isIdentity() { return identity; } public void setPrimary(boolean primary) { this.primary = primary; } public boolean isPrimary() { return primary; } public void setNullable(boolean nullable) { this.nullable = nullable; } public boolean isNullable() { return nullable; } public String getDefaultValue() { return defaultValue; } public void setDefaultValue(String defaultValue) { this.defaultValue = defaultValue; } public void setReferences(Table foreignTable, String foreignKey) { this.foreignTable = foreignTable; this.foreignKey = foreignKey; } public Table getForeignTable() { return foreignTable; } public String getForeignKey() { return foreignKey; } public String getSqlTypeString() { return jdbcTypeString; } public String getSqlBaseTypeString() { return jdbcBaseTypeString; } public void setToPreparedStatement(PreparedStatement ps, int index, Serializable value) throws SQLException { if (value == null) { ps.setNull(index, jdbcType); return; } if ((jdbcType == Types.ARRAY) && !(value instanceof Object[])) { throw new SQLException("Expected an array value instead of: " + value); } dialect.setToPreparedStatement(ps, index, value, this); } public Serializable getFromResultSet(ResultSet rs, int index) throws SQLException { Serializable result = dialect.getFromResultSet(rs, index, this); if (rs.wasNull()) { result = null; } return result; } @Override public String toString() { return getClass().getSimpleName() + '(' + physicalName + ')'; } }