📄 column.java
字号:
/*
* Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.table;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import org.h2.command.Parser;
import org.h2.constant.ErrorCode;
import org.h2.engine.Constants;
import org.h2.engine.Mode;
import org.h2.engine.Session;
import org.h2.expression.ConditionAndOr;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
import org.h2.expression.SequenceValue;
import org.h2.expression.ValueExpression;
import org.h2.message.Message;
import org.h2.result.Row;
import org.h2.schema.Schema;
import org.h2.schema.Sequence;
import org.h2.util.MathUtils;
import org.h2.util.StringUtils;
import org.h2.value.DataType;
import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import org.h2.value.ValueString;
import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
import org.h2.value.ValueUuid;
/**
* This class represents a column in a table.
*/
public class Column {
private final int type;
private final long precision;
private final int scale;
private final int displaySize;
private Table table;
private String name;
private int columnId;
private boolean nullable = true;
private Expression defaultExpression;
private Expression checkConstraint;
private String checkConstraintSQL;
private String originalSQL;
private boolean autoIncrement;
private long start;
private long increment;
private boolean convertNullToDefault;
private Sequence sequence;
private boolean isComputed;
private TableFilter computeTableFilter;
private int selectivity;
private SingleColumnResolver resolver;
private String comment;
private boolean primaryKey;
// must be equal to ResultSetMetaData columnNoNulls, columnNullable,
// columnNullableUnknown
public static final int NOT_NULLABLE = 0, NULLABLE = 1, NULLABLE_UNKNOWN = 2;
public Column(String name, int type) {
this(name, type, -1, -1, -1);
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Column)) {
return false;
}
Column other = (Column) o;
if (table == null || other.table == null || name == null || other.name == null) {
return false;
}
return table == other.table && name.equals(other.name);
}
public int hashCode() {
if (table == null || name == null) {
return 0;
}
return table.getId() ^ name.hashCode();
}
public Column(String name, int type, long precision, int scale, int displaySize) {
this.name = name;
this.type = type;
if (precision == -1 && scale == -1 && displaySize == -1) {
DataType dt = DataType.getDataType(type);
precision = dt.defaultPrecision;
scale = dt.defaultScale;
displaySize = dt.defaultDisplaySize;
}
this.precision = precision;
this.scale = scale;
this.displaySize = displaySize;
}
public Column getClone() {
Column newColumn = new Column(name, type, precision, scale, displaySize);
// table is not set
// columnId is not set
newColumn.nullable = nullable;
newColumn.defaultExpression = defaultExpression;
newColumn.originalSQL = originalSQL;
// autoIncrement, start, increment is not set
newColumn.convertNullToDefault = convertNullToDefault;
newColumn.sequence = sequence;
newColumn.comment = comment;
newColumn.isComputed = isComputed;
newColumn.selectivity = selectivity;
newColumn.primaryKey = primaryKey;
return newColumn;
}
public boolean getComputed() {
return isComputed;
}
public Value computeValue(Session session, Row row) throws SQLException {
synchronized (this) {
computeTableFilter.setSession(session);
computeTableFilter.set(row);
return defaultExpression.getValue(session);
}
}
public void setComputed(boolean computed, Expression expression) {
this.isComputed = computed;
this.defaultExpression = expression;
}
void setTable(Table table, int columnId) {
this.table = table;
this.columnId = columnId;
}
public Table getTable() {
return table;
}
public void setDefaultExpression(Session session, Expression defaultExpression) throws SQLException {
// also to test that no column names are used
if (defaultExpression != null) {
defaultExpression = defaultExpression.optimize(session);
if (defaultExpression.isConstant()) {
defaultExpression = ValueExpression.get(defaultExpression.getValue(session));
}
}
this.defaultExpression = defaultExpression;
}
public int getColumnId() {
return columnId;
}
public String getSQL() {
return Parser.quoteIdentifier(name);
}
public String getName() {
return name;
}
public int getType() {
return type;
}
public long getPrecision() {
return precision;
}
public int getDisplaySize() {
return displaySize;
}
public int getScale() {
return scale;
}
public void setNullable(boolean b) {
nullable = b;
}
public Value validateConvertUpdateSequence(Session session, Value value) throws SQLException {
if (value == null) {
if (defaultExpression == null) {
value = ValueNull.INSTANCE;
} else {
synchronized (this) {
value = defaultExpression.getValue(session).convertTo(type);
}
if (primaryKey) {
session.setLastIdentity(value);
}
}
}
Mode mode = session.getDatabase().getMode();
if (value == ValueNull.INSTANCE) {
if (convertNullToDefault) {
synchronized (this) {
value = defaultExpression.getValue(session).convertTo(type);
}
}
if (value == ValueNull.INSTANCE && !nullable) {
if (mode.convertInsertNullToZero) {
DataType dt = DataType.getDataType(type);
if (dt.decimal) {
value = ValueInt.get(0).convertTo(type);
} else if (dt.type == Value.TIMESTAMP) {
value = ValueTimestamp.getNoCopy(new Timestamp(System.currentTimeMillis()));
} else if (dt.type == Value.TIME) {
// need to normalize
value = ValueTime.get(Time.valueOf("0:0:0"));
} else if (dt.type == Value.DATE) {
value = ValueTimestamp.getNoCopy(new Timestamp(System.currentTimeMillis())).convertTo(dt.type);
} else {
value = ValueString.get("").convertTo(type);
}
} else {
throw Message.getSQLException(ErrorCode.NULL_NOT_ALLOWED, name);
}
}
}
if (checkConstraint != null) {
resolver.setValue(value);
Value v;
synchronized (this) {
v = checkConstraint.getValue(session);
}
// Both TRUE and NULL are ok
if (Boolean.FALSE.equals(v.getBoolean())) {
throw Message.getSQLException(ErrorCode.CHECK_CONSTRAINT_VIOLATED_1, checkConstraint.getSQL());
}
}
value = value.convertScale(mode.convertOnlyToSmallerScale, scale);
if (precision > 0) {
if (!value.checkPrecision(precision)) {
throw Message.getSQLException(ErrorCode.VALUE_TOO_LONG_2, new String[]{name, value.getSQL()});
}
}
updateSequenceIfRequired(session, value);
return value;
}
private void updateSequenceIfRequired(Session session, Value value) throws SQLException {
if (sequence != null) {
long current = sequence.getCurrentValue();
long increment = sequence.getIncrement();
long now = value.getLong();
boolean update = false;
if (increment > 0 && now > current) {
update = true;
} else if (increment < 0 && now < current) {
update = true;
}
if (update) {
sequence.setStartValue(now + increment);
session.setLastIdentity(ValueLong.get(now));
sequence.flush();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -