in HSQL/src/org/hsqldb1/DatabaseCommandInterpreter.java [721:884]
private Column processCreateColumn(HsqlName hsqlName)
throws HsqlException {
boolean isIdentity = false;
long identityStart = database.firstIdentity;
long identityIncrement = 1;
boolean isPrimaryKey = false;
String typeName;
int type;
int length = 0;
int scale = 0;
boolean hasLength = false;
boolean isNullable = true;
Expression defaultExpr = null;
String token;
typeName = tokenizer.getSimpleToken();
type = Types.getTypeNr(typeName);
if (type == Types.CHAR) {
if (tokenizer.isGetThis(Token.T_VARYING)) {
type = Types.VARCHAR;
}
}
if (typeName.equals(Token.T_IDENTITY)) {
isIdentity = true;
isPrimaryKey = true;
}
// fredt - when SET IGNORECASE is in effect, all new VARCHAR columns are defined as VARCHAR_IGNORECASE
if (type == Types.DOUBLE) {
tokenizer.isGetThis(Token.T_PRECISION);
}
if (tokenizer.isGetThis(Token.T_OPENBRACKET)) {
hasLength = true;
length = tokenizer.getInt();
Trace.check(Types.acceptsPrecisionCreateParam(type),
Trace.UNEXPECTED_TOKEN);
if (type != Types.TIMESTAMP && type != Types.TIME && length == 0) {
throw Trace.error(Trace.INVALID_SIZE_PRECISION);
}
if (tokenizer.isGetThis(Token.T_COMMA)) {
Trace.check(Types.acceptsScaleCreateParam(type),
Trace.UNEXPECTED_TOKEN);
scale = tokenizer.getInt();
}
tokenizer.getThis(Token.T_CLOSEBRACKET);
} else if (type == Types.CHAR && database.sqlEnforceStrictSize) {
length = 1;
} else if (type == Types.VARCHAR && database.sqlEnforceStrictSize) {
throw Trace.error(Trace.COLUMN_SIZE_REQUIRED);
}
/**
* @todo fredt - drop support for SET IGNORECASE and replace the
* type name with a qualifier specifying the case sensitivity of VARCHAR
*/
if (type == Types.VARCHAR && database.isIgnoreCase()) {
type = Types.VARCHAR_IGNORECASE;
}
if (type == Types.FLOAT && length > 53) {
throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
}
if (type == Types.TIMESTAMP) {
if (!hasLength) {
length = 6;
} else if (length != 0 && length != 6) {
throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
}
}
if (type == Types.TIME) {
if (length != 0) {
throw Trace.error(Trace.NUMERIC_VALUE_OUT_OF_RANGE);
}
}
token = tokenizer.getSimpleToken();
if (token.equals(Token.T_DEFAULT)) {
defaultExpr = processCreateDefaultExpression(type, length, scale);
token = tokenizer.getSimpleToken();
} else if (token.equals(Token.T_GENERATED)) {
tokenizer.getThis(Token.T_BY);
tokenizer.getThis(Token.T_DEFAULT);
tokenizer.getThis(Token.T_AS);
tokenizer.getThis(Token.T_IDENTITY);
if (tokenizer.isGetThis(Token.T_OPENBRACKET)) {
tokenizer.getThis(Token.T_START);
tokenizer.getThis(Token.T_WITH);
identityStart = tokenizer.getBigint();
if (tokenizer.isGetThis(Token.T_COMMA)) {
tokenizer.getThis(Token.T_INCREMENT);
tokenizer.getThis(Token.T_BY);
identityIncrement = tokenizer.getBigint();
}
tokenizer.getThis(Token.T_CLOSEBRACKET);
}
isIdentity = true;
isPrimaryKey = true;
token = tokenizer.getSimpleToken();
}
// fredt@users - accept IDENTITY before or after NOT NULL
if (token.equals(Token.T_IDENTITY)) {
isIdentity = true;
isPrimaryKey = true;
token = tokenizer.getSimpleToken();
}
if (token.equals(Token.T_NULL)) {
token = tokenizer.getSimpleToken();
} else if (token.equals(Token.T_NOT)) {
tokenizer.getThis(Token.T_NULL);
isNullable = false;
token = tokenizer.getSimpleToken();
}
if (token.equals(Token.T_IDENTITY)) {
if (isIdentity) {
throw Trace.error(Trace.SECOND_PRIMARY_KEY, Token.T_IDENTITY);
}
isIdentity = true;
isPrimaryKey = true;
token = tokenizer.getSimpleToken();
}
if (token.equals(Token.T_PRIMARY)) {
tokenizer.getThis(Token.T_KEY);
isPrimaryKey = true;
} else {
tokenizer.back();
}
// make sure IDENTITY and DEFAULT are not used together
if (isIdentity && defaultExpr != null) {
throw Trace.error(Trace.UNEXPECTED_TOKEN, Token.T_DEFAULT);
}
Column column = new Column(hsqlName, isNullable, type, length, scale,
isPrimaryKey, defaultExpr);
column.setIdentity(isIdentity, identityStart, identityIncrement);
return column;
}