自己动手写数据库系统:解释执行 update 和 delete 对应的 sql 语句

在上一节我们完成了 select 语句的解释执行,本节我们看看 Update 和 Delete 对应的语句如何解释执行,当然他们的实现原理跟我们前面实现的 select 语句执行大同小异。无论是 update还是 delete 都是对数据表的修改,因此他们的实现方法基本相同。

假设我们要执行如下 sql 语句:

update STUDENT set MajorId=20 where MajorId=30 and GradYear=2020delete from STUDENT where MajorId=30 and GradYear=2020

要完成上面的代码,我们需要 scan底层的文件块,找到所有满足 where 条件的记录,如果语句是 update,那么把找到的记录修改掉,如果是 delete,那么把找到的记录给删除掉。我们看看具体的代码实现,首先我们添加 UpdatePlanner 的接口定义,在 planner 的 interface.go 文件中增加代码如下:

package plannerimport ("parser""record_manager""tx"
)type Plan interface {Open() interface{}BlocksAccessed() int               //对应 B(s)RecordsOutput() int                //对应 R(s)DistinctValues(fldName string) int //对应 V(s,F)Schema() record_manager.SchemaInterface
}type QueryPlanner interface {CreatePlan(data *parser.QueryData, tx *tx.Transation) Plan
}type UpdatePlanner interface {/*解释执行 insert 语句,返回被修改的记录条数*/ExecuteInsert(data *parser.InsertData, tx *tx.Transation) int/*解释执行 delete 语句,返回被删除的记录数*/ExecuteDelete(data *parser.DeleteData, tx *tx.Transation) int/*解释执行 create table 语句,返回新建表中的记录数*/ExecuteCreateTable(data *parser.CreateTableData, tx *tx.Transation) int/*解释执行 create index 语句,返回当前建立了索引的记录数TODO*///ExecuteCreateIndex(data *parser.CreateIndexData, tx *tx.Transation) int
}

在 planner 目录下新建文件 update_planner.go,输入代码如下:

package plannerimport (metadata_manager "metadata_management""parser""query""tx"
)type BasicUpdatePlanner struct {mdm *metadata_manager.MetaDataManager
}func NewBasicUpdatePlanner(mdm *metadata_manager.MetaDataManager) *BasicUpdatePlanner {return &BasicUpdatePlanner{mdm: mdm,}
}func (b *BasicUpdatePlanner) ExecuteDelete(data *parser.DeleteData, tx *tx.Transation) int {/*先 scan 出要处理的记录,然后执行删除*/tablePlan := NewTablePlan(tx, data.TableName(), b.mdm)selectPlan := NewSelectPlan(tablePlan, data.Pred())scan := selectPlan.Open()updateScan := scan.(*query.SelectionScan)count := 0for updateScan.Next() {updateScan.Delete()count += 1}updateScan.Close()return count
}func (b *BasicUpdatePlanner) ExecuteModify(data *parser.ModifyData, tx *tx.Transation) int {/*先 scan 出选中的记录,然后修改记录的信息*/tablePlan := NewTablePlan(tx, data.TableName(), b.mdm)selectPlan := NewSelectPlan(tablePlan, data.Pred())scan := selectPlan.Open()updateScan := scan.(*query.SelectionScan)count := 0for updateScan.Next() {val := data.NewValue().Evaluate(scan.(query.Scan))updateScan.SetVal(data.TargetField(), val)count += 1}return count
}func (b *BasicUpdatePlanner) ExecuteInsert(data *parser.InsertData, tx *tx.Transation) int {tablePlan := NewTablePlan(tx, data.TableName(), b.mdm)updateScan := tablePlan.Open().(*query.TableScan)updateScan.Insert()insertFields := data.Fields()insertedVals := data.Vals()for i := 0; i < len(insertFields); i++ {updateScan.SetVal(insertFields[i], insertedVals[i])}updateScan.Close()return 1
}func (b *BasicUpdatePlanner) ExecuteCreateTable(data *parser.CreateTableData, tx *tx.Transation) int {b.mdm.CreateTable(data.TableName(), data.NewSchema(), tx)return 0
}func (b *BasicUpdatePlanner) ExecuteView(data *parser.ViewData, tx *tx.Transation) int {b.mdm.CreateView(data.ViewName(), data.ViewDef(), tx)return 0
}func (b *BasicUpdatePlanner) ExecuteIndex(data *parser.IndexData, tx *tx.Transation) int {//b.mdm.CreateIndex//TODOreturn 0
}

在上面代码中BasicUpdatePlanner用于负责实现与数据库表内容修改相关的操作,例如插入,修改和删除,它导出的接口 ExecuteDelete, ExecuteModify, ExecuteInsert 分别负责表的删除,修改和插入,删除和修改的逻辑类似,首先都是通过 TablePlan 和 SelectPlan 找出要修改的记录,然后进行相应的操作,在上面代码实现中我们留有与索引相关的操作没有实现,因为索引是我们后续章节的一个重要内容。

完成了上面代码后,我们看看如何调用他们然后检验一下实现效果,在 main.go 中增加代码如下:

package mainimport (bmg "buffer_manager"fm "file_manager""fmt"lm "log_manager"metadata_manager "metadata_management""parser""planner""query""tx"
)func PrintStudentTable(tx *tx.Transation, mdm *metadata_manager.MetaDataManager) {queryStr := "select name, majorid, gradyear from STUDENT"p := parser.NewSQLParser(queryStr)queryData := p.Query()test_planner := planner.CreateBasicQueryPlanner(mdm)test_plan := test_planner.CreatePlan(queryData, tx)test_interface := (test_plan.Open())test_scan, _ := test_interface.(query.Scan)for test_scan.Next() {fmt.Printf("name: %s, majorid: %d, gradyear: %d\n",test_scan.GetString("name"), test_scan.GetInt("majorid"),test_scan.GetInt("gradyear"))}
}func CreateInsertUpdateByUpdatePlanner() {file_manager, _ := fm.NewFileManager("student", 2048)log_manager, _ := lm.NewLogManager(file_manager, "logfile.log")buffer_manager := bmg.NewBufferManager(file_manager, log_manager, 3)tx := tx.NewTransation(file_manager, log_manager, buffer_manager)mdm := metadata_manager.NewMetaDataManager(false, tx)updatePlanner := planner.NewBasicUpdatePlanner(mdm)createTableSql := "create table STUDENT (name varchar(16), majorid int, gradyear int)"p := parser.NewSQLParser(createTableSql)tableData := p.UpdateCmd().(*parser.CreateTableData)updatePlanner.ExecuteCreateTable(tableData, tx)insertSQL := "insert into STUDENT (name, majorid, gradyear) values(\"tylor\", 30, 2020)"p = parser.NewSQLParser(insertSQL)insertData := p.UpdateCmd().(*parser.InsertData)updatePlanner.ExecuteInsert(insertData, tx)insertSQL = "insert into STUDENT (name, majorid, gradyear) values(\"tom\", 35, 2023)"p = parser.NewSQLParser(insertSQL)insertData = p.UpdateCmd().(*parser.InsertData)updatePlanner.ExecuteInsert(insertData, tx)fmt.Println("table after insert:")PrintStudentTable(tx, mdm)updateSQL := "update STUDENT set majorid=20 where majorid=30 and gradyear=2020"p = parser.NewSQLParser(updateSQL)updateData := p.UpdateCmd().(*parser.ModifyData)updatePlanner.ExecuteModify(updateData, tx)fmt.Println("table after update:")PrintStudentTable(tx, mdm)deleteSQL := "delete from STUDENT where majorid=35"p = parser.NewSQLParser(deleteSQL)deleteData := p.UpdateCmd().(*parser.DeleteData)updatePlanner.ExecuteDelete(deleteData, tx)fmt.Println("table after delete")PrintStudentTable(tx, mdm)
}func main() {CreateInsertUpdateByUpdatePlanner()
}

在上面代码实现中,CreateInsertUpdateByUpdatePlanner函数先创建BasicUpdatePlanner对象,然后调用其 ExecuteCreateTable接口创建 STUDENT 表,接着使用 sql 解释器解析 insert 语句后创建 InsertData 对象,然后调用ExecuteInsert接口将记录插入数据库表,接下来以同样的方式调用ExecuteModify, ExecuteDelete接口来实现对数据库表中有关记录的修改和删除,完成上面代码后 运行go run main.go,执行起来效果如下:

able after insert:
name: tylor, majorid: 30, gradyear: 2020
name: tom, majorid: 35, gradyear: 2023
table after update:
name: tylor, majorid: 20, gradyear: 2020
name: tom, majorid: 35, gradyear: 2023
table after delete
name: tylor, majorid: 20, gradyear: 2020

从运行结果可以看到,我们对数据库表的建立,插入,修改和删除等操作的基本结果是正确的。更多内容和调试演示视频请在 b 站搜索:Coding 迪斯尼。完整代码下载地址:
https://github.com/wycl16514/database_SQL_execute_create_insert_update_delete.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/633522.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

建筑类中级工程师职称证明业绩材料有哪些?

三、建筑类中级工程师职称造价类工程业绩材料 1.合同&#xff1a;证明项目合作关系的凭证。 2.预&#xff08;结&#xff09;算报告等(重点是体现封面有你的名字和执业印章等) 3.单位证明或任命书(本人在项目中的职务聘书) 4.工程获奖证明&#xff1a;项目获得市优的证书、省优…

Ubuntu 22.04.1 LTS VirtualBox7.0 解决虚拟机窗口失去焦点一段时间后,虚拟机显示不刷新问题

故障描述&#xff1a; virtualbox安装在ubuntu系统上&#xff0c;虚拟机内安装了windows操作系统。使用中发现&#xff0c;当linux系统窗口被激活&#xff0c;如firefox浏览器&#xff0c;虚拟机的显示一段时间后会暂停刷新&#xff0c;鼠标划入虚拟机窗口后&#xff0c;才会立…

分布式概念

文章目录 一、CAP定理和BASE定理1.1 CAP定理1.2 CAP取舍1.3 BASE定理 二、分布式事务2.1 柔性事务2.2 两阶段提交协议2.3 三阶段提交协议 三、分布式ID3.1 数据库自增ID3.2 数据库多主模式3.3 号段模式3.4 雪花算法3.5 Leaf3.6 使用Redis生成ID 四、限流算法4.1 固定窗口计数器…

插入排序-insertSort

1、基本思路 与冒泡排序和插入排序一样&#xff0c;也是两个元素比较&#xff1b;不过不同的是&#xff0c;在插入排序中&#xff0c;数组的左边会维护一个有序数组&#xff0c;这个数组刚开始时只有一个元素&#xff0c;即数组第一个元素&#xff0c;后续将拿有序数组后的第一…

TypeScript实现一个贪吃蛇小游戏

游戏效果 文件目录 准备1&#xff1a;新建index.html&#xff0c;编写游戏静态页面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-…

小程序开发实战案例五 | 小程序如何嵌入H5页面

在接入小程序过程中会遇到需要将 H5 页面集成到小程序中情况&#xff0c;今天我们就来聊一聊怎么把 H5 页面塞到小程序中。 本篇文章将会从下面这几个方面来介绍&#xff1a; 小程序承载页面的前期准备小程序如何承载 H5小程序和 H5 页面如何通讯小程序和 H5 页面的相互跳转 小…

安全加速SCDN是什么

安全加速SCDN&#xff08;Secure Content Delivery Network&#xff0c;SCDN&#xff09; 是集分布式DDoS防护、CC防护、WAF防护、BOT行为分析为一体的安全加速解决方案。已使用内容分发网络&#xff08;CDN&#xff09;或全站加速网络&#xff08;ECDN&#xff09;的用户&…

【JavaEE】_网络通信原理

目录 1. 网络发展史 2. 网络通信基础 1.1 IP地址 1.2 端口号 1.3 协议 1.3.1 概念 1.3.2 五元组 1.4 协议分层 1.4.1 协议分层的优点 1.4.2 协议分层的分类 1.4.3网络设备所在分层 1.4.4 两台主机通过TCP/IP协议通讯过程 1.5 封装与分用 1.5.1 封装 1.5.2 分用…

Docker 容器连接

Docker 容器连接 前面我们实现了通过网络端口来访问运行在 docker 容器内的服务。 容器中可以运行一些网络应用&#xff0c;要让外部也可以访问这些应用&#xff0c;可以通过 -P 或 -p 参数来指定端口映射。 下面我们来实现通过端口连接到一个 docker 容器。 网络端口映射 …

OpenCV-Python(46):基于KNN的手写数字OCR识别

目标 根据掌握的kNN 知识创建一个基本的OCR 程序使用OpenCV自带的手写数字和字母数据测试我们的程序 手写数字的OCR 我们的目的是创建一个可以对手写数字进行识别的程序。为了达到这个目的我们需要训练数据和测试数据。OpenCV安装包中有一副图片(/samples/ python2/data/digi…

使用java模拟兰顿蚂蚁

兰顿蚂蚁是一个经典的计算机科学问题&#xff0c;它模拟了一只蚂蚁在一个无限大的网格上移动的行为。下面是一个使用Java模拟兰顿蚂蚁的示例代码&#xff1a; public class LangtonAnt {private int[][] grid;private int antX;private int antY;private int antDirection; //…

用一条命令导出 uiautomator dump 内容

# TLNR adb shell -t uiautomator dump --compressed /dev/tty # 说明 解决了一般先导出&#xff0c;再pull的问题。内容直接输出到本地shell。 --compressed 可有可无&#xff0c;压缩能减少一些信息

算法练习-A+B/财务管理/实现四舍五入/牛牛的菱形字符(题目链接+题解打卡)

难度参考 难度&#xff1a;简单 分类&#xff1a;熟悉OJ与IDE的操作 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。以下内容均为个人笔记&#xff0c;旨在督促自己认真学习。 题目 A B1. A B - AcWing题库财务管理1004:财…

openlayers [六] 地图交互 interaction 详解

文章目录 interaction 是什么interaction 简介interaction defaults- 默认添加的功能举例结论 interaction 是什么 地图的交互功能包含很多&#xff0c;如地图双击放大&#xff0c;鼠标滚轮缩放&#xff0c;矢量要素点选&#xff0c;地图上绘制图形等等。只要是涉及到与地图的…

VsCode + CMake构建项目 C/C++连接Mysql数据库 | 数据库增删改查C++封装 | 信息管理系统通用代码 ---- 课程笔记

这个是B站Up主&#xff1a;程序员程子青的视频 C封装Mysql增删改查操作_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1m24y1a79o/?p6&spm_id_frompageDriver&vd_sourcea934d7fc6f47698a29dac90a922ba5a3安装mysql:mysql 下载和安装和修改MYSQL8.0 数据库存储…

7、Python使用外部库

导入、运算符重载以及冒险进入外部库世界的生存技巧! 在本教程中,您将了解 Python 中的Imports,获得一些使用不熟悉的库(以及它们返回的对象)的技巧,并深入研究运算符重载。 文章目录 1.导入(Imports)其他导入语法子模块哦,你将去的地方,哦,你将看到的对象了解奇怪对象…

【现代密码学】笔记9-10.3-- 公钥(非对称加密)、混合加密理论《introduction to modern cryphtography》

【现代密码学】笔记9-10.3-- 公钥&#xff08;非对称加密&#xff09;、混合加密理论《introduction to modern cryphtography》 写在最前面8.1 公钥加密理论随机预言机模型&#xff08;Random Oracle Model&#xff0c;ROM&#xff09; 写在最前面 主要在 哈工大密码学课程 张…

深入vue响应式原理

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项&#xff0c;Vue 将遍历此对象所有的 property&#xff0c;并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。 这些 getter/setter 对用户来说是不可见的&#xff0c;但是在内部它们让 Vue …

Docker 47 个常见故障的原因和解决方法

本文针对Docker容器部署、维护过程中&#xff0c;产生的问题和故障&#xff0c;做出有针对性的说明和解决方案&#xff0c;希望可以帮助到大家去快速定位和解决类似问题故障。 Docker是一种相对使用较简单的容器&#xff0c;我们可以通过以下几种方式获取信息&#xff1a; 1、…

简单理解自动驾驶-看这篇够了!

本文主要介绍自动驾驶技术的整体框架&#xff0c;旨在从宏观理解自动驾驶技术。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;自动驾驶技术 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人生秘诀&#xff1a…