Skip to content

Commit ca6538a

Browse files
messfishwumpz
authored andcommitted
fix issue #424 (INSERT with SET) (#481)
* update insert with set language * update insert with set * update insert with set * update insert test * add removed lines
1 parent 9c2cc2c commit ca6538a

File tree

4 files changed

+163
-2
lines changed

4 files changed

+163
-2
lines changed

src/main/java/net/sf/jsqlparser/statement/insert/Insert.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ public class Insert implements Statement {
5454
private boolean returningAllColumns = false;
5555

5656
private List<SelectExpressionItem> returningExpressionList = null;
57+
58+
/* these lines of codes are used to handle SET syntax in the insert part.
59+
* the SET syntax is based on this: https://dev.mysql.com/doc/refman/5.6/en/insert.html. */
60+
private boolean useSet = false;
61+
private List<Column> setColumns;
62+
private List<Expression> setExpressionList;
5763

5864
@Override
5965
public void accept(StatementVisitor statementVisitor) {
@@ -173,6 +179,30 @@ public boolean isModifierIgnore() {
173179
public void setModifierIgnore(boolean modifierIgnore) {
174180
this.modifierIgnore = modifierIgnore;
175181
}
182+
183+
public void setUseSet(boolean useSet) {
184+
this.useSet = useSet;
185+
}
186+
187+
public boolean isUseSet() {
188+
return useSet;
189+
}
190+
191+
public void setSetColumns(List<Column> setColumns) {
192+
this.setColumns = setColumns;
193+
}
194+
195+
public List<Column> getSetColumns() {
196+
return setColumns;
197+
}
198+
199+
public void setSetExpressionList(List<Expression> setExpressionList) {
200+
this.setExpressionList = setExpressionList;
201+
}
202+
203+
public List<Expression> getSetExpressionList() {
204+
return setExpressionList;
205+
}
176206

177207
@Override
178208
public String toString() {
@@ -208,6 +238,17 @@ public String toString() {
208238
sql.append(")");
209239
}
210240
}
241+
242+
if (useSet) {
243+
sql.append("SET ");
244+
for (int i = 0; i < getSetColumns().size(); i++) {
245+
if (i != 0) {
246+
sql.append(", ");
247+
}
248+
sql.append(setColumns.get(i)).append(" = ");
249+
sql.append(setExpressionList.get(i));
250+
}
251+
}
211252

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

230271
return sql.toString();
231272
}
273+
232274
}

src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,22 @@ public void deParse(Insert insert) {
115115
buffer.append(")");
116116
}
117117
}
118+
119+
if (insert.isUseSet()) {
120+
buffer.append(" SET ");
121+
for (int i = 0; i < insert.getSetColumns().size(); i++) {
122+
Column column = insert.getSetColumns().get(i);
123+
column.accept(expressionVisitor);
124+
125+
buffer.append(" = ");
126+
127+
Expression expression = insert.getSetExpressionList().get(i);
128+
expression.accept(expressionVisitor);
129+
if (i < insert.getSetColumns().size() - 1) {
130+
buffer.append(", ");
131+
}
132+
}
133+
}
118134

