Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/insert/Insert.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ public class Insert implements Statement {
private boolean returningAllColumns = false;

private List<SelectExpressionItem> returningExpressionList = null;

/* these lines of codes are used to handle SET syntax in the insert part.
* the SET syntax is based on this: https://dev.mysql.com/doc/refman/5.6/en/insert.html. */
private boolean useSet = false;
private List<Column> setColumns;
private List<Expression> setExpressionList;

@Override
public void accept(StatementVisitor statementVisitor) {
Expand Down Expand Up @@ -173,6 +179,30 @@ public boolean isModifierIgnore() {
public void setModifierIgnore(boolean modifierIgnore) {
this.modifierIgnore = modifierIgnore;
}

public void setUseSet(boolean useSet) {
this.useSet = useSet;
}

public boolean isUseSet() {
return useSet;
}

public void setSetColumns(List<Column> setColumns) {
this.setColumns = setColumns;
}

public List<Column> getSetColumns() {
return setColumns;
}

public void setSetExpressionList(List<Expression> setExpressionList) {
this.setExpressionList = setExpressionList;
}

public List<Expression> getSetExpressionList() {
return setExpressionList;
}

@Override
public String toString() {
Expand Down Expand Up @@ -208,6 +238,17 @@ public String toString() {
sql.append(")");
}
}

if (useSet) {
sql.append("SET ");
for (int i = 0; i < getSetColumns().size(); i++) {
if (i != 0) {
sql.append(", ");
}
sql.append(setColumns.get(i)).append(" = ");
sql.append(setExpressionList.get(i));
}
}

if (useDuplicate) {
sql.append(" ON DUPLICATE KEY UPDATE ");
Expand All @@ -229,4 +270,5 @@ public String toString() {

return sql.toString();
}

}
16 changes: 16 additions & 0 deletions src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,22 @@ public void deParse(Insert insert) {
buffer.append(")");
}
}

if (insert.isUseSet()) {
buffer.append(" SET ");
for (int i = 0; i < insert.getSetColumns().size(); i++) {
Column column = insert.getSetColumns().get(i);
column.accept(expressionVisitor);

buffer.append(" = ");

Expression expression = insert.getSetExpressionList().get(i);
expression.accept(expressionVisitor);
if (i < insert.getSetColumns().size() - 1) {
buffer.append(", ");
}
}
}

if (insert.isUseDuplicate()) {
buffer.append(" ON DUPLICATE KEY UPDATE ");
Expand Down
38 changes: 33 additions & 5 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -507,9 +507,9 @@ Update Update():
]

{
update.setColumns(columns);
update.setExpressions(expList);
update.setTables(tables);
update.setColumns(columns);
update.setExpressions(expList);
update.setTables(tables);
update.setFromItem(fromItem);
update.setJoins(joins);
update.setSelect(select);
Expand Down Expand Up @@ -583,20 +583,24 @@ Insert Insert():
Insert insert = new Insert();
Table table = null;
Column tableColumn = null;
List<Column> columns = new ArrayList<Column>();
List<Column> columns = new ArrayList<Column>();
List<Expression> primaryExpList = new ArrayList<Expression>();
ItemsList itemsList = null;
Expression exp = null;
MultiExpressionList multiExpr = null;
List<SelectExpressionItem> returning = null;
Select select = null;
boolean useValues = true;
boolean useSelectBrackets = false;
boolean useDuplicate = false;
List<Column> duplicateUpdateColumns = null;
List<Expression> duplicateUpdateExpressionList = null;
Token tk = null;
InsertModifierPriority modifierPriority = null;
boolean modifierIgnore = false;
boolean useSet = false;
List<Column> setColumns = new ArrayList<Column>();
List<Expression> setExpressionList = new ArrayList<Expression>();
}
{
<K_INSERT>
Expand Down Expand Up @@ -633,6 +637,26 @@ Insert Insert():
{ insert.setUseValues(false); }
select = Select()
)

|

<K_SET>
(
{
useSet = true;
insert.setUseValues(false);
}
tableColumn=Column() "=" exp=SimpleExpression()
{
setColumns = new ArrayList<Column>();
setExpressionList = new ArrayList<Expression>();
setColumns.add(tableColumn);
setExpressionList.add(exp);
}
("," tableColumn=Column() "=" exp=SimpleExpression()
{ setColumns.add(tableColumn);
setExpressionList.add(exp); } )*
)
)

[ <K_ON> <K_DUPLICATE> <K_KEY> <K_UPDATE>
Expand Down Expand Up @@ -668,6 +692,9 @@ Insert Insert():
insert.setReturningExpressionList(returning);
insert.setModifierPriority(modifierPriority);
insert.setModifierIgnore(modifierIgnore);
insert.setUseSet(useSet);
insert.setSetColumns(setColumns);
insert.setSetExpressionList(setExpressionList);
return insert;
}
}
Expand Down Expand Up @@ -3428,4 +3455,5 @@ Commit Commit():
{
return commit;
}
}

}
76 changes: 76 additions & 0 deletions src/test/java/net/sf/jsqlparser/test/insert/InsertTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.PlainSelect;

