public SQLInsertStatement parseInsert()

in core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java [4549:4903]


    public SQLInsertStatement parseInsert() {
        MySqlInsertStatement stmt = new MySqlInsertStatement();

        SQLName tableName = null;
        if (lexer.token() == Token.INSERT) {
            lexer.nextToken();

            for (; ; ) {
                if (lexer.token() == Token.IDENTIFIER) {
                    long hash = lexer.hashLCase();

                    if (hash == FnvHash.Constants.LOW_PRIORITY) {
                        stmt.setLowPriority(true);
                        lexer.nextToken();
                        continue;
                    }

                    if (hash == FnvHash.Constants.DELAYED) {
                        stmt.setDelayed(true);
                        lexer.nextToken();
                        continue;
                    }

                    if (hash == FnvHash.Constants.HIGH_PRIORITY) {
                        stmt.setHighPriority(true);
                        lexer.nextToken();
                        continue;
                    }

                    if (hash == FnvHash.Constants.IGNORE) {
                        stmt.setIgnore(true);
                        lexer.nextToken();
                        continue;
                    }

                    if (hash == FnvHash.Constants.ROLLBACK_ON_FAIL) {
                        stmt.setRollbackOnFail(true);
                        lexer.nextToken();
                        continue;
                    }
                }

                break;
            }

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

            if (lexer.token() == Token.INTO) {
                lexer.nextToken();
                if (lexer.token() == TABLE) {
                    lexer.nextToken();
                }
            } else if (lexer.identifierEquals(FnvHash.Constants.OVERWRITE)) {
                lexer.nextToken();
                stmt.setOverwrite(true);
                if (lexer.token() == TABLE) {
                    lexer.nextToken();
                } else if (lexer.token() == Token.INTO) {
                    lexer.nextToken();
                }
            }

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

            if (lexer.token() == Token.FULLTEXT) {
                lexer.nextToken();
                if (lexer.identifierEquals(FnvHash.Constants.DICTIONARY)) {
                    lexer.nextToken();
                    stmt.setFulltextDictionary(true);
                }
            }

            tableName = this.exprParser.name();
            stmt.setTableName(tableName);

            if (lexer.token() == Token.HINT) {
                String comment = "/*" + lexer.stringVal() + "*/";
                lexer.nextToken();
                stmt.getTableSource().addAfterComment(comment);
            }

            if (lexer.token() == Token.IDENTIFIER
                    && !lexer.identifierEquals(FnvHash.Constants.VALUE)) {
                stmt.setAlias(lexer.stringVal());
                lexer.nextToken();
            }

            if (lexer.token() == WITH) {
                SQLSelectStatement withStmt = (SQLSelectStatement) parseWith();
                stmt.setQuery(withStmt.getSelect());
            }

            if (lexer.token() == Token.PARTITION) {
                lexer.nextToken();
                accept(Token.LPAREN);
                for (; ; ) {
                    SQLAssignItem ptExpr = new SQLAssignItem();
                    ptExpr.setTarget(this.exprParser.name());
                    if (lexer.token() == Token.EQ) {
                        lexer.nextToken();
                        SQLExpr ptValue = this.exprParser.expr();
                        ptExpr.setValue(ptValue);
                    }
                    stmt.addPartition(ptExpr);
                    if (lexer.token() != Token.COMMA) {
                        break;
                    } else {
                        lexer.nextToken();
                    }
                }
                accept(Token.RPAREN);

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

                    stmt.setIfNotExists(true);
                }
            }
        }

        int columnSize = 0;
        List<SQLColumnDefinition> columnDefinitionList = null;

        if (lexer.token() == Token.LPAREN) {
            boolean useInsertColumnsCache = lexer.isEnabled(SQLParserFeature.UseInsertColumnsCache);
            InsertColumnsCache insertColumnsCache = null;

            long tableNameHash = 0;
            InsertColumnsCache.Entry cachedColumns = null;
            if (useInsertColumnsCache) {
                insertColumnsCache = this.insertColumnsCache;
                if (insertColumnsCache == null) {
                    insertColumnsCache = InsertColumnsCache.global;
                }

                if (tableName != null) {
                    tableNameHash = tableName.nameHashCode64();
                    cachedColumns = insertColumnsCache.get(tableNameHash);
                }
            }

            SchemaObject tableObject = null;
            int pos = lexer.pos();
            if (cachedColumns != null
                    && lexer.text.startsWith(cachedColumns.columnsString, pos)) {
                if (!lexer.isEnabled(SQLParserFeature.OptimizedForParameterized)) {
                    List<SQLExpr> columns = stmt.getColumns();
                    List<SQLExpr> cachedColumns2 = cachedColumns.columns;
                    for (int i = 0, size = cachedColumns2.size(); i < size; i++) {
                        columns.add(cachedColumns2.get(i).clone());
                    }
                }
                stmt.setColumnsString(cachedColumns.columnsFormattedString, cachedColumns.columnsFormattedStringHash);
                int p2 = pos + cachedColumns.columnsString.length();
                lexer.reset(p2);
                lexer.nextToken();
            } else {
                Lexer.SavePoint mark = lexer.mark();
                lexer.nextToken();
                if (lexer.token() == Token.SELECT) {
                    lexer.reset(mark);
                    SQLSelect select = this.exprParser.createSelectParser().select();
                    select.setParent(stmt);
                    stmt.setQuery(select);
                } else {
                    if (repository != null && lexer.isEnabled(SQLParserFeature.InsertValueCheckType)) {
                        tableObject = repository.findTable(tableName.nameHashCode64());
                    }

                    if (tableObject != null) {
                        columnDefinitionList = new ArrayList<SQLColumnDefinition>();
                    }

                    List<SQLExpr> columns = stmt.getColumns();

                    if (lexer.token() != Token.RPAREN) {
                        for (; ; ) {
                            String identName;
                            long hash;

                            Token token = lexer.token();
                            if (token == Token.IDENTIFIER) {
                                identName = lexer.stringVal();
                                hash = lexer.hashLCase();
                            } else if (token == Token.LITERAL_CHARS) {
                                if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {
                                    identName = lexer.stringVal();
                                } else {
                                    identName = '\'' + lexer.stringVal() + '\'';
                                }
                                hash = 0;
                            } else if (token == Token.LITERAL_ALIAS) {
                                identName = lexer.stringVal();
                                if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {
                                    identName = SQLUtils.normalize(identName, dbType);
                                }
                                hash = 0;
                            } else {
                                identName = lexer.stringVal();
                                hash = 0;
                            }
                            SQLExpr expr = new SQLIdentifierExpr(identName, hash);
                            if (lexer.hasComment()) {
                                expr.addBeforeComment(lexer.readAndResetComments());
                            }
                            lexer.nextTokenComma();
                            while (lexer.token() == Token.DOT) {
                                lexer.nextToken();
                                String propertyName = lexer.stringVal();
                                lexer.nextToken();
                                expr = new SQLPropertyExpr(expr, propertyName);
                            }
                            if (lexer.hasComment()) {
                                expr.addAfterComment(lexer.readAndResetComments());
                            }
                            expr.setParent(stmt);
                            columns.add(expr);
                            columnSize++;

                            if (tableObject != null) {
                                SQLColumnDefinition columnDefinition = tableObject.findColumn(hash);
                                columnDefinitionList.add(columnDefinition);
                            }

                            if (lexer.token() == Token.COMMA) {
                                lexer.nextTokenIdent();
                                continue;
                            }

                            break;
                        }
                        columnSize = stmt.getColumns().size();

                        if (insertColumnsCache != null && tableName != null) {
                            String columnsString = lexer.subString(pos, lexer.pos() - pos);

                            List<SQLExpr> clonedColumns = new ArrayList<SQLExpr>(columnSize);
                            for (int i = 0; i < columns.size(); i++) {
                                clonedColumns.add(columns.get(i).clone());
                            }

                            StringBuilder buf = new StringBuilder();
                            SQLASTOutputVisitor outputVisitor = SQLUtils.createOutputVisitor(buf, dbType);
                            outputVisitor.printInsertColumns(columns);

                            String formattedColumnsString = buf.toString();
                            long columnsFormattedStringHash = FnvHash.fnv1a_64_lower(formattedColumnsString);

                            insertColumnsCache.put(tableName.hashCode64(), columnsString, formattedColumnsString, clonedColumns);
                            stmt.setColumnsString(formattedColumnsString, columnsFormattedStringHash);
                        }
                    }
                    accept(Token.RPAREN);
                }
            }
        }

        List<SQLCommentHint> commentHints = null;
        if (lexer.token() == Token.HINT) {
            commentHints = this.exprParser.parseHints();
        } else if (lexer.token() == Token.LINE_COMMENT) {
            lexer.nextToken();
        }

        if (lexer.token() == Token.VALUES || lexer.identifierEquals(FnvHash.Constants.VALUE)) {
            lexer.nextTokenLParen();
            if (lexer.isEnabled(SQLParserFeature.InsertReader)) {
                return stmt;
            }

            if (lexer.isEnabled(SQLParserFeature.InsertValueNative)) {
                parseValueClauseNative(stmt.getValuesList(), columnDefinitionList, columnSize, stmt);
            } else {
                parseValueClause(stmt.getValuesList(), columnDefinitionList, columnSize, stmt);
            }
        } else if (lexer.token() == Token.SET) {
            lexer.nextToken();

            SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();
            stmt.addValueCause(values);

            for (; ; ) {
                SQLName name = this.exprParser.name();
                stmt.addColumn(name);
                if (lexer.token() == Token.EQ) {
                    lexer.nextToken();
                } else {
                    accept(Token.COLONEQ);
                }
                values.addValue(this.exprParser.expr());

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

                break;
            }

        } else if (lexer.token() == (Token.SELECT)) {
            SQLSelect select = this.exprParser.createSelectParser().select();
            if (commentHints != null && !commentHints.isEmpty()) {
                select.setHeadHint(commentHints.get(0));
            }
            select.setParent(stmt);
            stmt.setQuery(select);
        } else if (lexer.token() == (Token.LPAREN)) {
            lexer.nextToken();
            SQLSelect select = this.exprParser.createSelectParser().select();
            select.setParent(stmt);
            stmt.setQuery(select);
            accept(Token.RPAREN);
        } else if (lexer.token() == WITH) {
            SQLSelect query = this.exprParser.createSelectParser().select();
            stmt.setQuery(query);
        }

        if (lexer.token() == Token.ON) {
            lexer.nextToken();
            acceptIdentifier("DUPLICATE");
            accept(Token.KEY);
            accept(Token.UPDATE);

            List<SQLExpr> duplicateKeyUpdate = stmt.getDuplicateKeyUpdate();
            for (; ; ) {
                SQLName name = this.exprParser.name();
                accept(Token.EQ);
                SQLExpr value;
                try {
                    value = this.exprParser.expr();
                } catch (EOFParserException e) {
                    throw new ParserException("EOF, " + name + "=", e);
                }

                SQLBinaryOpExpr assignment = new SQLBinaryOpExpr(name, SQLBinaryOperator.Equality, value);
                assignment.setParent(stmt);
                duplicateKeyUpdate.add(assignment);

                if (lexer.token() == Token.COMMA) {
                    lexer.nextTokenIdent();
                    continue;
                }
                break;
            }
        }

        return stmt;
    }