提交 12d3d3ad 编写于 作者: T tristaZero

Support insert without columns.

上级 4038db19
......@@ -18,17 +18,21 @@
package io.shardingjdbc.core.parsing.parser.clause;
import com.google.common.base.Optional;
import io.shardingjdbc.core.metadata.ShardingMetaData;
import io.shardingjdbc.core.parsing.lexer.LexerEngine;
import io.shardingjdbc.core.parsing.lexer.token.Assist;
import io.shardingjdbc.core.parsing.lexer.token.Symbol;
import io.shardingjdbc.core.parsing.parser.context.condition.Column;
import io.shardingjdbc.core.parsing.parser.sql.dml.insert.InsertStatement;
import io.shardingjdbc.core.parsing.parser.token.ItemsToken;
import io.shardingjdbc.core.parsing.parser.token.SymbolToken;
import io.shardingjdbc.core.rule.ShardingRule;
import io.shardingjdbc.core.util.SQLUtil;
import lombok.RequiredArgsConstructor;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
/**
* Insert columns clause parser.
......@@ -46,13 +50,14 @@ public final class InsertColumnsClauseParser implements SQLClauseParser {
* Parse insert columns.
*
* @param insertStatement insert statement
* @param shardingMetaData sharding meta data
*/
public void parse(final InsertStatement insertStatement) {
public void parse(final InsertStatement insertStatement, final ShardingMetaData shardingMetaData) {
Collection<Column> result = new LinkedList<>();
String tableName = insertStatement.getTables().getSingleTableName();
Optional<Column> generateKeyColumn = shardingRule.getGenerateKeyColumn(tableName);
int count = 0;
if (lexerEngine.equalAny(Symbol.LEFT_PAREN)) {
String tableName = insertStatement.getTables().getSingleTableName();
Optional<Column> generateKeyColumn = shardingRule.getGenerateKeyColumn(tableName);
int count = 0;
do {
lexerEngine.nextToken();
String columnName = SQLUtil.getExactlyValue(lexerEngine.getCurrentToken().getLiterals());
......@@ -65,6 +70,23 @@ public final class InsertColumnsClauseParser implements SQLClauseParser {
} while (!lexerEngine.equalAny(Symbol.RIGHT_PAREN) && !lexerEngine.equalAny(Assist.END));
insertStatement.setColumnsListLastPosition(lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length());
lexerEngine.nextToken();
} else {
List<String> columnNames = shardingMetaData.getTableMetaDataMap().get(tableName).getAllColumnNames();
int beginPosition = lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length() - 1;
insertStatement.getSqlTokens().add(new SymbolToken(beginPosition, Symbol.LEFT_PAREN));
ItemsToken columnsToken = new ItemsToken(beginPosition);
columnsToken.setFirstOfItemsSpecial(true);
for (String columnName : columnNames) {
result.add(new Column(columnName, tableName));
if (generateKeyColumn.isPresent() && generateKeyColumn.get().getName().equalsIgnoreCase(columnName)) {
insertStatement.setGenerateKeyColumnIndex(count);
}
columnsToken.getItems().add(columnName);
count++;
}
insertStatement.getSqlTokens().add(columnsToken);
insertStatement.getSqlTokens().add(new SymbolToken(beginPosition, Symbol.RIGHT_PAREN));
insertStatement.setColumnsListLastPosition(beginPosition);
}
insertStatement.getColumns().addAll(result);
}
......
......@@ -17,21 +17,24 @@
package io.shardingjdbc.core.parsing.parser.clause;
import com.google.common.base.Optional;
import io.shardingjdbc.core.exception.ShardingJdbcException;
import io.shardingjdbc.core.metadata.ShardingMetaData;
import io.shardingjdbc.core.parsing.lexer.LexerEngine;
import io.shardingjdbc.core.parsing.lexer.token.DefaultKeyword;
import io.shardingjdbc.core.parsing.lexer.token.Keyword;
import io.shardingjdbc.core.parsing.lexer.token.Symbol;
import io.shardingjdbc.core.parsing.parser.clause.expression.BasicExpressionParser;
import io.shardingjdbc.core.parsing.parser.context.condition.GeneratedKeyCondition;
import io.shardingjdbc.core.parsing.parser.context.condition.Column;
import io.shardingjdbc.core.parsing.parser.context.condition.Condition;
import io.shardingjdbc.core.parsing.parser.context.condition.Conditions;
import io.shardingjdbc.core.parsing.parser.context.condition.GeneratedKeyCondition;
import io.shardingjdbc.core.parsing.parser.dialect.ExpressionParserFactory;
import io.shardingjdbc.core.parsing.parser.expression.SQLExpression;
import io.shardingjdbc.core.parsing.parser.expression.SQLNumberExpression;
import io.shardingjdbc.core.parsing.parser.expression.SQLPlaceholderExpression;
import io.shardingjdbc.core.parsing.parser.sql.dml.insert.InsertStatement;
import io.shardingjdbc.core.parsing.parser.token.ItemsToken;
import io.shardingjdbc.core.parsing.parser.token.MultipleInsertValuesToken;
import io.shardingjdbc.core.rule.ShardingRule;
......@@ -64,8 +67,9 @@ public class InsertValuesClauseParser implements SQLClauseParser {
* Parse insert values.
*
* @param insertStatement insert statement
* @param shardingMetaData sharding meta data
*/
public void parse(final InsertStatement insertStatement) {
public void parse(final InsertStatement insertStatement, final ShardingMetaData shardingMetaData) {
Collection<Keyword> valueKeywords = new LinkedList<>();
valueKeywords.add(DefaultKeyword.VALUES);
valueKeywords.addAll(Arrays.asList(getSynonymousKeywordsForValues()));
......@@ -84,13 +88,15 @@ public class InsertValuesClauseParser implements SQLClauseParser {
private void parseValues(final InsertStatement insertStatement) {
lexerEngine.accept(Symbol.LEFT_PAREN);
int count = 0;
List<SQLExpression> sqlExpressions = new LinkedList<>();
do {
sqlExpressions.add(basicExpressionParser.parse(insertStatement));
skipsDoubleColon();
count++;
} while (lexerEngine.skipIfEqual(Symbol.COMMA));
insertStatement.setValuesListLastPosition(lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length());
int count = 0;
removeGenerateKeyColumn(insertStatement, count);
count = 0;
for (Column each : insertStatement.getColumns()) {
SQLExpression sqlExpression = sqlExpressions.get(count);
insertStatement.getConditions().add(new Condition(each, sqlExpression), shardingRule);
......@@ -102,6 +108,19 @@ public class InsertValuesClauseParser implements SQLClauseParser {
lexerEngine.accept(Symbol.RIGHT_PAREN);
}
private void removeGenerateKeyColumn(final InsertStatement insertStatement, final int valueCount) {
insertStatement.setValuesListLastPosition(lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length());
Optional<Column> generateKeyColumn = shardingRule.getGenerateKeyColumn(insertStatement.getTables().getSingleTableName());
if (generateKeyColumn.isPresent() && valueCount < insertStatement.getColumns().size()) {
List<ItemsToken> itemsTokens = insertStatement.getItemsTokens();
insertStatement.getColumns().remove(new Column(generateKeyColumn.get().getName(), insertStatement.getTables().getSingleTableName()));
for (ItemsToken each : itemsTokens) {
each.getItems().remove(generateKeyColumn.get().getName());
insertStatement.setGenerateKeyColumnIndex(-1);
}
}
}
private GeneratedKeyCondition createGeneratedKeyCondition(final Column column, final SQLExpression sqlExpression) {
GeneratedKeyCondition result;
if (sqlExpression instanceof SQLPlaceholderExpression) {
......
......@@ -17,6 +17,7 @@
package io.shardingjdbc.core.parsing.parser.dialect.mysql.sql;
import io.shardingjdbc.core.metadata.ShardingMetaData;
import io.shardingjdbc.core.parsing.lexer.LexerEngine;
import io.shardingjdbc.core.parsing.parser.dialect.mysql.clause.facade.MySQLInsertClauseParserFacade;
import io.shardingjdbc.core.parsing.parser.sql.dml.insert.AbstractInsertParser;
......@@ -26,10 +27,11 @@ import io.shardingjdbc.core.rule.ShardingRule;
* Insert parser for MySQL.
*
* @author zhangliang
* @author panjuan
*/
public final class MySQLInsertParser extends AbstractInsertParser {
public MySQLInsertParser(final ShardingRule shardingRule, final LexerEngine lexerEngine) {
super(shardingRule, lexerEngine, new MySQLInsertClauseParserFacade(shardingRule, lexerEngine));
public MySQLInsertParser(final ShardingRule shardingRule, final LexerEngine lexerEngine, final ShardingMetaData shardingMetaData) {
super(shardingRule, shardingMetaData, lexerEngine, new MySQLInsertClauseParserFacade(shardingRule, lexerEngine));
}
}
......@@ -17,6 +17,7 @@
package io.shardingjdbc.core.parsing.parser.dialect.oracle.sql;
import io.shardingjdbc.core.metadata.ShardingMetaData;
import io.shardingjdbc.core.parsing.lexer.LexerEngine;
import io.shardingjdbc.core.parsing.parser.dialect.oracle.clause.facade.OracleInsertClauseParserFacade;
import io.shardingjdbc.core.parsing.parser.sql.dml.insert.AbstractInsertParser;
......@@ -26,10 +27,11 @@ import io.shardingjdbc.core.rule.ShardingRule;
* Insert parser for Oracle.
*
* @author zhangliang
* @author panjuan
*/
public final class OracleInsertParser extends AbstractInsertParser {
public OracleInsertParser(final ShardingRule shardingRule, final LexerEngine lexerEngine) {
super(shardingRule, lexerEngine, new OracleInsertClauseParserFacade(shardingRule, lexerEngine));
public OracleInsertParser(final ShardingRule shardingRule, final LexerEngine lexerEngine, final ShardingMetaData shardingMetaData) {
super(shardingRule, shardingMetaData, lexerEngine, new OracleInsertClauseParserFacade(shardingRule, lexerEngine));
}
}
......@@ -17,6 +17,7 @@
package io.shardingjdbc.core.parsing.parser.dialect.postgresql.sql;
import io.shardingjdbc.core.metadata.ShardingMetaData;
import io.shardingjdbc.core.parsing.lexer.LexerEngine;
import io.shardingjdbc.core.parsing.parser.dialect.postgresql.clause.facade.PostgreSQLInsertClauseParserFacade;
import io.shardingjdbc.core.parsing.parser.sql.dml.insert.AbstractInsertParser;
......@@ -26,10 +27,11 @@ import io.shardingjdbc.core.rule.ShardingRule;
* Insert parser for PostgreSQL.
*
* @author zhangliang
* @author panjuan
*/
public final class PostgreSQLInsertParser extends AbstractInsertParser {
public PostgreSQLInsertParser(final ShardingRule shardingRule, final LexerEngine lexerEngine) {
super(shardingRule, lexerEngine, new PostgreSQLInsertClauseParserFacade(shardingRule, lexerEngine));
public PostgreSQLInsertParser(final ShardingRule shardingRule, final LexerEngine lexerEngine, final ShardingMetaData shardingMetaData) {
super(shardingRule, shardingMetaData, lexerEngine, new PostgreSQLInsertClauseParserFacade(shardingRule, lexerEngine));
}
}
......@@ -17,6 +17,7 @@
package io.shardingjdbc.core.parsing.parser.dialect.sqlserver.sql;
import io.shardingjdbc.core.metadata.ShardingMetaData;
import io.shardingjdbc.core.parsing.lexer.LexerEngine;
import io.shardingjdbc.core.parsing.parser.dialect.sqlserver.clause.facade.SQLServerInsertClauseParserFacade;
import io.shardingjdbc.core.parsing.parser.sql.dml.insert.AbstractInsertParser;
......@@ -26,10 +27,11 @@ import io.shardingjdbc.core.rule.ShardingRule;
* Insert parser for SQLServer.
*
* @author zhangliang
* @author panjuan
*/
public final class SQLServerInsertParser extends AbstractInsertParser {
public SQLServerInsertParser(final ShardingRule shardingRule, final LexerEngine lexerEngine) {
super(shardingRule, lexerEngine, new SQLServerInsertClauseParserFacade(shardingRule, lexerEngine));
public SQLServerInsertParser(final ShardingRule shardingRule, final LexerEngine lexerEngine, final ShardingMetaData shardingMetaData) {
super(shardingRule, shardingMetaData, lexerEngine, new SQLServerInsertClauseParserFacade(shardingRule, lexerEngine));
}
}
......@@ -45,6 +45,7 @@ import lombok.NoArgsConstructor;
* SQL parser factory.
*
* @author zhangliang
* @author panjuan
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class SQLParserFactory {
......@@ -64,7 +65,7 @@ public final class SQLParserFactory {
return getDQLParser(dbType, shardingRule, lexerEngine, shardingMetaData);
}
if (isDML(tokenType)) {
return getDMLParser(dbType, tokenType, shardingRule, lexerEngine);
return getDMLParser(dbType, tokenType, shardingRule, lexerEngine, shardingMetaData);
}
if (isDDL(tokenType)) {
return getDDLParser(dbType, tokenType, shardingRule, lexerEngine);
......@@ -103,10 +104,10 @@ public final class SQLParserFactory {
return SelectParserFactory.newInstance(dbType, shardingRule, lexerEngine, shardingMetaData);
}
private static SQLParser getDMLParser(final DatabaseType dbType, final TokenType tokenType, final ShardingRule shardingRule, final LexerEngine lexerEngine) {
private static SQLParser getDMLParser(final DatabaseType dbType, final TokenType tokenType, final ShardingRule shardingRule, final LexerEngine lexerEngine, final ShardingMetaData shardingMetaData) {
switch ((DefaultKeyword) tokenType) {
case INSERT:
return InsertParserFactory.newInstance(dbType, shardingRule, lexerEngine);
return InsertParserFactory.newInstance(dbType, shardingRule, lexerEngine, shardingMetaData);
case UPDATE:
return UpdateParserFactory.newInstance(dbType, shardingRule, lexerEngine);
case DELETE:
......
......@@ -18,6 +18,7 @@
package io.shardingjdbc.core.parsing.parser.sql.dml.insert;
import com.google.common.base.Optional;
import io.shardingjdbc.core.metadata.ShardingMetaData;
import io.shardingjdbc.core.parsing.lexer.LexerEngine;
import io.shardingjdbc.core.parsing.lexer.token.DefaultKeyword;
import io.shardingjdbc.core.parsing.lexer.token.Symbol;
......@@ -35,33 +36,39 @@ import lombok.Getter;
* Insert parser.
*
* @author zhangliang
* @author panjuan
*/
public abstract class AbstractInsertParser implements SQLParser {
@Getter(AccessLevel.PROTECTED)
private final ShardingRule shardingRule;
@Getter(AccessLevel.PROTECTED)
private final ShardingMetaData shardingMetaData;
@Getter(AccessLevel.PROTECTED)
private final LexerEngine lexerEngine;
private final AbstractInsertClauseParserFacade insertClauseParserFacade;
public AbstractInsertParser(final ShardingRule shardingRule, final LexerEngine lexerEngine, final AbstractInsertClauseParserFacade insertClauseParserFacade) {
public AbstractInsertParser(final ShardingRule shardingRule, final ShardingMetaData shardingMetaData, final LexerEngine lexerEngine, final AbstractInsertClauseParserFacade insertClauseParserFacade) {
this.shardingRule = shardingRule;
this.shardingMetaData = shardingMetaData;
this.lexerEngine = lexerEngine;
this.insertClauseParserFacade = insertClauseParserFacade;
}
@Override
public final DMLStatement parse() {
// ======
lexerEngine.nextToken();
InsertStatement result = new InsertStatement();
insertClauseParserFacade.getInsertIntoClauseParser().parse(result);
insertClauseParserFacade.getInsertColumnsClauseParser().parse(result);
insertClauseParserFacade.getInsertColumnsClauseParser().parse(result, shardingMetaData);
if (lexerEngine.equalAny(DefaultKeyword.SELECT, Symbol.LEFT_PAREN)) {
throw new UnsupportedOperationException("Cannot INSERT SELECT");
}
insertClauseParserFacade.getInsertValuesClauseParser().parse(result);
insertClauseParserFacade.getInsertValuesClauseParser().parse(result, shardingMetaData);
insertClauseParserFacade.getInsertSetClauseParser().parse(result);
appendGenerateKeyToken(result);
return result;
......@@ -72,10 +79,14 @@ public abstract class AbstractInsertParser implements SQLParser {
Optional<Column> generateKeyColumn = shardingRule.getGenerateKeyColumn(tableName);
if (!generateKeyColumn.isPresent() || null != insertStatement.getGeneratedKeyCondition()) {
return;
}
ItemsToken columnsToken = new ItemsToken(insertStatement.getColumnsListLastPosition());
columnsToken.getItems().add(generateKeyColumn.get().getName());
insertStatement.getSqlTokens().add(columnsToken);
}
if (!insertStatement.getItemsTokens().isEmpty()) {
insertStatement.getItemsTokens().get(0).getItems().add(generateKeyColumn.get().getName());
} else {
ItemsToken columnsToken = new ItemsToken(insertStatement.getColumnsListLastPosition());
columnsToken.getItems().add(generateKeyColumn.get().getName());
insertStatement.getSqlTokens().add(columnsToken);
}
insertStatement.getSqlTokens().add(new GeneratedKeyToken(insertStatement.getValuesListLastPosition()));
}
}
......@@ -18,6 +18,7 @@
package io.shardingjdbc.core.parsing.parser.sql.dml.insert;
import io.shardingjdbc.core.constant.DatabaseType;
import io.shardingjdbc.core.metadata.ShardingMetaData;
import io.shardingjdbc.core.parsing.lexer.LexerEngine;
import io.shardingjdbc.core.parsing.parser.dialect.mysql.sql.MySQLInsertParser;
import io.shardingjdbc.core.parsing.parser.dialect.oracle.sql.OracleInsertParser;
......@@ -31,6 +32,7 @@ import lombok.NoArgsConstructor;
* Insert parser factory.
*
* @author zhangliang
* @author panjuan
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class InsertParserFactory {
......@@ -43,17 +45,17 @@ public final class InsertParserFactory {
* @param lexerEngine lexical analysis engine.
* @return insert parser instance
*/
public static AbstractInsertParser newInstance(final DatabaseType dbType, final ShardingRule shardingRule, final LexerEngine lexerEngine) {
public static AbstractInsertParser newInstance(final DatabaseType dbType, final ShardingRule shardingRule, final LexerEngine lexerEngine, final ShardingMetaData shardingMetaData) {
switch (dbType) {
case H2:
case MySQL:
return new MySQLInsertParser(shardingRule, lexerEngine);
return new MySQLInsertParser(shardingRule, lexerEngine, shardingMetaData);
case Oracle:
return new OracleInsertParser(shardingRule, lexerEngine);
return new OracleInsertParser(shardingRule, lexerEngine, shardingMetaData);
case SQLServer:
return new SQLServerInsertParser(shardingRule, lexerEngine);
return new SQLServerInsertParser(shardingRule, lexerEngine, shardingMetaData);
case PostgreSQL:
return new PostgreSQLInsertParser(shardingRule, lexerEngine);
return new PostgreSQLInsertParser(shardingRule, lexerEngine, shardingMetaData);
default:
throw new UnsupportedOperationException(String.format("Cannot support database [%s].", dbType));
}
......
......@@ -23,11 +23,13 @@ import io.shardingjdbc.core.parsing.parser.context.condition.Column;
import io.shardingjdbc.core.parsing.parser.context.condition.Conditions;
import io.shardingjdbc.core.parsing.parser.sql.dml.DMLStatement;
import io.shardingjdbc.core.parsing.parser.token.GeneratedKeyToken;
import io.shardingjdbc.core.parsing.parser.token.ItemsToken;
import io.shardingjdbc.core.parsing.parser.token.SQLToken;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
......@@ -69,4 +71,19 @@ public final class InsertStatement extends DMLStatement {
}
return Optional.absent();
}
/**
* Get items tokens.
*
* @return items token list.
*/
public List<ItemsToken> getItemsTokens() {
List<ItemsToken> itemsTokens = new ArrayList<>();
for (SQLToken each : getSqlTokens()) {
if (each instanceof ItemsToken) {
itemsTokens.add((ItemsToken) each);
}
}
return itemsTokens;
}
}
......@@ -19,6 +19,7 @@ package io.shardingjdbc.core.parsing.parser.token;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import java.util.LinkedList;
......@@ -28,6 +29,7 @@ import java.util.List;
* Select items token.
*
* @author zhangliang
* @author panjuan
*/
@RequiredArgsConstructor
@Getter
......@@ -36,5 +38,8 @@ public final class ItemsToken implements SQLToken {
private final int beginPosition;
@Setter
private boolean isFirstOfItemsSpecial = false;
private final List<String> items = new LinkedList<>();
}
/*
* 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 io.shardingjdbc.core.parsing.parser.token;
import io.shardingjdbc.core.parsing.lexer.token.Symbol;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
/**
* Symbol token.
*
* @author panjuan
*/
@RequiredArgsConstructor
@Getter
@ToString
public final class SymbolToken implements SQLToken {
private final int beginPosition;
private final Symbol symbol;
}
......@@ -34,6 +34,7 @@ import io.shardingjdbc.core.parsing.parser.token.OrderByToken;
import io.shardingjdbc.core.parsing.parser.token.RowCountToken;
import io.shardingjdbc.core.parsing.parser.token.SQLToken;
import io.shardingjdbc.core.parsing.parser.token.SchemaToken;
import io.shardingjdbc.core.parsing.parser.token.SymbolToken;
import io.shardingjdbc.core.parsing.parser.token.TableToken;
import io.shardingjdbc.core.rewrite.placeholder.IndexPlaceholder;
import io.shardingjdbc.core.rewrite.placeholder.SchemaPlaceholder;
......@@ -131,6 +132,8 @@ public final class SQLRewriteEngine {
appendLimitOffsetToken(result, (OffsetToken) each, count, sqlTokens, isRewriteLimit);
} else if (each instanceof OrderByToken) {
appendOrderByToken(result, count, sqlTokens);
} else if (each instanceof SymbolToken) {
appendSymbolToken(result, (SymbolToken) each, count, sqlTokens);
}
count++;
}
......@@ -171,12 +174,15 @@ public final class SQLRewriteEngine {
}
private void appendItemsToken(final SQLBuilder sqlBuilder, final ItemsToken itemsToken, final int count, final List<SQLToken> sqlTokens) {
for (String item : itemsToken.getItems()) {
sqlBuilder.appendLiterals(", ");
sqlBuilder.appendLiterals(SQLUtil.getOriginalValue(item, databaseType));
for (int i = 0; i < itemsToken.getItems().size(); i++) {
if (itemsToken.isFirstOfItemsSpecial() && 0 == i) {
sqlBuilder.appendLiterals(SQLUtil.getOriginalValue(itemsToken.getItems().get(i), databaseType));
} else {
sqlBuilder.appendLiterals(", ");
sqlBuilder.appendLiterals(SQLUtil.getOriginalValue(itemsToken.getItems().get(i), databaseType));
}
}
int beginPosition = itemsToken.getBeginPosition();
appendRest(sqlBuilder, count, sqlTokens, beginPosition);
appendRest(sqlBuilder, count, sqlTokens, itemsToken.getBeginPosition());
}
private void appendGenerateKeyToken(final SQLBuilder sqlBuilder, final GeneratedKeyToken generatedKeyToken, final int count, final List<SQLToken> sqlTokens) {
......@@ -229,6 +235,11 @@ public final class SQLRewriteEngine {
appendRest(sqlBuilder, count, sqlTokens, beginPosition);
}
private void appendSymbolToken(final SQLBuilder sqlBuilder, final SymbolToken symbolToken, final int count, final List<SQLToken> sqlTokens) {
sqlBuilder.appendLiterals(symbolToken.getSymbol().getLiterals());
appendRest(sqlBuilder, count, sqlTokens, symbolToken.getBeginPosition());
}
private void appendRest(final SQLBuilder sqlBuilder, final int count, final List<SQLToken> sqlTokens, final int beginPosition) {
int endPosition = sqlTokens.size() - 1 == count ? originalSQL.length() : sqlTokens.get(count + 1).getBeginPosition();
sqlBuilder.appendLiterals(originalSQL.substring(beginPosition, endPosition));
......
......@@ -22,12 +22,19 @@ import io.shardingjdbc.core.api.algorithm.fixture.TestComplexKeysShardingAlgorit
import io.shardingjdbc.core.api.config.ShardingRuleConfiguration;
import io.shardingjdbc.core.api.config.TableRuleConfiguration;
import io.shardingjdbc.core.api.config.strategy.ComplexShardingStrategyConfiguration;
import io.shardingjdbc.core.metadata.ColumnMetaData;
import io.shardingjdbc.core.metadata.ShardingMetaData;
import io.shardingjdbc.core.metadata.TableMetaData;
import io.shardingjdbc.core.rule.ShardingRule;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
......@@ -53,4 +60,20 @@ public abstract class AbstractStatementParserTest {
shardingRuleConfig.getTableRuleConfigs().add(tableRuleConfig);
return new ShardingRule(shardingRuleConfig, Lists.newArrayList("ds"));
}
protected final ShardingMetaData createShardingMetaData() {
Map<String, TableMetaData> tableMetaDataMap = new HashMap<>();
tableMetaDataMap.put("TABLE_XXX", getTableMetaData(new ArrayList<String>(){{add("field1");add("field2");}}));
ShardingMetaData shardingMetaData = mock(ShardingMetaData.class);
when(shardingMetaData.getTableMetaDataMap()).thenReturn(tableMetaDataMap);
return shardingMetaData;
}
private static TableMetaData getTableMetaData(final List<String> columnNames) {
List<ColumnMetaData> columnMetaDataList = new ArrayList<>();
for (String columnName : columnNames) {
columnMetaDataList.add(new ColumnMetaData(columnName, "int(11)", ""));
}
return new TableMetaData(columnMetaDataList);
}
}
......@@ -26,6 +26,7 @@ import io.shardingjdbc.core.api.config.strategy.ComplexShardingStrategyConfigura
import io.shardingjdbc.core.constant.DatabaseType;
import io.shardingjdbc.core.constant.ShardingOperator;
import io.shardingjdbc.core.keygen.fixture.IncrementKeyGenerator;
import io.shardingjdbc.core.metadata.ShardingMetaData;
import io.shardingjdbc.core.parsing.SQLParsingEngine;
import io.shardingjdbc.core.parsing.parser.context.condition.Column;
import io.shardingjdbc.core.parsing.parser.context.condition.Condition;
......@@ -88,6 +89,42 @@ public final class InsertStatementParserTest extends AbstractStatementParserTest
assertInsertStatementWithParameter(insertStatement);
}
@Test
public void assertParseWithoutColumnsWithGenerateKeyColumnsWithoutParameter() {
ShardingRule shardingRule = createShardingRuleWithGenerateKeyColumns();
ShardingMetaData shardingMetaData = createShardingMetaData();
SQLParsingEngine statementParser = new SQLParsingEngine(DatabaseType.MySQL, "INSERT INTO `TABLE_XXX` VALUES (10)", shardingRule, shardingMetaData);
InsertStatement insertStatement = (InsertStatement) statementParser.parse(false);
assertInsertStatementWithoutParameter(insertStatement);
}
@Test
public void assertParseWithoutColumnsWithGenerateKeyColumnsWithParameter() {
ShardingRule shardingRule = createShardingRuleWithGenerateKeyColumns();
ShardingMetaData shardingMetaData = createShardingMetaData();
SQLParsingEngine statementParser = new SQLParsingEngine(DatabaseType.MySQL, "INSERT INTO `TABLE_XXX` VALUES (?)", shardingRule, shardingMetaData);
InsertStatement insertStatement = (InsertStatement) statementParser.parse(false);
assertInsertStatementWithParameter(insertStatement);
}
@Test
public void assertParseWithoutColumnsWithoutParameter() {
ShardingRule shardingRule = createShardingRule();
ShardingMetaData shardingMetaData = createShardingMetaData();
SQLParsingEngine statementParser = new SQLParsingEngine(DatabaseType.MySQL, "INSERT INTO `TABLE_XXX` VALUES (10,20)", shardingRule, shardingMetaData);
InsertStatement insertStatement = (InsertStatement) statementParser.parse(false);
assertInsertStatementWithoutParameter(insertStatement);
}
@Test
public void assertParseWithoutColumnsWithParameter() {
ShardingRule shardingRule = createShardingRule();
ShardingMetaData shardingMetaData = createShardingMetaData();
SQLParsingEngine statementParser = new SQLParsingEngine(DatabaseType.MySQL, "INSERT INTO `TABLE_XXX` VALUES (?, ?)", shardingRule, shardingMetaData);
InsertStatement insertStatement = (InsertStatement) statementParser.parse(false);
assertInsertStatementWithParameter(insertStatement);
}
private void assertInsertStatementWithParameter(final InsertStatement insertStatement) {
assertThat(insertStatement.getTables().find("TABLE_XXX").get().getName(), is("TABLE_XXX"));
Condition condition = insertStatement.getConditions().find(new Column("field1", "TABLE_XXX")).get();
......@@ -129,7 +166,8 @@ public final class InsertStatementParserTest extends AbstractStatementParserTest
@SuppressWarnings("unchecked")
private void parseWithSpecialSyntax(final DatabaseType dbType, final String actualSQL) {
ShardingRule shardingRule = createShardingRule();
InsertStatement insertStatement = (InsertStatement) new SQLParsingEngine(dbType, actualSQL, shardingRule, null).parse(false);
ShardingMetaData shardingMetaData = createShardingMetaData();
InsertStatement insertStatement = (InsertStatement) new SQLParsingEngine(dbType, actualSQL, shardingRule, shardingMetaData).parse(false);
assertThat(insertStatement.getTables().find("TABLE_XXX").get().getName(), is("TABLE_XXX"));
assertFalse(insertStatement.getTables().find("TABLE_XXX").get().getAlias().isPresent());
Condition condition = insertStatement.getConditions().find(new Column("field1", "TABLE_XXX")).get();
......
......@@ -21,6 +21,7 @@ import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import io.shardingjdbc.core.constant.DatabaseType;
import io.shardingjdbc.core.constant.OrderDirection;
import io.shardingjdbc.core.parsing.lexer.token.Symbol;
import io.shardingjdbc.core.parsing.parser.context.OrderItem;
import io.shardingjdbc.core.parsing.parser.context.condition.Column;
import io.shardingjdbc.core.parsing.parser.context.limit.Limit;
......@@ -35,8 +36,8 @@ import io.shardingjdbc.core.parsing.parser.token.OffsetToken;
import io.shardingjdbc.core.parsing.parser.token.OrderByToken;
import io.shardingjdbc.core.parsing.parser.token.RowCountToken;
import io.shardingjdbc.core.parsing.parser.token.SchemaToken;
import io.shardingjdbc.core.parsing.parser.token.SymbolToken;
import io.shardingjdbc.core.parsing.parser.token.TableToken;
import io.shardingjdbc.core.routing.SQLUnit;
import io.shardingjdbc.core.routing.router.GeneratedKey;
import io.shardingjdbc.core.routing.type.TableUnit;
import io.shardingjdbc.core.routing.type.complex.CartesianTableReference;
......@@ -134,6 +135,78 @@ public final class SQLRewriteEngineTest {
assertThat(rewriteEngine.rewrite(true).toSQL(tableTokens, null).getSql(), is("INSERT INTO table_1 (name, age, id) VALUES (?, ?, ?)"));
}
@Test
public void assertRewriteForAutoGeneratedKeyColumnWithoutColumnsWithParameter() {
List<Object> parameters = new ArrayList<>();
parameters.add("Bill");
insertStatement.setParametersIndex(1);
insertStatement.getSqlTokens().add(new TableToken(12, "`table_x`"));
insertStatement.setGenerateKeyColumnIndex(0);
insertStatement.getSqlTokens().add(new SymbolToken(21, Symbol.LEFT_PAREN));
ItemsToken itemsToken = new ItemsToken(21);
itemsToken.setFirstOfItemsSpecial(true);
itemsToken.getItems().add("name");
itemsToken.getItems().add("id");
insertStatement.getSqlTokens().add(itemsToken);
insertStatement.getSqlTokens().add(new SymbolToken(21, Symbol.RIGHT_PAREN));
insertStatement.getSqlTokens().add(new GeneratedKeyToken(31));
SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(
shardingRule, "INSERT INTO `table_x` VALUES (?)", DatabaseType.MySQL, insertStatement, parameters, new GeneratedKey(new Column("id", "table_x"), 2, 1));
assertThat(rewriteEngine.rewrite(true).toSQL(tableTokens, null).getSql(), is("INSERT INTO table_1(name, id) VALUES (?, ?)"));
}
@Test
public void assertRewriteForAutoGeneratedKeyColumnWithoutColumnsWithoutParameter() {
List<Object> parameters = new ArrayList<>();
insertStatement.getSqlTokens().add(new TableToken(12, "`table_x`"));
insertStatement.setGenerateKeyColumnIndex(0);
insertStatement.getSqlTokens().add(new SymbolToken(21, Symbol.LEFT_PAREN));
ItemsToken itemsToken = new ItemsToken(21);
itemsToken.setFirstOfItemsSpecial(true);
itemsToken.getItems().add("name");
itemsToken.getItems().add("id");
insertStatement.getSqlTokens().add(itemsToken);
insertStatement.getSqlTokens().add(new SymbolToken(21, Symbol.RIGHT_PAREN));
insertStatement.getSqlTokens().add(new GeneratedKeyToken(32));
SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(
shardingRule, "INSERT INTO `table_x` VALUES (10)", DatabaseType.MySQL, insertStatement, parameters, new GeneratedKey(new Column("id", "table_x"), 2, 1));
assertThat(rewriteEngine.rewrite(true).toSQL(tableTokens, null).getSql(), is("INSERT INTO table_1(name, id) VALUES (10, 1)"));
}
@Test
public void assertRewriteColumnWithoutColumnsWithoutParameter() {
List<Object> parameters = new ArrayList<>();
insertStatement.getSqlTokens().add(new TableToken(12, "`table_x`"));
insertStatement.setGenerateKeyColumnIndex(0);
insertStatement.getSqlTokens().add(new SymbolToken(21, Symbol.LEFT_PAREN));
ItemsToken itemsToken = new ItemsToken(21);
itemsToken.setFirstOfItemsSpecial(true);
itemsToken.getItems().add("name");
itemsToken.getItems().add("id");
insertStatement.getSqlTokens().add(itemsToken);
insertStatement.getSqlTokens().add(new SymbolToken(21, Symbol.RIGHT_PAREN));
SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(
shardingRule, "INSERT INTO `table_x` VALUES (10, 1)", DatabaseType.MySQL, insertStatement, parameters, null);
assertThat(rewriteEngine.rewrite(true).toSQL(tableTokens, null).getSql(), is("INSERT INTO table_1(name, id) VALUES (10, 1)"));
}
@Test
public void assertRewriteColumnWithoutColumnsWithParameter() {
List<Object> parameters = new ArrayList<>();
insertStatement.getSqlTokens().add(new TableToken(12, "`table_x`"));
insertStatement.setGenerateKeyColumnIndex(0);
insertStatement.getSqlTokens().add(new SymbolToken(21, Symbol.LEFT_PAREN));
ItemsToken itemsToken = new ItemsToken(21);
itemsToken.setFirstOfItemsSpecial(true);
itemsToken.getItems().add("name");
itemsToken.getItems().add("id");
insertStatement.getSqlTokens().add(itemsToken);
insertStatement.getSqlTokens().add(new SymbolToken(21, Symbol.RIGHT_PAREN));
SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(
shardingRule, "INSERT INTO `table_x` VALUES (?, ?)", DatabaseType.MySQL, insertStatement, parameters, null);
assertThat(rewriteEngine.rewrite(true).toSQL(tableTokens, null).getSql(), is("INSERT INTO table_1(name, id) VALUES (?, ?)"));
}
@Test
public void assertRewriteForLimit() {
selectStatement.setLimit(new Limit(DatabaseType.MySQL));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册