這一篇我們主要具體看一下Insert語句的values解析
public void parse(final InsertStatement insertStatement) {
Collection<Keyword> valueKeywords = new LinkedList<>();
valueKeywords.add(DefaultKeyword.VALUES);
valueKeywords.addAll(Arrays.asList(getSynonymousKeywordsForValues()));
if (lexerEngine.skipIfEqual(valueKeywords.toArray(new Keyword[valueKeywords.size()]))) {
insertStatement.setAfterValuesPosition(lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length());
//解析values
parseValues(insertStatement);
if (lexerEngine.equalAny(Symbol.COMMA)) {
//插入多條數據解析
parseMultipleValues(insertStatement);
}
}
}
我們先看一下解析一條數據的情況
private void parseValues(final InsertStatement insertStatement) {
lexerEngine.accept(Symbol.LEFT_PAREN);
List<SQLExpression> sqlExpressions = new LinkedList<>();
do {
//這裏循環解析每個字段的條件表達式
sqlExpressions.add(basicExpressionParser.parse(insertStatement));
} while (lexerEngine.skipIfEqual(Symbol.COMMA));
insertStatement.setValuesListLastPosition(lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.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 (insertStatement.getGenerateKeyColumnIndex() == count) {
insertStatement.setGeneratedKey(createGeneratedKey(each, sqlExpression));
}
count++;
}
lexerEngine.accept(Symbol.RIGHT_PAREN);
}
看一下解析條件表達式:這裏主要是解析成SQLExpression,我們看一下這個接口的實現關係
那麼這裏是如何對應解析關係和SQLExpression的呢
private SQLExpression getExpression(final String literals, final SQLStatement sqlStatement) {
//問號解析成 佔位符表達式,存儲的是參數的下標
if (lexerEngine.equalAny(Symbol.QUESTION)) {
sqlStatement.increaseParametersIndex();
return new SQLPlaceholderExpression(sqlStatement.getParametersIndex() - 1);
}
//字符解析成 文本表達式,存儲字符的值
if (lexerEngine.equalAny(Literals.CHARS)) {
return new SQLTextExpression(literals);
}
//整型數值解析成 數字表達式,存儲數字的值
if (lexerEngine.equalAny(Literals.INT)) {
return new SQLNumberExpression(NumberUtil.getExactlyNumber(literals, 10));
}
//浮點型數值解析成 數字表達式,存儲數字的值
if (lexerEngine.equalAny(Literals.FLOAT)) {
return new SQLNumberExpression(Double.parseDouble(literals));
}
//十六進制數值解析成 數字表達式,存儲數字的值
if (lexerEngine.equalAny(Literals.HEX)) {
return new SQLNumberExpression(NumberUtil.getExactlyNumber(literals, 16));
}
//標識符 解析成標識符表達式,存儲當前標識符的值
if (lexerEngine.equalAny(Literals.IDENTIFIER)) {
return new SQLIdentifierExpression(SQLUtil.getExactlyValue(literals));
}
//其他 默認解析成忽略的表達式
return new SQLIgnoreExpression(literals);
}
解析成表達式後,我們看一下字段跟表達式的關係建立
insertStatement.getConditions().add(new Condition(each, sqlExpression), shardingRule);
我們首先看一下這個Condition的字段以及構造方法
column:字段信息
operator:條件的類型(EQUAL,BETWEEN,IN)
positionValueMap:這裏存儲的是需要的參數下標與值(數字或者文字)的關係
positionIndexMap:這裏存儲的是需要的參數下標與入參的下標的關係
舉例:INSERT INTO user(name) VALUES ("曉明") column:user operator:EQUAL positionValueMap:(0,"曉明")
INSERT INTO user(name) VALUES (?) column:user operator:EQUAL positionIndexMap:(0,0)
INSERT INTO user(name,sex) VALUES (“曉明”,?)
column:user operator:EQUAL positionIndexMap:(0,0) positionValueMap:(0,"曉明")
如果是between ? and ? 這種形式的 解析成positionIndexMap:(0,0) (1,1),positionValueMap:(0,"曉明")(1,"曉紅")
第一個值代表的是between and中問號的下標,第二個值是當前執行語句的參數的下標。
public void add(final Condition condition, final ShardingRule shardingRule) {
// TODO self-join has problem, table name maybe use alias
if (shardingRule.isShardingColumn(condition.getColumn())) {
conditions.put(condition.getColumn(), condition);
}
}
最終我們發現,在insert,values解析的時候,只有分庫分表的字段才被保留對應的關係,其他字段的對應關係是沒有要的。
單條記錄解析完成之後,我們看一下如果同時插入多條數據怎麼辦?
private void parseMultipleValues(final InsertStatement insertStatement) {
//把第一條添加的數據條件放到MultipleConditions中
insertStatement.getMultipleConditions().add(new Conditions(insertStatement.getConditions()));
//把第一條添加的數據放到MultipleInsertValuesToken的values中
MultipleInsertValuesToken valuesToken = new MultipleInsertValuesToken(insertStatement.getAfterValuesPosition());
valuesToken.getValues().add(
lexerEngine.getInput().substring(insertStatement.getAfterValuesPosition(), lexerEngine.getCurrentToken().getEndPosition() - Symbol.COMMA.getLiterals().length()));
//遍歷後續的插入值
while (lexerEngine.skipIfEqual(Symbol.COMMA)) {
int beginPosition = lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length();
//解析插入值
parseValues(insertStatement);
//把當前的這條插入條件添加到MultipleConditions
insertStatement.getMultipleConditions().add(new Conditions(insertStatement.getConditions()));
int endPosition = lexerEngine.equalAny(Symbol.COMMA)
? lexerEngine.getCurrentToken().getEndPosition() - Symbol.COMMA.getLiterals().length() : lexerEngine.getCurrentToken().getEndPosition();
//把當前這條添加的數據放到MultipleInsertValuesToken的values中valuesToken.getValues().add(lexerEngine.getInput().substring(beginPosition, endPosition));
}
//把MultipleInsertValuesToken添加到sqlToken中
insertStatement.getSqlTokens().add(valuesToken);
}