ShardingSphere LogicSQL 的生成探索

阿里云Ubuntu部署Steam饥荒联机版服务器:从零到多人联机的完整指南 本文详细介绍了在阿里云Ubuntu系统上部署Steam饥荒联机版服务器的完整流程,包括环境准备、SteamCMD安装、服务端配置、Mod管理及后台运行技巧。通过2核4GB的ECS实例配置和端口设置,实现5人流畅联机体验,适合游戏爱好者快速搭建专属服务器。 阅读详情

简介

在上两篇文中,我们探索了SQLToken和真实SQL的生成的想关代码,本文继续来探索最开始的一个LogicSQL的生成,补全这一块拼图

源码探索

继续上面两篇的探索:

其中生成真实的SQL有两个要素:

  • 逻辑表名到真实表名的映射:这个在SQLToken生成的
  • 拼接SQL语句时,对应的index位置,这个目前看来是在LogicSQL中就生成好了的

目前就还差index生成的东西,我们接下来就看看LogicSQL的相关代码:

寻找切入点

下面是LogicSQL的生成部分:

    private ExecutionContext createExecutionContext() {
        LogicSQL logicSQL = createLogicSQL();
        SQLCheckEngine.check(logicSQL.getSqlStatementContext().getSqlStatement(), logicSQL.getParameters(), 
                metaDataContexts.getMetaData(connection.getSchemaName()).getRuleMetaData().getRules(), connection.getSchemaName(), metaDataContexts.getMetaDataMap(), null);
        ExecutionContext result = kernelProcessor.generateExecutionContext(logicSQL, metaDataContexts.getMetaData(connection.getSchemaName()), metaDataContexts.getProps());
        findGeneratedKey(result).ifPresent(generatedKey -> generatedValues.addAll(generatedKey.getGeneratedValues()));
        return result;
    }
    
    private LogicSQL createLogicSQL() {
        List<Object> parameters = new ArrayList<>(getParameters());
        SQLStatementContext<?> sqlStatementContext = SQLStatementContextFactory.newInstance(metaDataContexts.getMetaDataMap(), parameters, sqlStatement, connection.getSchemaName());
        return new LogicSQL(sqlStatementContext, sql, parameters);
    }

但通过debug看到相关的东西其实之前就生成好了:

image.png

其中的preparedStatement就有了相关的index信息,看来是在某一步就初始化好了的,我们找到对应的初始化语句,如下:

# ShardingSpherePreparedStatement.java
    private ShardingSpherePreparedStatement(final ShardingSphereConnection connection, final String sql,
                                            final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final boolean returnGeneratedKeys) throws SQLException {
        if (Strings.isNullOrEmpty(sql)) {
            throw new SQLException(SQLExceptionConstant.SQL_STRING_NULL_OR_EMPTY);
        }
        this.connection = connection;
        metaDataContexts = connection.getContextManager().getMetaDataContexts();
        this.sql = sql;
        statements = new ArrayList<>();
        parameterSets = new ArrayList<>();
        ShardingSphereSQLParserEngine sqlParserEngine = new ShardingSphereSQLParserEngine(
                DatabaseTypeRegistry.getTrunkDatabaseTypeName(metaDataContexts.getMetaData(connection.getSchemaName()).getResource().getDatabaseType()));
	// 这里进行生成的
        sqlStatement = sqlParserEngine.parse(sql, true);
        parameterMetaData = new ShardingSphereParameterMetaData(sqlStatement);
        statementOption = returnGeneratedKeys ? new StatementOption(true) : new StatementOption(resultSetType, resultSetConcurrency, resultSetHoldability);
        JDBCExecutor jdbcExecutor = new JDBCExecutor(metaDataContexts.getExecutorEngine(), connection.isHoldTransaction());
        driverJDBCExecutor = new DriverJDBCExecutor(connection.getSchemaName(), metaDataContexts, jdbcExecutor);
        rawExecutor = new RawExecutor(metaDataContexts.getExecutorEngine(), connection.isHoldTransaction(), metaDataContexts.getProps());
        // TODO Consider FederateRawExecutor
        federateExecutor = new FederateJDBCExecutor(connection.getSchemaName(), metaDataContexts.getOptimizeContextFactory(), metaDataContexts.getProps(), jdbcExecutor);
        batchPreparedStatementExecutor = new BatchPreparedStatementExecutor(metaDataContexts, jdbcExecutor, connection.getSchemaName());
        kernelProcessor = new KernelProcessor();
    }

我们再往前找找,看到是在OrderRepositoryImpl.java中进行触发的:

