Sharding-Sphere初始化(二)

版权声明: https://blog.csdn.net/ph3636/article/details/83095273

5. 开始解析insert语句,AbstractInsertParser#parse,执行nextToken获取到下一个字符段INTO,

public final DMLStatement parse() {
        lexerEngine.nextToken();
        InsertStatement result = new InsertStatement();
        insertClauseParserFacade.getInsertIntoClauseParser().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, shardingMetaData);
        insertClauseParserFacade.getInsertSetClauseParser().parse(result);
        processGeneratedKey(result);
        return result;
    }
InsertIntoClauseParser#parse,校验不支持的关键词,如果该字段不是INTO关键词或者是Assist.END,则跳过获取下一个字符段
 public void parse(final InsertStatement insertStatement) {
        lexerEngine.unsupportedIfEqual(getUnsupportedKeywordsBeforeInto());
        lexerEngine.skipUntil(DefaultKeyword.INTO);
        lexerEngine.nextToken();
        tableReferencesClauseParser.parse(insertStatement, true);
        skipBetweenTableAndValues(insertStatement);
    }

继续获取下移字符段,表名,TableReferencesClauseParser以及子类MySQLTableReferencesClauseParser

 public final void parse(final SQLStatement sqlStatement, final boolean isSingleTableOnly) {
        do {
            parseTableReference(sqlStatement, isSingleTableOnly);
        } while (lexerEngine.skipIfEqual(Symbol.COMMA));
    }

protected void parseTableReference(final SQLStatement sqlStatement, final boolean isSingleTableOnly) {
        parseTableFactor(sqlStatement, isSingleTableOnly);
        parsePartition();
        parseIndexHint(sqlStatement);
    }

获取表名以及下标解析出正确的表名,解析别名,保存表名以及它的相关标识TableToken,解析强制走索引标识以及JOIN.最后解析分区字符段和索引标识,最后跳过一些mysql的分区关键词,完成解析。

protected final void parseTableFactor(final SQLStatement sqlStatement, final boolean isSingleTableOnly) {
        final int beginPosition = lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length();
        String literals = lexerEngine.getCurrentToken().getLiterals();
        int skippedSchemaNameLength = 0;
        lexerEngine.nextToken();
        if (lexerEngine.skipIfEqual(Symbol.DOT)) {
            skippedSchemaNameLength = literals.length() + Symbol.DOT.getLiterals().length();
            literals = lexerEngine.getCurrentToken().getLiterals();
        }
        String tableName = SQLUtil.getExactlyValue(literals);
        if (Strings.isNullOrEmpty(tableName)) {
            return;
        }
        Optional<String> alias = aliasExpressionParser.parseTableAlias();
        if (isSingleTableOnly || shardingRule.tryFindTableRuleByLogicTable(tableName).isPresent() || shardingRule.findBindingTableRule(tableName).isPresent()
                || shardingRule.getShardingDataSourceNames().getDataSourceNames().contains(shardingRule.getShardingDataSourceNames().getDefaultDataSourceName())) {
            sqlStatement.getSqlTokens().add(new TableToken(beginPosition, skippedSchemaNameLength, literals));
            sqlStatement.getTables().add(new Table(tableName, alias));
        }
        parseForceIndex(tableName, sqlStatement);
        parseJoinTable(sqlStatement);
        if (isSingleTableOnly && !sqlStatement.getTables().isSingleTable()) {
            throw new UnsupportedOperationException("Cannot support Multiple-Table.");
        }
    }

6. 解析字段InsertColumnsClauseParser,获取表名以及分表字段,解析具体的字段以及逗号标识,碰到相应的分表字段则记录相应的下标,记录最后一个字段的下标,最后记录字段列的相关数据。

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)) {
            do {
                lexerEngine.nextToken();
                String columnName = SQLUtil.getExactlyValue(lexerEngine.getCurrentToken().getLiterals());
                result.add(new Column(columnName, tableName));
                lexerEngine.nextToken();
                if (generateKeyColumn.isPresent() && generateKeyColumn.get().getName().equalsIgnoreCase(columnName)) {
                    insertStatement.setGenerateKeyColumnIndex(count);
                }
                count++;
            } 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 InsertColumnToken(beginPosition, "("));
            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 InsertColumnToken(beginPosition, ")"));
            insertStatement.setColumnsListLastPosition(beginPosition);
        }
        insertStatement.getColumns().addAll(result);
    }

