commit 5e2d14886f1c5b72be92ae655199a028d9b9cef8 Author: Sam Stevens Date: Thu May 31 21:21:20 2018 +0100 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93a40ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,83 @@ +# Created by https://www.gitignore.io/api/cmake,clion + +### CLion ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Ruby plugin and RubyMine +/.rakeTasks + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### CLion Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + +### CMake ### +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +build + + +# End of https://www.gitignore.io/api/cmake,clion + +cmake-build-debug* \ No newline at end of file diff --git a/.idea/SDB.iml b/.idea/SDB.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/SDB.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..8822db8 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..360b2c1 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..17fe73e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.10) +project(SDB C) + +set(CMAKE_C_STANDARD 11) + +add_executable(SDB src/main.c src/InputBuffer.c src/InputBuffer.h src/SQL.c src/SQL.h) \ No newline at end of file diff --git a/Language.txt b/Language.txt new file mode 100644 index 0000000..1ae9177 --- /dev/null +++ b/Language.txt @@ -0,0 +1,26 @@ +Select A, B, C From X Where A = '1' +Insert Into X Set A = '1', B = 2, C = 'C' +Update X Set A = '2' Where A = '1' +Delete From X Where A = '1' +Create Table X (A String(50) Index, B Int, C String(5)) +Drop Table X + +Statement = SelectStmt | InsertStmt | UpdateStmt | DeleteStmt | CreateStmt | DropStmt ';' ; +SelectStmt = 'Select', FieldList, 'From', Identifier, AssignmentList ; +InsertStmt = 'Insert Into', Identifier, 'Set', AssignmentList ; +UpdateStmt = 'Update', Identifier, 'Set', AssignmentList, 'Where', AssignmentList ; +DeleteStmt = 'Delete From', Identifier, 'Where', AssignmentList ; +CreateStmt = 'Create Table', Identifier, '(', ColumnSpecList, ')' ; +DropStmt = 'Drop Table', Identifier ; + +ColumnSpecList = ColumnSpec | ColumnSpecList, ',', ColumnSpec ; +ColumnSpec = Identifier, ColumnType | Identifier, ColumnType, ColumnOption ; +ColumnType = 'String(', number, ')' | 'Int' ; +ColumnOption = 'Index' ; + +FieldList = Identifier | FieldList, ',', Identifier ; +AssignmentList = Assignment | AssignmentList, ',', Assignment ; +Assignment = Identifier, '=', Value ; + +Identifier = { letter, '_' } , { letter | digit | '_' } ; +Value = "'" character ""'" | '"', character, '"' | number ; \ No newline at end of file diff --git a/src/InputBuffer.c b/src/InputBuffer.c new file mode 100644 index 0000000..34e08c7 --- /dev/null +++ b/src/InputBuffer.c @@ -0,0 +1,24 @@ +// +// Created by Sam on 15/05/2018. +// + +#include "InputBuffer.h" + +InputBuffer* input_buffer_new() { + InputBuffer* buffer = malloc(sizeof(InputBuffer)); + buffer->buffer = NULL; + buffer->bufferLength = 0; + buffer->inputLength = 0; + + return buffer; +} + +void input_buffer_free(InputBuffer* buffer) { + if (buffer->buffer != NULL) { + free(buffer->buffer); + } + buffer->buffer = NULL; + buffer->inputLength = 0; + buffer->bufferLength = 0; + free(buffer); +} \ No newline at end of file diff --git a/src/InputBuffer.h b/src/InputBuffer.h new file mode 100644 index 0000000..92567d3 --- /dev/null +++ b/src/InputBuffer.h @@ -0,0 +1,22 @@ +// +// Created by Sam on 15/05/2018. +// + +#ifndef SDB_INPUTBUFFER_H +#define SDB_INPUTBUFFER_H + +#include +#include +#include + +struct InputBuffer_t { + char* buffer; + size_t bufferLength; + ssize_t inputLength; +}; +typedef struct InputBuffer_t InputBuffer; + +InputBuffer* input_buffer_new(); +void input_buffer_free(InputBuffer* buffer); + +#endif //SDB_INPUTBUFFER_H diff --git a/src/SQL.c b/src/SQL.c new file mode 100644 index 0000000..ef2c952 --- /dev/null +++ b/src/SQL.c @@ -0,0 +1,291 @@ +// +// Created by Sam on 19/05/2018. +// + +#include +#include "SQL.h" + +T_Value *new_t_value() { + T_Value *value = malloc(sizeof(T_Value)); + value->number = 0; + value->string = NULL; + return value; +} + +void free_t_value(T_Value *value) { + if (value->string != NULL) { + free(value->string); + } + free(value); +} + +T_Assignment *new_t_assignment() { + T_Assignment *assignment = malloc(sizeof(T_Assignment)); + assignment->value = NULL; + assignment->identifier = NULL; +} + +void free_t_assignment(T_Assignment *assignment) { + if (assignment->identifier != NULL) { + free(assignment->identifier); + } + if (assignment->value != NULL) { + free(assignment->value); + } + free(assignment); +} + +T_AssignmentList *new_t_assignment_list() { + T_AssignmentList *assignmentList = malloc(sizeof(T_AssignmentList)); + assignmentList->assignments = NULL; + assignmentList->length = 0; + return assignmentList; +} + +void free_t_assignment_list(T_AssignmentList *assignmentList) { + if (assignmentList->length > 0) { + for (size_t i = 0; i < assignmentList->length; i++) { + free_t_assignment(assignmentList->assignments[i]); + } + free(assignmentList->assignments); + assignmentList->length = 0; + } + free(assignmentList); +} + +void append_t_assignment_list(T_AssignmentList *list, T_Assignment *assignment) { + list->length++; + list->assignments = realloc(list->assignments, sizeof(T_Assignment) * list->length); + list->assignments[list->length - 1] = assignment; +} + +T_FieldList *new_t_field_list() { + T_FieldList *list = malloc(sizeof(T_FieldList)); + list->length = 0; + list->fields = NULL; + return list; +} + +void free_t_field_list(T_FieldList *list) { + if (list->length > 0) { + for (size_t i = 0; i < list->length; i++) { + free(list->fields[i]); + } + free(list->fields); + list->length = 0; + list->fields = NULL; + } + free(list); +} + +void append_t_field_list(T_FieldList *list, char *field) { + list->length++; + list->fields = realloc(list->fields, sizeof(char *) * list->length); + list->fields[list->length - 1] = field; +} + +T_ColumnSpec *new_t_column_spec() { + T_ColumnSpec *spec = malloc(sizeof(T_ColumnSpec)); + spec->identifier = NULL; + spec->option = COLOPT_NONE; + spec->size = 0; + spec->type = COLTYPE_NONE; + return spec; +} + +void free_t_column_spec(T_ColumnSpec *spec) { + if (spec->identifier != NULL) { + free(spec->identifier); + } + free(spec); +} + +T_ColumnSpecList *new_t_column_spec_list() { + T_ColumnSpecList *list = malloc(sizeof(T_ColumnSpecList)); + list->length = 0; + list->columns = NULL; + return list; +} + +void free_t_column_spec_list(T_ColumnSpecList *list) { + if (list->length > 0) { + for (size_t i = 0; i < list->length; i++) { + free_t_column_spec(list->columns[i]); + } + free(list->columns); + list->columns = NULL; + list->length = 0; + } + free(list); +} + +void append_t_column_spec_list(T_ColumnSpecList *list, T_ColumnSpec *spec) { + list->length++; + list->columns = realloc(list->columns, sizeof(T_ColumnSpec) * list->length); + list->columns[list->length - 1] = spec; +} + +T_SelectStmt *new_t_select_stmt() { + T_SelectStmt *stmt = malloc(sizeof(T_SelectStmt)); + stmt->fields = NULL; + stmt->tableName = NULL; + stmt->where = NULL; + return stmt; +} + +void free_t_select_stmt(T_SelectStmt *stmt) { + if (stmt->where != NULL) { + free_t_assignment_list(stmt->where); + } + if (stmt->tableName != NULL) { + free(stmt->tableName); + } + if (stmt->fields != NULL) { + free_t_field_list(stmt->fields); + } + free(stmt); +} + +T_InsertStmt *new_t_insert_stmt() { + T_InsertStmt *stmt = malloc(sizeof(T_InsertStmt)); + stmt->tableName = NULL; + stmt->values = NULL; + return stmt; +} + +void free_t_insert_stmt(T_InsertStmt *stmt) { + if (stmt->values != NULL) { + free_t_assignment_list(stmt->values); + } + if (stmt->tableName != NULL) { + free(stmt->tableName); + } + free(stmt); +} + +T_UpdateStmt *new_t_update_stmt() { + T_UpdateStmt *stmt = malloc(sizeof(T_UpdateStmt)); + stmt->tableName = NULL; + stmt->values = NULL; + stmt->where = NULL; + return stmt; +} + +void free_t_update_stmt(T_UpdateStmt *stmt) { + if (stmt->tableName != NULL) { + free(stmt->tableName); + } + if (stmt->where != NULL) { + free_t_assignment_list(stmt->where); + } + if (stmt->values != NULL) { + free_t_assignment_list(stmt->values); + } + free(stmt); +} + +T_DeleteStmt *new_t_delete_stmt() { + T_DeleteStmt *stmt = malloc(sizeof(T_DeleteStmt)); + stmt->tableName = NULL; + stmt->where = NULL; +} + +void free_t_delete_stmt(T_DeleteStmt *stmt) { + if (stmt->tableName != NULL) { + free(stmt->tableName); + } + if (stmt->where != NULL) { + free_t_assignment_list(stmt->where); + } + free(stmt); +} + +T_CreateStmt *new_t_create_stmt() { + T_CreateStmt *spec = malloc(sizeof(T_CreateStmt)); + spec->tableName = NULL; + spec->columns = NULL; + return spec; +} + +void free_t_create_stmt(T_CreateStmt *spec) { + if (spec->tableName != NULL) { + free(spec->tableName); + } + if (spec->columns != NULL) { + free_t_column_spec_list(spec->columns); + } + free(spec); +} + +T_DropStmt *new_t_drop_stmt() { + T_DropStmt *stmt = malloc(sizeof(T_DropStmt)); + stmt->tableName = NULL; + return stmt; +} + +void free_t_drop_stmt(T_DropStmt *stmt) { + if (stmt->tableName != NULL) { + free(stmt->tableName); + } + free(stmt); +} + +T_Statement *new_t_statement() { + T_Statement *stmt = malloc(sizeof(T_Statement)); + stmt->type = STMT_NONE; + stmt->stmt = NULL; + return stmt; +} + +void free_t_statement(T_Statement *stmt) { + switch (stmt->type) { + case STMT_SELECT: + free_t_select_stmt(stmt->stmt); + break; + case STMT_INSERT: + free_t_insert_stmt(stmt->stmt); + break; + case STMT_UPDATE: + free_t_update_stmt(stmt->stmt); + break; + case STMT_DELETE: + free_t_delete_stmt(stmt->stmt); + break; + case STMT_CREATE: + free_t_create_stmt(stmt->stmt); + break; + case STMT_DROP: + free_t_drop_stmt(stmt->stmt); + break; + default: + break; + } + stmt->stmt = NULL; + stmt->type = STMT_NONE; + free(stmt); +} + +T_StatementList *new_t_statement_list() { + T_StatementList *list = malloc(sizeof(T_StatementList)); + list->length = 0; + list->statements = NULL; + return list; +} + +void free_t_statement_list(T_StatementList *list) { + if (list->length > 0) { + for (size_t i = 0; i < list->length; i++) { + free_t_statement(list->statements[i]); + } + free(list->statements); + list->statements = NULL; + list->length = 0; + } + free(list); +} + +void append_t_statement_list(T_StatementList *list, T_Statement *statement) { + list->length++; + list->statements = realloc(list->statements, sizeof(T_Statement) * list->length); + list->statements[list->length - 1] = statement; +} \ No newline at end of file diff --git a/src/SQL.h b/src/SQL.h new file mode 100644 index 0000000..2722970 --- /dev/null +++ b/src/SQL.h @@ -0,0 +1,185 @@ +// +// Created by Sam on 19/05/2018. +// + +#ifndef SDB_SQL_H +#define SDB_SQL_H + +#include + +union T_Value_t { + char *string; + int number; +}; +typedef union T_Value_t T_Value; + +T_Value *new_t_value(); + +void free_t_value(T_Value *value); + +struct T_Assignment_t { + char *identifier; + T_Value *value; +}; +typedef struct T_Assignment_t T_Assignment; + +T_Assignment *new_t_assignment(); + +void free_t_assignment(T_Assignment *assignment); + +struct T_AssignmentList_t { + T_Assignment **assignments; + size_t length; +}; +typedef struct T_AssignmentList_t T_AssignmentList; + +T_AssignmentList *new_t_assignment_list(); + +void free_t_assignment_list(T_AssignmentList *assignmentList); + +void append_t_assignment_list(T_AssignmentList *list, T_Assignment *assignment); + +struct T_FieldList_t { + char **fields; + size_t length; +}; +typedef struct T_FieldList_t T_FieldList; + +T_FieldList *new_t_field_list(); + +void free_t_field_list(T_FieldList *list); + +void append_t_field_list(T_FieldList *list, char *field); + +enum T_ColumnOption_t { + COLOPT_NONE = 0, + COLOPT_INDEX = 1 +}; +typedef enum T_ColumnOption_t T_ColumnOption; + +enum T_ColumnType_t { + COLTYPE_NONE, + COLTYPE_STRING, + COLTYPE_INT +}; +typedef enum T_ColumnType_t T_ColumnType; + +struct T_ColumnSpec_t { + char *identifier; + T_ColumnType type; + size_t size; + T_ColumnOption option; +}; +typedef struct T_ColumnSpec_t T_ColumnSpec; + +T_ColumnSpec *new_t_column_spec(); + +void free_t_column_spec(T_ColumnSpec *spec); + +struct T_ColumnSpecList_t { + T_ColumnSpec **columns; + size_t length; +}; +typedef struct T_ColumnSpecList_t T_ColumnSpecList; + +T_ColumnSpecList *new_t_column_spec_list(); + +void free_t_column_spec_list(T_ColumnSpecList *list); + +void append_t_column_spec_list(T_ColumnSpecList *list, T_ColumnSpec *spec); + +struct T_SelectStmt_t { + T_FieldList *fields; + char *tableName; + T_AssignmentList *where; +}; +typedef struct T_SelectStmt_t T_SelectStmt; + +T_SelectStmt *new_t_select_stmt(); + +void free_t_select_stmt(T_SelectStmt *stmt); + +struct T_InsertStmt_t { + char *tableName; + T_AssignmentList *values; +}; +typedef struct T_InsertStmt_t T_InsertStmt; + +T_InsertStmt *new_t_insert_stmt(); + +void free_t_insert_stmt(T_InsertStmt *stmt); + +struct T_UpdateStmt_t { + char *tableName; + T_AssignmentList *values; + T_AssignmentList *where; +}; +typedef struct T_UpdateStmt_t T_UpdateStmt; + +T_UpdateStmt *new_t_update_stmt(); + +void free_t_update_stmt(T_UpdateStmt *stmt); + +struct T_DeleteStmt_t { + char *tableName; + T_AssignmentList *where; +}; +typedef struct T_DeleteStmt_t T_DeleteStmt; + +T_DeleteStmt *new_t_delete_stmt(); + +void free_t_delete_stmt(T_DeleteStmt *stmt); + +struct T_CreateStmt_t { + char *tableName; + T_ColumnSpecList *columns; +}; +typedef struct T_CreateStmt_t T_CreateStmt; + +T_CreateStmt *new_t_create_stmt(); + +void free_t_create_stmt(T_CreateStmt *spec); + +struct T_DropStmt_t { + char *tableName; +}; +typedef struct T_DropStmt_t T_DropStmt; + +T_DropStmt *new_t_drop_stmt(); + +void free_t_drop_stmt(T_DropStmt *stmt); + +enum T_StatementType_t { + STMT_NONE = 0, + STMT_SELECT, + STMT_INSERT, + STMT_UPDATE, + STMT_DELETE, + STMT_CREATE, + STMT_DROP +}; +typedef enum T_StatementType_t T_StatementType; + +struct T_Statement_t { + T_StatementType type; + void *stmt; +}; +typedef struct T_Statement_t T_Statement; + +T_Statement *new_t_statement(); + +void free_t_statement(T_Statement *stmt); + +struct T_StatementList_t { + T_Statement **statements; + size_t length; +}; +typedef struct T_StatementList_t T_StatementList; + +T_StatementList *new_t_statement_list(); + +void free_t_statement_list(T_StatementList *list); + +void append_t_statement_list(T_StatementList *list, T_Statement *statement); + +#endif //SDB_SQL_H diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..4bd1ee8 --- /dev/null +++ b/src/main.c @@ -0,0 +1,40 @@ +#include +#include +#include + +#include "InputBuffer.h" + +void prompt() { + printf("SDB> "); +} + +void readInput(InputBuffer *buffer) { + ssize_t read = getline(&buffer->buffer, &buffer->bufferLength, stdin); + + if (read <= 0) { + printf("Failed to read input\n"); + exit(EXIT_FAILURE); + } + + //Remove newline + buffer->inputLength = read - 1; + buffer->buffer[read - 1] = 0; +} + +int main() { + InputBuffer *buffer = input_buffer_new(); + + while (true) { + prompt(); + readInput(buffer); + + if (strcmpi(buffer->buffer, ".exit") == 0) { + break; + } else { + printf("Unknown Command or Query\n"); + } + } + + input_buffer_free(buffer); + return EXIT_SUCCESS; +} \ No newline at end of file