# OrderRepositoryImpl.java
    @Override
    public Long insert(final Order order) throws SQLException {
        String sql = "INSERT INTO t_order (user_id, address_id, status) VALUES (?, ?, ?)";
        try (Connection connection = dataSource.getConnection();
             PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
            preparedStatement.setInt(1, order.getUserId());
            preparedStatement.setLong(2, order.getAddressId());
            preparedStatement.setString(3, order.getStatus());
            preparedStatement.executeUpdate();
            try (ResultSet resultSet = preparedStatement.getGeneratedKeys()) {
                if (resultSet.next()) {
                    order.setOrderId(resultSet.getLong(1));
                }
            }
        }
        return order.getOrderId();
    }

那我们就继续探索:sqlStatement = sqlParserEngine.parse(sql, true);

我们一直跟着下去,来到一个SQL处理的相关类:MySQLStatementParser.java

其给人的第一个感觉是相当的复杂,我们跟着debug下去,看到进入到相关的insert处理的分支

			case XA:
				enterOuterAlt(_localctx, 1);
				{
				setState(1246);
				_errHandler.sync(this);
				switch ( getInterpreter().adaptivePredict(_input,0,_ctx) ) {
				case 1:
					{
					setState(1146);
					select();
					}
					break;
				case 2:
					{
					setState(1147);
					insert();
					}
					break;

跟着下去,来到insert语句处理具体函数:

# MySQLStatementParser.java
	public final InsertContext insert() throws RecognitionException {
		InsertContext _localctx = new InsertContext(_ctx, getState());
		enterRule(_localctx, 2, RULE_insert);
		int _la;
		try {
			enterOuterAlt(_localctx, 1);
			{
			setState(1258);
			// Insert相关处理
			match(INSERT);
			setState(1259);
			insertSpecification();
			setState(1261);
			_errHandler.sync(this);
			_la = _input.LA(1);
			if (_la==INTO) {
				{
				setState(1260);
				// into 相关处理
				match(INTO);
				}
			}

			setState(1263);
			// 表名相关处理
			tableName();
			setState(1265);
			_errHandler.sync(this);
			_la = _input.LA(1);
			if (_la==PARTITION) {
				{
				setState(1264);
				partitionNames();
				}
			}

			setState(1270);
			_errHandler.sync(this);
			switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) {
			case 1:
				{
				setState(1267);
				// values相关处理
				insertValuesClause();
				}
				break;
			case 2:
				{
				setState(1268);
				setAssignmentsClause();
				}
				break;
			case 3:
				{
				setState(1269);
				insertSelectClause();
				}
				break;
			}
			setState(1273);
			_errHandler.sync(this);
			_la = _input.LA(1);
			if (_la==ON) {
				{
				setState(1272);
				onDuplicateKeyClause();
				}
			}

			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.reportError(this, re);
			_errHandler.recover(this, re);
		}
		finally {
			exitRule();
		}
		return _localctx;
	}

在上面的函数中,我们大意看到几个比较关键的处理函数:

  • Insert相关处理 : match(INSERT);
  • into 相关处理 : match(INTO);
  • 表名相关处理 : tableName();
  • values相关处理 : insertValuesClause();

其规则跟下来有点复杂了,有循环和嵌套处理的,目前是梳理不清楚了

但其大意都是得到对应的开始和结束位置之类的,如下图:

image.png

最终得到结果如下:

image.png

到结果后,相关的返回函数如下:

@RequiredArgsConstructor
public final class SQLParserExecutor {
    
    private final String databaseType;
    
    /**
     * Parse SQL.
     * 
     * @param sql SQL to be parsed
     * @return parse tree
     */
    public ParseTree parse(final String sql) {
        ParseASTNode result = twoPhaseParse(sql);
        if (result.getRootNode() instanceof ErrorNode) {
            throw new SQLParsingException("Unsupported SQL of `%s`", sql);
        }
        return result.getRootNode();
    }
}

result.getRootNode() 如下:

@RequiredArgsConstructor
public final class ParseASTNode implements ASTNode {
    
    private final ParseTree parseTree;
    
    /**
     * Get root node.
     * 
     * @return root node
     */
    public ParseTree getRootNode() {
        return parseTree.getChild(0);
    }
}

而result的结果如下图,getChild(0)就是得到上面我们Insert解析后得到的结果

image.png

总结

感觉看的迷迷糊糊的,很多地方目前还不能很好的理解

但我们起码通过本次的探索知道了真实SQL的关键路径:

  • 通过原始的LogicSQL语句,经过的ShardingSphere的语法树解析,得到对应的各个部分的元数据,如开始和结束index
  • 根据语法树解析结果,得到对应的SQLToken,其中包含了如分库分表中的逻辑表到真实表的映射等关键信息
  • 根据SQLToken生成真实的SQL
利用mininet模拟SDN架构并进行DDoS攻击与防御模拟(Ryu+mininet+sflow+postman) 1、知识概述 (1)软件定义网络: (2)mininet: Mininet是一个强大的网络仿真平台,通过这个平台,我们可以很方便的模拟真实环境中的网络操作与架构。特别是SDN,在真实网络中进行相关的网络实验有一定难度,自然需要一个仿真平台可以学习这种新型的网络架构,而Mininet就应运而生,承担了这个光荣而艰巨的使命。Mininet自带交换机(switchs)、主机(hosts)、控制器(controllers),同时,在mininet上可以安装OpenvSwitch、多种控制器(NOX\POX 阅读详情

相关推荐

基于MYD-YT153与AD7616的16通道高速ADC采集系统实战指南

在嵌入式系统与工业数据采集领域,模拟信号采集是连接物理世界与数字系统的关键技术。其核心原理是通过模数转换器(ADC)将连续的模拟电压信号转换为离散的数字码值,供处理器处理。这项技术的价值在于实现了对温度、压力、振动等关键物理量的精确感知与数字化,是工业自动化、设备监测、科学实验等场景的基石。本文聚焦于**多通道**、**高精度**采集这一常见需求,深入剖析如何利用全志T153处理器的LocalBus并行总线接口,高效驱动ADI的16位、16通道同步采样ADC芯片AD7616,构建一个稳定可靠的高速数据采集系

weixin_30335353的博客 443

如何在 ShardingSphere 中开发自己的 DistSQL

在《DistSQL:像数据库一样使用 Apache ShardingSphere》和《SCTL 涅槃重生:投入 RAL 的怀抱》中,已经为大家介绍了 DistSQL 的设计初衷和语法体系,...

ShardingSphere官微 1026

Doris副本修复实战:从状态机到手动修复的完整指南

在分布式数据库系统中,多副本机制是实现高可用与数据一致性的核心技术。其原理是通过在不同节点存储数据的多个拷贝,确保部分节点故障时服务仍可继续。这项技术的核心价值在于保障数据可靠性,并支撑在线分析处理(OLAP)等对数据一致性要求高的应用场景。当副本出现损坏、丢失或版本不一致时,系统通常依赖自动修复机制,但在元数据损坏、多副本同时故障等复杂场景下,自动修复可能失效,需要深入理解副本状态机并借助手动工具介入。本文将聚焦Doris数据库,解析Tablet副本状态流转(如BAD、VERSION_ERROR),并详细

weixin_32288959的博客 454

第六章 shardingsphere源码-SQL解析

SQL 是比较简单的。不过,它依然是一门完善的编程语言,因此对 SQL 的语法进行解析,与解析其他编程语言(如:Java 语言、C 语言、Go 语言等)并无本质区别。解析过程分为词法解析和语法解析。词法解析器用于将 SQL 拆解为不可再分的原子符号,称为 Token。并根据不同数据库方言所提供的字典,将其归类为关键字,表达式,字面量和操作符。再使用语法解析器将词法解析器的输出转换为抽象语法树。本篇主要介绍了,shardingsphere SQL解析,中间经过了什么流程,实际上真正解析的是antlr。

chengxunzun的博客 1395

扫地机器人视觉+IMU融合导航路径规划技术详解

本文介绍了基于视觉-惯性里程计(VIO)的扫地机器人自主导航系统。系统硬件由RGB摄像头、IMU传感器和编码器组成,软件架构采用分层设计,包括传感器数据采集层、数据融合层、SLAM定位层和路径规划层。核心技术包括:1)融合视觉特征提取(ORB算法)与IMU预积分的VIO;2)基于栅格地图的SLAM构建;3)结合A*全局规划和动态窗口法(DWA)局部避障的路径规划。文章提供了完整的Python实现代码,涵盖传感器数据融合、特征匹配和运动估计等关键功能模块。该系统实现了扫地机器人的精准定位和环境感知能力。

