【SimpleDB】Part 6 - The Cursor Abstraction

陆涵畅
2023-12-01

一、概述

在这一节中,我们要增加一个“游标 Cursor”属性,为之后改造成B树做准备

游标出现场景:

  • 在表的开始创建Cursor
  • 在表的结尾创建Cursor
  • 通过指定Cursor访问数据
  • 增加一行数据时Cursor值也要增加

具体如下:

  • 删除游标指向的记录
  • 修改游标指向的记录
  • 搜索游标指向的记录

二、代码实现

数据结构定义以及初始化:

typedef struct {
  Table* table;
  uint32_t row_num;
  bool end_of_table;  // Indicates a position one past the last element
} Cursor;

表明这是table表的游标x
如果该cursor是表中的最后一个的下一个,那么end_of_table=true。
通常我们需要在这个cursor上插入新数据。

相关方法:
获取表的第一个指针和最后一个指针:

Cursor* table_start(Table* table){
    Cursor *cursor= malloc(sizeof(Cursor));
    cursor->table=table;
    cursor->row_num=0;
    cursor->end_of_table=(cursor->row_num==table->row_num);

    return cursor;
}

Cursor* table_end(Table* table){
    Cursor* cursor= malloc(sizeof (Cursor));
    cursor->table=table;
    cursor->row_num=table->row_num;
    cursor->end_of_table=true;

    return cursor;
}

通过游标插入和查找:插入需要获得table_end,查找则需要table_start
所以把execute方法改一下:

ExecuteResult execute_insert(Statement* statement,Table* table){
    Cursor *cursor= table_end(table);
    if(table->row_num>=TABLE_MAX_ROWS){
        return EXECUTE_TABLE_FULL;
    }
    Row *row=&(statement->row);
    serialize_row(row, cursor_value(cursor));
    table->row_num++;
    return EXECUTE_SUCCESS;
}
ExecuteResult execute_select_all(Statement* statement,Table* table){
    Cursor *cursor= table_start(table);
    uint32_t all_num=table->row_num;
    if(all_num<0) return EXECUTE_ERROR;
    Row row;
//    for(uint32_t i=0;i<all_num;i++){
//        deserialize_row(read_slot(table,i),&row);
//        print_row(&row);
//    }

    while(cursor->end_of_table!=true){
        deserialize_row(cursor_value(cursor),&row);
        print_row(&row);
        cursor_advance(cursor);
    }
    free(cursor);
    return EXECUTE_SUCCESS;
}

cursor_value则获取cursor->row_num地址:

void* cursor_value(Cursor* cursor){

//    int page_id=row_num/ROW_NUM_PER_PAGE;
//    void* page=table->page[page_id];
//
//   if(page==NULL){
//       //insert
//       page=malloc(PAGE_SIZE);
//       table->page[page_id]=page;
//   }
    uint32_t row_num=cursor->row_num;
    uint32_t page_num=row_num/ROW_NUM_PER_PAGE;
    void* page=get_page(cursor->table->pager,page_num);
   uint32_t row_offset=row_num%ROW_NUM_PER_PAGE;
   uint32_t offset=row_offset*ROW_SIZE;
   return offset+page;
}

相关阅读

相关文章

相关问答