6.2 表扫描table scan

我们一个物理查询计划中可以做的最基本的事情是读一个关系 R 的整个内容。扫描的时候会进行各种关系代数的运算,例如选择关系的实现,就是基于全表扫描,逐条扫描之后,假如满足选择关系,则返回;否则就继续扫描

physicalplan代表了物理计划,而物理计划包含了关系代数、更新操作、删除操作、插入操作、扫描操作的物理实现,所以physicalscan是包含在physicalplan中的。但是前面说到物理查询计划中可能最基本的操作就是读一个关系 R 的所有内容,所以说physicalscan几乎是physicalplan中的所有操作的基础。所以先从物理扫描说起。

在进行表扫描的时候,可能会有选择、连接、投影等操作的实现,但是全表扫描、带选择的扫描、带投影的扫描、带连接的扫描都会有相同的功能,比如说:带选择的扫描需要有一个setInt写到数据库里面,全表扫描也需要有一个setInt写数据库。在 C++ 中可以利用多态来实现这个功能,创建一个表扫描的父类,然后分别继承出选择、连接、投影等扫描的子类,然后使用虚函数或者函数重载实现同一函数名在不同类中的不同行为。但是 c 语言中没有类、多态的概念,因此函数指针就派上了用场。

函数指针,顾名思义,就是指向函数的指针。因此只需要在结构体中,将函数指针指向不同的函数就可以实现调用同一函数名而进行不同行为了。 例如physical_scan_project.c中的physcial_scan_project_init_scan 与physical_scan_select.c中的physical_scan_select_init_scan 对传入的physical_scan结构体中的函数指针分别进行赋值,指向了不同的函数,但是调用的时候,用的却是同一函数名(实质上是函数指针名称一样,但函数指针指向的函数不一样)。

主要函数

physical_scan physical_scan_table_create(dongmendb db, char tableName, transaction tx);

创建一个表扫描的物理计划,

void physical_scan_table_init_scan(physical_scan *scan)

初始化表扫描的物理计划

int physical_scan_table_before_first(physical_scan *scan)

在初次进行表扫描时,将读取的位置移动到第一条记录上

int physical_scan_table_next(physical_scan *scan)

获得下一条记录,如果存在,则返回1;否则返回0

int physical_scan_table_close(physical_scan *scan)

关闭表扫描的物理计划

int physical_scan_table_get_int(physical_scan scan, char tableName, char *fieldName)

从当前记录中读取一个4 bytes整数

int physical_scan_table_get_string(physical_scan scan, char tableName, char fieldName, char value)

从当前记录中读取一个字符串

int physical_scan_table_has_field(physical_scan scan, char tableName, char *fieldName)

判断当前表中是否存在fieldName字段

field_info physical_scan_table_get_field(physical_scan scan, char tableName, char fieldName)

获取当前表中fieldName的详细信息,返回一个field_info结构体

arraylist physical_scan_table_get_fields_name(physical_scan scan, char *tableName)

获取当前表中的所有字段名

int physical_scan_table_set_int(physical_scan scan, char tableName, char *fieldName, int value)

向 tableName表中的fieldName字段中写入一个 4 bytes 整数

int physical_scan_table_set_string(physical_scan scan, char tableName, char fieldName, char value)

向 tableName表中的fieldName字段中写入一个字符串

int physical_scan_table_delete(physical_scan *scan)

删除表扫描计划

int physical_scan_table_insert(physical_scan *scan)

向记录页面中添加一个页面

int physical_scan_table_get_rid(physical_scan scan, record_id recordId)

修改传入的recordId,在其中记录当前当前记录的记录页面的块,同时也记录当前记录文件的磁盘块号,返回0

int physical_scan_table_moveto_rid(physical_scan scan, record_id recordId)

将记录文件要读取的位置移动到recordId所在的磁盘块上 将记录页面要读取的位置移动到record->Id所在的页面上