// // Created by Sam on 19/05/2018. // #include #include #include #include #include "SQL.h" #include "MurmurHash3.h" #include "random.h" Value *new_value() { Value *value = malloc(sizeof(Value)); value->type = VALUE_NONE; value->integer = 0; value->string = NULL; return value; } void free_value(Value *value) { if (value->string != NULL) { free(value->string); } free(value); } Comparison *new_comparison() { Comparison *comparison = malloc(sizeof(Comparison)); comparison->identifier = NULL; comparison->value = NULL; comparison->comp = COMP_NONE; return comparison; } void free_comparison(Comparison *comparison) { if (comparison->value != NULL) { free_value(comparison->value); } if (comparison->identifier != NULL) { free(comparison->identifier); } free(comparison); } ComparisonGroup *new_comparision_group() { ComparisonGroup *group = malloc(sizeof(ComparisonGroup)); group->comparisons = NULL; group->length = 0; return group; } void free_comparison_group(ComparisonGroup *group) { if (group->length > 0) { for (size_t i = 0; i < group->length; i++) { free_comparison(group->comparisons[i]); } free(group->comparisons); group->length = 0; } free(group); } void append_comparison_group(ComparisonGroup *group, Comparison *comparison) { group->length++; group->comparisons = realloc(group->comparisons, sizeof(Assignment *) * group->length); group->comparisons[group->length - 1] = comparison; } Assignment *new_assignment() { Assignment *assignment = malloc(sizeof(Assignment)); assignment->value = NULL; assignment->identifier = NULL; } void free_assignment(Assignment *assignment) { if (assignment->identifier != NULL) { free(assignment->identifier); } if (assignment->value != NULL) { free(assignment->value); } free(assignment); } AssignmentList *new_assignment_list() { AssignmentList *assignmentList = malloc(sizeof(AssignmentList)); assignmentList->assignments = NULL; assignmentList->length = 0; return assignmentList; } void free_assignment_list(AssignmentList *assignmentList) { if (assignmentList->length > 0) { for (size_t i = 0; i < assignmentList->length; i++) { free_assignment(assignmentList->assignments[i]); } free(assignmentList->assignments); assignmentList->length = 0; } free(assignmentList); } void append_assignment_list(AssignmentList *list, Assignment *assignment) { list->length++; list->assignments = realloc(list->assignments, sizeof(Assignment *) * list->length); list->assignments[list->length - 1] = assignment; } FieldList *new_field_list() { FieldList *list = malloc(sizeof(FieldList)); list->length = 0; list->fields = NULL; return list; } void free_field_list(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_field_list(FieldList *list, char *field) { list->length++; list->fields = realloc(list->fields, sizeof(char *) * list->length); list->fields[list->length - 1] = 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; spec->type = COLTYPE_NONE; return spec; } void free_column_spec(ColumnSpec *spec) { if (spec->identifier != NULL) { free(spec->identifier); } 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; list->columns = NULL; return list; } void free_column_spec_list(ColumnSpecList *list) { if (list->length > 0) { for (size_t i = 0; i < list->length; i++) { free_column_spec(list->columns[i]); } free(list->columns); list->columns = NULL; list->length = 0; } free(list); } void append_column_spec_list(ColumnSpecList *list, ColumnSpec *spec) { list->length++; list->columns = realloc(list->columns, sizeof(ColumnSpec *) * list->length); list->columns[list->length - 1] = spec; } SelectStmt *new_select_stmt() { SelectStmt *stmt = malloc(sizeof(SelectStmt)); stmt->fields = NULL; stmt->tableName = NULL; stmt->where = NULL; return stmt; } void free_select_stmt(SelectStmt *stmt) { if (stmt->where != NULL) { free_comparison_group(stmt->where); } if (stmt->tableName != NULL) { free(stmt->tableName); } if (stmt->fields != NULL) { free_field_list(stmt->fields); } free(stmt); } InsertStmt *new_insert_stmt() { InsertStmt *stmt = malloc(sizeof(InsertStmt)); stmt->tableName = NULL; stmt->values = NULL; return stmt; } void free_insert_stmt(InsertStmt *stmt) { if (stmt->values != NULL) { free_assignment_list(stmt->values); } if (stmt->tableName != NULL) { free(stmt->tableName); } free(stmt); } UpdateStmt *new_update_stmt() { UpdateStmt *stmt = malloc(sizeof(UpdateStmt)); stmt->tableName = NULL; stmt->values = NULL; stmt->where = NULL; return stmt; } void free_update_stmt(UpdateStmt *stmt) { if (stmt->tableName != NULL) { free(stmt->tableName); } if (stmt->where != NULL) { free_comparison_group(stmt->where); } if (stmt->values != NULL) { free_assignment_list(stmt->values); } free(stmt); } DeleteStmt *new_delete_stmt() { DeleteStmt *stmt = malloc(sizeof(DeleteStmt)); stmt->tableName = NULL; stmt->where = NULL; } void free_delete_stmt(DeleteStmt *stmt) { if (stmt->tableName != NULL) { free(stmt->tableName); } if (stmt->where != NULL) { free_comparison_group(stmt->where); } free(stmt); } CreateStmt *new_create_stmt() { CreateStmt *spec = malloc(sizeof(CreateStmt)); spec->tableName = NULL; spec->columns = NULL; return spec; } void free_create_stmt(CreateStmt *spec) { if (spec->tableName != NULL) { free(spec->tableName); } if (spec->columns != NULL) { free_column_spec_list(spec->columns); } free(spec); } DropStmt *new_drop_stmt() { DropStmt *stmt = malloc(sizeof(DropStmt)); stmt->tableName = NULL; return stmt; } void free_drop_stmt(DropStmt *stmt) { if (stmt->tableName != NULL) { free(stmt->tableName); } free(stmt); } Statement *new_statement(StatementType type, void *statement) { Statement *stmt = malloc(sizeof(Statement)); stmt->type = type; stmt->stmt = statement; return stmt; } void free_statement(Statement *stmt) { switch (stmt->type) { case STMT_SELECT: free_select_stmt(stmt->stmt); break; case STMT_INSERT: free_insert_stmt(stmt->stmt); break; case STMT_UPDATE: free_update_stmt(stmt->stmt); break; case STMT_DELETE: free_delete_stmt(stmt->stmt); break; case STMT_CREATE: free_create_stmt(stmt->stmt); break; case STMT_DROP: free_drop_stmt(stmt->stmt); break; default: break; } stmt->stmt = NULL; stmt->type = STMT_NONE; free(stmt); } StatementList *new_statement_list() { StatementList *list = malloc(sizeof(StatementList)); list->length = 0; list->statements = NULL; return list; } void free_statement_list(StatementList *list) { if (list->length > 0) { for (size_t i = 0; i < list->length; i++) { free_statement(list->statements[i]); } free(list->statements); list->statements = NULL; list->length = 0; } free(list); } void append_statement_list(StatementList *list, Statement *statement) { list->length++; list->statements = realloc(list->statements, sizeof(Statement *) * list->length); list->statements[list->length - 1] = statement; } void print_statement_list(StatementList *list) { for (size_t i = 0; i < list->length; i++) { Statement *stmt = list->statements[i]; switch (stmt->type) { case STMT_SELECT: { SelectStmt *select = stmt->stmt; printf("SELECT "); print_field_list(select->fields); printf(" FROM %s", select->tableName); if (select->where->length > 0) { printf(" WHERE "); print_comparison_group(select->where); } } break; case STMT_INSERT: { InsertStmt *insert = stmt->stmt; printf("INSERT INTO %s SET ", insert->tableName); print_assignment_list(insert->values); } break; case STMT_UPDATE: { UpdateStmt *update = stmt->stmt; printf("UPDATE %s SET ", update->tableName); print_assignment_list(update->values); if (update->where->length > 0) { printf(" WHERE "); print_comparison_group(update->where); } } break; case STMT_DELETE: { DeleteStmt *delete = stmt->stmt; printf("DELETE FROM %s", delete->tableName); if (delete->where->length > 0) { printf(" "); print_comparison_group(delete->where); } } break; case STMT_CREATE: { CreateStmt *create = stmt->stmt; printf("CREATE TABLE %s (", create->tableName); print_column_spec_list(create->columns); printf(")"); } break; case STMT_DROP: { DropStmt *drop = stmt->stmt; printf("DELETE TABLE %s", drop->tableName); } break; default: break; } printf(";\n"); } } void print_field_list(FieldList *list) { for (size_t i = 0; i < list->length; i++) { printf("%s%s", list->fields[i], i + 1 < list->length ? ", " : ""); } } void print_assignment_list(AssignmentList *list) { for (size_t i = 0; i < list->length; i++) { Assignment *assignment = list->assignments[i]; printf("%s=", assignment->identifier); print_value(assignment->value); if (i + 1 < list->length) { printf(", "); } } } void print_comparison_group(ComparisonGroup *group) { for (size_t i = 0; i < group->length; i++) { Comparison *comparison = group->comparisons[i]; printf("%s=", comparison->identifier); print_value(comparison->value); if (i + 1 < group->length) { printf(" AND "); } } } 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_CHAR) { printf("%s CHAR(%ld)", spec->identifier, spec->size); } else if (spec->type == COLTYPE_INT) { printf("%s INTEGER", spec->identifier); } if (spec->option == COLOPT_INDEX) { printf(" INDEX"); } if (i + 1 < list->length) { printf(", "); } } } void print_value(Value *value) { if (value->type == VALUE_STRING) { printf("'"); size_t len = strlen(value->string); for (size_t i = 0; i < len; i++) { char next = value->string[i]; switch (next) { case '\'': printf("\\'"); break; case '\n': printf("\\n"); break; case '\r': printf("\\r"); break; case '\t': printf("\\t"); break; case '\\': printf("\\\\"); break; default: printf("%c", next); break; } } printf("'"); } else if (value->type == VALUE_INTEGER) { printf("%ld", value->integer); } }