对数据库的理解

对数据库的理解

最近编译原理课程布置了一个实习课程,大致内容是使用ParserGenerator与VC++两个软件来实现对SQL语句的编译,包括词法、语法、语义三部分;其中ParserGenerator中已经封装了lex和yacc两个工具。在这个实习过程中遇到了很多问题,也收获很多;下边是我对这次实习的初步总结;前三部分网上的内容都比较多,我重点描述我在读别人源码的过程中对数据库的理解(第四部分):

1. 使用lex进行词法分析
2.使用yacc进行语法分析
3.使用yacc进行语义分析
4.对数据库的理解

在对语法可以进行识别之后,我们需要根据语义进行相应处理。假如我们已经可以成功的从yacc中输出* 已经通过语法分析*的语句,那么我们就需要对这个语句的各个部分进行处理,比如:我们正确的识别了一个create_table的语句,我们就真的可以在数据库中创建一个table;正确识别一个insert_record语句,那么就真的可以放在数据库中。

数据库部分需要我们自行设计,题目所给的建议是使用.db.bat文件,并且参考对数据库的各个部分进行分页;这一下就蒙了,于是我想先把这个题目简化一下,比如:创建一个表,就干脆建一个文本文件,命名为表名;然后对表的处理,就是对这个文本文件的处理…..被我的无能所折服

我去github上搜到了相关的源码,那部分源码还没有实现全部功能,但是却已经令我佩服,从这部分源码中我理解到很多东西,下面详述:

  1. 先放两个图,这勉强算是我在读源码时的思维导图吧:

.db
.bat

  1. 接下来据图描述我对数据库新的认识:

    2.1 数据库被分为.db文件和.bat文件;两个文件相辅相成,共同完成对数据库的操作。

    2.2其中.db文件主要存放的内容是:

    page0:整个系统的元数据:已建数据库的数目;当前所在的表地址页(这个有待确认)?;系统中的用户数。

    每一个数据所占的位数都是可以自定义的。

    page1:所有数据库的元数据(数据库头):数据库名;数据库中已建表的数目。

    每一个数据所占位数自定义;此页中可以描述的数据库的数量计算方式为:表长度/数据库头长度;其中表长度也是在设计数据库的时候自定义的。

    page2-page17:一共16页;如果定义半页存放一个数据库的表的元数据;那么一共可以定义32个数据库;每半页存放的是:

    表1:名字 属性在.db文件中的位置 此表的用户数 此表的记录数 此表的属性数

    表2:…….

    page18 and later:存放属性的元数据

    属性信息:[属性名,属性数据类型,属性参数长度,属性对应数据信息所在页]+

    2.3其中的.bat文件主要存放的内容是:

    page0:数据段的位置信息??

    page1:用户信息

    page2-page65:…………………………不太确定,大致和用户和表有关吧………………………………………………..

    page66:记录数;数据信息

总的来说,找位置的大致位置是这样的:

  1. 首先用户在使用此系统过程中,需要use_database;这个时候确定了数据库的元数据所在的位置;可以计算出这个数据库的表信息在.db 文件中的页数。

  2. 接着加入用户create_table;用户利用1中得到的数据库序号就可以在它专属的页(查找.db文件)中增加表;在此页的最后增加表的元数据

  3. 用户需要insert_record时;利用1中的数据库句柄(查找.db文件)和2中该表的页信息(查找.db文件),可以得到这个表中的各个属性所在的位置;其中这些属性的元数据中包含对应数据在bat文件中的位置

  4. 如果用户需要插入的数据共包含5个属性,那么他通过.db文件中这五个属性的元信息分别得到属性的数据信息在.bat文件中的位置,每得到一个正确的位置,便把自己的用户数据插入

偏移量和元数据的作用真的令我敬佩;其实还有很多细节问题需要我去理解。





下边是供我自己看的阅读笔记:

创建数据库:

fin打开db文件;SEEK_SET=0;