电脑管家 1459

解决Visual C++2008安装失败,error 1935

重装系统后Visual C++没了,其他都能装上但VC2008会报这个error 1935。鉴于我把网上所有的解决方法排了一遍错,我也不知道是哪一步起效,所以就都放上来了。特别注意:报error 1935的错误原因可能不尽相同,比如我的报错开头为An error occurred,结尾为HRESULT:0x80070005。80070005 拒绝访问通常是权限问题,安装Visual C++无法写入文件夹或注册表(直接跳转第7步)

weixin_44427808的博客 1万+

Mybatis Plus 3.x 注入逻辑删除 LogicSqlInjector 报错

3.4.2

hkl_Forever的博客 5084

荒岛逃生游戏

正负表示逃生方向(正表示向右逃生,负表示向左逃生),绝对值表示战斗力,越左边的数字表示里左边港口越近,逃生方向相同的人永远不会发生决斗。- 如果左逃生者的战斗力大于右逃生者,则左逃生者获胜,减少其战斗力,并将右逃生者出栈。- 处理完所有输入后,统计仍在右逃生者栈和左逃生者栈中的战斗力,即可得到成功逃生的人数。- 如果左逃生者的战斗力小于右逃生者,则右逃生者获胜,减少其战斗力,左逃生者出局。- 向左逃生:从右逃生者栈中取出元素,与当前逃生者进行决斗。- 继续进行决斗,直到没有右逃生者或左逃生者的战斗力用尽。

