创建表的逻辑
1.ExecuteStage::handle_request函数处理一个request请求,通过sql解析,发现这是一个创建表的sql语句,进入do_create_table函数
2.do_create_table函数
定义一个CreateTable变量,通过输入的sql语句得到创建表的名字、字段数量、字段类型数据。
获取sql语句的SessionEvent变量
获取当前的数据库类型(Db)
进入db->create_table函数,传入创建表的名字、字段数量、字段类型
3.db->create_table函数
参数检查,判断数据表名字是否重复
获取当前数据库存放的位置,构造出新创建表的元数据存储路径
建立一个新的table变量
调用table->create函数,传入元数据存储路径,数据表名字,数据库的路径,字段数和字段类型
函数结束之后,将当前表名加入到记录已打开数据表的映射中
4.table->create函数
(1)再次进行参数检查,检查数据表名字,检查字段数,字段类型
(2)调用
int fd = ::open(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0600);
打开元数据存储路径,
O_WRONLY 只写模式
O_CREAT 如果指定文件不存在,则创建这个文件
O_EXCL 如果要创建的文件已存在,则返回 -1,并且修改 errno 的值
O_CLOEXEC,当调用exec成功后,文件会自动关闭
0600表示创建的文件可读可写。
所以实际的意思是,根据传入的元数据存储位置,创建一个可读可写的文件(如果已存在,返回-1)
(3)调用
table_meta_.init(name, attribute_count, attributes))
首先进行参数检查
如果sys_fields_为空的话,初始化sys_fields_
fields进行拓展,拓展到sys_fields_的长度加上当前创建表的字段数量,然后将前面sys_fields_中的变量赋值到fields_中,调用
fields_[i + sys_fields_.size()].init(attr_info.name, attr_info.type, field_offset, attr_info.length, true);
将新创建表的字段属性进行初始化加入到fields_中
增加偏移量field_offset
设置record_size_ = field_offset;
(4)调用
std::fstream fs;
fs.open(path, std::ios_base::out | std::ios_base::binary);
打开元数据文件,并且通过二进制的方式进行写操作
(5)调用
table_meta_.serialize(fs);
将元数据进行序列化然后写入文件
(6)
通过数据库存放位置和数据表名,获得当前数据表文件存放位置
实例化一个BufferPoolManager变量,然后调用create_file函数,创建数据表文件。
(7)调用
BufferPoolManager::create_file(const char *file_name)
create_file函数,首先根据路径打开数据表文件
fd = open(file_name, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
O_RDWR 读写模式
O_CREAT 如果指定文件不存在,则创建这个文件
O_EXCL 如果要创建的文件已存在,则返回 -1,并且修改 errno 的值
S_IREAD 所有者拥有读权限
S_IWRITE 所有者拥有写权限
以读写的方式创建一个新文件,新文件所有者拥有读写权限
然后以读写方式打开这个文件,创建Page文件,并且初始化为全0
将page.data中的前面部分转化成BPFileHeader变量指针,设置分配的页面为1,总页面为1,设置bitmap
调用lseek(fd, 0, SEEK_SET),将打开文件的指针移到文件开头
调用writen(fd, (char *)&page, sizeof(Page)),将刚才创建的Page变量写入文件
(8)
init_record_handler(base_dir);
初始化record_handler变量,设置table类中的base_dir_为当前数据库的存储位置
返回SUCCESS