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

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

码农世界 2024-06-08 后端 91 次浏览 0个评论

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

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

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

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

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

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

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)

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

正文

print(each.get_type())
 ![](https://img-blog.csdnimg.cn/3d49c1f47c8043d99c6f6f36b0205776.png)
里面的判断逻辑也是根据 Keyword.DML和Keyword.DDL来判断的。根据第一次获取到的token来判断。有了get\_type那么我们要实现的SQL解析的第一步已经有了,首先就可以确定这个SQL的功能与用户的读写查改权限匹配了。先不急我们还需要知道如何解析成一颗树。
## 二、基类-TokenList
这个类就相当的大了,也正是我们了解解析成AST抽象解析树的关键所在了。源码就不贴上去可太多了,主要找一些能够改写使用到的方法即可。
该类继承Token,而Statement就是继承的此类,也就是Statement最终继承的此两者全部方法。

query = ‘CREATE TABLE AS Select a, col_2 as b from Table_A;select * from foo’

stmt=sqlparse.parse(query)

stmt_1=stmt[0].tokens

#for each_token in stmt_1:

#print(each_token)

sqlparse.sql.TokenList(stmt_1)._get_repr_name()

stmt[0]._get_repr_name()

### 1. \_get\_repr\_name()方法
将输出自身数据结构:

def _get_repr_name(self):

return type(self).name

### 2.\_pprint\_tree()方法
这里有关树的解析在这个打印\_pprint\_tree函数上面:

def _pprint_tree(self, max_depth=None, depth=0, f=None, _pre=‘’):

“”“Pretty-print the object tree.”“”

token_count = len(self.tokens)

for idx, token in enumerate(self.tokens):

cls = token._get_repr_name()

value = token._get_repr_value()

        last = idx == (token_count - 1)
        pre = '`- ' if last else '|- '
        q = '"' if value.startswith("'") and value.endswith("'") else "'"
        print("{_pre}{pre}{idx} {cls} {q}{value}{q}"
              .format(**locals()), file=f)
        if token.is_group and (max_depth is None or depth < max_depth):
            parent_pre = '   ' if last else '|  '
            token._pprint_tree(max_depth, depth + 1, f, _pre + parent_pre)
第一次看到这个函数我就认为使用sqlparse解析SQL血缘是可以做成功的:
![](https://img-blog.csdnimg.cn/2246b3d43f6d414aa58b0116b80c9ce2.png)
从打印的函数循迹看是否能够得到血缘关系。这点是可以做到的,先遍历最底层的结构,再依次输出,此时这里我已经有了一个明确的实现思路,但是这里先不开展,我们还是先将此类看明白再下定论。先通读这个方法:
和我之前写的树递归函数差不多,这里要注意到一点就是空格会影响树的输出,所以传入sql之前还是得做去除空格的操作,最好还是化成一句没有空格和缩进的语句。当然也可以通过改写去除Whitespace这一标识符。
通过解析树的输出我们发现到IdentifierList 此类就开始往下层调了,这取决于这段代码:

if token.is_group and (max_depth is None or depth < max_depth):

parent_pre = ’ ’ if last else '| ’

token._pprint_tree(max_depth, depth + 1, f, _pre + parent_pre)

 也就是说is\_group为True就会开始下一层的遍历,而token的初始is\_group则为False,也就是解析为TokenList的时候才为True。此Tokenlist就很明显是与IdentifierList 这个类有关了。下个小节我们再细细研究IdentifierList 基类,先让我们再看看TokenList的其他功能函数。
### 3.get\_token\_at\_offset(self, offset)
该方法将返回一个位置偏移上的token。

offsert_token=stmt[0].get_token_at_offset(1)

offsert_token

![](https://img-blog.csdnimg.cn/185a7967885b4ad885c08efaa2527093.png)
### 4.flatten(self)
和token的方法几乎差不多,但是生产的没有分类的tokens。对所有子tokens递归时调用此方法。
### 5.\_token\_matching(self, funcs, start=0, end=None, reverse=False)
该函数就是将token与funcs功能函数进行匹配,内部调用。
### 6.token\_first(self, skip\_ws=True, skip\_cm=False)
这个是一个比较重要的方法,返回第一个子token。也就是可以返回这条sql的功能类型。

stmt[0].token_first()

![](https://img-blog.csdnimg.cn/03cd1202a1b2489299919b089f204ed2.png)
其他方法很多都是主类方法的工具函数,主要是现在抓到了重点先搞清楚。Identifier这个类
## 三、Identifier类
这个类继承了两个父类NameAliasMixin和TokenList,前者为主要为实现get\_real\_name和get\_alias的方法,后者也是我们摸清楚了的TokenList方法。
Identifier类主要代表标识符。标识符可能有别名或类型转换。其中有四个主要方法:
### 1.`get_array_indices`()
返回索引token列表的迭代器:

print(stmt_1[13].get_array_indices())

###  2.`get_ordering`()
将order或None作为大写字符串返回。

print(Identifier.get_ordering(stmt[0]))

![](https://img-blog.csdnimg.cn/214cb9e74b374aae8c63bf8ad99282b1.png)
我写的sql没有order故为None。
### 3.`get_typecast`()
以字符串形式返回此对象的`typecast`或None。
### 4.`is_wildcard`()
如果此标识符包含通配符,则返回True。
以上就是Identifier的四大类,也就是说这个类以后如果我们想要识别什么新的功能函数可以继承此类。
先大体研究这么多,写出点相关的代码再继续深入研究,下篇文章我会将一些初步构思和代码加入其中完成简单的SQL语法解析。
#### 点关注,防走丢,**如有纰漏之处,请留言指教,非常感谢**
以上就是本期全部内容。我是fanstuck ,有问题大家随时留言讨论 ,我们下期见

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
![img](https://img-blog.csdnimg.cn/img_convert/63b231cf355f61592919298318b4359f.png)
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
[外链图片转存中...(img-8hEq8W7m-1713317382971)]
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

转载请注明来自码农世界,本文标题:《Python-sqlparse解析SQL工具库一文详解(二)》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,91人围观)参与讨论

还没有评论,来说两句吧...

Top