Skip to content

Commit 8f21c66

Browse files
committed
multi value expression for insert included
1 parent 955274b commit 8f21c66

File tree

8 files changed

+182
-48
lines changed

8 files changed

+182
-48
lines changed
Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,33 @@
1-
/* ================================================================
2-
* JSQLParser : java based sql parser
3-
* ================================================================
4-
*
5-
* Project Info: http://jsqlparser.sourceforge.net
6-
* Project Lead: Leonardo Francalanci (leoonardoo@yahoo.it);
7-
*
8-
* (C) Copyright 2004, by Leonardo Francalanci
9-
*
10-
* This library is free software; you can redistribute it and/or modify it under the terms
11-
* of the GNU Lesser General Public License as published by the Free Software Foundation;
12-
* either version 2.1 of the License, or (at your option) any later version.
13-
*
14-
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15-
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16-
* See the GNU Lesser General Public License for more details.
17-
*
18-
* You should have received a copy of the GNU Lesser General Public License along with this
19-
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20-
* Boston, MA 02111-1307, USA.
21-
*/
22-
23-
package net.sf.jsqlparser.expression.operators.relational;
24-
25-
import net.sf.jsqlparser.statement.select.SubSelect;
26-
27-
public interface ItemsListVisitor {
28-
public void visit(SubSelect subSelect);
29-
30-
public void visit(ExpressionList expressionList);
31-
}
1+
/* ================================================================
2+
* JSQLParser : java based sql parser
3+
* ================================================================
4+
*
5+
* Project Info: http://jsqlparser.sourceforge.net
6+
* Project Lead: Leonardo Francalanci (leoonardoo@yahoo.it);
7+
*
8+
* (C) Copyright 2004, by Leonardo Francalanci
9+
*
10+
* This library is free software; you can redistribute it and/or modify it under the terms
11+
* of the GNU Lesser General Public License as published by the Free Software Foundation;
12+
* either version 2.1 of the License, or (at your option) any later version.
13+
*
14+
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16+
* See the GNU Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License along with this
19+
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20+
* Boston, MA 02111-1307, USA.
21+
*/
22+
23+
package net.sf.jsqlparser.expression.operators.relational;
24+
25+
import net.sf.jsqlparser.statement.select.SubSelect;
26+
27+
public interface ItemsListVisitor {
28+
public void visit(SubSelect subSelect);
29+
30+
public void visit(ExpressionList expressionList);
31+
32+
public void visit(MultiExpressionList multiExprList);
33+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (C) 2013 toben.
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2.1 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17+
* MA 02110-1301 USA
18+
*/
19+
package net.sf.jsqlparser.expression.operators.relational;
20+
21+
import java.util.ArrayList;
22+
import java.util.Iterator;
23+
import java.util.List;
24+
25+
/**
26+
* A list of ExpressionList items. e.g. multi values of insert statements. This one allows
27+
* only equally sized ExpressionList.
28+
* @author toben
29+
*/
30+
public class MultiExpressionList implements ItemsList {
31+
32+
List<ExpressionList> exprList;
33+
34+
public MultiExpressionList() {
35+
this.exprList = new ArrayList<ExpressionList>();
36+
}
37+
38+
@Override
39+
public void accept(ItemsListVisitor itemsListVisitor) {
40+
itemsListVisitor.visit(this);
41+
}
42+
43+
public List<ExpressionList> getExprList() {
44+
return exprList;
45+
}
46+
47+
public void addExpressionList(ExpressionList el) {
48+
if (!exprList.isEmpty()) {
49+
if (exprList.get(0).getExpressions().size() != el.getExpressions().size()) {
50+
throw new IllegalArgumentException("different count of parameters");
51+
}
52+
}
53+
exprList.add(el);
54+
}
55+
56+
@Override
57+
public String toString() {
58+
StringBuilder b = new StringBuilder();
59+
for (Iterator<ExpressionList> it = exprList.iterator(); it.hasNext() ;) {
60+
b.append(it.next().toString());
61+
if (it.hasNext()) b.append(", ");
62+
}
63+
return b.toString();
64+
}
65+
}

src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import net.sf.jsqlparser.expression.operators.relational.Matches;
4949
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
5050
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
51+
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
5152
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
5253
import net.sf.jsqlparser.schema.Column;
5354
import net.sf.jsqlparser.schema.Table;
@@ -367,4 +368,11 @@ public void visit(ExtractExpression eexpr) {
367368
public void visit(LateralSubSelect lateralSubSelect) {
368369
lateralSubSelect.getSubSelect().getSelectBody().accept(this);
369370
}
371+
372+
@Override
373+
public void visit(MultiExpressionList multiExprList) {
374+
for (ExpressionList exprList : multiExprList.getExprList()) {
375+
exprList.accept(this);
376+
}
377+
}
370378
}

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import net.sf.jsqlparser.expression.operators.relational.Matches;
4848
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
4949
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
50+
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
5051
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
5152
import net.sf.jsqlparser.schema.Column;
5253
import net.sf.jsqlparser.statement.select.SelectVisitor;
@@ -340,7 +341,7 @@ public void visit(ExpressionList expressionList) {
340341
buffer.append("(");
341342
}
342343
for (Iterator<Expression> iter = expressionList.getExpressions().iterator(); iter.hasNext();) {
343-
Expression expression = (Expression) iter.next();
344+
Expression expression = iter.next();
344345
expression.accept(this);
345346
if (iter.hasNext()) {
346347
buffer.append(", ");
@@ -467,4 +468,14 @@ public void visit(AnalyticExpression aexpr) {
467468
public void visit(ExtractExpression eexpr) {
468469
buffer.append(eexpr.toString());
469470
}
471+
472+
@Override
473+
public void visit(MultiExpressionList multiExprList) {
474+
for (Iterator<ExpressionList> it = multiExprList.getExprList().iterator(); it.hasNext();) {
475+
it.next().accept(this);
476+
if (it.hasNext()) {
477+
buffer.append(", ");
478+
}
479+
}
480+
}
470481
}

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

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@
66
import net.sf.jsqlparser.expression.ExpressionVisitor;
77
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
88
import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor;
9+
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
910
import net.sf.jsqlparser.schema.Column;
1011
import net.sf.jsqlparser.statement.insert.Insert;
1112
import net.sf.jsqlparser.statement.select.SelectVisitor;
1213
import net.sf.jsqlparser.statement.select.SubSelect;
1314

1415
/**
15-
* A class to de-parse (that is, tranform from JSqlParser hierarchy into a string) an
16-
* {@link net.sf.jsqlparser.statement.insert.Insert}
16+
* A class to de-parse (that is, tranform from JSqlParser hierarchy into a
17+
* string) an {@link net.sf.jsqlparser.statement.insert.Insert}
1718
*/
1819
public class InsertDeParser implements ItemsListVisitor {
20+
1921
protected StringBuilder buffer;
2022
protected ExpressionVisitor expressionVisitor;
2123
protected SelectVisitor selectVisitor;
@@ -24,16 +26,15 @@ public InsertDeParser() {
2426
}
2527

2628
/**
27-
* @param expressionVisitor
28-
* a {@link ExpressionVisitor} to de-parse {@link net.sf.jsqlparser.expression.Expression}s. It has to
29-
* share the same<br>
30-
* StringBuilder (buffer parameter) as this object in order to work
31-
* @param selectVisitor
32-
* a {@link SelectVisitor} to de-parse {@link net.sf.jsqlparser.statement.select.Select}s. It has to
33-
* share the same<br>
34-
* StringBuilder (buffer parameter) as this object in order to work
35-
* @param buffer
36-
* the buffer that will be filled with the insert
29+
* @param expressionVisitor a {@link ExpressionVisitor} to de-parse
30+
* {@link net.sf.jsqlparser.expression.Expression}s. It has to share the
31+
* same<br>
32+
* StringBuilder (buffer parameter) as this object in order to work
33+
* @param selectVisitor a {@link SelectVisitor} to de-parse
34+
* {@link net.sf.jsqlparser.statement.select.Select}s. It has to share the
35+
* same<br>
36+
* StringBuilder (buffer parameter) as this object in order to work
37+
* @param buffer the buffer that will be filled with the insert
3738
*/
3839
public InsertDeParser(ExpressionVisitor expressionVisitor, SelectVisitor selectVisitor, StringBuilder buffer) {
3940
this.buffer = buffer;
@@ -81,6 +82,25 @@ public void visit(ExpressionList expressionList) {
8182
buffer.append(")");
8283
}
8384

85+
@Override
86+
public void visit(MultiExpressionList multiExprList) {
87+
buffer.append(" VALUES ");
88+
for (Iterator<ExpressionList> it = multiExprList.getExprList().iterator(); it.hasNext();) {
89+
buffer.append("(");
90+
for (Iterator<Expression> iter = it.next().getExpressions().iterator(); iter.hasNext();) {
91+
Expression expression = iter.next();
92+
expression.accept(expressionVisitor);
93+
if (iter.hasNext()) {
94+
buffer.append(", ");
95+
}
96+
}
97+
buffer.append(")");
98+
if (it.hasNext()) {
99+
buffer.append(", ");
100+
}
101+
}
102+
}
103+
84104
@Override
85105
public void visit(SubSelect subSelect) {
86106
subSelect.getSelectBody().accept(selectVisitor);
@@ -101,5 +121,4 @@ public void setExpressionVisitor(ExpressionVisitor visitor) {
101121
public void setSelectVisitor(SelectVisitor visitor) {
102122
selectVisitor = visitor;
103123
}
104-
105124
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import net.sf.jsqlparser.expression.ExpressionVisitor;
77
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
88
import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor;
9+
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
910
import net.sf.jsqlparser.schema.Column;
1011
import net.sf.jsqlparser.statement.replace.Replace;
1112
import net.sf.jsqlparser.statement.select.SelectVisitor;
@@ -116,4 +117,9 @@ public void setSelectVisitor(SelectVisitor visitor) {
116117
selectVisitor = visitor;
117118
}
118119

120+
@Override
121+
public void visit(MultiExpressionList multiExprList) {
122+
throw new UnsupportedOperationException("Not supported yet.");
123+
}
124+
119125
}

src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ import net.sf.jsqlparser.expression.operators.relational.Matches;
104104
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
105105
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
106106
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
107+
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
107108
import net.sf.jsqlparser.schema.Column;
108109
import net.sf.jsqlparser.schema.Table;
109110
import net.sf.jsqlparser.statement.Statement;
@@ -392,6 +393,7 @@ Insert Insert():
392393
List<Expression> primaryExpList = new ArrayList<Expression>();
393394
ItemsList itemsList = null;
394395
Expression exp = null;
396+
MultiExpressionList multiExpr = null;
395397
}
396398
{
397399
<K_INSERT> [<K_INTO>] table=Table()
@@ -402,6 +404,16 @@ Insert Insert():
402404
(
403405
LOOKAHEAD(2) [<K_VALUES> | <K_VALUE>] "(" exp=SimpleExpression() { primaryExpList.add(exp); }
404406
("," exp=SimpleExpression() { primaryExpList.add(exp); } )* ")" { itemsList = new ExpressionList(primaryExpList); }
407+
408+
("," "(" exp=SimpleExpression() {
409+
if (multiExpr==null) {
410+
multiExpr=new MultiExpressionList();
411+
multiExpr.addExpressionList((ExpressionList)itemsList);
412+
itemsList = multiExpr;
413+
}
414+
primaryExpList = new ArrayList<Expression>();
415+
primaryExpList.add(exp); }
416+
("," exp=SimpleExpression() { primaryExpList.add(exp); } )* ")" { multiExpr.addExpressionList(new ExpressionList(primaryExpList)); } )*
405417

406418
|
407419

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import net.sf.jsqlparser.util.deparser.StatementDeParser;
2121

2222
public class InsertTest extends TestCase {
23+
2324
CCJSqlParserManager parserManager = new CCJSqlParserManager();
2425

2526
public InsertTest(String arg0) {
@@ -79,11 +80,21 @@ public void testInsertFromSelect() throws JSQLParserException {
7980
String statementToString = "INSERT INTO mytable (col1, col2, col3) (SELECT * FROM mytable2)";
8081
assertEquals(statementToString, "" + insert);
8182
}
82-
83+
8384
public void testInsertMultiRowValue() throws JSQLParserException {
84-
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (col1, col2) VALUES (a, b)");
85+
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (col1, col2) VALUES (a, b), (d, e)");
86+
}
87+
88+
public void testInsertMultiRowValueDifferent() throws JSQLParserException {
89+
try {
90+
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (col1, col2) VALUES (a, b), (d, e, c)");
91+
} catch (Exception e) {
92+
return;
93+
}
94+
95+
fail("should not work");
8596
}
86-
97+
8798
private void assertSqlCanBeParsedAndDeparsed(String statement) throws JSQLParserException {
8899
Statement parsed = parserManager.parse(new StringReader(statement));
89100
assertStatementCanBeDeparsedAs(parsed, statement);

0 commit comments

Comments
 (0)