Skip to content

Commit

Permalink
multi value expression for insert included
Browse files Browse the repository at this point in the history
  • Loading branch information
wumpz committed Mar 14, 2013
1 parent 955274b commit 8f21c66
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
/* ================================================================
* JSQLParser : java based sql parser
* ================================================================
*
* Project Info: http://jsqlparser.sourceforge.net
* Project Lead: Leonardo Francalanci (leoonardoo@yahoo.it);
*
* (C) Copyright 2004, by Leonardo Francalanci
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/

package net.sf.jsqlparser.expression.operators.relational;

import net.sf.jsqlparser.statement.select.SubSelect;

public interface ItemsListVisitor {
public void visit(SubSelect subSelect);

public void visit(ExpressionList expressionList);
}
/* ================================================================
* JSQLParser : java based sql parser
* ================================================================
*
* Project Info: http://jsqlparser.sourceforge.net
* Project Lead: Leonardo Francalanci (leoonardoo@yahoo.it);
*
* (C) Copyright 2004, by Leonardo Francalanci
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/

package net.sf.jsqlparser.expression.operators.relational;

import net.sf.jsqlparser.statement.select.SubSelect;

public interface ItemsListVisitor {
public void visit(SubSelect subSelect);

public void visit(ExpressionList expressionList);

public void visit(MultiExpressionList multiExprList);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2013 toben.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package net.sf.jsqlparser.expression.operators.relational;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
* A list of ExpressionList items. e.g. multi values of insert statements. This one allows
* only equally sized ExpressionList.
* @author toben
*/
public class MultiExpressionList implements ItemsList {

List<ExpressionList> exprList;

public MultiExpressionList() {
this.exprList = new ArrayList<ExpressionList>();
}

@Override
public void accept(ItemsListVisitor itemsListVisitor) {
itemsListVisitor.visit(this);
}

public List<ExpressionList> getExprList() {
return exprList;
}

public void addExpressionList(ExpressionList el) {
if (!exprList.isEmpty()) {
if (exprList.get(0).getExpressions().size() != el.getExpressions().size()) {
throw new IllegalArgumentException("different count of parameters");
}
}
exprList.add(el);
}

@Override
public String toString() {
StringBuilder b = new StringBuilder();
for (Iterator<ExpressionList> it = exprList.iterator(); it.hasNext() ;) {
b.append(it.next().toString());
if (it.hasNext()) b.append(", ");
}
return b.toString();
}
}
8 changes: 8 additions & 0 deletions src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import net.sf.jsqlparser.expression.operators.relational.Matches;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
Expand Down Expand Up @@ -367,4 +368,11 @@ public void visit(ExtractExpression eexpr) {
public void visit(LateralSubSelect lateralSubSelect) {
lateralSubSelect.getSubSelect().getSelectBody().accept(this);
}

@Override
public void visit(MultiExpressionList multiExprList) {
for (ExpressionList exprList : multiExprList.getExprList()) {
exprList.accept(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import net.sf.jsqlparser.expression.operators.relational.Matches;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.SelectVisitor;
Expand Down Expand Up @@ -340,7 +341,7 @@ public void visit(ExpressionList expressionList) {
buffer.append("(");
}
for (Iterator<Expression> iter = expressionList.getExpressions().iterator(); iter.hasNext();) {
Expression expression = (Expression) iter.next();
Expression expression = iter.next();
expression.accept(this);
if (iter.hasNext()) {
buffer.append(", ");
Expand Down Expand Up @@ -467,4 +468,14 @@ public void visit(AnalyticExpression aexpr) {
public void visit(ExtractExpression eexpr) {
buffer.append(eexpr.toString());
}

@Override
public void visit(MultiExpressionList multiExprList) {
for (Iterator<ExpressionList> it = multiExprList.getExprList().iterator(); it.hasNext();) {
it.next().accept(this);
if (it.hasNext()) {
buffer.append(", ");
}
}
}
}
45 changes: 32 additions & 13 deletions src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.SelectVisitor;
import net.sf.jsqlparser.statement.select.SubSelect;

/**
* A class to de-parse (that is, tranform from JSqlParser hierarchy into a string) an
* {@link net.sf.jsqlparser.statement.insert.Insert}
* A class to de-parse (that is, tranform from JSqlParser hierarchy into a
* string) an {@link net.sf.jsqlparser.statement.insert.Insert}
*/
public class InsertDeParser implements ItemsListVisitor {

protected StringBuilder buffer;
protected ExpressionVisitor expressionVisitor;
protected SelectVisitor selectVisitor;
Expand All @@ -24,16 +26,15 @@ public InsertDeParser() {
}

/**
* @param expressionVisitor
* a {@link ExpressionVisitor} to de-parse {@link net.sf.jsqlparser.expression.Expression}s. It has to
* share the same<br>
* StringBuilder (buffer parameter) as this object in order to work
* @param selectVisitor
* a {@link SelectVisitor} to de-parse {@link net.sf.jsqlparser.statement.select.Select}s. It has to
* share the same<br>
* StringBuilder (buffer parameter) as this object in order to work
* @param buffer
* the buffer that will be filled with the insert
* @param expressionVisitor a {@link ExpressionVisitor} to de-parse
* {@link net.sf.jsqlparser.expression.Expression}s. It has to share the
* same<br>
* StringBuilder (buffer parameter) as this object in order to work
* @param selectVisitor a {@link SelectVisitor} to de-parse
* {@link net.sf.jsqlparser.statement.select.Select}s. It has to share the
* same<br>
* StringBuilder (buffer parameter) as this object in order to work
* @param buffer the buffer that will be filled with the insert
*/
public InsertDeParser(ExpressionVisitor expressionVisitor, SelectVisitor selectVisitor, StringBuilder buffer) {
this.buffer = buffer;
Expand Down Expand Up @@ -81,6 +82,25 @@ public void visit(ExpressionList expressionList) {
buffer.append(")");
}

@Override
public void visit(MultiExpressionList multiExprList) {
buffer.append(" VALUES ");
for (Iterator<ExpressionList> it = multiExprList.getExprList().iterator(); it.hasNext();) {
buffer.append("(");
for (Iterator<Expression> iter = it.next().getExpressions().iterator(); iter.hasNext();) {
Expression expression = iter.next();
expression.accept(expressionVisitor);
if (iter.hasNext()) {
buffer.append(", ");
}
}
buffer.append(")");
if (it.hasNext()) {
buffer.append(", ");
}
}
}

@Override
public void visit(SubSelect subSelect) {
subSelect.getSelectBody().accept(selectVisitor);
Expand All @@ -101,5 +121,4 @@ public void setExpressionVisitor(ExpressionVisitor visitor) {
public void setSelectVisitor(SelectVisitor visitor) {
selectVisitor = visitor;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.replace.Replace;
import net.sf.jsqlparser.statement.select.SelectVisitor;
Expand Down Expand Up @@ -116,4 +117,9 @@ public void setSelectVisitor(SelectVisitor visitor) {
selectVisitor = visitor;
}

@Override
public void visit(MultiExpressionList multiExprList) {
throw new UnsupportedOperationException("Not supported yet.");
}

}
12 changes: 12 additions & 0 deletions src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ import net.sf.jsqlparser.expression.operators.relational.Matches;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
Expand Down Expand Up @@ -392,6 +393,7 @@ Insert Insert():
List<Expression> primaryExpList = new ArrayList<Expression>();
ItemsList itemsList = null;
Expression exp = null;
MultiExpressionList multiExpr = null;
}
{
<K_INSERT> [<K_INTO>] table=Table()
Expand All @@ -402,6 +404,16 @@ Insert Insert():
(
LOOKAHEAD(2) [<K_VALUES> | <K_VALUE>] "(" exp=SimpleExpression() { primaryExpList.add(exp); }
("," exp=SimpleExpression() { primaryExpList.add(exp); } )* ")" { itemsList = new ExpressionList(primaryExpList); }

("," "(" exp=SimpleExpression() {
if (multiExpr==null) {
multiExpr=new MultiExpressionList();
multiExpr.addExpressionList((ExpressionList)itemsList);
itemsList = multiExpr;
}
primaryExpList = new ArrayList<Expression>();
primaryExpList.add(exp); }
("," exp=SimpleExpression() { primaryExpList.add(exp); } )* ")" { multiExpr.addExpressionList(new ExpressionList(primaryExpList)); } )*

|

Expand Down
17 changes: 14 additions & 3 deletions src/test/java/net/sf/jsqlparser/test/insert/InsertTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.sf.jsqlparser.util.deparser.StatementDeParser;

public class InsertTest extends TestCase {

CCJSqlParserManager parserManager = new CCJSqlParserManager();

public InsertTest(String arg0) {
Expand Down Expand Up @@ -79,11 +80,21 @@ public void testInsertFromSelect() throws JSQLParserException {
String statementToString = "INSERT INTO mytable (col1, col2, col3) (SELECT * FROM mytable2)";
assertEquals(statementToString, "" + insert);
}

public void testInsertMultiRowValue() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (col1, col2) VALUES (a, b)");
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (col1, col2) VALUES (a, b), (d, e)");
}

public void testInsertMultiRowValueDifferent() throws JSQLParserException {
try {
assertSqlCanBeParsedAndDeparsed("INSERT INTO mytable (col1, col2) VALUES (a, b), (d, e, c)");
} catch (Exception e) {
return;
}

fail("should not work");
}

private void assertSqlCanBeParsedAndDeparsed(String statement) throws JSQLParserException {
Statement parsed = parserManager.parse(new StringReader(statement));
assertStatementCanBeDeparsedAs(parsed, statement);
Expand Down

0 comments on commit 8f21c66

Please sign in to comment.