Python-sqlparse解析SQL工具库一文详解(一)

这篇具有很好参考价值的文章主要介绍了Python-sqlparse解析SQL工具库一文详解(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

一、sqlparse简介

二、功能代码解析

1.初始方法

1.parse

 2.parsestream

3.format

4.split

2.基类-Token

1.flatten()

 2.match(ttype, values, regex=False)

点关注,防走丢,如有纰漏之处,请留言指教,非常感谢


前言

写此sqlparse库的目的还是寻找在python编程内可行的SQL血缘解析,JAVA去解析Hive的源码实践的话我还是打算放到后期来做,先把Python能够实现的先实现完。上篇系列讲述的基于antrl解析说是用python其实还是太牵强了,无非就是使用PyJnius调用JAVA的类方法来实现,没有多大的意义来牵扯到Python编程。主要是HiveSQL的底层就是JAVA代码,怎么改写还是绕不开JAVA的。不过上篇系列我有提到过sqlparse,其实这个库用来解析血缘的话也不是不可以,但是能够实现的功能是有限的,目前我实验还行,一些复杂超过千行的数据分析SQL没有测试过。做一些简单的血缘解析的话还是没有应该太大问题,后续我会在此基础之上开发尝试。


一、sqlparse简介

首先先给官网地址:python-sqlparse。有足够好编码能力可以直接上github上面看源码,解读更细:github.sqlparse

sqlparse是用于Python的非验证SQL解析器。它支持解析、拆分和格式化SQL语句。既然有解析功能那么我们就能做初步的血缘解析功能。这个库的函数解析没有像Pandas和numpy写的那么详细,毕竟是人家个人的开源库,功能写的已经很不错了,能够省去我们很多递归剥离AST树的时间。官网上关于该库使用操作很简单,很多比较好的功能函数也没有使用到,我希望可以尽力将此库开发为通用SQL血缘解析的基础工具库。如果该功能开发完我会将此项目开源。

我通过细读源码来了解此库的大体功能。

二、功能代码解析

1.初始方法

看初始化代码方法有四种:parse,parsestream,format,split这四种

1.parse

def parse(sql, encoding=None):
    """Parse sql and return a list of statements.
    :param sql: A string containing one or more SQL statements.
    :param encoding: The encoding of the statement (optional).
    :returns: A tuple of :class:`~sqlparse.sql.Statement` instances.
    """
    return tuple(parsestream(sql, encoding))

传入一个SQL语句,返回一个 sqlparse.sql.Statement的元组,我们可以递归方式获得输出。

query = 'Select a, col_2 as b from Table_A;'
for each in sqlparse.parse(query):
    print(each)

sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql

其元组根据;符号来进行切分存储:

query = 'Select a, col_2 as b from Table_A;select * from foo'
for each in sqlparse.parse(query):
    print(each)

sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql

 2.parsestream

可以看到第一个方法是调用了parsestream来完成流式解析的,那么这个方法也就是循环读取sql语句来完成转换statment的:

def parsestream(stream, encoding=None):
    """Parses sql statements from file-like object.
    :param stream: A file-like object.
    :param encoding: The encoding of the stream contents (optional).
    :returns: A generator of :class:`~sqlparse.sql.Statement` instances.
    """
    stack = engine.FilterStack()
    stack.enable_grouping()
    return stack.run(stream, encoding)

这里的引擎是可以替换的。

sqlparse.parsestream(query)

sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql

它将返回一个sqlparse.sql.Statement实例的发生器。来看看这个run方法:

def run(self, sql, encoding=None):
        stream = lexer.tokenize(sql, encoding)
        # Process token stream
        for filter_ in self.preprocess:
            stream = filter_.process(stream)

        stream = StatementSplitter().process(stream)

        # Output: Stream processed Statements
        for stmt in stream:
            if self._grouping:
                stmt = grouping.group(stmt)

            for filter_ in self.stmtprocess:
                filter_.process(stmt)

            for filter_ in self.postprocess:
                stmt = filter_.process(stmt)

            yield stmt

 该方法就是生产一个statment,这个类应该就是这个库的基类了,多半围绕这个数据结构来处理。

3.format

该方法就是将sql语句标准化:

query = 'Select a, col_2 as b from Table_A;select * from foo'
print(sqlparse.format(query, reindent=True, keyword_case='upper'))

 sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql

format()函数接受关键字参数:

  •     keyword_case 关键词upper、lowersql的保留字大小写
  •     identifier_case 标识符的upper、lower大小写
  •     strip_comments=Ture删除注释
  •     reindent=Ture美化sq缩进语句发生改变

4.split

该方法用于分割sql语句:

sqlparse.split(query)

sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql 这里补充一下calss类sqlparse.sql.Statement是可以直接通过str转换为字符串的。

结果返回一个分割后的list。至此初始方法就写完了,下面我将详解一下基类,这将决定是我们是否能灵活运用此库。

2.基类-Token

我们来看看Token的初始方法属性:

def __init__(self, ttype, value):
        value = str(value)
        self.value = value
        self.ttype = ttype
        self.parent = None
        self.is_group = False
        self.is_keyword = ttype in T.Keyword
        self.is_whitespace = self.ttype in T.Whitespace
        self.normalized = value.upper() if self.is_keyword else value

 这个Token类也就是语法解析器的重点数据流了:

sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql

 此类需要生成Tokens使用,这牵扯到另一个方法tokens.py:

此方法也就是将statment类转换为Token流:

parsed = sqlparse.parse(query)
stmt = parsed[0]
stmt.tokens

 sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql

 其中我们需要解析的每个Token的标识码也就是第一个ttype属性,解析之后:

for each_token in sql_tokens:
    print(each_token.ttype,each_token.value)

 sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql

 我们拿一个Token来研究就能逐渐解析到其他token。我们建立一个列表将其主要属性ttype和value收集起来:

type(list_ttype[0])
type(list_value[0])

 第一个属性为sqlparse.tokens._TokenType第二个value直接就是str了。上tokens看_TokenType:

# Special token types
Text = Token.Text
Whitespace = Text.Whitespace
Newline = Whitespace.Newline
Error = Token.Error
# Text that doesn't belong to this lexer (e.g. HTML in PHP)
Other = Token.Other

# Common token types for source code
Keyword = Token.Keyword
Name = Token.Name
Literal = Token.Literal
String = Literal.String
Number = Literal.Number
Punctuation = Token.Punctuation
Operator = Token.Operator
Comparison = Operator.Comparison
Wildcard = Token.Wildcard
Comment = Token.Comment
Assignment = Token.Assignment

# Generic types for non-source code
Generic = Token.Generic
Command = Generic.Command

# String and some others are not direct children of Token.
# alias them:
Token.Token = Token
Token.String = String
Token.Number = Number

# SQL specific tokens
DML = Keyword.DML
DDL = Keyword.DDL
CTE = Keyword.CTE

 可以发现这就是Token的识别解析类型码,通过该码就可以访问获得解析出的关键字了。

关于此基类又有五种主要的方法:

1.flatten()

用于解析子组

for each_token in sql_tokens:
    #list_ttype.append(each_token.ttype),list_value.append(each_token.value)
    print(each_token.flatten())

sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql

 2.match(ttype, values, regex=False)

检查标记是否与给定参数匹配。

list_ttype=[]
list_value=[]
for each_token in sql_tokens:
    #list_ttype.append(each_token.ttype),list_value.append(each_token.value)
    print(each_token.match(each_token.ttype,each_token.ttype))

 sqlparse,sqlparse血缘解析,python,sql,开发语言,数据库,mysql

 or运算为None匹配为True输出。

ttype是一种token类型。如果此标记与给定的标记类型不匹配。values是此标记的可能值列表。这些values一起进行OR运算,因此如果只有一个值与True匹配,则返回。除关键字标记外,比较区分大小写。为了方便起见,可以传入单个字符串。如果regex为True(默认值为False),则给定值将被视为正则表达式。

另外还有三种方法has_ancestor(other),is_child_of(other),within(group_cls)这都有调用功能函数相关,可以先不用了解。

由此Token传入流单体已经差不多分析完,但是AST树该如何生成这是个问题,还有关于树的递归问题和层级问题,我们继续根据基类来慢慢摸清。这篇文章已经足够多内容了,先打住。下一篇再细讲。

点关注,防走丢,如有纰漏之处,请留言指教,非常感谢

以上就是本期全部内容。我是fanstuck ,有问题大家随时留言讨论 ,我们下期见文章来源地址https://www.toymoban.com/news/detail-784686.html


到了这里,关于Python-sqlparse解析SQL工具库一文详解(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 一文搞定接口测试及常用接口测试工具解析

    一文搞定接口测试及常用接口测试工具解析

    目录 首先,什么是接口呢? 一、常见接口: 二、前端和后端: 三、什么是接口测试: 四、接口组成 五、为什么要做接口测试: 六、接口测试怎么测:  七、用什么工具测 接口一般来说有两种,一种是程序内部的接口,一种是系统对外的接口。 系统对外的接口:比如你要

    2024年02月03日
    浏览(9)
  • 一文详解 DolphinDB SQL 标准化

    一文详解 DolphinDB SQL 标准化

    在脚本层面,自 1.30.22 / 2.00.10 版本起,DolphinDB SQL 开始支持: 全大写或全小写的书写方式 脚本的换行不影响语法解析,但存在两种特殊情况: 组合不允许拆分,如 order by, group by, context by, pivot by, union all, inner join, nulls first 等。 不使用 as 指定字段别名时,别名

    2024年02月13日
    浏览(7)
  • 一文详解pyspark中sql的join

    大家好,今天分享一下pyspark中各种sql join。 数据准备 本文以学生和班级为单位进行介绍。 学生表有sid(学生id)、sname(学生姓名)、sclass(学生班级id)。 班级表有cid(班级id)、cname(班级名称)。 通过学生表的sclass和班级表的cid将两张表关联在一起。 下面是数据文件

    2024年01月21日
    浏览(10)
  • 一文详解RocketMQ-Spring的源码解析与实战

    摘要: 这篇文章主要介绍 Spring Boot 项目使用 rocketmq-spring SDK 实现消息收发的操作流程,同时笔者会从开发者的角度解读 SDK 的设计逻辑。 本文分享自华为云社区《RocketMQ-Spring : 实战与源码解析一网打尽》,作者:勇哥java实战分享。 RocketMQ 是大家耳熟能详的消息队列,开源项

    2023年04月24日
    浏览(11)
  • 一文详解:自动化测试工具——Selenium

    一文详解:自动化测试工具——Selenium

    Selenium是一个用于Web应用程序测试的工具。是一个开源的Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,可以按指定的命令自动操作,不同是Selenium可以直接运行在浏览器上,它支持所有主流的浏览器,支持的浏览器包括IE(7, 8,

    2024年01月16日
    浏览(17)
  • 「ABAP」万字详解,一文带你入门SAT事务码【SQL优化必备】

    「ABAP」万字详解,一文带你入门SAT事务码【SQL优化必备】

    💂 作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后端的开发语言ABAP,SQL进行任务的完成,对SAP企业管理系统,SAP ABAP开发和数据库具有较

    2023年04月09日
    浏览(11)
  • SQL 语句解析过程详解

    SQL 语句解析过程详解

    说明1:使用Flex和Bison工具实现SQL解析器,完整代码见: SQL解析器完整实例 https://mp.csdn.net/mp_blog/creation/editor/132514880 说明2:该笔记是在学习编译原理相关视频时整理,视频链接如下: 编译原理学习视频 https://www.bilibili.com/video/BV17W41187gL/?spm_id_from=333.337.search-card.all.click 说明

    2024年02月13日
    浏览(11)
  • 一文详解新一代高效前端构建工具VITE-达观数据

    一文详解新一代高效前端构建工具VITE-达观数据

    Vite 是一个快速、简单且高效的前端构建工具,它的出现为前端开发者带来了新的构建体验。在本文中,我们将探讨 Vite 的技术原理、优点和使用方法。 Vite 的技术原理 Vite 的核心技术是基于 ES Modules 和浏览器原生模块系统的构建工具。Vite 的构建过程是基于 ES Modules 实现的,

    2024年02月16日
    浏览(19)
  • SQL 语句解析过程详解(附带完整demo)

    SQL 语句解析过程详解(附带完整demo)

    文末有惊喜哦  👇👇👇 本文主要是使用 Flex 和 Bison 工具实现一个简单的 SQL 解析器,最终生成抽象语法树! 下面先分别对 Flex 和 Biosn 原理进行介绍,然后给出 SQL 解析器的完整 Demo! 1.输入SQL语句 2.  Flex词法分析器  2.1 Flex 原理 1、使用 flex 工具定义正则表达式规则来匹

    2024年02月10日
    浏览(12)
  • 【进阶篇】MySQL的SQL解析原理详解

    【进阶篇】MySQL的SQL解析原理详解

    你是否已经深入了解了MySQL中 SQL解析过程,以及解析过程中每个环节扮演的具体角色? 你是否好奇MySQL是如何将一条SQL语句解析成一系列的\\\"Item\\\"和\\\"TABLE_LIST\\\" 最终通过 这些完成指令的执行和结果的反馈 你是否清楚在查询优化和执行阶段MySQL进行了哪些处理的? 那么,让我们一

    2024年02月09日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包