Adding tables

This commit is contained in:
2019-12-08 11:24:29 +00:00
parent 5430222e26
commit 0ea1bb2e3d
10 changed files with 299 additions and 32 deletions

View File

@@ -17,7 +17,7 @@ DropStmt = 'Drop Table', Identifier ;
ColumnSpecList = ColumnSpec | ColumnSpecList, ',', ColumnSpec ;
ColumnSpec = Identifier, ColumnType | Identifier, ColumnType, ColumnOption ;
ColumnType = 'String', '(', number, ')' | 'Int' | 'Integer' ;
ColumnType = 'String', '(', integer, ')' | 'Int' | 'Integer' ;
ColumnOption = 'Index' ;
FieldList = Identifier | FieldList, ',', Identifier ;
@@ -29,4 +29,4 @@ Comparison = Identifier, Comparator, Value;
Comparator = '=' | '<>';
Identifier = { letter, '_' } , { letter | digit | '_' } ;
Value = "'", string, "'" | '"', string, '"' | number ;
Value = "'", string, "'" | '"', string, '"' | integer ;

View File

@@ -7,7 +7,7 @@ add_library(SDBLib STATIC
scanner.c scanner.h
parser.c parser.h
bplus_tree.c bplus_tree.h
../lib/MurmurHash3.c ../lib/MurmurHash3.h random.c random.h)
../lib/MurmurHash3.c ../lib/MurmurHash3.h random.c random.h Table.c Table.h)
add_executable(SDB main.c)
target_link_libraries(SDB SDBLib)

View File

