Giter Site home page Giter Site logo

db_tutorial's Introduction

Let's Build a Simple Database

View rendered tutorial (with more details on what this is.)

Notes to myself

Run site locally:

bundle exec jekyll serve

db_tutorial's People

Contributors

ananduri avatar cagmz avatar cstack avatar denniskovshov avatar dependabot[bot] avatar graywd avatar kodemartin avatar lpereira avatar mattmolo avatar mgalgs avatar nilesr avatar ohbarye avatar raphael0202 avatar ryanluker avatar sairoutine avatar shaqsnake avatar stardustman avatar tinyboy186 avatar whtsky avatar xnacly avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

db_tutorial's Issues

Compilation errors!

I get some errors below when I try to compile the code in "Part 3 - An In-Memory, Append-Only, Singe-Table Database".
...
db.c:38:7: error: unknown type name ‘uint32_t’
db.c:42:7: error: variably modified ‘username’ at file scope
....

This is my environment, gcc version 5.4.0 on ubuntu 16.04.2 LTS.
Could you tell me the gcc version of you ?

Thanks.

initializer element is not constant

environment: ubuntu 18.04 ,gcc version 7.3.0

I had finished the part 3, but when i compile the source code, it reports the following two type errors:

(1) variably modified ‘username’ at file scope
char username[COLUMN_USERNAME_SIZE];

(2) initializer element is not constant
const uint32_t USERNAME_OFFSET = ID_OFFSET + ID_SIZE;

I had google the problem,one question at stackoverflow say that this is because the const just means "read only" not a real constant.

I'm very interested in how can you compile the code successfully.

Can i continue this awesome project, dear cstack?

I have learned a lot from this tutorial, and i thought part 13 will complete this project.
Emm... So can i continue this project? For instance, Part 14?
If you agree, can you give me some advice?
I have translate all parts of this article in chinese on my github pages( I have said the original article is on your website).
😤😤

Part 4 regression: invalid integers parsed as 0

For the first few parts, when we're reading input to insert statements using scanf, scanf will return an error if the first field is not an integer. However in part 4 we stop using scanf and switch to strtok. To convert the ID field to an integer, we call atoi.

The problem is that if atoi is given a garbage string like "abcdef", it will just return zero, which is a valid ID. With scanf this would have correctly returned an error.

