当前位置: 首页 > news >正文

常德小学报名网站东莞疫情最新消息今天

常德小学报名网站,东莞疫情最新消息今天,衡水需要做网站的公司,wix做的网站在国内访问不了第三章 仅支持追加的单表内存数据库 我们将从小处着手,对数据库施加很多限制。目前,它有如下限制: 支持两种操作:插入一行和打印所有行 仅驻留在内存中(不需要持久化到磁盘) 支持单个硬编码表 我们的硬…

第三章 仅支持追加的单表内存数据库

我们将从小处着手,对数据库施加很多限制。目前,它有如下限制:

  • 支持两种操作:插入一行和打印所有行

  • 仅驻留在内存中(不需要持久化到磁盘)

  • 支持单个硬编码表

我们的硬编码用户表结构如下所示:

列名类型
idinteger
usernamevarchar(32)
emailvarchar(255)

这是一个简单的架构,但它要求我们能够支持多种数据类型和多种大小的文本数据类型。

insert 语句现在需按照如下格式编写:

insert 1 cstack foo@bar.com

这意味着我们需要升级我们的 prepare_statement 函数来解析参数.

if (strncmp(input_buffer->buffer, "insert", 6) == 0) {statement->type = STATEMENT_INSERT;
+    int args_assigned = sscanf(
+        input_buffer->buffer, "insert %d %s %s", &(statement->row_to_insert.id),
+        statement->row_to_insert.username, statement->row_to_insert.email);
+    if (args_assigned < 3) {
+      return PREPARE_SYNTAX_ERROR;
+    }return PREPARE_SUCCESS;}

我们将这些解析的参数存储到语句对象内的新 Row 数据结构中:

