Skip to content

Commit

Permalink
for #290 parse multiple insert
Browse files Browse the repository at this point in the history
  • Loading branch information
terrymanu committed Aug 15, 2017
1 parent 58c408e commit 3cfc166
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,32 @@

import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.google.common.base.Optional;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

/**
* 条件对象集合.
*
* @author zhangliang
*/
@RequiredArgsConstructor
@Getter
@ToString
public final class Conditions {

private final Map<Column, Condition> conditions = new LinkedHashMap<>();

public Conditions(final Conditions conditions) {
for (Entry<Column, Condition> entry : conditions.conditions.entrySet()) {
this.conditions.put(entry.getKey(), entry.getValue());
}
}

/**
* 添加条件对象.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.GeneratedKey;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.condition.Column;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.condition.Condition;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.condition.Conditions;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.exception.SQLParsingUnsupportedException;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.expression.SQLExpression;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.expression.SQLNumberExpression;
Expand All @@ -35,6 +36,7 @@
import com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.dml.DMLStatement;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.token.GeneratedKeyToken;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.token.ItemsToken;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.token.MultipleInsertValuesToken;
import com.dangdang.ddframe.rdb.sharding.util.SQLUtil;
import com.google.common.base.Optional;
import lombok.AccessLevel;
Expand Down Expand Up @@ -62,6 +64,8 @@ public abstract class AbstractInsertParser implements SQLStatementParser {

private int columnsListLastPosition;

private int afterValuesPosition;

private int valuesListLastPosition;

private int generateKeyColumnIndex = -1;
Expand All @@ -78,10 +82,14 @@ public final DMLStatement parse() {
parseInto();
parseColumns();
if (sqlParser.equalAny(DefaultKeyword.SELECT, Symbol.LEFT_PAREN)) {
throw new UnsupportedOperationException("Cannot support subquery");
throw new UnsupportedOperationException("Cannot INSERT SELECT");
}
if (sqlParser.skipIfEqual(getValuesKeywords())) {
afterValuesPosition = sqlParser.getLexer().getCurrentToken().getEndPosition() - sqlParser.getLexer().getCurrentToken().getLiterals().length();
parseValues();
if (sqlParser.equalAny(Symbol.COMMA)) {
parseMultipleValues();
}
} else if (sqlParser.skipIfEqual(getCustomizedInsertKeywords())) {
parseCustomizedInsert();
}
Expand Down Expand Up @@ -143,30 +151,22 @@ protected Keyword[] getValuesKeywords() {
}

private void parseValues() {
boolean parsed = false;
sqlParser.accept(Symbol.LEFT_PAREN);
List<SQLExpression> sqlExpressions = new LinkedList<>();
do {
if (parsed) {
throw new UnsupportedOperationException("Cannot support multiple insert");
sqlExpressions.add(sqlParser.parseExpression());
} while (sqlParser.skipIfEqual(Symbol.COMMA));
valuesListLastPosition = sqlParser.getLexer().getCurrentToken().getEndPosition() - sqlParser.getLexer().getCurrentToken().getLiterals().length();
int count = 0;
for (Column each : insertStatement.getColumns()) {
SQLExpression sqlExpression = sqlExpressions.get(count);
insertStatement.getConditions().add(new Condition(each, sqlExpression), shardingRule);
if (generateKeyColumnIndex == count) {
insertStatement.setGeneratedKey(createGeneratedKey(each, sqlExpression));
}
sqlParser.accept(Symbol.LEFT_PAREN);
List<SQLExpression> sqlExpressions = new LinkedList<>();
do {
sqlExpressions.add(sqlParser.parseExpression());
} while (sqlParser.skipIfEqual(Symbol.COMMA));
valuesListLastPosition = sqlParser.getLexer().getCurrentToken().getEndPosition() - sqlParser.getLexer().getCurrentToken().getLiterals().length();
int count = 0;
for (Column each : insertStatement.getColumns()) {
SQLExpression sqlExpression = sqlExpressions.get(count);
insertStatement.getConditions().add(new Condition(each, sqlExpression), shardingRule);
if (generateKeyColumnIndex == count) {
insertStatement.setGeneratedKey(createGeneratedKey(each, sqlExpression));
}
count++;
}
sqlParser.accept(Symbol.RIGHT_PAREN);
parsed = true;
count++;
}
while (sqlParser.skipIfEqual(Symbol.COMMA));
sqlParser.accept(Symbol.RIGHT_PAREN);
}

private GeneratedKey createGeneratedKey(final Column column, final SQLExpression sqlExpression) {
Expand All @@ -181,6 +181,21 @@ private GeneratedKey createGeneratedKey(final Column column, final SQLExpression
return result;
}

private void parseMultipleValues() {
insertStatement.getMultipleConditions().add(new Conditions(insertStatement.getConditions()));
MultipleInsertValuesToken valuesToken = new MultipleInsertValuesToken(afterValuesPosition);
valuesToken.getValues().add(sqlParser.getLexer().getInput().substring(afterValuesPosition, sqlParser.getLexer().getCurrentToken().getEndPosition() - Symbol.COMMA.getLiterals().length()));
while (sqlParser.skipIfEqual(Symbol.COMMA)) {
int beginPosition = sqlParser.getLexer().getCurrentToken().getEndPosition() - sqlParser.getLexer().getCurrentToken().getLiterals().length();
parseValues();
insertStatement.getMultipleConditions().add(new Conditions(insertStatement.getConditions()));
int endPosition = sqlParser.equalAny(Symbol.COMMA)
? sqlParser.getLexer().getCurrentToken().getEndPosition() - Symbol.COMMA.getLiterals().length() : sqlParser.getLexer().getCurrentToken().getEndPosition();
valuesToken.getValues().add(sqlParser.getLexer().getInput().substring(beginPosition, endPosition));
}
insertStatement.getSqlTokens().add(valuesToken);
}

protected Keyword[] getCustomizedInsertKeywords() {
return new Keyword[0];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.GeneratedKey;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.condition.Column;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.condition.Condition;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.condition.Conditions;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.expression.SQLNumberExpression;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.expression.SQLPlaceholderExpression;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.dml.DMLStatement;
Expand All @@ -36,6 +37,7 @@

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

/**
* Insert SQL语句对象.
Expand All @@ -49,6 +51,8 @@ public final class InsertStatement extends DMLStatement {

private final Collection<Column> columns = new LinkedList<>();

private final List<Conditions> multipleConditions = new LinkedList<>();

private GeneratedKey generatedKey;

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/

package com.dangdang.ddframe.rdb.sharding.parsing.parser.token;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

import java.util.LinkedList;
import java.util.List;

/**
* 批量插入标记对象.
*
* @author zhangliang
*/
@RequiredArgsConstructor
@Getter
@ToString
public final class MultipleInsertValuesToken implements SQLToken {

private final int beginPosition;

private final List<String> values = new LinkedList<>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,11 @@ private void parseWithSpecialSyntax(final DatabaseType dbType, final String actu
assertThat(condition.getShardingValue(Collections.emptyList()).getValue(), is((Comparable) 1));
}

@Test(expected = UnsupportedOperationException.class)
@Test
// TODO assert
public void parseMultipleInsertForMySQL() {
ShardingRule shardingRule = createShardingRule();
new SQLParsingEngine(DatabaseType.Oracle, "INSERT INTO TABLE_XXX (`field1`, `field2`) VALUES (1, 'value_char'), (2, 'value_char')", shardingRule).parse();
new SQLParsingEngine(DatabaseType.MySQL, "INSERT INTO TABLE_XXX (`field1`, `field2`) VALUES (1, 'value_char'), (2, 'value_char')", shardingRule).parse();
}

@Test(expected = SQLParsingUnsupportedException.class)
Expand Down

1 comment on commit 3cfc166

@dingxihao1991
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个可以解决 批量新增的问题吗?

Please sign in to comment.