blob: b1600b6c2bb3de213869ad62667127c79bf32572 [file] [log] [blame]
/* Copyright (c) 2001-2010, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hsqldb;
import org.hsqldb.HsqlNameManager.HsqlName;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.lib.Iterator;
import org.hsqldb.lib.OrderedHashSet;
import org.hsqldb.rights.Grantee;
import org.hsqldb.types.Type;
import org.hsqldb.types.Types;
/**
* Implementation of SQL table column metadata.<p>
*
* @author Fred Toussi (fredt@users dot sourceforge.net)
* @version 1.9.0
* @since 1.9.0
*/
public final class ColumnSchema extends ColumnBase implements SchemaObject {
public final static ColumnSchema[] emptyArray = new ColumnSchema[]{};
//
private HsqlName columnName;
private boolean isPrimaryKey;
private Expression defaultExpression;
private Expression generatingExpression;
private NumberSequence sequence;
private OrderedHashSet references = new OrderedHashSet();
private Expression accessor;
/**
* Creates a column defined in DDL statement.
*/
public ColumnSchema(HsqlName name, Type type, boolean isNullable,
boolean isPrimaryKey, Expression defaultExpression) {
columnName = name;
nullability = isNullable ? SchemaObject.Nullability.NULLABLE
: SchemaObject.Nullability.NO_NULLS;
this.dataType = type;
this.isPrimaryKey = isPrimaryKey;
this.defaultExpression = defaultExpression;
setReferences();
}
public int getType() {
return columnName.type;
}
public HsqlName getName() {
return columnName;
}
public String getNameString() {
return columnName.name;
}
public String getTableNameString() {
return columnName.parent == null ? null
: columnName.parent.name;
}
public HsqlName getSchemaName() {
return columnName.schema;
}
public String getSchemaNameString() {
return columnName.schema == null ? null
: columnName.schema.name;
}
public HsqlName getCatalogName() {
return columnName.schema == null ? null
: columnName.schema.schema;
}
public String getCatalogNameString() {
return columnName.schema == null ? null
: columnName.schema.schema == null
? null
: columnName.schema.schema.name;
}
public Grantee getOwner() {
return columnName.schema == null ? null
: columnName.schema.owner;
}
public OrderedHashSet getReferences() {
return references;
}
public OrderedHashSet getComponents() {
return null;
}
public void compile(Session session, SchemaObject table) {
if (generatingExpression == null) {
return;
}
generatingExpression.resetColumnReferences();
generatingExpression.resolveCheckOrGenExpression(session,
((Table) table).defaultRanges, false);
if (dataType.typeComparisonGroup
!= generatingExpression.getDataType().typeComparisonGroup) {
throw Error.error(ErrorCode.X_42561);
}
setReferences();
}
public String getSQL() {
StringBuffer sb = new StringBuffer();
switch (parameterMode) {
case SchemaObject.ParameterModes.PARAM_IN :
sb.append(Tokens.T_IN).append(' ');
break;
case SchemaObject.ParameterModes.PARAM_OUT :
sb.append(Tokens.T_OUT).append(' ');
break;
case SchemaObject.ParameterModes.PARAM_INOUT :
sb.append(Tokens.T_INOUT).append(' ');
break;
}
if (columnName != null) {
sb.append(columnName.statementName);
sb.append(' ');
}
sb.append(dataType.getTypeDefinition());
return sb.toString();
}
public long getChangeTimestamp() {
return 0;
}
public void setType(Type type) {
this.dataType = type;
setReferences();
}
public void setName(HsqlName name) {
this.columnName = name;
}
void setIdentity(NumberSequence sequence) {
this.sequence = sequence;
isIdentity = sequence != null;
}
void setType(ColumnSchema other) {
nullability = other.nullability;
dataType = other.dataType;
}
public NumberSequence getIdentitySequence() {
return sequence;
}
/**
* Is column nullable.
*
* @return boolean
*/
public boolean isNullable() {
boolean isNullable = super.isNullable();
if (isNullable) {
if (dataType.isDomainType()) {
return dataType.userTypeModifier.isNullable();
}
}
return isNullable;
}
public byte getNullability() {
return isPrimaryKey ? SchemaObject.Nullability.NO_NULLS
: super.getNullability();
}
public boolean isGenerated() {
return generatingExpression != null;
}
public boolean hasDefault() {
return getDefaultExpression() != null;
}
/**
* Is column writeable or always generated
*
* @return boolean
*/
public boolean isWriteable() {
return !isGenerated();
}
public void setWriteable(boolean value) {
throw Error.runtimeError(ErrorCode.U_S0500, "ColumnSchema");
}
public boolean isSearchable() {
return Types.isSearchable(dataType.typeCode);
}
/**
* Is this single column primary key of the table.
*
* @return boolean
*/
public boolean isPrimaryKey() {
return isPrimaryKey;
}
/**
* Set primary key.
*
*/
void setPrimaryKey(boolean value) {
isPrimaryKey = value;
}
/**
* Returns default value in the session context.
*/
public Object getDefaultValue(Session session) {
return defaultExpression == null ? null
: defaultExpression.getValue(session,
dataType);
}
/**
* Returns generated value in the session context.
*/
public Object getGeneratedValue(Session session) {
return generatingExpression == null ? null
: generatingExpression.getValue(
session, dataType);
}
/**
* Returns SQL for default value.
*/
public String getDefaultSQL() {
String ddl = null;
ddl = defaultExpression == null ? null
: defaultExpression.getSQL();
return ddl;
}
/**
* Returns default expression for the column.
*/
Expression getDefaultExpression() {
if (defaultExpression == null) {
if (dataType.isDomainType()) {
return dataType.userTypeModifier.getDefaultClause();
}
return null;
} else {
return defaultExpression;
}
}
void setDefaultExpression(Expression expr) {
defaultExpression = expr;
}
/**
* Returns generated expression for the column.
*/
public Expression getGeneratingExpression() {
return generatingExpression;
}
void setGeneratingExpression(Expression expr) {
generatingExpression = expr;
}
public ColumnSchema duplicate() {
ColumnSchema copy = new ColumnSchema(columnName, dataType,
isNullable(), isPrimaryKey,
defaultExpression);
copy.setGeneratingExpression(generatingExpression);
copy.setIdentity(sequence);
return copy;
}
public Expression getAccessor() {
if (accessor == null) {
accessor = new ExpressionColumnAccessor(this);
}
return accessor;
}
private void setReferences() {
references.clear();
if (dataType.isDomainType() || dataType.isDistinctType()) {
HsqlName name = ((SchemaObject) dataType).getName();
references.add(name);
}
if (generatingExpression != null) {
generatingExpression.collectObjectNames(references);
Iterator it = references.iterator();
while (it.hasNext()) {
HsqlName name = (HsqlName) it.next();
if (name.type == SchemaObject.COLUMN
|| name.type == SchemaObject.TABLE) {
it.remove();
}
}
}
}
}