119135
if (insert.isUseDuplicate()) {
120136
buffer.append(" ON DUPLICATE KEY UPDATE ");

src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,20 +583,24 @@ Insert Insert():
583583
Insert insert = new Insert();
584584
Table table = null;
585585
Column tableColumn = null;
586-
List<Column> columns = new ArrayList<Column>();
586+
List<Column> columns = new ArrayList<Column>();
587587
List<Expression> primaryExpList = new ArrayList<Expression>();
588588
ItemsList itemsList = null;
589589
Expression exp = null;
590590
MultiExpressionList multiExpr = null;
591591
List<SelectExpressionItem> returning = null;
592592
Select select = null;
593+
boolean useValues = true;
593594
boolean useSelectBrackets = false;
594595
boolean useDuplicate = false;
595596
List<Column> duplicateUpdateColumns = null;
596597
List<Expression> duplicateUpdateExpressionList = null;
597598
Token tk = null;
598599
InsertModifierPriority modifierPriority = null;
599600
boolean modifierIgnore = false;
601+
boolean useSet = false;
602+
List<Column> setColumns = new ArrayList<Column>();
603+
List<Expression> setExpressionList = new ArrayList<Expression>();
600604
}
601605
{
602606
<K_INSERT>
@@ -633,6 +637,26 @@ Insert Insert():
633637
{ insert.setUseValues(false); }
634638
select = Select()
635639
)
640+
641+
|
642+
643+
<K_SET>
644+
(
645+
{
646+
useSet = true;
647+
insert.setUseValues(false);
648+
}
649+
tableColumn=Column() "=" exp=SimpleExpression()
650+
{
651+
setColumns = new ArrayList<Column>();
652+
setExpressionList = new ArrayList<Expression>();
653+
setColumns.add(tableColumn);
654+
setExpressionList.add(exp);
655+
}
656+
("," tableColumn=Column() "=" exp=SimpleExpression()
657+
{ setColumns.add(tableColumn);
658+
setExpressionList.add(exp); } )*
659+
)
636660
)
637661

638662
[ <K_ON> <K_DUPLICATE> <K_KEY> <K_UPDATE>
@@ -668,6 +692,9 @@ Insert Insert():
668692
insert.setReturningExpressionList(returning);
669693
insert.setModifierPriority(modifierPriority);
670694
insert.setModifierIgnore(modifierIgnore);
695+
insert.setUseSet(useSet);
696+
insert.setSetColumns(setColumns);
697+
insert.setSetExpressionList(setExpressionList);
671698
return insert;
672699
}
673700
}
@@ -3431,4 +3458,4 @@ Commit Commit():
34313458
{
34323459
return commit;
34333460
}
3434-
}
3461+
}

src/test/java/net/sf/jsqlparser/test/insert/InsertTest.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import net.sf.jsqlparser.schema.Table;
1414
import net.sf.jsqlparser.statement.insert.Insert;
1515
import net.sf.jsqlparser.statement.select.PlainSelect;
16+
1617
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
1718
import static org.junit.Assert.*;
1819