import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
import static org.junit.Assert.*;

Expand Down Expand Up @@ -83,6 +84,63 @@ public void testInsertFromSelect() throws JSQLParserException {
String statementToString = "INSERT INTO mytable (col1, col2, col3) SELECT * FROM mytable2";
assertEquals(statementToString, "" + insert);
}

@Test
public void testInsertFromSet() throws JSQLParserException {
String statement = "INSERT INTO mytable SET col1 = 12, col2 = name1 * name2";
Insert insert = (Insert) parserManager.parse(new StringReader(statement));
assertEquals("mytable", insert.getTable().getName());
assertEquals(2, insert.getSetColumns().size());
assertEquals("col1", ((Column) insert.getSetColumns().get(0)).getColumnName());
assertEquals("col2", ((Column) insert.getSetColumns().get(1)).getColumnName());
assertEquals(2, insert.getSetExpressionList().size());
assertEquals("12", insert.getSetExpressionList().get(0).toString());
assertEquals("name1 * name2", insert.getSetExpressionList().get(1).toString());
assertEquals(statement, "" + insert);
}

@Test
public void testInsertValuesWithDuplicateElimination() throws JSQLParserException {
String statement = "INSERT INTO TEST (ID, COUNTER) VALUES (123, 0) "
+ "ON DUPLICATE KEY UPDATE COUNTER = COUNTER + 1";
Insert insert = (Insert) parserManager.parse(new StringReader(statement));
assertEquals("TEST", insert.getTable().getName());
assertEquals(2, insert.getColumns().size());
assertTrue(insert.isUseValues());
assertEquals("ID", ((Column) insert.getColumns().get(0)).getColumnName());
assertEquals("COUNTER", ((Column) insert.getColumns().get(1)).getColumnName());
assertEquals(2, ((ExpressionList) insert.getItemsList()).getExpressions().size());
assertEquals(123, ((LongValue) ((ExpressionList) insert.getItemsList()).getExpressions().
get(0)).getValue());
assertEquals(0, ((LongValue) ((ExpressionList) insert.getItemsList()).getExpressions().
get(1)).getValue());
assertEquals(1, insert.getDuplicateUpdateColumns().size());
assertEquals("COUNTER", ((Column) insert.getDuplicateUpdateColumns().get(0)).getColumnName());
assertEquals(1, insert.getDuplicateUpdateExpressionList().size());
assertEquals("COUNTER + 1", insert.getDuplicateUpdateExpressionList().get(0).toString());
assertFalse(insert.isUseSelectBrackets());
assertTrue(insert.isUseDuplicate());
assertEquals(statement, "" + insert);
}

@Test
public void testInsertFromSetWithDuplicateElimination() throws JSQLParserException {
String statement = "INSERT INTO mytable SET col1 = 122 "
+ "ON DUPLICATE KEY UPDATE col2 = col2 + 1, col3 = 'saint'";
Insert insert = (Insert) parserManager.parse(new StringReader(statement));
assertEquals("mytable", insert.getTable().getName());
assertEquals(1, insert.getSetColumns().size());
assertEquals("col1", ((Column) insert.getSetColumns().get(0)).getColumnName());
assertEquals(1, insert.getSetExpressionList().size());
assertEquals("122", insert.getSetExpressionList().get(0).toString());
assertEquals(2, insert.getDuplicateUpdateColumns().size());
assertEquals("col2", ((Column) insert.getDuplicateUpdateColumns().get(0)).getColumnName());
assertEquals("col3", ((Column) insert.getDuplicateUpdateColumns().get(1)).getColumnName());
assertEquals(2, insert.getDuplicateUpdateExpressionList().size());
assertEquals("col2 + 1", insert.getDuplicateUpdateExpressionList().get(0).toString());
assertEquals("'saint'", insert.getDuplicateUpdateExpressionList().get(1).toString());
assertEquals(statement, "" + insert);
}

@Test
public void testInsertMultiRowValue() throws JSQLParserException {
Expand Down Expand Up @@ -191,4 +249,22 @@ public void testKeywordPrecisionIssue363() throws JSQLParserException {
public void testWithDeparsingIssue406() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("insert into mytab3 (a,b,c) select a,b,c from mytab where exists(with t as (select * from mytab2) select * from t)", true);
}

@Test
public void testInsertSetInDeparsing() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable SET col1 = 12, col2 = name1 * name2");
}

@Test
public void testInsertValuesWithDuplicateEliminationInDeparsing() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("INSERT INTO TEST (ID, COUNTER) VALUES (123, 0) "
+ "ON DUPLICATE KEY UPDATE COUNTER = COUNTER + 1");
}

@Test
public void testInsertSetWithDuplicateEliminationInDeparsing() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable SET col1 = 122 "
+ "ON DUPLICATE KEY UPDATE col2 = col2 + 1, col3 = 'saint'");
}

}