7. 解析值字符段VALUES,InsertValuesClauseParser#parse,mysql也支持value关键词

public void parse(final InsertStatement insertStatement, final ShardingMetaData shardingMetaData) {
        Collection<Keyword> valueKeywords = new LinkedList<>();
        valueKeywords.add(DefaultKeyword.VALUES);
        valueKeywords.addAll(Arrays.asList(getSynonymousKeywordsForValues()));
        if (lexerEngine.skipIfEqual(valueKeywords.toArray(new Keyword[valueKeywords.size()]))) {
            parseValues(insertStatement);
        }
    }

解析()内的字符,添加值token标识,在BasicExpressionParser中解析值表达式?等等,循环判断英文逗号,获取所有的值,保存SQLExpression表达式,当分表列需要自动生成时,需要把该列数据清除掉removeGenerateKeyColumn,保存分库分表列,单独记录分表列,记录需要设置的参数数量,保存值字符段为InsertValue,最后把所有解析后的数据保存在InsertStatement,最后InsertSetClauseParser解析mysql的SET关键词,处理分表字段的相关逻辑,sql解析完毕。把结果保存在以该sql为key的缓存中

private void parseValues(final InsertStatement insertStatement) {
        int beginPosition = lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length();
        int endPosition;
        insertStatement.getSqlTokens().add(new InsertValuesToken(beginPosition, insertStatement.getTables().getSingleTableName()));
        do {
            beginPosition = lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length();
            lexerEngine.accept(Symbol.LEFT_PAREN);
            List<SQLExpression> sqlExpressions = new LinkedList<>();
            int columnsCount = 0;
            do {
                sqlExpressions.add(basicExpressionParser.parse(insertStatement));
                skipsDoubleColon();
                columnsCount++;
            } while (lexerEngine.skipIfEqual(Symbol.COMMA));
            removeGenerateKeyColumn(insertStatement, columnsCount);
            columnsCount = 0;
            int parametersCount = 0;
            AndCondition andCondition = new AndCondition();
            for (Column each : insertStatement.getColumns()) {
                SQLExpression sqlExpression = sqlExpressions.get(columnsCount);
                if (shardingRule.isShardingColumn(each)) {
                    andCondition.getConditions().add(new Condition(each, sqlExpression));
                }
                if (insertStatement.getGenerateKeyColumnIndex() == columnsCount) {
                    insertStatement.getGeneratedKeyConditions().add(createGeneratedKeyCondition(each, sqlExpression));
                }
                columnsCount++;
                if (sqlExpression instanceof SQLPlaceholderExpression) {
                    parametersCount++;
                }
            }
            lexerEngine.accept(Symbol.RIGHT_PAREN);
            endPosition = lexerEngine.getCurrentToken().getEndPosition() - lexerEngine.getCurrentToken().getLiterals().length();
            insertStatement.getInsertValues().getInsertValues().add(new InsertValue(lexerEngine.getInput().substring(beginPosition, endPosition), parametersCount));
            insertStatement.getConditions().getOrCondition().getAndConditions().add(andCondition);
        } while (lexerEngine.skipIfEqual(Symbol.COMMA));
        insertStatement.setInsertValuesListLastPosition(endPosition);
    }

8. 在ParsingSQLRouter中进行路由设置,获取分表列GeneratedKey,并且解析出要设置的参数值

