本文通过PLY实现一个简单的sql库

本文主要简述一下,有关语法解析的库的使用,并使用改实例编写一个简单的模仿最基本的sql语句的数据库,本文代码仅供示例参考。

语法解析与上下文

语法解析是一个比较大的内容,早起比较成熟的有lex与yacc,该工具相对比较成熟,详细的资料大家可以自行查阅资料,在编译中使用较多的是上下文无关文法主要的是BNF,大家有兴趣可查阅sql语句的BNF文档,标准的sql的文法相对复杂,本文只是为了实现最基本的工作故只是做了最简单的解析。

示例代码
import ply.lex as lex
import ply.yacc as yaccimport collectionstokens = ('LFPARENTH','RGPARENTH','TABLE','CREATE','INSERT','UPDATE','INTO','VALUES','SELECT','COLUMN',"COMMA",'WHERE','FROM','AND','SET','EQUAL','STAR',"END"
)t_LFPARENTH = r'\('
t_RGPARENTH = r'\)'
t_SELECT = r'SELECT|select'
t_CREATE = r'CREATE|create'
t_INSERT = r'INSERT|insert'
t_UPDATE = r'UPDATE|update'
t_INTO = r'INTO|into'
t_VALUES = r'VALUES|values'
t_WHERE = r'WHERE|where'
t_FROM = r'FROM|from'
t_AND = r'AND|and'
t_SET = r'SET|set'
t_EQUAL = r'\='
t_TABLE = r'TABLE|table'
t_COMMA = r','
t_STAR = r'\*'
t_END = r';'def t_COLUMN(t):r'[a-zA-Z0-9/.-]+'if t.value in ['FROM', 'from']:t.type = 'FROM'if t.value in ['CREATE', 'create']:t.type = 'CREATE'if t.value in ['TABLE', 'table']:t.type = 'TABLE'if t.value in ['INSERT', 'insert']:t.type = 'INSERT'if t.value in ['INTO', 'into']:t.type = 'INTO'if t.value in ['VALUES', 'values']:t.type = 'VALUES'if t.value in ['UPDATE', 'update']:t.type = 'UPDATE'if t.value in ['SET', 'set']:t.type = 'SET'if t.value in ['WHERE', 'where']:t.type = 'WHERE'if t.value in ['SELECT', 'select']:t.type = 'SELECT'if t.value in ['AND', 'and']:t.type = 'AND'return tdef t_newline(t):r'\n+'t.lexer.lineno += len(t.value)t_ignore = ' \t'def t_error(t):print("Illegal character {0}".format(t.value[0]))t.lexer.skip(1)lexer = lex.lex()datas = {}class Stack(object):def __init__(self):self.is_columns = Falseself._stack = []def reset(self):self._stack = []def append(self, value):self._stack.append(value)def __iter__(self):return iter(self._stack)def __len__(self):return len(self._stack)def __str__(self):print(self._stack)return "stack"def __getitem__(self, item):return self._stack[item]def __setslice__(self, i, j, sequence):return self._stack[i:j]stack = Stack()current_action = Nonecolumns_dict = {}condition_dict = {}def reset_action():global current_action, stack, columns_dict, condition_dictcurrent_action = Nonestack.reset()columns_dict = {}condition_dict = {}class Select(object):def __init__(self):self.values = []self.table = Nonedef set_table(self, table):self.table = tablereturn table in datasdef add_stack(self, stack):[self.add_values(v) for v in stack if v not in self.values]def add_values(self, value):self.values.append(value)def action(self):"""展示数据"""if self.table not in datas:print("table {0} not exists")returntable = datas[self.table]if self.values:for v in self.values:if v in table:print("   {0} = {1}".format(v, table[v]))else:print("   {0} not in table {1}".format(v, self.table))else:for v in table:print("   {0} = {1}".format(v, table[v]))class Create(object):def __init__(self):self.values = []self.table = Nonedef set_table(self, table):self.table = tablereturn table not in datasdef add_stack(self, stack):[self.add_values(v) for v in stack if v not in self.values]def add_values(self, value):self.values.append(value)def action(self):datas[self.table] = collections.OrderedDict()for v in self.values:datas[self.table][v] = []print("create : ", datas)class Insert(object):def __init__(self):self.values = []self.columns = set()self.table = Noneself._stack = Nonedef set_table(self, table):self.table = tablereturn table not in datasdef add_stack(self, stack):# 判断是否输入的sql 为 insert into table(c1, c2, c3) values(1,2,3)self._stack = stackdef action(self):table = datas[self.table]if self._stack.is_columns:if len(self._stack) and len(self._stack) % 2 == 0:index = int(len(self._stack) / 2)if index != len(table.keys()):print("error default columns")returnfor i in range(index):if self._stack[i] in table:table[self._stack[i]].append(self._stack[i + index])else:print(" error columns and values not equal")returnelse:if len(table.keys()) != len(self._stack):print("input values len {0} not equal table columes len {1}".format(len(self._stack), len(table.keys())))returnt_index = 0for v in table.keys():table[v].append(self._stack[t_index])t_index += 1print("insert : ", datas)class Update(object):def __init__(self):self.values = []self.table = Noneself.condition_dict = {}self.columns_dict = {}self.index_list = Nonedef set_table(self, table):self.table = tablereturn table not in datasdef add_stack(self, condition, colums):self.condition_dict = conditionself.columns_dict = columsdef check_dict_key(self, val_dict, table):for key in val_dict.keys():if key not in table:return Falsereturn Truedef find_keys(self, val_dict, table):keys = [key for key in val_dict]values = [val_dict[key] for key in val_dict]self.index_list = []print(keys)print(table)result_list = []if keys:first_line = table[keys[0]]for i in range(len(first_line)):detail_value = []for key in keys:detail_value.append(table[key][i])result_list.append(detail_value)print(values)print(result_list)for index, v in enumerate(result_list):if v == values:self.index_list.append(index)print(self.index_list)return self.index_listdef action(self):table = datas[self.table]if not (self.check_dict_key(self.condition_dict, table) and\self.check_dict_key(self.columns_dict, table)):print(" error found keys ")returnindex_list = self.find_keys(self.condition_dict, table)if not index_list:print(" update condition not found")returnfor k in self.columns_dict:for index in index_list:table[k][index] = self.columns_dict[k]def p_statement_expr(t):'''expressions : expression| expressions expression'''if current_action:current_action.action()reset_action()def p_expression_start(t):'''expression :  exp_select| exp_create| exp_insert| exp_update'''def p_expression_select(t):'''exp_select : SELECT columns FROM COLUMN END| SELECT STAR FROM COLUMN END'''print(t[1], t[2])global current_actioncurrent_action = Select()if not current_action.set_table(t[4]):print("{0} table not exists".format(t[4]))returnif not t[2]:current_action.add_stack(stack)def p_expression_create(t):'''exp_create : CREATE TABLE COLUMN LFPARENTH columns RGPARENTH END'''print(t[1])global current_actioncurrent_action = Create()if not current_action.set_table(t[3]):print("{0} table already exists".format(t[3]))return# 处理参数current_action.add_stack(stack)def p_expression_insert(t):'''exp_insert : INSERT INTO COLUMN exp_insert_end'''print(t[1])global current_actioncurrent_action = Insert()if current_action.set_table(t[3]):print("{0} table not exists".format(t[3]))reset_action()return# 处理insert的参数current_action.add_stack(stack)def p_expression_update(t):'''exp_update : UPDATE COLUMN SET exp_update_colums WHERE exp_update_condition END'''print(t[1])global current_actioncurrent_action = Update()if current_action.set_table(t[2]):print("{0} table not exists".format(t[2]))returnprint(condition_dict, columns_dict)current_action.add_stack(condition_dict, columns_dict)def p_expression_update_columns(t):'''exp_update_colums : COLUMN EQUAL COLUMN| COLUMN EQUAL COLUMN COMMA exp_update_colums'''columns_dict[t[1]] = t[3]def p_expression_update_condition(t):'''exp_update_condition : COLUMN EQUAL COLUMN| COLUMN EQUAL COLUMN AND exp_update_condition'''condition_dict[t[1]] = t[3]def p_expresssion_insert_end(t):'''exp_insert_end : VALUES LFPARENTH columns RGPARENTH END| LFPARENTH columns RGPARENTH VALUES LFPARENTH columns RGPARENTH END'''if len(t) == 9:stack.is_columns = Truedef p_expression_columns(t):'''columns : COLUMN| COLUMN COMMA columns'''stack.append(t[1])def p_error(p):if p:print("Syntax error at {0}".format(p.value))else:print("Syntax error at EOF")while True:data = input("sql>")yacc.yacc()yacc.parse(data)