fseek函数用于重定位流(数据流/文件)上的文件内部位置指针。
函数原型int fseek(FILE *stream, long offset, int fromwhere);
参数:
stream为文件流的指针
offset  偏移量
fromwhere 起始位置
具体功能:如果执行成功,stream将指向以fromwhere(起始位置:文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END))为基准,偏移offset(指针偏移量)个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。


函数原型
size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;
参 数
buffer
用于接收数据的内存地址
size
要读的每个数据项的字节数,单位是字节
count
要读count个数据项,每个数据项size个字节.
stream
输入流
返回值
返回真实读取的项数,若大于count则意味着产生了错误。另外,产生错误后,文件位置指示器是无法确定的。若其他stream或buffer为空指针,或在unicode模式中写入的字节数为奇数,此函数设置errno为EINVAL以及返回0.

atoi (表示 ascii to integer)是把字符串转换成整型数的一个函数,应用在计算机程序和办公软件中。

size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
注意:这个函数以二进制形式对文件进行操作,不局限于文本文件
返回值:返回实际写入的数据块数目
(1)buffer:是一个指针,对fwrite来说,是要获取数据的地址;
(2)size:要写入内容的单字节数;
(3count:要进行写入size字节的数据项的个数;
(4)stream:目标文件指针;
(5)返回实际写入的数据项个数count

read_D(fin,1*2048+i*64,32)

每一页的长度是2048;

第一页存放数据库名字;每一个数据库名用32位表示;每一个数据库所有信息有64位;

fill_D(fin,1*2048+已有数据库数目*64,64,null);

write_D(fin,1*2048+num*64,name);

fprintf(fin,”%d”,0);

上述三个函数将一个数据库信息名字+信息写入到长度为64位

fprintf(fin,”%d”,num+1);

此函数修改了当前数据库数量

创建表:

//这里是不是有bug,因为fin都还没有定义

//假装已经放在这个文件里边,那么有下:

offset=1*2048+(i)*64

read_D(fin,offset+32,32)

//上述操作完成选出待操作的数据库;并且读出此数据库下的table数目

fseek(fin,offset+32,SEEK_SET);

fprintf(fin,”%d”,table_num+1);

offset=T_LIST_PAGE*PAGE_SIZE+DT_HANDLE*T_LIST_SIZE+table_num*T_HEAD_SIZE;

offset=2*2048+i*1024+table_num*64;

fill_D(fin,offset,T_HEAD_SIZE,null);初始化为空

write_D(fin,offset,table->name);写入表名

read_D(fin,8,12);12位当前字段表地址?

fseek(fin,offset+T_NAME_SIZE,SEEK_SET);

fseek(fin,offset+32,SEEK_SET);表名后边写入字段表地址页

fprintf(fin,”%d”,num);

fseek(fin,offset+T_NAME_SIZE+T_PAGE+T_USERNUM,SEEK_SET);

fseek(fin,offset+32+12+4,SEEK_SET);

fprintf(fin,”%d”,0);

fseek(fin,8,SEEK_SET);

fprintf(fin,”%d”,num+1);下一个字段表

建立用户表下面:

if (USER_NUM==0) { fseek(fin,offset+T_NAME_SIZE+T_PAGE,SEEK_SET);fprintf(fin,"%d",1); }
else {fseek(fin,offset+T_NAME_SIZE+T_PAGE,SEEK_SET);fprintf(fin,"%d",2); } ????2

offset=U_LISTPAGE*PAGE_SIZE+(num-18)*U_LISTSIZE;

offset=2*2048+(num-18)*256;???

fseek(fout,offset,SEEK_SET);

fprintf(fout,”%d”,0);

fseek(fout,offset+U_NUM,SEEK_SET);

fprintf(fout,”%d”,15);15???

if (USER_NUM!=0){
    offset=offset+U_WORDSIZE;
    fseek(fout,offset,SEEK_SET);
    fprintf(fout,"%d",USER_NUM);
    fseek(fout,offset+8,SEEK_SET);
    fprintf(fout,"%d",15);
}????
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值