@@ -83,6 +84,63 @@ public void testInsertFromSelect() throws JSQLParserException {
8384
String statementToString = "INSERT INTO mytable (col1, col2, col3) SELECT * FROM mytable2";
8485
assertEquals(statementToString, "" + insert);
8586
}
87+
88+
@Test
89+
public void testInsertFromSet() throws JSQLParserException {
90+
String statement = "INSERT INTO mytable SET col1 = 12, col2 = name1 * name2";
91+
Insert insert = (Insert) parserManager.parse(new StringReader(statement));
92+
assertEquals("mytable", insert.getTable().getName());
93+
assertEquals(2, insert.getSetColumns().size());
94+
assertEquals("col1", ((Column) insert.getSetColumns().get(0)).getColumnName());
95+
assertEquals("col2", ((Column) insert.getSetColumns().get(1)).getColumnName());
96+
assertEquals(2, insert.getSetExpressionList().size());
97+
assertEquals("12", insert.getSetExpressionList().get(0).toString());
98+
assertEquals("name1 * name2", insert.getSetExpressionList().get(1).toString());
99+
assertEquals(statement, "" + insert);
100+
}
101+
102+
@Test
103+
public void testInsertValuesWithDuplicateElimination() throws JSQLParserException {
104+
String statement = "INSERT INTO TEST (ID, COUNTER) VALUES (123, 0) "
105+
+ "ON DUPLICATE KEY UPDATE COUNTER = COUNTER + 1";
106+
Insert insert = (Insert) parserManager.parse(new StringReader(statement));
107+
assertEquals("TEST", insert.getTable().getName());
108+
assertEquals(2, insert.getColumns().size());
109+
assertTrue(insert.isUseValues());
110+
assertEquals("ID", ((Column) insert.getColumns().get(0)).getColumnName());
111+
assertEquals("COUNTER", ((Column) insert.getColumns().get(1)).getColumnName());
112+
assertEquals(2, ((ExpressionList) insert.getItemsList()).getExpressions().size());
113+
assertEquals(123, ((LongValue) ((ExpressionList) insert.getItemsList()).getExpressions().
114+
get(0)).getValue());
115+
assertEquals(0, ((LongValue) ((ExpressionList) insert.getItemsList()).getExpressions().
116+
get(1)).getValue());
117+
assertEquals(1, insert.getDuplicateUpdateColumns().size());
118+
assertEquals("COUNTER", ((Column) insert.getDuplicateUpdateColumns().get(0)).getColumnName());
119+
assertEquals(1, insert.getDuplicateUpdateExpressionList().size());
120+
assertEquals("COUNTER + 1", insert.getDuplicateUpdateExpressionList().get(0).toString());
121+
assertFalse(insert.isUseSelectBrackets());
122+
assertTrue(insert.isUseDuplicate());
123+
assertEquals(statement, "" + insert);
124+
}
125+
126+
@Test
127+
public void testInsertFromSetWithDuplicateElimination() throws JSQLParserException {
128+
String statement = "INSERT INTO mytable SET col1 = 122 "
129+
+ "ON DUPLICATE KEY UPDATE col2 = col2 + 1, col3 = 'saint'";
130+
Insert insert = (Insert) parserManager.parse(new StringReader(statement));
131+
assertEquals("mytable", insert.getTable().getName());
132+
assertEquals(1, insert.getSetColumns().size());
133+
assertEquals("col1", ((Column) insert.getSetColumns().get(0)).getColumnName());
134+
assertEquals(1, insert.getSetExpressionList().size());
135+
assertEquals("122", insert.getSetExpressionList().get(0).toString());
136+
assertEquals(2, insert.getDuplicateUpdateColumns().size());
137+
assertEquals("col2", ((Column) insert.getDuplicateUpdateColumns().get(0)).getColumnName());
138+
assertEquals("col3", ((Column) insert.getDuplicateUpdateColumns().get(1)).getColumnName());
139+
assertEquals(2, insert.getDuplicateUpdateExpressionList().size());
140+
assertEquals("col2 + 1", insert.getDuplicateUpdateExpressionList().get(0).toString());
141+
assertEquals("'saint'", insert.getDuplicateUpdateExpressionList().get(1).toString());
142+
assertEquals(statement, "" + insert);
143+
}
86144

87145
@Test
88146
public void testInsertMultiRowValue() throws JSQLParserException {
@@ -191,4 +249,22 @@ public void testKeywordPrecisionIssue363() throws JSQLParserException {
191249
public void testWithDeparsingIssue406() throws JSQLParserException {
192250
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);
193251
}
252+
253+
@Test
254+
public void testInsertSetInDeparsing() throws JSQLParserException {
255+
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable SET col1 = 12, col2 = name1 * name2");
256+
}
257+
258+
@Test
259+
public void testInsertValuesWithDuplicateEliminationInDeparsing() throws JSQLParserException {
260+
assertSqlCanBeParsedAndDeparsed("INSERT INTO TEST (ID, COUNTER) VALUES (123, 0) "
261+
+ "ON DUPLICATE KEY UPDATE COUNTER = COUNTER + 1");
262+
}
263+
264+
@Test
265+
public void testInsertSetWithDuplicateEliminationInDeparsing() throws JSQLParserException {
266+
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable SET col1 = 122 "
267+
+ "ON DUPLICATE KEY UPDATE col2 = col2 + 1, col3 = 'saint'");
268+
}
269+
194270
}

0 commit comments

Comments
 (0)