public SQLDataType parseDataType()

in core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java [4188:4408]


    public SQLDataType parseDataType(boolean restrict) {
        if (lexer.keepSourceLocation) {
            lexer.computeRowAndColumn();
        }
        int sourceLine = lexer.getPosLine(), sourceColumn = lexer.getPosColumn();

        Token token = lexer.token;
        if (token == Token.DEFAULT || token == Token.NOT || token == Token.NULL) {
            return null;
        }

        if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {
            return parseArrayDataType();
        }

        if (lexer.identifierEquals(FnvHash.Constants.MAP)) {
            lexer.nextToken();

            if (lexer.token == Token.LPAREN) { // presto
                lexer.nextToken();
                SQLDataType keyType = parseDataType();
                accept(Token.COMMA);
                SQLDataType valueType = parseDataType();
                accept(Token.RPAREN);
                return new SQLMapDataType(keyType, valueType, dbType);
            }

            accept(Token.LT);

            SQLDataType keyType = parseDataType();
            accept(Token.COMMA);
            SQLDataType valueType = parseDataType();
            if (lexer.token == Token.GTGT) {
                lexer.token = Token.GT;
            } else {
                accept(Token.GT);
            }

            return new SQLMapDataType(keyType, valueType, dbType);
        }

        if (lexer.identifierEquals(FnvHash.Constants.STRUCT)) {
            return parseDataTypeStruct();
        } else if (lexer.token == Token.TABLE) {
            lexer.nextToken();
            SQLTableDataType table = new SQLTableDataType();
            accept(Token.LPAREN);
            for (; ; ) {
                SQLColumnDefinition column;
                if (lexer.token == Token.STAR) {
                    lexer.nextToken();
                    column = new SQLColumnDefinition();
                    column.setName("*");
                    accept(Token.ANY);
                } else {
                    column = this.parseColumn();
                }
                column.setParent(table);
                table.getColumns().add(column);
                if (lexer.token == Token.COMMA) {
                    lexer.nextToken();
                    continue;
                }
                break;
            }
            accept(Token.RPAREN);
            return table;
        } else if (lexer.identifierEquals(FnvHash.Constants.ROW) || lexer.token == Token.ROW) {
            lexer.nextToken();
            return parseDataTypeRow();
        } else if (lexer.identifierEquals(FnvHash.Constants.NESTED)) {
            SQLDataType dataType = parseDataTypeNested();
            if (dataType != null) {
                return dataType;
            }
        }

        if (lexer.identifierEquals(FnvHash.Constants.UNIONTYPE)) {
            lexer.nextToken();
            accept(Token.LT);

            SQLUnionDataType unionType = new SQLUnionDataType();
            for (; ; ) {
                SQLDataType item = this.parseDataType();
                unionType.add(item);
                if (lexer.token == Token.COMMA) {
                    lexer.nextToken();
                    continue;
                }

                break;
            }
            accept(Token.GT);
            return unionType;
        }

        if (lexer.identifierEquals(FnvHash.Constants.GENERATED)
                || lexer.identifierEquals(FnvHash.Constants.RENAME)) {
            return null;
        }

        SQLName typeExpr = name();
        final long typeNameHashCode = typeExpr.nameHashCode64();
        StringBuilder typeName = new StringBuilder(typeExpr.toString());

        if (typeNameHashCode == FnvHash.Constants.LONG
                && lexer.identifierEquals(FnvHash.Constants.BYTE)) {
            parseDataTypeByte(typeName);
        } else if (typeNameHashCode == FnvHash.Constants.DOUBLE) {
            parseDataTypeDouble(typeName);
            parseDataTypePrecision(typeName);
        }

        if (typeNameHashCode == FnvHash.Constants.UNSIGNED) {
            if (lexer.token == Token.IDENTIFIER) {
                typeName.append(' ').append(lexer.stringVal());
                lexer.nextToken();
            }
        } else if (typeNameHashCode == FnvHash.Constants.SIGNED) {
            if (lexer.token == Token.IDENTIFIER) {
                typeName.append(' ').append(lexer.stringVal());
                lexer.nextToken();
            }
        } else if (isCharType(typeNameHashCode)) {
            SQLCharacterDataType charType = new SQLCharacterDataType(typeName.toString());

            //for ads
            if (lexer.token == Token.LBRACKET) {
                SQLArrayDataType arrayDataType = new SQLArrayDataType(charType, dbType);
                lexer.nextToken();
                accept(Token.RBRACKET);
                arrayDataType.putAttribute("ads.arrayDataType", Boolean.TRUE);
                return arrayDataType;
            }

            if (lexer.token == Token.LPAREN) {
                lexer.nextToken();
                if (typeNameHashCode == FnvHash.Constants.ENUM) {
                    exprList(charType.getArguments(), charType);
                } else {
                    SQLExpr arg = this.expr();
                    arg.setParent(charType);
                    charType.addArgument(arg);
                }
                accept(Token.RPAREN);
            }

            charType = (SQLCharacterDataType) parseCharTypeRest(charType);

            if (lexer.token == Token.HINT) {
                List<SQLCommentHint> hints = this.parseHints();
                charType.setHints(hints);
            }

            if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {
                return parseDataTypeRest(charType);
            } else if (lexer.token == Token.LBRACKET) {
                return parseDataTypeRest(charType);
            }

            return charType;
        } else if (typeNameHashCode == FnvHash.Constants.DATE) {
            return parseDataTypeRest(parseDataTypeDate(typeName, sourceLine, sourceColumn));
        }

        if ("national".equalsIgnoreCase(typeName.toString()) &&
                (lexer.identifierEquals(FnvHash.Constants.CHAR)
                        || lexer.identifierEquals(FnvHash.Constants.VARCHAR))) {
            typeName.append(' ').append(lexer.stringVal());
            lexer.nextToken();

            SQLCharacterDataType charType = new SQLCharacterDataType(typeName.toString());

            if (lexer.token == Token.LPAREN) {
                lexer.nextToken();
                SQLExpr arg = this.expr();
                arg.setParent(charType);
                charType.addArgument(arg);
                accept(Token.RPAREN);
            }

            charType = (SQLCharacterDataType) parseCharTypeRest(charType);

            if (lexer.token == Token.HINT) {
                List<SQLCommentHint> hints = this.parseHints();
                charType.setHints(hints);
            }

            if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {
                return parseDataTypeRest(charType);
            }

            return charType;
        }

        if ("character".equalsIgnoreCase(typeName.toString()) && "varying".equalsIgnoreCase(lexer.stringVal())) {
            typeName.append(' ').append(lexer.stringVal());
            lexer.nextToken();
        }

        parseDataTypeComplex(typeName);

        SQLDataType dataType = new SQLDataTypeImpl(typeName.toString());
        dataType.setDbType(dbType);

        //for ads
        if (lexer.token == Token.LBRACKET) {
            dataType = new SQLArrayDataType(dataType, dbType);
            lexer.nextToken();
            if (lexer.token == Token.LITERAL_INT) {
                SQLExpr arg = this.expr();
                arg.setParent(dataType);
                dataType.getArguments().add(arg);
            }
            accept(Token.RBRACKET);
            dataType.putAttribute("ads.arrayDataType", Boolean.TRUE);
        }

        dataType.setSource(sourceLine, sourceColumn);
        return parseDataTypeRest(dataType);
    }