From 56af725129c7903319518ea8a123384a984301df Mon Sep 17 00:00:00 2001 From: dengliming Date: Sun, 22 Feb 2026 23:58:42 +0800 Subject: [PATCH 1/2] Add support for insert as row_alias --- .../net/sf/jsqlparser/statement/insert/Insert.java | 13 +++++++++++++ .../sf/jsqlparser/util/deparser/InsertDeParser.java | 3 +++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 12 +++++++++++- .../sf/jsqlparser/statement/insert/InsertTest.java | 12 ++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java index 1a750494c..6c53346d8 100644 --- a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java +++ b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java @@ -9,6 +9,7 @@ */ package net.sf.jsqlparser.statement.insert; +import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.schema.Column; @@ -53,6 +54,7 @@ public class Insert implements Statement { private InsertConflictTarget conflictTarget; private InsertConflictAction conflictAction; private InsertDuplicateAction duplicateAction; + private Alias rowAlias; public List getDuplicateUpdateSets() { if (duplicateAction != null) { @@ -340,6 +342,9 @@ public String toString() { if (setUpdateSets != null && !setUpdateSets.isEmpty()) { sql.append("SET "); sql = UpdateSet.appendUpdateSetsTo(sql, setUpdateSets); + if (rowAlias != null) { + sql.append(" ").append(rowAlias); + } } if (duplicateAction != null) { @@ -411,4 +416,12 @@ public InsertDuplicateAction getDuplicateAction() { public void setDuplicateAction(InsertDuplicateAction duplicateAction) { this.duplicateAction = duplicateAction; } + + public Alias getRowAlias() { + return rowAlias; + } + + public void setRowAlias(Alias rowAlias) { + this.rowAlias = rowAlias; + } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java index 58a3018c5..41fd3fb22 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java @@ -113,6 +113,9 @@ public void deParse(Insert insert) { if (insert.getSetUpdateSets() != null) { builder.append(" SET "); deparseUpdateSets(insert.getSetUpdateSets(), builder, expressionVisitor); + if (insert.getRowAlias() != null) { + builder.append(" ").append(insert.getRowAlias()); + } } if (insert.getDuplicateAction() != null) { diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index d57b29f16..471f214ef 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -2809,6 +2809,8 @@ Insert Insert(): String name = null; boolean useAs = false; + boolean useSet = false; + Alias rowAlias = null; OutputClause outputClause = null; InsertConflictTarget conflictTarget = null; @@ -2846,12 +2848,20 @@ Insert Insert(): { insert.setOnlyDefaultValues(true); } | ( - updateSets = UpdateSets() { insert.withSetUpdateSets(updateSets); } + updateSets = UpdateSets() { insert.withSetUpdateSets(updateSets); useSet = true; } ) | select = Select() ) + [ LOOKAHEAD(2, { select instanceof Values || useSet }) rowAlias = Alias() { + if (select instanceof Values) { + select.setAlias(rowAlias); + } else { + insert.setRowAlias(rowAlias); + } + } ] + [ LOOKAHEAD(2) duplicateAction = InsertDuplicateAction() { insert.setDuplicateAction(duplicateAction); } ] diff --git a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java index 95e1d069b..272057340 100644 --- a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java @@ -395,10 +395,22 @@ public void testInsertValuesWithDuplicateEliminationInDeparsing() throws JSQLPar + "ON DUPLICATE KEY UPDATE COUNTER = COUNTER + 1"); } + @Test + public void testInsertValuesAliasWithDuplicateEliminationIssue() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new" + + " ON DUPLICATE KEY UPDATE c = new.a+new.b;"); + + assertSqlCanBeParsedAndDeparsed("INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new(m,n,p) " + + " ON DUPLICATE KEY UPDATE c = m+n;"); + } + @Test public void testInsertSetWithDuplicateEliminationInDeparsing() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable SET col1 = 122 " + "ON DUPLICATE KEY UPDATE col2 = col2 + 1, col3 = 'saint'"); + + assertSqlCanBeParsedAndDeparsed("INSERT INTO t1 SET a=1,b=2,c=3 AS new" + + " ON DUPLICATE KEY UPDATE c = new.a+new.b;"); } @Test From 1af5f90a287b0e0ddf2dff75fe052c29fa8b697d Mon Sep 17 00:00:00 2001 From: dengliming Date: Mon, 23 Feb 2026 00:03:58 +0800 Subject: [PATCH 2/2] format code --- .../statement/insert/InsertTest.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java index 272057340..cd73f7dd8 100644 --- a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java @@ -9,6 +9,20 @@ */ package net.sf.jsqlparser.statement.insert; +import static net.sf.jsqlparser.test.TestUtils.assertDeparse; +import static net.sf.jsqlparser.test.TestUtils.assertOracleHintExists; +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import static net.sf.jsqlparser.test.TestUtils.assertStatementCanBeDeparsedAs; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.StringReader; +import java.util.List; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.DoubleValue; @@ -34,21 +48,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import java.io.StringReader; -import java.util.List; - -import static net.sf.jsqlparser.test.TestUtils.assertDeparse; -import static net.sf.jsqlparser.test.TestUtils.assertOracleHintExists; -import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; -import static net.sf.jsqlparser.test.TestUtils.assertStatementCanBeDeparsedAs; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertThrowsExactly; -import static org.junit.jupiter.api.Assertions.assertTrue; - public class InsertTest { private final CCJSqlParserManager parserManager = new CCJSqlParserManager(); @@ -400,8 +399,9 @@ public void testInsertValuesAliasWithDuplicateEliminationIssue() throws JSQLPars assertSqlCanBeParsedAndDeparsed("INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new" + " ON DUPLICATE KEY UPDATE c = new.a+new.b;"); - assertSqlCanBeParsedAndDeparsed("INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new(m,n,p) " - + " ON DUPLICATE KEY UPDATE c = m+n;"); + assertSqlCanBeParsedAndDeparsed( + "INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new(m,n,p) " + + " ON DUPLICATE KEY UPDATE c = m+n;"); } @Test