面试高手的博客 2101

第八章 shardingsphere源码-SQL执行

本篇主要介绍了,shardingsphere SQL执行。最后真正执行的依旧由jar来执行,所以无论怎么样都是使用的jdbc方式。

chengxunzun的博客 1531

AMS TMF8820/21/28 SPAD 掩码和模式选择

为了实现最快的测距周期,将报告周期设置在测距周期以下的毫秒,以确保不会有等待时间。除了8X8固定了pixel的位置意外,其他模式客户可以设计自己的spad掩码,并将spad单独分配给通道。对于这些spad掩码,有一些约束。左下角提示红色代表光学中心,绿色方框表示单个spad,每个MP里可能有2X3个spad,也有2X5个spad,也有3X6+3个spad,这部分适配光学,最大的程度的利用spad区域。以下是几种预定义的spad掩码,非常灵活的配置,来适配各种3X3,4X4,8X8的模式选择。

dream it possible 700

【人工智能之深度学习】15. 工业时序预测实战:LSTM与TCN融合的装备故障预警系统设计与实现

摘要:工业装备故障预警是智能制造领域的核心技术之一,其通过分析传感器时序数据实现故障提前预测,可显著降低运维成本并提升设备可靠性。本文针对工业时序数据多源异构、非平稳性、噪声干扰及样本不平衡等挑战,提出一种LSTM与TCN融合的故障预警架构——利用TCN捕捉局部时序特征,结合注意力增强LSTM建模长期依赖关系,通过门控机制实现特征自适应融合。以3MW风电齿轮箱为研究对象,设计包含数据预处理、特征工程、模型训练及部署的完整流程,实验结果表明,该融合模型准确率达94.6%,故障预测提前量较单一模型提升30%以上

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1438

多表关联 shardingsphere 实战详细步骤

多表关联。

2201_75287294的博客 3615

动力学约束下的运动规划算法——Kinodynamic RRT*算法

动力学约束下的运动规划算法——Kinodynamic RRT*算法

慕羽★的博客 6746

分库分表实战

分库分表简介 在准备开发工作前,我们需要了解一下分库分表的基础知识,为什么要分库分表,有哪些优缺点。带着问题去实践收获更多。 为分库分表一定是为了支撑高并发、数据量大两个问题的。 分库分表插件: Cobar TDDL Atlas Sharding-jdbc Mycat Cobar:阿里 b2b 团队开发和开源的,属于 proxy 层方案,就是介于应用服务器和数据库服务器之间。应用程序通过 JDBC 驱动访问 Cobar 集群,Cobar 根据 SQL 和分库规则对 SQL 做分解,然后分发到 My

kunfeisang5551的博客 8886

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Sharding-JDBC使用文档

Sharding-JDBC应用 Spring-Boot项目pom.xml依赖 <properties> <java.version>1.8</java.version> <spring-boot.version>2.3.7.RELEASE</spring-boot.version> <sharding-sphere.version>4.0.0-RC1</sharding-sp

gutf0827的博客 3942

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

ShardingSphere 5.1.1 读写分离实战 | sharding-jdbc | 详细步骤

读写分离。

2201_75287294的博客 1493

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

ShardingSphere 针对SQL IN语法问题小记

ShardingSphere支持IN语法查询,但也存在问题。 官网说明:https://shardingsphere.apache.org/document/current/cn/features/sharding/concept/sharding/ 当查询多条数据时,入参为分片键,进行测试 当数据路由都在一个库同一张表时,会去相应表进行查询(分片键:1504, 1508) 2020-05-26 22:05:01.331 INFO 6476 --- [nio-8080-exec-8] Shardi