public SQLRouteResult route(final String logicSQL, final List<Object> parameters, final SQLStatement sqlStatement) {
        GeneratedKey generatedKey = null;
        if (sqlStatement instanceof InsertStatement) {
            generatedKey = getGenerateKey(shardingRule, (InsertStatement) sqlStatement, parameters);
        }
        SQLRouteResult result = new SQLRouteResult(sqlStatement, generatedKey);
        ShardingConditions shardingConditions = OptimizeEngineFactory.newInstance(shardingRule, sqlStatement, parameters, generatedKey).optimize();
        if (null != generatedKey) {
            setGeneratedKeys(result, generatedKey);
        }
        RoutingResult routingResult = route(parameters, sqlStatement, shardingConditions);
        SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(shardingRule, logicSQL, databaseType, sqlStatement, shardingConditions, parameters);
        boolean isSingleRouting = routingResult.isSingleRouting();
        if (sqlStatement instanceof SelectStatement && null != ((SelectStatement) sqlStatement).getLimit()) {
            processLimit(parameters, (SelectStatement) sqlStatement, isSingleRouting);
        }
        SQLBuilder sqlBuilder = rewriteEngine.rewrite(!isSingleRouting);
        for (TableUnit each : routingResult.getTableUnits().getTableUnits()) {
            result.getExecutionUnits().add(new SQLExecutionUnit(each.getDataSourceName(), rewriteEngine.generateSQL(each, sqlBuilder)));
        }
        if (showSQL) {
            SQLLogger.logSQL(logicSQL, sqlStatement, result.getExecutionUnits());
        }
        return result;
    }

InsertOptimizeEngine#optimize解析出需要拆分的条件,取出全部值表达式以及需要设置的具体值组成InsertShardingCondition,getShardingCondition方法主要用来获取表中每个字段以及需要设置的具体值,具体值的获取在Condition#getConditionValues中,字段标识的下标在解析sql表达式时已经创建过init(sqlExpression, 0);根据下标把具体的参数值获取出来最后保存在ListShardingValue,最后把结果保存在ShardingConditions返回。当generatedKey不为空时设置最新的generatedKeys

public ShardingConditions optimize() {
        List<AndCondition> andConditions = insertStatement.getConditions().getOrCondition().getAndConditions();
        List<InsertValue> insertValues = insertStatement.getInsertValues().getInsertValues();
        List<ShardingCondition> result = new ArrayList<>(andConditions.size());
        Iterator<Number> generatedKeys = null;
        int count = 0;
        for (AndCondition each : andConditions) {
            InsertValue insertValue = insertValues.get(count);
            List<Object> currentParameters = new ArrayList<>(insertValue.getParametersCount() + 1);
            currentParameters.addAll(parameters.subList(count * insertValue.getParametersCount(), (count + 1) * insertValue.getParametersCount()));
            
            String logicTableName = insertStatement.getTables().getSingleTableName();
            Optional<Column> generateKeyColumn = shardingRule.getGenerateKeyColumn(logicTableName);
            InsertShardingCondition insertShardingCondition;
            if (-1 != insertStatement.getGenerateKeyColumnIndex() || !generateKeyColumn.isPresent()) {
                insertShardingCondition = new InsertShardingCondition(insertValue.getExpression(), currentParameters);
            } else {
                if (null == generatedKeys) {
                    generatedKeys = generatedKey.getGeneratedKeys().iterator();
                }
                String expression;
                Number currentGeneratedKey = generatedKeys.next();
                if (0 == parameters.size()) {
                    expression = insertValue.getExpression().substring(0, insertValue.getExpression().length() - 1) + ", " + currentGeneratedKey.toString() + ")";
                } else {
                    expression = insertValue.getExpression().substring(0, insertValue.getExpression().length() - 1) + ", ?)";
                    currentParameters.add(currentGeneratedKey);
                }
                insertShardingCondition = new InsertShardingCondition(expression, currentParameters);
                insertShardingCondition.getShardingValues().add(getShardingCondition(generateKeyColumn.get(), currentGeneratedKey));
            }
            insertShardingCondition.getShardingValues().addAll(getShardingCondition(each));
            result.add(insertShardingCondition);
            count++;
        }
        return new ShardingConditions(result);
    }

猜你喜欢

转载自blog.csdn.net/ph3636/article/details/83095273