Additionally, the error messages surrounding IDs are further misleading. One of the tests we write tries to insert with an ID of negative one, and we fix the code to reject IDs that are less than zero. (if (id < 0) {). However the error message we print says "ID must be positive." This is misleading because 0 is a valid ID in the code, but 0 is not positive.

To fix this, we could replace atoi with strtol and check the endptr, and change the error message to "IDs may not be negative." However this would make the code more complex, so I wanted to ask about it in an issue before opening a pull request.

Could not get the code compiled...

  1. using TDM-GCC 9.2.0 could not get code on page 1 compiled at all.. I am using Embarcadero Dev C++. Which compiler or IDE recommended for compiling and running the code.

Could you add a license file of the source code?

Hi! Thanks to publish this interesting tutorial. I learned a lot from this tutorial.

BTW, I try to implement this database in Rust (and Python3 for testing). And I wanna publish the source codes on my github account. But the license file is not found in this repository. Could you add a license file? If you don't allow it, I close this issue and I don't publish the source codes.

Thanks.

pager_open function optimization

After implementing B-tree, each node occupies exactly one page of the table, so there is no need to test whether db file is a whole number of pages in pager_open function.

Pager* pager_open(const char* filename) {

    .............

    off_t file_length = lseek(fd, 0, SEEK_END);

    Pager* pager = malloc(sizeof(Pager));
    pager->file_descriptor = fd;
    pager->file_length = file_length;
    pager->num_pages = (file_length / PAGE_SIZE);

    // if (file_length % PAGE_SIZE != 0) {
    //     printf("Db file is not a whole number of pages. Corrupt file.\n");
    //     exit(EXIT_FAILURE);
    // }

    for (uint32_t i = 0; i < TABLE_MAX_PAGES; i++) {
        pager->pages[i] = NULL;
    }

Use ruby script to test

Hello, the test ruby script I wrote according to your article cannot run, can you tell me the solution

make failed on ubuntu

When I compile part3 branch, I got the following errors:

 make
gcc db.c -o db
db.c:32:7: error: unknown type name ‘uint32_t’
 const uint32_t COLUMN_USERNAME_SIZE = 32;
       ^
db.c:33:7: error: unknown type name ‘uint32_t’
 const uint32_t COLUMN_EMAIL_SIZE = 255;
       ^
db.c:35:3: error: unknown type name ‘uint32_t’
   uint32_t id;
   ^
db.c:36:8: error: variably modified ‘username’ at file scope
   char username[COLUMN_USERNAME_SIZE];
        ^
db.c:37:8: error: variably modified ‘email’ at file scope
   char email[COLUMN_EMAIL_SIZE];
        ^
db.c:47:7: error: unknown type name ‘uint32_t’
 const uint32_t ID_SIZE = sizeof(((Row*)0)->id);
       ^
db.c:48:7: error: unknown type name ‘uint32_t’
 const uint32_t USERNAME_SIZE = sizeof(((Row*)0)->username);
       ^
db.c:49:7: error: unknown type name ‘uint32_t’
 const uint32_t EMAIL_SIZE = sizeof(((Row*)0)->email);
       ^
db.c:50:7: error: unknown type name ‘uint32_t’
 const uint32_t ID_OFFSET = 0;
       ^
db.c:51:7: error: unknown type name ‘uint32_t’
 const uint32_t USERNAME_OFFSET = ID_OFFSET + ID_SIZE;
       ^
db.c:51:34: error: initializer element is not constant
 const uint32_t USERNAME_OFFSET = ID_OFFSET + ID_SIZE;
                                  ^
db.c:52:7: error: unknown type name ‘uint32_t’
 const uint32_t EMAIL_OFFSET = USERNAME_OFFSET + USERNAME_SIZE;
       ^
db.c:52:31: error: initializer element is not constant
 const uint32_t EMAIL_OFFSET = USERNAME_OFFSET + USERNAME_SIZE;
                               ^
db.c:53:7: error: unknown type name ‘uint32_t’
 const uint32_t ROW_SIZE = ID_SIZE + USERNAME_SIZE + EMAIL_SIZE;
       ^
db.c:53:27: error: initializer element is not constant
 const uint32_t ROW_SIZE = ID_SIZE + USERNAME_SIZE + EMAIL_SIZE;
                           ^
db.c:55:7: error: unknown type name ‘uint32_t’
 const uint32_t PAGE_SIZE = 4096;
       ^
db.c:56:7: error: unknown type name ‘uint32_t’
 const uint32_t TABLE_MAX_PAGES = 100;
       ^
db.c:57:7: error: unknown type name ‘uint32_t’
 const uint32_t ROWS_PER_PAGE = PAGE_SIZE / ROW_SIZE;
       ^
db.c:57:32: error: initializer element is not constant
 const uint32_t ROWS_PER_PAGE = PAGE_SIZE / ROW_SIZE;
                                ^
db.c:58:7: error: unknown type name ‘uint32_t’
 const uint32_t TABLE_MAX_ROWS = ROWS_PER_PAGE * TABLE_MAX_PAGES;
       ^
db.c:58:33: error: initializer element is not constant
 const uint32_t TABLE_MAX_ROWS = ROWS_PER_PAGE * TABLE_MAX_PAGES;
                                 ^
db.c:61:9: error: variably modified ‘pages’ at file scope
   void* pages[TABLE_MAX_PAGES];
         ^
db.c:62:3: error: unknown type name ‘uint32_t’
   uint32_t num_rows;
   ^
db.c:82:30: error: unknown type name ‘uint32_t’
 void* row_slot(Table* table, uint32_t row_num) {
                              ^
db.c: In function ‘execute_insert’:
db.c:161:32: warning: implicit declaration of function ‘row_slot’ [-Wimplicit-function-declaration]
   serialize_row(row_to_insert, row_slot(table, table->num_rows));
                                ^
db.c:161:32: warning: passing argument 2 of ‘serialize_row’ makes pointer from integer without a cast [-Wint-conversion]
db.c:70:6: note: expected ‘void *’ but argument is of type ‘int’
 void serialize_row(Row* source, void* destination) {
      ^
db.c: In function ‘execute_select’:
db.c:169:8: error: unknown type name ‘uint32_t’
   for (uint32_t i = 0; i < table->num_rows; i++) {
        ^
db.c:170:21: warning: passing argument 1 of ‘deserialize_row’ makes pointer from integer without a cast [-Wint-conversion]
     deserialize_row(row_slot(table, i), &row);
                     ^
db.c:76:6: note: expected ‘void *’ but argument is of type ‘int’
 void deserialize_row(void* source, Row* destination) {
      ^
Makefile:2: recipe for target 'db' failed
make: *** [db] Error 1

According to the errors, I found the uint32_t type is unknown type, we should add stdint.h header file.
The errors about variably modified ‘xxx’ at file scope can be resolved by exchanging the const variables to macro. For example:

Change the following codes

const uint32_t ID_SIZE = sizeof(((Row*)0)->id);
const uint32_t USERNAME_SIZE = sizeof(((Row*)0)->username);
const uint32_t EMAIL_SIZE = sizeof(((Row*)0)->email);
const uint32_t ID_OFFSET = 0;
const uint32_t USERNAME_OFFSET = ID_OFFSET + ID_SIZE;
const uint32_t EMAIL_OFFSET = USERNAME_OFFSET + USERNAME_SIZE;
const uint32_t ROW_SIZE = ID_SIZE + USERNAME_SIZE + EMAIL_SIZE;

to

#define ID_SIZE          sizeof(((Row*)0)->id)
#define USERNAME_SIZE    sizeof(((Row*)0)->username)
#define EMAIL_SIZE       sizeof(((Row*)0)->email)
#define ID_OFFSET        0
#define USERNAME_OFFSET  (ID_OFFSET + ID_SIZE)
#define EMAIL_OFFSET     (USERNAME_OFFSET + USERNAME_SIZE)
#define ROW_SIZE         (ID_SIZE + USERNAME_SIZE + EMAIL_SIZE)

Here is my gcc version

$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Storing code per tutorial part

what if the code is also stored per part,
so that it makes it easier to validate the correctness of program per part tutorial?

btw, thanks for the very nice tutorial 👍

translate to zh

Hello, this is a really helpful project to me especially the tutorial. I am a Chinese native speaker,so I want to translate this awesome tutorial to Chinese inorder to share to more Chinese student such as me. Should I create a new repository or new pull requests
? Thank for your advice.

Is there possibility of having overflow ?

According to the code in line uint32_t index = ( one_past_max_index+min_index ) / 2; // ?? overflow it seems possible to have an overflow because according to binary search algorithm there is possibility of having an overflow when using the formular m=(l+r)/2 instead of this formula m=l+(r-l)/2
source : https://medium.com/swlh/overflow-bug-in-binary-search-c4d4a824807a

Cursor* leaf_node_find(Table* table, uint32_t page_num, uint32_t key)
{
            // code  ....
    while (one_past_max_index != min_index) {
    uint32_t index = ( one_past_max_index+min_index ) / 2; // ??  overflow
    uint32_t key_at_index = *leaf_node_key(node, index);
    if (key == key_at_index) {
        // set the cursor to the current position before returning it 
        cursor->cell_num = index;
        return cursor;
    }
    // follow the normal binary search algorithm based
    // on where the condition fall to whether mid-1 of mid + 1
    if (key < key_at_index) { 
        one_past_max_index = index;
    } else {
        min_index = index + 1;
    }
  }
}

or what do you think ?

Pull requests about translation

@cstack Hi,
First, Thank you for your awesome work!
I've translated the article into korean. this repo
If translated version include in this project, that would be great.
Could I pull requests to this repo?

Related issues : #22, #35

  • Example of result
index part
index part

How would you create multiple tables ?

Hi,

I was wondering how you would stock, in the same file, multiple tables (with the same or different fields, it doesnt matter) ?

Any idea of an implementation ?

Bug with internal_node_key()

Hi, there! Great work! But I found a bug:

uint32_t *internal_node_key(void *node, uint32_t key_num)
{
    return internal_node_cell(node, key_num) + INTERNAL_NODE_CHILD_SIZE;
}

should be

uint32_t *internal_node_key(void *node, uint32_t key_num)
{
    return internal_node_cell(node, key_num) + INTERNAL_NODE_CHILD_SIZE/sizeof(uint32_t);
}

Otherwise, the position of max key would get a 12 bytes offset compared to Internal Node Header Layout because the internal_node_cell() returns a uint32_t pointer, which means, when we plus INTERNAL_NODE_CHILD_SIZE(4 bytes) to it, it would be 4*4 =16bytes.

a

a

Why 4 pages can search 500GB data

In actuality, we can’t store a full 4 KB of data per leaf node due to the overhead of the header, keys, and wasted space. But we can search through something like 500 GB of data by loading only 4 pages from disk. This is why the B-Tree is a useful data structure for databases.

why 4 pages can search 500GB data?

In my opinion 4 pages just can search 8M data.
4 * 512 * 4 = 8M

Do I misunderstand it?

Thanks in advance.

There need to be an entire section on pre requisites

I have reached section 4, and its already hurting my brain how many assumptions this tutorial has on the pre requisites we need.

  1. What compiler should I be using, gcc ? (I ended up g++)
  2. What ruby things should I be installing and how (bundle? gem? rspec).
  3. How should I be saving/structuring my files (in a single db.c ?)

Can I translate it into Chinese?

I think your project is very good and deserves to be understood by more people. Can I translate it into Chinese and make it know by more people?

part2.md second strncmp miss size of "select" 6

PrepareResult prepare_statement(InputBuffer* input_buffer,
Statement* statement) {
if (strncmp(input_buffer->buffer, "insert", 6) == 0) {
statement->type = STATEMENT_INSERT;
return PREPARE_SUCCESS;
}
if (strcmp(input_buffer->buffer, "select") == 0) {
statement->type = STATEMENT_SELECT;
return PREPARE_SUCCESS;
}

return PREPARE_UNRECOGNIZED_STATEMENT;
}

Test error in Part 10

Hello,

Thanks for your tutorial, it's very awesome.
However, when I practiced the part 10, I found some error about test-cases below:

image

And I also found that this sentence, "Need to implement searching an internal node.", does not exist so far.
Are there any steps the tutorial misses?

Part 5: page_num out of bounds

If page_num start from 0 to TABLE_MAX_PAGE - 1, not 1, the if statement should be this instead. Tell me if I am right or wrong.

void* get_page(Pager* pager, uint32_t page_number){
    if(page_number >= TABLE_MAX_PAGES){
        printf("Tried to fetch page number out of bounds. %d > %d\n", page_number, TABLE_MAX_PAGES);
        exit(EXIT_FAILURE);
    }

Create table statement

First of all thank you for this tutorial. Just fantastic. I have a question for you. From tutorial we directly insert the table inside the code and make insertions and more. But if i wanted to create a table through the "CREATE TABLE" command you would have some advice on how to do it?

Part 3: Too few arguments for calloc

Looks like a second argument is required for calloc. In the tutorial, we have:

Table* table = calloc(sizeof(Table));

which results in a compilation error:

main.c:96:38: error: too few arguments to function call, expected 2, have 1
  Table* table = calloc(sizeof(Table));
                 ~~~~~~              ^

I think it should be changed to:

Table* table = calloc(sizeof(Table), TABLE_MAX_PAGES * PAGE_SIZE);

Mobile Usability Issues

Report generated by Google Search Console:

Mobile Usability issues detected on https://cstack.github.io/db_tutorial/

To the owner of https://cstack.github.io/db_tutorial/:

Search Console has identified that your site is affected by 3 Mobile Usability issues:

Top Issues

The following issues were found on your site:

Text too small to read

Clickable elements too close together

Content wider than screen

We recommend that you fix these issues when possible to enable the best experience and coverage in Google Search.

serialize and deserialize in part3

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);
}

these code confused me.
memcpy(destination + USERNAME_OFFSET, &(source->username), USERNAME_SIZE);
when the input is "insert 1 csstack [email protected] " the length of Row.username is 7, but the args for memcpy copy size is USERNAME_SIZE, which is 32. Is there is some problem? The size of the given username(csstack) is smaller than the USER_SIZE. This may be copy some bytes that doesn't need. Same problem for the EMAIL_SIZE. I was blocked by these code. Could you help me? Thanks a lot.

deserialize_row the '\0' problem

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);
}

We know that the clang stirng was terminated by '\0'. Copy the entire buffer in the deserialize_row method. char username[USERNAME_SIZE] in Row is csstack, username[7] was not set '\0' explicitly. If the value of username[7] is not '\0', when execute 'select', this may be wrong.
I can't write proper code, my platform is ubuntu18.04. Is there someone can provide the code running properly on Ubuntu? Thanks a lot.

Regarding uint8_t in node header definition

Hello, I'm still a learner of the c programming language and database. The below line has uint8_t but the definitions above it are all uint32_t, I think they should use the same def, all uint8_t or all uint32_t, is there any detail here I didn't notice?

const uint8_t COMMON_NODE_HEADER_SIZE =

Fail to Compile Make (initializer element is not constant)

error: initializer element is not constant
const uint32_t USERNAME_OFFSET = ID_OFFSET + ID_SIZE;
^~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:56:31: error: initializer element is not constant
const uint32_t EMAIL_OFFSET = USERNAME_OFFSET + USERNAME_SIZE;
^~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:57:27: error: initializer element is not constant
const uint32_t ROW_SIZE = ID_SIZE + USERNAME_SIZE + EMAIL_SIZE;
^~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:93:33: error: initializer element is not constant
const uint32_t IS_ROOT_OFFSET = NODE_TYPE_SIZE;
^~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:95:40: error: initializer element is not constant
const uint32_t PARENT_POINTER_OFFSET = IS_ROOT_OFFSET + IS_ROOT_SIZE;
^~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:97:5: error: initializer element is not constant
NODE_TYPE_SIZE + IS_ROOT_SIZE + PARENT_POINTER_SIZE;
^~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:103:48: error: initializer element is not constant
const uint32_t INTERNAL_NODE_NUM_KEYS_OFFSET = COMMON_NODE_HEADER_SIZE;
^~~~~~~~~~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:106:5: error: initializer element is not constant
INTERNAL_NODE_NUM_KEYS_OFFSET + INTERNAL_NODE_NUM_KEYS_SIZE;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:107:44: error: initializer element is not constant
const uint32_t INTERNAL_NODE_HEADER_SIZE = COMMON_NODE_HEADER_SIZE +
^~~~~~~~~~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:117:5: error: initializer element is not constant
INTERNAL_NODE_CHILD_SIZE + INTERNAL_NODE_KEY_SIZE;
^~~~~~~~~~~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:125:45: error: initializer element is not constant
const uint32_t LEAF_NODE_NUM_CELLS_OFFSET = COMMON_NODE_HEADER_SIZE;
^~~~~~~~~~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:128:5: error: initializer element is not constant
LEAF_NODE_NUM_CELLS_OFFSET + LEAF_NODE_NUM_CELLS_SIZE;
^~~~~~~~~~~~~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:129:40: error: initializer element is not constant
const uint32_t LEAF_NODE_HEADER_SIZE = COMMON_NODE_HEADER_SIZE +
^~~~~~~~~~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:138:39: error: initializer element is not constant
const uint32_t LEAF_NODE_VALUE_SIZE = ROW_SIZE;
^~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:140:5: error: initializer element is not constant
LEAF_NODE_KEY_OFFSET + LEAF_NODE_KEY_SIZE;
^~~~~~~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:141:38: error: initializer element is not constant
const uint32_t LEAF_NODE_CELL_SIZE = LEAF_NODE_KEY_SIZE + LEAF_NODE_VALUE_SIZE;
^~~~~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:142:44: error: initializer element is not constant
const uint32_t LEAF_NODE_SPACE_FOR_CELLS = PAGE_SIZE - LEAF_NODE_HEADER_SIZE;
^~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:144:5: error: initializer element is not constant
LEAF_NODE_SPACE_FOR_CELLS / LEAF_NODE_CELL_SIZE;
^~~~~~~~~~~~~~~~~~~~~~~~~
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:145:46: error: initializer element is not constant
const uint32_t LEAF_NODE_RIGHT_SPLIT_COUNT = (LEAF_NODE_MAX_CELLS + 1) / 2;
^
/cygdrive/c/Users/RJ/CLionProjects/DB Minor/rj/db.c:147:5: error: initializer element is not constant
(LEAF_NODE_MAX_CELLS + 1) - LEAF_NODE_RIGHT_SPLIT_COUNT;
^
make[3]: *** [CMakeFiles/db.dir/build.make:63: CMakeFiles/db.dir/rj/db.c.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:73: CMakeFiles/db.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/db.dir/rule] Error 2
make: *** [Makefile:118: db] Error 2

Will the series continue?

Hi, I was wondering if you had any intention of finishing the series? I've followed along all the way through part 13 and found it very helpful and educational, and was hoping to finish the series but I found no steps after part 13.

Structures ending with _t

I presume you have a lot of coding experience. I don't know why but you append all the names of your structures with _t, example:

enum MetaCommandResult_t {
 META_COMMAND_SUCCESS,
 META_COMMAND_UNRECOGNIZED_COMMAND
};
typedef enum MetaCommandResult_t MetaCommandResult;

and then later redefine it.

Is there any advantage to doing this?

Unreadable website

Due to the crazy formatting on your web page, I have roughly 80% white space on each line and 20% code. So of course I have to scroll sideways to read the code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.