public MySqlCreateTableStatement parseCreateTable()

in core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java [91:563]


    public MySqlCreateTableStatement parseCreateTable() {
        MySqlCreateTableStatement stmt = new MySqlCreateTableStatement();
        if (lexer.hasComment() && lexer.isKeepComments()) {
            stmt.addBeforeComment(lexer.readAndResetComments());
        }
        accept(Token.CREATE);

        if (lexer.nextIfIdentifier("TEMPORARY")) {
            stmt.config(SQLCreateTableStatement.Feature.Temporary);
        } else if (lexer.nextIfIdentifier("SHADOW")) {
            stmt.config(SQLCreateTableStatement.Feature.Shadow);
        }

        if (lexer.identifierEquals(FnvHash.Constants.DIMENSION)) {
            lexer.nextToken();
            stmt.setDimension(true);
        }

        if (lexer.token() == Token.HINT) {
            this.exprParser.parseHints(stmt.getHints());
        }

        if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {
            lexer.nextToken();
            stmt.setExternal(true);
        }

        accept(Token.TABLE);

        if (lexer.token() == Token.IF || lexer.identifierEquals("IF")) {
            lexer.nextToken();
            accept(Token.NOT);
            accept(Token.EXISTS);

            stmt.setIfNotExists(true);
        }

        stmt.setName(this.exprParser.name());

        if (lexer.token() == Token.LIKE) {
            lexer.nextToken();
            SQLName name = this.exprParser.name();
            stmt.setLike(name);
        }

        if (lexer.token() == Token.WITH) {
            SQLSelect query = new MySqlSelectParser(this.exprParser).select();
            stmt.setSelect(query);
        } else if (lexer.token() == (Token.LPAREN)) {
            lexer.nextToken();

            if (lexer.token() == Token.SELECT) {
                SQLSelect query = new MySqlSelectParser(this.exprParser).select();
                stmt.setSelect(query);
            } else {
                for (; ; ) {
                    SQLColumnDefinition column = null;

                    boolean global = false;
                    if (lexer.identifierEquals(FnvHash.Constants.GLOBAL)) {
                        final Lexer.SavePoint mark = lexer.mark();
                        lexer.nextToken();
                        if (lexer.token() == Token.INDEX || lexer.token() == Token.UNIQUE) {
                            global = true;
                        } else {
                            lexer.reset(mark);
                        }
                    }

                    boolean local = false;
                    if (lexer.identifierEquals(FnvHash.Constants.LOCAL)) {
                        final Lexer.SavePoint mark = lexer.mark();
                        lexer.nextToken();
                        if (lexer.token() == Token.INDEX || lexer.token() == Token.KEY
                            || lexer.token() == Token.UNIQUE) {
                            local = true;
                        } else if (lexer.token() == Token.FULLTEXT) {
                            lexer.nextToken();

                            if (lexer.token() == Token.KEY) {
                                MySqlKey fulltextKey = new MySqlKey();
                                this.exprParser.parseIndex(fulltextKey.getIndexDefinition());
                                fulltextKey.setIndexType("FULLTEXT");
                                fulltextKey.setParent(stmt);
                                stmt.getTableElementList().add(fulltextKey);

                                while (lexer.token() == Token.HINT) {
                                    lexer.nextToken();
                                }

                                if (lexer.token() == Token.RPAREN) {
                                    break;
                                } else if (lexer.token() == Token.COMMA) {
                                    lexer.nextToken();
                                    continue;
                                }
                            } else if (lexer.token() == Token.INDEX) {
                                MySqlTableIndex idx = new MySqlTableIndex();
                                this.exprParser.parseIndex(idx.getIndexDefinition());
                                idx.setIndexType("FULLTEXT");
                                idx.setParent(stmt);
                                stmt.getTableElementList().add(idx);

                                if (lexer.token() == Token.RPAREN) {
                                    break;
                                } else if (lexer.token() == Token.COMMA) {
                                    lexer.nextToken();
                                    continue;
                                }
                            } else if (lexer.token() == Token.IDENTIFIER && MySqlUtils.isBuiltinDataType(
                                lexer.stringVal())) {
                                lexer.reset(mark);
                            } else {
                                MySqlTableIndex idx = new MySqlTableIndex();
                                this.exprParser.parseIndex(idx.getIndexDefinition());
                                idx.setIndexType("FULLTEXT");
                                idx.setParent(stmt);
                                stmt.getTableElementList().add(idx);

                                if (lexer.token() == Token.RPAREN) {
                                    break;
                                } else if (lexer.token() == Token.COMMA) {
                                    lexer.nextToken();
                                    continue;
                                }
                            }

                        } else if (lexer.identifierEquals(FnvHash.Constants.SPATIAL)) {
                            lexer.nextToken();
                            if (lexer.token() == Token.INDEX || lexer.token() == Token.KEY ||
                                lexer.token() != Token.IDENTIFIER || !MySqlUtils.isBuiltinDataType(lexer.stringVal())) {
                                MySqlTableIndex idx = new MySqlTableIndex();
                                this.exprParser.parseIndex(idx.getIndexDefinition());
                                idx.setIndexType("SPATIAL");
                                idx.setParent(stmt);
                                stmt.getTableElementList().add(idx);

                                if (lexer.token() == Token.RPAREN) {
                                    break;
                                } else if (lexer.token() == Token.COMMA) {
                                    lexer.nextToken();
                                    continue;
                                }
                            } else {
                                lexer.reset(mark);
                            }
                        } else {
                            lexer.reset(mark);
                        }
                    }

                    if (lexer.token() == Token.FULLTEXT) {
                        Lexer.SavePoint mark = lexer.mark();
                        lexer.nextToken();

                        if (lexer.token() == Token.KEY) {
                            MySqlKey fulltextKey = new MySqlKey();
                            this.exprParser.parseIndex(fulltextKey.getIndexDefinition());
                            fulltextKey.setIndexType("FULLTEXT");
                            fulltextKey.setParent(stmt);
                            stmt.getTableElementList().add(fulltextKey);

                            while (lexer.token() == Token.HINT) {
                                lexer.nextToken();
                            }

                            if (lexer.token() == Token.RPAREN) {
                                break;
                            } else if (lexer.token() == Token.COMMA) {
                                lexer.nextToken();
                                continue;
                            }
                        } else if (lexer.token() == Token.INDEX) {
                            MySqlTableIndex idx = new MySqlTableIndex();
                            this.exprParser.parseIndex(idx.getIndexDefinition());
                            idx.setIndexType("FULLTEXT");
                            idx.setParent(stmt);
                            stmt.getTableElementList().add(idx);

                            if (lexer.token() == Token.RPAREN) {
                                break;
                            } else if (lexer.token() == Token.COMMA) {
                                lexer.nextToken();
                                continue;
                            }
                        } else if (lexer.token() == Token.IDENTIFIER && MySqlUtils.isBuiltinDataType(lexer.stringVal())) {
                            lexer.reset(mark);
                        } else {
                            MySqlTableIndex idx = new MySqlTableIndex();
                            this.exprParser.parseIndex(idx.getIndexDefinition());
                            idx.setIndexType("FULLTEXT");
                            idx.setParent(stmt);
                            stmt.getTableElementList().add(idx);

                            if (lexer.token() == Token.RPAREN) {
                                break;
                            } else if (lexer.token() == Token.COMMA) {
                                lexer.nextToken();
                                continue;
                            }
                        }

                    } else if (lexer.identifierEquals(FnvHash.Constants.SPATIAL)) {
                        Lexer.SavePoint mark = lexer.mark();
                        lexer.nextToken();
                        if (lexer.token() == Token.INDEX || lexer.token() == Token.KEY ||
                                lexer.token() != Token.IDENTIFIER || !MySqlUtils.isBuiltinDataType(lexer.stringVal())) {
                            MySqlTableIndex idx = new MySqlTableIndex();
                            this.exprParser.parseIndex(idx.getIndexDefinition());
                            idx.setIndexType("SPATIAL");
                            idx.setParent(stmt);
                            stmt.getTableElementList().add(idx);

                            if (lexer.token() == Token.RPAREN) {
                                break;
                            } else if (lexer.token() == Token.COMMA) {
                                lexer.nextToken();
                                continue;
                            }
                        } else {
                            lexer.reset(mark);
                        }
                    }

                    if (lexer.identifierEquals(FnvHash.Constants.ANN)) {
                        Lexer.SavePoint mark = lexer.mark();
                        lexer.nextToken();
                        if (lexer.token() == Token.INDEX || lexer.token() == Token.KEY) {
                            MySqlTableIndex idx = new MySqlTableIndex();
                            this.exprParser.parseIndex(idx.getIndexDefinition());
                            idx.setIndexType("ANN");
                            idx.setParent(stmt);
                            stmt.getTableElementList().add(idx);

                            if (lexer.token() == Token.RPAREN) {
                                break;
                            } else if (lexer.token() == Token.COMMA) {
                                lexer.nextToken();
                                continue;
                            }
                        } else {
                            lexer.reset(mark);
                        }
                    }
                    if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {
                        lexer.nextToken();
                        if (lexer.token() == Token.KEY) {
                            MySqlKey clsKey = new MySqlKey();
                            this.exprParser.parseIndex(clsKey.getIndexDefinition());
                            clsKey.setIndexType("CLUSTERED");
                            clsKey.setParent(stmt);
                            stmt.getTableElementList().add(clsKey);

                            if (lexer.token() == Token.COMMA) {
                                lexer.nextToken();
                                continue;
                            }
                        } else if (lexer.token() == Token.INDEX) {
                            MySqlTableIndex idx = new MySqlTableIndex();
                            this.exprParser.parseIndex(idx.getIndexDefinition());
                            idx.setIndexType("CLUSTERED");
                            idx.setParent(stmt);
                            stmt.getTableElementList().add(idx);

                            if (lexer.token() == Token.RPAREN) {
                                break;
                            } else if (lexer.token() == Token.COMMA) {
                                lexer.nextToken();
                                continue;
                            }
                        }
                    } else if (lexer.identifierEquals(FnvHash.Constants.CLUSTERING)) {
                        lexer.nextToken();
                        if (lexer.token() == Token.KEY) {
                            MySqlKey clsKey = new MySqlKey();
                            this.exprParser.parseIndex(clsKey.getIndexDefinition());
                            clsKey.setIndexType("CLUSTERING");
                            clsKey.setParent(stmt);
                            stmt.getTableElementList().add(clsKey);

                            if (lexer.token() == Token.COMMA) {
                                lexer.nextToken();
                                continue;
                            }
                        } else if (lexer.token() == Token.INDEX) {
                            MySqlTableIndex idx = new MySqlTableIndex();
                            this.exprParser.parseIndex(idx.getIndexDefinition());
                            idx.setIndexType("CLUSTERING");
                            idx.setParent(stmt);
                            stmt.getTableElementList().add(idx);

                            if (lexer.token() == Token.RPAREN) {
                                break;
                            } else if (lexer.token() == Token.COMMA) {
                                lexer.nextToken();
                                continue;
                            }
                        }
                    } else if (lexer.token() == Token.IDENTIFIER //
                            || lexer.token() == Token.LITERAL_CHARS) {
                        column = this.exprParser.parseColumn();
                        column.setParent(stmt);
                        stmt.getTableElementList().add(column);

                        if (lexer.isKeepComments() && lexer.hasComment()) {
                            column.addAfterComment(lexer.readAndResetComments());
                        }
                    } else if (lexer.token() == Token.CONSTRAINT //
                            || lexer.token() == Token.PRIMARY //
                            || lexer.token() == Token.UNIQUE) {
                        SQLTableConstraint constraint = this.parseConstraint();
                        constraint.setParent(stmt);

                        if (constraint instanceof MySqlUnique) {
                            MySqlUnique unique = (MySqlUnique) constraint;
                            if (global) {
                                unique.setGlobal(true);
                            }
                            if (local) {
                                unique.setLocal(true);
                            }
                        }

                        stmt.getTableElementList().add(constraint);
                    } else if (lexer.token() == (Token.INDEX)) {
                        MySqlTableIndex idx = new MySqlTableIndex();
                        this.exprParser.parseIndex(idx.getIndexDefinition());

                        if (global) {
                            idx.getIndexDefinition().setGlobal(true);
                        }

                        if (local) {
                            idx.getIndexDefinition().setLocal(true);
                        }

                        idx.setParent(stmt);
                        stmt.getTableElementList().add(idx);
                    } else if (lexer.token() == (Token.KEY)) {
                        Lexer.SavePoint savePoint = lexer.mark();
                        lexer.nextToken();

                        boolean isColumn = false;
                        if (lexer.identifierEquals(FnvHash.Constants.VARCHAR)) {
                            isColumn = true;
                        }
                        lexer.reset(savePoint);

                        if (isColumn) {
                            column = this.exprParser.parseColumn();
                            stmt.getTableElementList().add(column);
                        } else {
                            stmt.getTableElementList().add(parseConstraint());
                        }
                    } else if (lexer.token() == (Token.PRIMARY)) {
                        SQLTableConstraint pk = parseConstraint();
                        pk.setParent(stmt);
                        stmt.getTableElementList().add(pk);
                    } else if (lexer.token() == (Token.FOREIGN)) {
                        SQLForeignKeyConstraint fk = this.getExprParser().parseForeignKey();
                        fk.setParent(stmt);
                        stmt.getTableElementList().add(fk);
                    } else if (lexer.token() == Token.CHECK) {
                        SQLCheck check = this.exprParser.parseCheck();
                        stmt.getTableElementList().add(check);
                    } else if (lexer.token() == Token.LIKE) {
                        lexer.nextToken();
                        SQLTableLike tableLike = new SQLTableLike();
                        tableLike.setTable(new SQLExprTableSource(this.exprParser.name()));
                        tableLike.setParent(stmt);
                        stmt.getTableElementList().add(tableLike);

                        if (lexer.identifierEquals(FnvHash.Constants.INCLUDING)) {
                            lexer.nextToken();
                            acceptIdentifier("PROPERTIES");
                            tableLike.setIncludeProperties(true);
                        } else if (lexer.identifierEquals(FnvHash.Constants.EXCLUDING)) {
                            lexer.nextToken();
                            acceptIdentifier("PROPERTIES");
                            tableLike.setExcludeProperties(true);
                        }
                    } else {
                        column = this.exprParser.parseColumn();
                        stmt.getTableElementList().add(column);
                    }

                    if (lexer.token() == Token.HINT) {
                        lexer.nextToken();
                    }

                    if (lexer.token() != Token.COMMA) {
                        break;
                    } else {
                        lexer.nextToken();
                        if (lexer.isKeepComments() && lexer.hasComment() && column != null) {
                            column.addAfterComment(lexer.readAndResetComments());
                        }
                    }
                }
            }

            if (lexer.token() == Token.HINT) {
                lexer.nextToken();
            }

            accept(Token.RPAREN);

            if (lexer.token() == Token.HINT && lexer.stringVal().charAt(0) == '!') {
                lexer.nextToken();
            }
        }

        parseOptions(stmt);

        if (lexer.token() == (Token.ON)) {
            throw new ParserException("TODO. " + lexer.info());
        }

        if (lexer.token() == Token.REPLACE) {
            lexer.nextToken();
            stmt.setReplace(true);
        } else if (lexer.identifierEquals("IGNORE")) {
            lexer.nextToken();
            stmt.setIgnore(true);
        } else if (lexer.identifierEquals("SINGLE")) { // for polardb-x
            lexer.nextToken();
            stmt.setSingle(true);
        }

        if (lexer.token() == (Token.AS)) {
            lexer.nextToken();

            if (lexer.token() == Token.LPAREN) {
                lexer.nextToken();
                SQLSelect query = new MySqlSelectParser(this.exprParser).select();
                stmt.setSelect(query);
                accept(Token.RPAREN);
            }
            if (lexer.token() == Token.WITH) {
                stmt.setWithSelect(this.parseWith());
            }
        }

        SQLCommentHint hint = null;
        if (lexer.token() == Token.HINT) {
            hint = this.exprParser.parseHint();
        }

        if (lexer.token() == (Token.SELECT)) {
            SQLSelect query = new MySqlSelectParser(this.exprParser).select();
            if (hint != null) {
                query.setHeadHint(hint);
            }
            stmt.setSelect(query);

            if (lexer.token() == Token.WITH) {
                lexer.nextToken();
                if (lexer.identifierEquals(FnvHash.Constants.NO)) {
                    lexer.nextToken();
                    acceptIdentifier("DATA");
                    stmt.setWithData(false);
                } else {
                    acceptIdentifier("DATA");
                    stmt.setWithData(true);
                }
            }
        }

        while (lexer.token() == (Token.HINT)) {
            this.exprParser.parseHints(stmt.getOptionHints());
        }
        return stmt;
    }