@@ -5,12 +5,15 @@
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "SQL.h"
#include "MurmurHash3.h"
#include "random.h"
Value *new_value() {
Value *value = malloc(sizeof(Value));
value->type = VALUE_NONE;
value->number = 0;
value->integer = 0;
value->string = NULL;
return value;
}
@@ -32,7 +35,7 @@ Comparison *new_comparison() {
void free_comparison(Comparison *comparison) {
if (comparison->value != NULL) {
free(comparison->value);
free_value(comparison->value);
}
if (comparison->identifier != NULL) {
free(comparison->identifier);
@@ -50,7 +53,7 @@ ComparisonGroup *new_comparision_group() {
void free_comparison_group(ComparisonGroup *group) {
if (group->length > 0) {
for (size_t i = 0; i < group->length; i++) {
free(group->comparisons[i]);
free_comparison(group->comparisons[i]);
}
free(group->comparisons);
group->length = 0;
@@ -131,6 +134,8 @@ void append_field_list(FieldList *list, char *field) {
ColumnSpec *new_column_spec() {
ColumnSpec *spec = malloc(sizeof(ColumnSpec));
spec->id = 0;
spec->rowOffset = 0;
spec->identifier = NULL;
spec->option = COLOPT_NONE;
spec->size = 0;
@@ -145,6 +150,17 @@ void free_column_spec(ColumnSpec *spec) {
free(spec);
}
size_t column_spec_data_size(ColumnSpec *spec) {
switch (spec->type) {
case COLTYPE_CHAR:
return (sizeof(char) * spec->size) + 1;
case COLTYPE_INT:
return sizeof(uint64_t);
default:
return 0;
}
}
ColumnSpecList *new_column_spec_list() {
ColumnSpecList *list = malloc(sizeof(ColumnSpecList));
list->length = 0;
@@ -427,8 +443,8 @@ void print_comparison_group(ComparisonGroup *group) {
void print_column_spec_list(ColumnSpecList *list) {
for (size_t i = 0; i < list->length; i++) {
ColumnSpec *spec = list->columns[i];
if (spec->type == COLTYPE_STRING) {
printf("%s STRING(%ld)", spec->identifier, spec->size);
if (spec->type == COLTYPE_CHAR) {
printf("%s CHAR(%ld)", spec->identifier, spec->size);
} else if (spec->type == COLTYPE_INT) {
printf("%s INTEGER", spec->identifier);
}
@@ -469,7 +485,7 @@ void print_value(Value *value) {
}
}
printf("'");
} else if (value->type == VALUE_NUMBER) {
printf("%ld", value->number);
} else if (value->type == VALUE_INTEGER) {
printf("%ld", value->integer);
}
}

View File

@@ -11,14 +11,14 @@
enum ValueType_t {
VALUE_NONE,
VALUE_STRING,
VALUE_NUMBER
VALUE_INTEGER
};
typedef enum ValueType_t ValueType;
struct Value_t {
ValueType type;
char *string;
int64_t number;
int64_t integer;
};
typedef struct Value_t Value;
@@ -98,12 +98,14 @@ typedef enum ColumnOption_t ColumnOption;
enum ColumnType_t {
COLTYPE_NONE,
COLTYPE_STRING,
COLTYPE_CHAR,
COLTYPE_INT
};
typedef enum ColumnType_t ColumnType;
struct ColumnSpec_t {
uint16_t id;
size_t rowOffset;
char *identifier;
ColumnType type;
size_t size;
@@ -115,6 +117,8 @@ ColumnSpec *new_column_spec();
void free_column_spec(ColumnSpec *spec);
size_t column_spec_data_size(ColumnSpec *spec);
struct ColumnSpecList_t {
ColumnSpec **columns;
size_t length;

173
src/Table.c Normal file
View File

@@ -0,0 +1,173 @@
//
// Created by sam on 07/12/2019.
//
#include <malloc.h>
#include <assert.h>
#include "Table.h"
TableIndex *new_table_index() {
TableIndex *index = malloc(sizeof(TableIndex));
index->name = NULL;
index->columnId = 0;
index->tree = NULL;
return index;
}
void free_table_index(TableIndex *index) {
if (index->name != NULL) {
free(index->name);
}
if (index->tree != NULL) {
free_bplus_tree(index->tree);
}
free(index);
}
TableIndexList *new_table_index_list() {
TableIndexList *list = malloc(sizeof(TableIndexList));
list->indexes = NULL;
list->length = 0;
return list;
}
void free_table_index_list(TableIndexList *list) {
if (list->length > 0) {
for (size_t i = 0; i < list->length; i++) {
free_table_index(list->indexes[i]);
}
free(list->indexes);
}
free(list);
}
void append_table_index_list(TableIndexList *list, TableIndex *index) {
list->length++;
list->indexes = realloc(list->indexes, sizeof(TableIndex *) * list->length);
list->indexes[list->length - 1] = index;
}
void table_index_list_remove(TableIndexList *list, TableIndex *index) {
if (list->length == 0) {
return;
}
for (size_t i = 0; i < list->length; i++) {
if (list->indexes[i] == index) {
while (i + 1 < list->length) {
list->indexes[i] = list->indexes[i + 1];
i++;
}
list->length--;
list->indexes = realloc(list->indexes, sizeof(TableIndex *) * list->length);
return;
}
}
}
TableIndex *table_index_list_get(TableIndexList *list, uint16_t columnId) {
if (list->length == 0) {
return NULL;
}
for (size_t i = 0; i < list->length; i++) {
if (list->indexes[i]->columnId == columnId) {
return list->indexes[i];
}
}
}
TableRow *new_table_row() {
TableRow *row = malloc(sizeof(TableRow));
row->rowId = 0;
row->data = NULL;
row->next = NULL;
return row;
}
void free_table_row(TableRow *row) {
if (row->data != NULL) {
free(row->data);
}
free(row);
}
Table *new_table() {
Table *table = malloc(sizeof(Table));
table->name = NULL;
table->columns = NULL;
table->columnLength = 0;
table->indexes = new_table_index_list();
table->rowCount = 0;
table->rowSize = 0;
table->rowFirst = NULL;
return table;
}
void free_table(Table *table) {
if (table->name != NULL) {
free(table->name);
}
if (table->columns != NULL) {
for (size_t i = 0; i < table->columnLength; i++) {
free_column_spec(table->columns[i]);
}
free(table->columns);
table->columnLength = 0;
}
if (table->indexes != NULL) {
free_table_index_list(table->indexes);
}
if (table->rowFirst != NULL) {
TableRow *row = table->rowFirst;
do {
TableRow *temp = row;
row = row->next;
free_table_row(temp);
} while (row == NULL);
}
free(table);
}
size_t table_determine_row_size(Table *table) {
size_t minSize = 0;
for (size_t i = 0; i < table->columnLength; i++) {
minSize += column_spec_data_size(table->columns[i]);
}
size_t rowSize = 0;
while (minSize > rowSize) rowSize += TABLE_PAGE_SIZE;
return rowSize;
}
TableRow *table_new_row(Table *table) {
TableRow *row = new_table_row();
row->data = calloc(1, table->rowSize);
if (table->rowFirst == NULL) {
table->rowFirst = row;
return row;
}
TableRow *lastRow = table->rowFirst;
while (lastRow->next != NULL) {
lastRow = lastRow->next;
}
lastRow->next = row;
return row;
}
void table_add_column(Table *table, ColumnSpec *spec) {
table->columnLength++;
table->columns = realloc(table->columns, sizeof(ColumnSpec) * table->columnLength);
table->columns[table->columnLength - 1] = spec;
table->rowSize = table_determine_row_size(table);
spec->id = table->columnLength - 1;
if (spec->id > 0) {
ColumnSpec *previousColumn = table->columns[spec->id - 1];
spec->rowOffset = previousColumn->rowOffset + column_spec_data_size(previousColumn);
} else {
spec->rowOffset = 0;
}
}
void* table_row_column_data(Table *table, TableRow *row, uint16_t columnId) {
assert(columnId < table->columnLength);
ColumnSpec *columnSpec = table->columns[columnId];
return row->data + columnSpec->rowOffset;
}

74
src/Table.h Normal file
View File

@@ -0,0 +1,74 @@
//
// Created by sam on 07/12/2019.
//
#ifndef SDB_TABLE_H
#define SDB_TABLE_H
#include "SQL.h"
#include "bplus_tree.h"
#define TABLE_PAGE_SIZE 4096
struct TableIndex_t {
char *name;
uint16_t columnId;
BPlusTree *tree;
};
typedef struct TableIndex_t TableIndex;
TableIndex *new_table_index();
void free_table_index(TableIndex *index);
struct TableIndexList_t {
TableIndex **indexes;
size_t length;
};
typedef struct TableIndexList_t TableIndexList;
TableIndexList *new_table_index_list();
void free_table_index_list(TableIndexList *list);
void append_table_index_list(TableIndexList *list, TableIndex *index);
void table_index_list_remove(TableIndexList *list, TableIndex *index);
TableIndex *table_index_list_get(TableIndexList *list, uint16_t columnId);
struct TableRow_t {
uint64_t rowId;
struct TableRow_t *next;
void *data;
};
typedef struct TableRow_t TableRow;
TableRow *new_table_row();
void free_table_row(TableRow *row);
struct Table_t {
char *name;
ColumnSpec **columns;
size_t columnLength;
TableIndexList *indexes;
size_t rowSize;
size_t rowCount;
TableRow *rowFirst;
};
typedef struct Table_t Table;
Table *new_table();
void free_table(Table *table);
void table_add_column(Table *table, ColumnSpec *spec);
size_t table_determine_row_size(Table *table);
TableRow *table_new_row(Table *table);
void* table_row_column_data(Table *table, TableRow *row, uint16_t columnId);
#endif //SDB_TABLE_H

View File

@@ -77,7 +77,7 @@ bool bplus_node_insert_kv(BPlusNode *node, BPlusKV *kv) {
return true;
}
//Find an index where we should insert
//Find an tree where we should insert
size_t i;
for (i = 0; i < node->keyCount; i++) {
if (kv->key < node->keys[i]->key) {

View File

@@ -163,8 +163,8 @@ ColumnSpecList *parser_node_convert_column_spec_list(ParserNode *node) {
append_column_spec_list(list, spec);
spec->identifier = strdup(specNode->token->valueStr);
ParserNode *colTypeNode = specNode->children[0];
if (colTypeNode->token->type == T_KW_STRING) {
spec->type = COLTYPE_STRING;
if (colTypeNode->token->type == T_KW_CHAR) {
spec->type = COLTYPE_CHAR;
spec->size = (size_t)colTypeNode->children[0]->token->valueInt;
} else if (colTypeNode->token->type == T_KW_INT) {
spec->type = COLTYPE_INT;
@@ -212,9 +212,9 @@ Value *parser_node_convert_value(ParserNode *node) {
if (node->token->type == T_STRING) {
value->type = VALUE_STRING;
value->string = strdup(node->token->valueStr);
} else if (node->token->type == T_NUMBER) {
value->type = VALUE_NUMBER;
value->number = node->token->valueInt;
} else if (node->token->type == T_INTEGER) {
value->type = VALUE_INTEGER;
value->integer = node->token->valueInt;
}
return value;
}
@@ -536,22 +536,22 @@ ParserNode *parser_parse(Parser *parser, Scanner *scanner) {
token = NULL;
append_parser_node(node, columnSpec);
NEXT_TOKEN();
if (token == NULL || (token->type != T_KW_STRING && token->type != T_KW_INT)) {
if (token == NULL || (token->type != T_KW_CHAR && token->type != T_KW_INT)) {
parser_set_error(parser, "Expected one of STRING, INT, INTEGER", token);
break;
}
if (token->type == T_KW_STRING) {
if (token->type == T_KW_CHAR) {
ParserNode *columnType = new_parser_node(NODE_COLUMN_TYPE, token);
token = NULL;
append_parser_node(columnSpec, columnType);
EXPECT(T_PAREN_OPEN);
NEXT_TOKEN();
if (token == NULL || token->type != T_NUMBER) {
parser_set_error(parser, "Expected number", token);
if (token == NULL || token->type != T_INTEGER) {
parser_set_error(parser, "Expected integer", token);
break;
}
if (token->valueInt < 1) {
parser_set_error(parser, "Expected positive number", token);
parser_set_error(parser, "Expected positive integer", token);
break;
}
append_parser_node(columnType, new_parser_node(NODE_COLUMN_TYPE_SPECIFIER, token));
@@ -599,7 +599,7 @@ ParserNode *parser_parse(Parser *parser, Scanner *scanner) {
append_parser_node(node, assignment);
EXPECT(T_COMP_EQ);
NEXT_TOKEN();
if (token == NULL || (token->type != T_STRING && token->type != T_NUMBER)) {
if (token == NULL || (token->type != T_STRING && token->type != T_INTEGER)) {
parser_set_error(parser, "Expected value", token);
break;
}
@@ -669,7 +669,7 @@ ParserNode *parser_parse(Parser *parser, Scanner *scanner) {
}
break;
case 2:
if (token->type == T_STRING || token->type == T_NUMBER) {
if (token->type == T_STRING || token->type == T_INTEGER) {
append_parser_node(node, new_parser_node(NODE_VALUE, token));
token = NULL;
node->phase = -1;
@@ -742,7 +742,7 @@ void parser_print_node_tree(ParserNode *node, size_t indent) {
case T_STRING:
printf("<%s>", node->token->valueStr);
break;
case T_NUMBER:
case T_INTEGER:
printf("<%ld>", node->token->valueInt);
break;
default:

View File

@@ -168,10 +168,10 @@ ScannerToken *scanner_next_token(Scanner *scanner, ScannerToken *token) {
else if (scanner_match(scanner, "create", true)) token->type = T_KW_CREATE;
else if (scanner_match(scanner, "table", true)) token->type = T_KW_TABLE;
else if (scanner_match(scanner, "drop", true)) token->type = T_KW_DROP;
else if (scanner_match(scanner, "string", true)) token->type = T_KW_STRING;
else if (scanner_match(scanner, "char", true)) token->type = T_KW_CHAR;
else if (scanner_match(scanner, "int", true)) token->type = T_KW_INT;
else if (scanner_match(scanner, "integer", true)) token->type = T_KW_INT;
else if (scanner_match(scanner, "index", true)) token->type = T_KW_INDEX;
else if (scanner_match(scanner, "tree", true)) token->type = T_KW_INDEX;
if (token->type != T_NONE) {
return token;
}
@@ -222,7 +222,7 @@ ScannerToken *scanner_next_token(Scanner *scanner, ScannerToken *token) {
free_scanner_token(token);
return NULL;
}
token->type = T_NUMBER;
token->type = T_INTEGER;
//convert number
token->valueInt = (int64_t) strtol(intInput, NULL, 10);
return token;

View File

@@ -12,7 +12,7 @@
#define SCANNER_TOKEN_TYPE_LIST \
X(T_NONE) \
X(T_STRING) \
X(T_NUMBER) \
X(T_INTEGER) \
X(T_IDENTIFIER) \
X(T_COMMA) \
X(T_SEMICOLON) \
@@ -32,7 +32,7 @@
X(T_KW_CREATE) \
X(T_KW_TABLE) \
X(T_KW_DROP) \
X(T_KW_STRING) \
X(T_KW_CHAR) \
X(T_KW_INT) \
X(T_KW_INDEX)