private Column processCreateColumn()

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;
    }