运行该示例代码如下;

sql>create table t1 (line1, line2, line3);
create
create :  {'t1': OrderedDict([('line3', []), ('line2', []), ('line1', [])])}
sql>insert into t1 values(1,2,3);
insert
insert :  {'t1': OrderedDict([('line3', ['3']), ('line2', ['2']), ('line1', ['1'])])}
sql>insert into t1 values(1,2,32);
insert
insert :  {'t1': OrderedDict([('line3', ['3', '32']), ('line2', ['2', '2']), ('line1', ['1', '1'])])}
sql>insert into t1 values(1,23, 33);
insert
insert :  {'t1': OrderedDict([('line3', ['3', '32', '33']), ('line2', ['2', '2', '23']), ('line1', ['1', '1', '1'])])}
sql>insert into t1 values(1,2, 43);
insert
insert :  {'t1': OrderedDict([('line3', ['3', '32', '33', '43']), ('line2', ['2', '2', '23', '2']), ('line1', ['1', '1', '1', '1'])])}
sql>update t1 set line1=0, line2=0 where line1=1 and line2=2;
update
{'line2': '2', 'line1': '1'} {'line2': '0', 'line1': '0'}
['line2', 'line1']
OrderedDict([('line3', ['3', '32', '33', '43']), ('line2', ['2', '2', '23', '2']), ('line1', ['1', '1', '1', '1'])])
['2', '1']
[['2', '1'], ['2', '1'], ['23', '1'], ['2', '1']]
[0, 1, 3]
sql>select * from t1;
select *line3 = ['3', '32', '33', '43']line2 = ['0', '0', '23', '0']line1 = ['0', '0', '1', '0']
sql>select line1, line2 from t1;
select Noneline2 = ['0', '0', '23', '0']line1 = ['0', '0', '1', '0']
sql>

