这一篇我们主要具体看一下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);
}