#/usr/local/env python
#_*_coding:utf-8_*_
#第一部分:sql解析
import xlrd
import xlwt
from xlutils.copy import copy
import os
def sql_parse(sql): #用户输入sql 转成结构化的字典
'''
第一步:sql解析 流程
1.收到 sql查询条件
2.sql_parse 来分发要求给 select_parse
3.select_parse 调用 handle_parse 解析sql
4.handle_parse 返回解析sql后的结果 sql_dic 给 select_parse
5.select_parse 把 sql_dic 返回给sql_parse
sql_dic=sql_parse(sql) #用户输入sql 转成结构化的字典sql_dic
sql语句四种操作格式:insert delete update select
提取用户输入sql 的操作关键词 再进行分析和分发操作
把sql字符串切分,提取命令信息,分发给具体解析函数去解析
:param sql:用户输入的字符串
:return:返回字典格式sql解析结果
'''
#sql命令操作 解析函数的字典 根据用户的命令来找相对应的函数
parse_func={
'insert':insert_parse,
'delete':delete_parse,
'update':update_parse,
'select':select_parse,
}
#print('用户输入 sql str is : %s' %sql) #打印用户输入的sql
sql_l=sql.split(' ') #按空格切割用户sql 成列表 方便提取命令信息
func=sql_l[0] #取出用户的sql命令
#判断用户输入的sql命令 是否在定义好的sql命令函数的字典里面,如果不在字典里面,则返回空
res=''
if func in parse_func:
res=parse_func[func](sql_l) #把切割后的 用户sql的列表 传入对应的sql命令函数里
return res
def insert_parse(sql_l):
'''
定义insert语句的语法结构,执行sql解析操作,返回sql_dic
:param sql:sql按照空格分割的列表
:return:返回字典格式的sql解析结果
'''
sql_dic={
'func':insert, #函数名
'insert':[], #insert选项,留出扩展
'into':[], #表名
'values':[], #值
}
return handle_parse(sql_l,sql_dic)
def delete_parse(sql_l):
'''
定义delete语句的语法结构,执行sql解析操作,返回sql_dic
:param sql:sql按照空格分割的列表
:return:返回字典格式的sql解析结果
'''
sql_dic = {
'func': delete,
'delete': [], # delete选项,留出扩展
'from': [], # 表名
'where': [], # filter条件
}
return handle_parse(sql_l, sql_dic)
def update_parse(sql_l):
'''
定义update语句的语法结构,执行sql解析操作,返回sql_dic
:param sql:sql按照空格分割的列表
:return:返回字典格式的sql解析结果
'''
sql_dic = {
'func': update,
'update': [], # update选项,留出扩展
'set': [], # 修改的值
'where': [], # filter条件
}
return handle_parse(sql_l, sql_dic)
def select_parse(sql_l):
'''
定义select语句的语法结构,执行sql解析操作,返回sql_dic
:param sql:sql按照空格分割的列表
:return:返回字典格式的sql解析结果
'''
# print('from in the select_parse :\033[42;1m%s\033[0m' %sql_l)
# select语句多种条件查询,列成字典,不同条件不同列表
sql_dic={
'func':select, #执行select语句
'select':[], #查询字段
'from':[], #数据库.表
'where':[], #filter条件,怎么找
'limit':[], #limit条件,限制
}
return handle_parse(sql_l,sql_dic)
def handle_parse(sql_l,sql_dic): #专门做sql解析操作
'''
执行sql解析操作,返回sql_dic
:param sql_l: sql按照空格分割的列表
:param sql_dic: 待填充的字典
>select * from Asswei.xlsx where not 队员编号 >= 3 limit 2
sql_dict is {'from': ['db1.emp'], 'where': ['not', 'id', '>=', '3'],
'limit': ['2'], 'select': ['id,name']}
:return: 返回字典格式的sql解析结果
'''
tag=False #设置警报 默认是关闭False
for item in sql_l: #循环 按空格切割用户sql的列表
if tag and item in sql_dic: #判断警报拉响是True 并且用户sql的条件 在条件select语句字典里面,则关闭警报
tag=False #关闭警报
if not tag and item in sql_dic: #判断警报没有拉响 并且用户sql的条件 在条件select语句字典里面
tag=True #拉响警报
key=item #取出用户sql的条件
continue #跳出本次判断
if tag: #判断报警拉响
sql_dic[key].append(item) #把取出的用户sql 添加到 select语句多种条件对应的字典里
if sql_dic.get('where'): #判断 用户sql where语句
sql_dic['where']=where_parse(sql_dic.get('where')) #['id>4','and','id<10']
#调用where_parse函数 把整理好的用户sql的where语句 覆盖之前没整理好的
return sql_dic #返回 解析好的 用户sql 字典
def where_parse(where_l): #['id>','4','and','id','<10'] ---> #['id>4','and','id<10']
'''
分析用户sql where的各种条件,再拼成合理的条件字符串
:param where_l:用户输入where后对应的过滤条件列表
:return:
'''
res=[] #存放最后整理好条件的列表
key=['and','or','not'] #逻辑运算符
char='' #存放拼接时的字符串
for i in where_l: #循环用户sql
if len(i) == 0 :continue #判断 长度是0 就继续循环
if i in key:
#i为key当中存放的逻辑运算符
if len(char) != 0: #必须 char的长度大于0
char=three_parse(char) #把char字符串 转成列表的形式
res.append(char) #把之前char的字符串,加入res #char='id>4'--->char=['id','>','4']
res.append(i) #把用户sql 的逻辑运算符 加入res
char='' #清空 char ,为了下次加入char到res时 数据不重复
else:
char+=i #'id>4' #除了逻辑运算符,都加入char #char='id<10'--->char=['id','>','4']
else:
char = three_parse(char) # 把char字符串 转成列表的形式
res.append(char) #循环完成后 char里面有数据 ,再加入到res里面
# ['id>4','and','id<10'] ---> #['id','>','4','and','id','<','10']
return res #返回整理好的 where语句列表
def three_parse(exp_str): # 把where_parse函数里面 char的字符串 转成字典
'''
将每一个小的过滤条件如,name>=1转换成['name','>=','1']
:param exp_str:条件表达式的字符串形式,例如'name>=1'
:return:
'''
key=['>','<','='] #区分运算符
res=[] #定义空列表 存放最终值
char='' #拼接 值的字符串
opt='' #拼接 运算符
tag=False #定义警报
for i in exp_str: #循环 字符串和运算符
if i in key: #判断 当是运算符时
tag=True #拉响警报
if len(char) != 0: #判断char的长度不等于0时(方便添加连续运算符)才做列表添加
res.append(char) #把拼接的字符串加入 res列表
char='' #清空char 使下次循环不重复添加数据到res列表
opt+=i #把循环的运算符加入opt
if not tag: #判断 警报没有拉响
char+=i #把循环的字符串加入 char
if tag and i not in key: #判断 警报拉响(表示上次循环到运算符),并且本次循环的不是运算符
tag=False #关闭警报
res.append(opt) #把opt里面的运算符 加入res列表
opt='' #清空opt 使下次循环不重复添加数据到res列表
char+=i #把循环到的 字符串加入char
else:
res.append(char) #循环结束,把最后char的字符串加入res列表
#新
评论0