小熙的博客 2万+

shardingsphere5.0 解决第一次执行sql慢的问题

springboot项目集成了shardingsphere5.0项目启动后,第一次执行sql查询特别慢,而之后的查询就响应比较快速。此处用了一个投机取巧的方法解决第一次查询慢的问题,就是项目启动后,执行一个select x 命令 import org.antlr.v4.runtime.tree.ParseTree; import org.apache.shardingsphere.infra.database.type.DatabaseType; import org.apache.shardingsph

奥法vx的笔记 3945

ShardingSphere代码阅读(二)

ShardingSphere源码阅读(二) 文章目录ShardingSphere源码阅读(二)前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、pandas是什么? 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。 二、使用步

Encin_Li的博客 848

ShardingSphere笔记(一): 经验和踩坑总结

这是我在使用和封装框架的过程中一个坑一个坑总结到的最深刻的经验。 利用Springboot spi 提供自动注入。维持原本的SardingSphere-jdbc-core-spring-boot-starter 配置不变,提供下面的功能。 1. 根据配置自动配置历史数据的按月分表 2. 无需配置真实数据表,框架启动后会根据路由判断真实表是否存在,真实表不存在自动创建表。(查询语句不创建表,否则将会导致大量空表) 3. 动态切换数据库

MengFly的博客 1万+

[shardingsphere]分表分库概念及实战

文章目录PowerSQL产品简介什么是分布式数据库为什么要做分布式数据存储什么是PowerSQL产品架构名词解释SQL逻辑表真实表数据节点绑定表广播表分片分片键分片算法(四种)分片策略SQL Hint配置分片规则数据源配置表配置数据节点配置分片策略配置自增主键生成策略编排治理配置中心数据脱敏读写分离主库从库主从同步负载均衡策略事务类型本地事务两阶段事务(XA)柔性事务产品优势快速上手1. 规则配置...

从前有座无庙山 3250

ShardingSphere之ShardingJDBC客户端分库分表上

ShardingSphere是一款起源于当当网内部的应用框架。2015年在当当网内部诞生,最初就叫ShardingJDBC。​ ShardingSphere这个词可以分为两个部分,其中Sharding就是指的数据分片。从官网介绍上就能看到,他的核心功能就是可以将任意数据库组合,转换成为一个分布式的数据库,提供整体的数据库集群服务。后面的Sphere是生态的意思。这意味着ShardingSphere不是一个单独的框架或者产品,而是一个由多个框架以及产品构成的一个完整的技术生态。

尽力而为! 1377

ShardingSphere使用(一)

数据分片 垂直分片:按照业务的方式进行拆分;核心理念是专库专用(按照业务将数据表分散到不同的数据库中) 水平分片:横向拆分(通过某些规则将数据分散至多个库或表中) 概念 SQL 水平拆分示例:订单实体order对应表名为t_order,拆分为t_order_0至t_order_9共10张表 逻辑表:水平拆分的数据库(表)的相同逻辑和数据结构表的总称。示例中的t_order 真实表:在分片的数据库中真实存在的物理表。示例中的t_order_0到t_order_9 数据节点:数据分片的最小单

yangcx 2062

动态SQL的实现原理

转自:http://learnworld.iteye.com/blog/1473491  动态SQL是ibatis框架的一个重要特性,本文将深入分析ibatis框架中动态SQL的实现原理。动态sql的使用参见官方文档:Dynamic SQL。本文使用的ibatis版本为2.3.4。  问题  在介绍动态SQL的实现原理之前,让我们先来思考几个问题。  1. 为什么需要动态SQL?

Wu_George的专栏 8133

Mybatis Plus 3.x 逻辑删除插件 LogicSqlInjector 提示错误信息

Cannot resolve symbol 'LogicSqlInjector' @Bean public ISqlInjector sqlInjector() { return new LogicSqlInjector(); } 原因是MP版本高: <!-- mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybati

2008的专栏 9623

sql 逻辑运算符_SQL AND,OR,NOT – SQL逻辑运算符

sql 逻辑运算符SQL provides logical operators which helps in filtering the result set based on some condition. SQL logical operators that we will be discussing are AND, OR and NOT. These three are the most ...

从零开始的教程世界 3862
上一篇: ShardingSphere 语句解析生成初探
下一篇: Alibaba Druid 源码阅读(一) 数据库连接池初步
_萧_
博客等级 码龄10年 55粉丝 157原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值