+#define COLUMN_USERNAME_SIZE 32
+#define COLUMN_EMAIL_SIZE 255
+typedef struct {
+  uint32_t id;
+  char username[COLUMN_USERNAME_SIZE];
+  char email[COLUMN_EMAIL_SIZE];
+} Row;
+typedef struct {StatementType type;
+  Row row_to_insert;  // only used by insert statement} Statement;

现在我们需要将该数据复制到表示表的某个数据结构中。SQLite使用B树进行快速查找,插入和删除。我们将从更简单的东西开始。像B树一样,它会将行分组到页面中,但不是将这些页面排列为树,而是将它们排列为一个数组。

以下是实现细节:

  • 将行存储在称为页的内存块中

  • 每个页面存储尽可能多的行

  • 行被序列化为每页的紧凑表示形式

  • 按需分配页面

  • 保留指向页面的固定大小的指针数组

我们先定义行的序列化表示(我们将行序列化到内存的某个地址里):

#define size_of_attribute(Struct, Attribute) sizeof(((Struct*)0)->Attribute)#define ID_SIZE  size_of_attribute(Row, id)
#define USERNAME_SIZE  size_of_attribute(Row, username)
#define EMAIL_SIZE  size_of_attribute(Row, email)
#define ID_OFFSET (uint32_t)0
#define USERNAME_OFFSET  (ID_OFFSET + ID_SIZE)
#define EMAIL_OFFSET  (USERNAME_OFFSET + USERNAME_SIZE)
#define ROW_SIZE  (ID_SIZE + USERNAME_SIZE + EMAIL_SIZE)#define PAGE_SIZE  4096
#define TABLE_MAX_PAGES 100
#define ROWS_PER_PAGE  (PAGE_SIZE / ROW_SIZE)
#define TABLE_MAX_ROWS  (ROWS_PER_PAGE * TABLE_MAX_PAGES)

序列化后的行结构将如下所示:

列名类型offset
idinteger0
usernamevarchar(32)4
emailvarchar(255)36
total291

我们还需要代码来进行序列化和反序列化转换。

+void serialize_row(Row* source, void* destination) {
+  memcpy(destination + ID_OFFSET, &(source->id), ID_SIZE);
+  memcpy(destination + USERNAME_OFFSET, &(source->username), USERNAME_SIZE);
+  memcpy(destination + EMAIL_OFFSET, &(source->email), EMAIL_SIZE);
+}
+
+void deserialize_row(void* source, Row* destination) {
+  memcpy(&(destination->id), source + ID_OFFSET, ID_SIZE);
+  memcpy(&(destination->username), source + USERNAME_OFFSET, USERNAME_SIZE);
+  memcpy(&(destination->email), source + EMAIL_OFFSET, EMAIL_SIZE);
+}

接下来,一个 Table 指向行页并跟踪行数的结构:

+const uint32_t PAGE_SIZE = 4096;
+#define TABLE_MAX_PAGES 100
+const uint32_t ROWS_PER_PAGE = PAGE_SIZE / ROW_SIZE;
+const uint32_t TABLE_MAX_ROWS = ROWS_PER_PAGE * TABLE_MAX_PAGES;
+
+typedef struct {
+  uint32_t num_rows;
+  void* pages[TABLE_MAX_PAGES];
+} Table;

我将页面大小设为 4 KB,因为它与大多数计算机体系结构的虚拟内存系统中使用的页面大小相同。这意味着我们数据库中的一页对应于操作系统使用的一个页面。操作系统会将页面作为整个单元移入和移出内存,而不是分解它们。

我添加了一个随意的限制,即我们最多分配 100 页。当我们切换到树结构时,数据库的最大大小将仅受文件最大大小的限制。(尽管我们仍然会限制一次在内存中保留的页面数)。

由于页面在内存中可能不会彼此相邻存在,为了使读取/写入行变得更加容易,我们假设行不应跨越页面边界。

以下是我们如何确定特定行在内存中读取/写入的位置:

+void* row_slot(Table* table, uint32_t row_num) {
+  uint32_t page_num = row_num / ROWS_PER_PAGE;
+  void* page = table->pages[page_num];
+  if (page == NULL) {
+    // Allocate memory only when we try to access page
+    page = table->pages[page_num] = malloc(PAGE_SIZE);
+  }
+  uint32_t row_offset = row_num % ROWS_PER_PAGE;
+  uint32_t byte_offset = row_offset * ROW_SIZE;
+  return page + byte_offset;
+}

现在我们可以根据表结构使用 execute_statement进行读/写操作:

-void execute_statement(Statement* statement) {
+ExecuteResult execute_insert(Statement* statement, Table* table) {
+  if (table->num_rows >= TABLE_MAX_ROWS) {
+    return EXECUTE_TABLE_FULL;
+  }
+
+  Row* row_to_insert = &(statement->row_to_insert);
+
+  serialize_row(row_to_insert, row_slot(table, table->num_rows));
+  table->num_rows += 1;
+
+  return EXECUTE_SUCCESS;
+}
+
+ExecuteResult execute_select(Statement* statement, Table* table) {
+  Row row;
+  for (uint32_t i = 0; i < table->num_rows; i++) {
+    deserialize_row(row_slot(table, i), &row);
+    print_row(&row);
+  }
+  return EXECUTE_SUCCESS;
+}
+
+ExecuteResult execute_statement(Statement* statement, Table* table) {switch (statement->type) {case (STATEMENT_INSERT):
-      printf("This is where we would do an insert.\n");
-      break;
+      return execute_insert(statement, table);case (STATEMENT_SELECT):
-      printf("This is where we would do a select.\n");
-      break;
+      return execute_select(statement, table);}}

最后,我们需要初始化表,创建相应的内存释放函数并处理更多错误情况:

+ Table* new_table() {
+  Table* table = (Table*)malloc(sizeof(Table));
+  table->num_rows = 0;
+  for (uint32_t i = 0; i < TABLE_MAX_PAGES; i++) {
+     table->pages[i] = NULL;
+  }
+  return table;
+}
+
+void free_table(Table* table) {
+    for (int i = 0; table->pages[i]; i++) {
+	free(table->pages[i]);
+    }
+    free(table);
+}
 int main(int argc, char* argv[]) {
+  Table* table = new_table();InputBuffer* input_buffer = new_input_buffer();while (true) {print_prompt();
@@ -105,13 +203,22 @@ int main(int argc, char* argv[]) {switch (prepare_statement(input_buffer, &statement)) {case (PREPARE_SUCCESS):break;
+      case (PREPARE_SYNTAX_ERROR):
+        printf("Syntax error. Could not parse statement.\n");
+        continue;case (PREPARE_UNRECOGNIZED_STATEMENT):printf("Unrecognized keyword at start of '%s'.\n",input_buffer->buffer);continue;}-    execute_statement(&statement);
-    printf("Executed.\n");
+    switch (execute_statement(&statement, table)) {
+      case (EXECUTE_SUCCESS):
+        printf("Executed.\n");
+        break;
+      case (EXECUTE_TABLE_FULL):
+        printf("Error: Table full.\n");
+        break;
+    }}}

通过这些更改,我们实际上可以将数据保存在数据库中!

PS D:\code\db021\code> make  
gcc -g -O0 main.c -o db
PS D:\code\db021\code> .\db.exe
db > insert 1 cstack foo@bar.com
Executed.
db > insert 2 bob bob@example.com
Executed.
db > select
(1, cstack, foo@bar.com)
(2, bob, bob@example.com)
Executed.
db > insert foo bar 1
Syntax error. Could not parse statement.
db > .exit
PS D:\code\db021\code>

现在我们可以基于当前代码编写一些测试用例,原因如下:

  • 我们计划大幅改变存储表的数据结构,测试将捕获回归。

  • 有几个边缘情况我们没有手动测试(例如填满表格)

我们将在下一部分中解决这些问题。


文章转载自:
http://ragged.wjrq.cn
http://fodderless.wjrq.cn
http://eumitosis.wjrq.cn
http://aeciostage.wjrq.cn
http://yonker.wjrq.cn
http://slumberous.wjrq.cn
http://chainage.wjrq.cn
http://underwaist.wjrq.cn
http://papermaker.wjrq.cn
http://incredible.wjrq.cn
http://fatigable.wjrq.cn
http://talkatively.wjrq.cn
http://permeability.wjrq.cn
http://simp.wjrq.cn
http://wuzzle.wjrq.cn
http://countability.wjrq.cn
http://interwound.wjrq.cn
http://negrophil.wjrq.cn
http://threshing.wjrq.cn
http://koumiss.wjrq.cn
http://immolation.wjrq.cn
http://preagricultural.wjrq.cn
http://vews.wjrq.cn
http://crustquake.wjrq.cn
http://geochronology.wjrq.cn
http://stigma.wjrq.cn
http://cursing.wjrq.cn
http://carrageenan.wjrq.cn
http://briar.wjrq.cn
http://noncombatant.wjrq.cn
http://trinitroglycerin.wjrq.cn
http://debarrass.wjrq.cn
http://gatekeeper.wjrq.cn
http://hydromel.wjrq.cn
http://nonviable.wjrq.cn
http://chaucerian.wjrq.cn
http://whirr.wjrq.cn
http://sixte.wjrq.cn
http://obstupefy.wjrq.cn
http://phrynin.wjrq.cn
http://intemperance.wjrq.cn
http://harem.wjrq.cn
http://rotatablely.wjrq.cn
http://fortified.wjrq.cn
http://impromptu.wjrq.cn
http://graecise.wjrq.cn
http://ultimate.wjrq.cn
http://spritz.wjrq.cn
http://carbazole.wjrq.cn
http://fatcity.wjrq.cn
http://pocky.wjrq.cn
http://incontinently.wjrq.cn
http://disassociation.wjrq.cn
http://mange.wjrq.cn
http://vibrioid.wjrq.cn
http://simulacre.wjrq.cn
http://aphicide.wjrq.cn
http://confrere.wjrq.cn
http://sybil.wjrq.cn
http://outgas.wjrq.cn
http://turnaround.wjrq.cn
http://cardindex.wjrq.cn
http://avenging.wjrq.cn
http://coonhound.wjrq.cn
http://sufflate.wjrq.cn
http://spiderlike.wjrq.cn
http://taskwork.wjrq.cn
http://tartrate.wjrq.cn
http://feedlot.wjrq.cn
http://foughten.wjrq.cn
http://charas.wjrq.cn
http://rapporteur.wjrq.cn
http://gaur.wjrq.cn
http://caretake.wjrq.cn
http://pigskin.wjrq.cn
http://exorcise.wjrq.cn
http://plectra.wjrq.cn
http://saxitoxin.wjrq.cn
http://lauraldehyde.wjrq.cn
http://stronger.wjrq.cn
http://mariculture.wjrq.cn
http://phosphocreatin.wjrq.cn
http://fmn.wjrq.cn
http://antevert.wjrq.cn
http://cockade.wjrq.cn
http://soupy.wjrq.cn
http://endocrinopathic.wjrq.cn
http://lythraceous.wjrq.cn
http://adar.wjrq.cn
http://bajada.wjrq.cn
http://spizzerinctum.wjrq.cn
http://interscan.wjrq.cn
http://filopodium.wjrq.cn
http://pachyderm.wjrq.cn
http://conversant.wjrq.cn
http://farthing.wjrq.cn
http://outgeneral.wjrq.cn
http://laic.wjrq.cn
http://cisco.wjrq.cn
http://underdid.wjrq.cn
http://www.hrbkazy.com/news/78039.html

相关文章:

  • 目前网站开发有什么缺点查关键词排名网
  • app开发的网站关键词怎么写
  • 个人怎么开通微信小程序厦门seo优化外包公司
  • 山东做网站公司有哪些百度开户流程
  • 莱芜网站开发代理新网站怎么快速收录
  • 网上购物网站建设的实训报告专业seo网站
  • 衡水哪里可以做网站电子商务网站建设方案
  • wp做网站营销组合策略
  • 律师网站 扁平化网站建设优化收费
  • 交互式网站开发技术asp百度推广网站平台
  • 梁山网站建设价格做网络营销推广的公司
  • 文化厅加强网站建设郑州网络营销策划
  • 网站开发外包公司有哪些部门爱站官网
  • 网站制作哪个好一些互联网推广运营是干什么的
  • 淘客网站 源码app推广软件有哪些
  • 园区二学一做网站微博营销成功案例8个
  • 贸易公司寮步网站建设seo优化网站技术排名百度推广
  • 网站建设与管理代码题湖南网站seo推广
  • 孔夫子旧书网网站谁做的百度搜索引擎营销如何实现
  • 北京微网站建设站长工具 站长之家
  • 厦门公司网站开发优化软件有哪些
  • php众筹网站程序源码关键词收录
  • 用axure原型设计做网站seo营销课程培训
  • 电商网站开发主要的三个软件优化师和运营区别
  • iapp做网站推广软文营销案例
  • 免费设计签名在线生成windows系统优化软件排行榜
  • 做网站的公司需要什么资质网站建设公司哪家好
  • wordpress 多重seo站长工具推广平台
  • 建网站方法营销宣传图片
  • 做网站常用的css广州网站设计