本文仅仅是支持简单的语法,基本的select 语法也没有支持where条件语句,update的操作支持多条件多行的更改,创建表的语句create也并没有支持字段属性,所有的数据都是存储在python的字典中。

总结

本文只是作为在sql语法与编译器相关的一些基本的原理的知识的梳理,展示的脚本也仅仅是作为演示使用,大家有兴趣可自行学习库。由于本人才疏学浅,如有错误请批评指正。

PLY库-实现最简单的sql语法的数据库相关推荐

  1. R语言构建仿真数据库(sqlite)并使用dplyr语法和SQL语法查询数据库、将dplyr语法查询语句翻译为SQL查询语句

    R语言构建仿真数据库(sqlite)并使用dplyr语法和SQL语法查询数据库.将dplyr语法查询语句翻译为SQL查询语句 目录

  2. 导学+初识MySQL+SQL语法规范+数据库相关操作+表相关操作+MySql存储引擎介绍+MySQL表的创建+测试数据类型

    一.导学 1.什么是SQL? 结构化查询语言,数据库管理系统通过SQL语言来管理数据库中的数据: 2.SQL语言组成部分 (1)DDL--数据定义语言,主要定义数据库.表.视图.索引和触发器等 (2) ...

  3. Java面向对象系列[v1.0.0][SQL语法之数据库约束]

    数据库约束 所有关系型数据库都支持对数据表使用约束,在表面上是强制执行的数据校验规则,通过约束可以更好的的保证数据表里数据的完整性 大部分数据库支持5中完整性约束 NOT NULL:非空约束,指定某列 ...

  4. mysql数据库sql语法_Mysql数据库SQL语句整理

    mysql [-h host] -u root -p 连接MySQL -h host:host代表要连接的主机地址 可以省略 -u root:root为MySQL中的管理员用户名 -p :root用户 ...

  5. Antlr4之简单的sql查询解析demo

    当前版本:jdk1.8.antlr4.8 1. 声明 当前内容主要为测试和使用Antlr4,并设计简单的SQL查询解析(本人解析IoTDB源码中发现其中使用了Antlr4来实现对sql执行的解析) 1 ...

  6. mysql语法大全w3school_(二)mysql:在w3schools文档上学习sql语法(使用数据库创建一张表)...

    1.选中要使用的数据库(选中上篇创建的test数据库) 现有的数据库 mysql>use test; 则选中test数据库: 2.创建一张表 2.1column代表每一列的名称,datatype ...

  7. SQL语法精讲(包括建库、建表、建视图、查询、增加、删除、修改)

    SQL语法精讲(包括建库.建表.建视图.查询.增加.删除.修改) SQL分类: DDL-数据定义语言(CREATE,ALTER,DROP,DECLARE) DML-数据操纵语言(SELECT,DELE ...

  8. mysql库与oracle库的区别_开源数据库Oracle与MySQL的SQL语法区别

    Oracle数据库与MySQL数据库的区别是本文我们主要要介绍的内容,接下来我们就开始介绍这部分内容,希望能够对您有所帮助. Oracle与MySQL的SQL语法区别: 1.在Oracle中用sele ...

  9. Python SQL 语法简单入门

    Python SQL 语法简单入门 大家好,今天给大家分享一些python中基本的sql语法.基本是按照sqlite3 来写的. 引题 为什么要使用数据库? 持久化 ,内存中的变量当程序重启和电脑断电 ...

最新文章

  1. 20145207 《Java程序设计》第5周学习总结
  2. 【python】数据结构与算法之快速排序(重要)
  3. vue 声明周期函数_【Vue】详解Vue生命周期
  4. 零基础学习 Python 之文件
  5. Android之打开继承DialogFragment对话框里面EditText获取光标并且弹出键盘把底部布局顶上去
  6. KTV阶段项目告一段落,让我们张开双臂迎接新阶段吧!!
  7. 解决:build_attrs() takes at most 2 arguments (3 given)
  8. 减治求有重复元素的全排列
  9. Java自定义Annotation方法
  10. Damp;G“辱华”争议广告女主发声:几乎断送了模特事业
  11. OpenSSL学习(二十二):基础-指令sess_id
  12. iOS9.3.3骚扰电话拦截黑名单数据库
  13. WPS Office 2016 专业增强精简版 附终身授权正版序列号
  14. 小程序分类图标提取_垃圾分类小程序上线 微信和支付宝都支持
  15. IDEA插件系列(105):IDEA Mind Map插件——IDEA思维导图
  16. 2020年医美行业网络关注度分析报告
  17. SpringBoot实现QQ邮箱注册和登录
  18. 判断栈的出栈顺序是否正确
  19. c语言程序负数,C程序,检查数字是正数还是负数
  20. Goland嗖嗖的: 快捷键,自动生成代码等效率小技巧

热门文章

  1. Python实战 | 送亲戚,送长辈,月饼可视化大屏来帮忙!
  2. 老码农:这是我见过最操蛋的代码,切勿模仿!
  3. 不用写代码就能学用Pandas,适合新老程序员的神器Bamboolib
  4. 取代Python?Rust凭什么
  5. 抛弃VS Code,我还能用啥编辑器?| 技术头条
  6. 上海大学建了一个“突发事件语料库”,包括地震、恐怖袭击等5大类
  7. MyBatis中使用流式查询避免数据量过大导致OOM
  8. Spring Boot 操作 Redis 的各种实现
  9. JDK中的坑:JDK中这些方法的bug你不要踩
  10. 关于Redis缓存,这3个问题一定要知道!