155 lines
4.7 KiB
Zig
155 lines
4.7 KiB
Zig
const std = @import("std");
|
|
const heap = std.heap;
|
|
|
|
const InputBuffer = struct { buffer: [*]u8, buffer_length: usize, input_length: usize };
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
const allocator = gpa.allocator();
|
|
|
|
const MetaCommandError = error{UNRECOGNIZED_COMMAND};
|
|
const PrepareResultError = error{ UNRECOGNIZED_STATEMENT, SYNTAX_ERROR };
|
|
|
|
const COLUMN_USERNAME_SIZE = 32;
|
|
const COLUMN_EMAIL_SIZE = 255;
|
|
|
|
const Row = struct { id: i16, username: [COLUMN_USERNAME_SIZE]u8, email: [COLUMN_EMAIL_SIZE]u8 };
|
|
|
|
var Table: [8]Row = undefined;
|
|
|
|
const StatementType = enum { INSERT, SELECT };
|
|
const Statement = struct { type: StatementType, data_to_insert: [*]anyopaque, data_inserted: usize = 0 };
|
|
|
|
pub fn new_input_buffer() !*InputBuffer {
|
|
const input_buffers = try allocator.alloc(InputBuffer, 1);
|
|
const input_buffer = &input_buffers[0];
|
|
input_buffer.buffer = undefined;
|
|
input_buffer.buffer_length = 0;
|
|
input_buffer.input_length = 0;
|
|
|
|
return input_buffer;
|
|
}
|
|
|
|
pub fn main() !void {
|
|
// DEBUG: Temporary data before insert is implemented
|
|
Table[0] = Row{ .id = 1, .username = undefined, .email = undefined };
|
|
|
|
std.mem.copyForwards(u8, &Table[0].username, "example");
|
|
std.mem.copyForwards(u8, &Table[0].email, "example@gml.com");
|
|
|
|
// END DEBUG
|
|
|
|
const input_buffer: *InputBuffer = try new_input_buffer();
|
|
// defer std.heap.page_allocator.free(input_buffer);
|
|
|
|
const stdout_file = std.io.getStdOut().writer();
|
|
var bw = std.io.bufferedWriter(stdout_file);
|
|
const stdout = bw.writer();
|
|
_ = stdout; // autofix
|
|
|
|
while (true) {
|
|
print_prompt();
|
|
try read_input(input_buffer);
|
|
|
|
const command = input_buffer.buffer[0 .. input_buffer.buffer_length - 1];
|
|
|
|
if (input_buffer.buffer[0] == '.') {
|
|
do_meta_command(command) catch |err| {
|
|
switch (err) {
|
|
MetaCommandError.UNRECOGNIZED_COMMAND => {
|
|
std.debug.print("Unrecognized command {s}\n", .{input_buffer.buffer[0 .. input_buffer.buffer_length - 1]});
|
|
continue;
|
|
},
|
|
}
|
|
};
|
|
}
|
|
|
|
var statement: Statement = (try allocator.alloc(Statement, 1))[0];
|
|
|
|
prepare_statement(input_buffer.*, &statement) catch |err| {
|
|
switch (err) {
|
|
PrepareResultError.UNRECOGNIZED_STATEMENT => {
|
|
std.debug.print("Unrecognized keyword at start of {s}\n", .{command});
|
|
continue;
|
|
},
|
|
PrepareResultError.SYNTAX_ERROR => {
|
|
std.debug.print("Unrecognized syntax near {s}\n", .{command});
|
|
continue;
|
|
},
|
|
}
|
|
};
|
|
|
|
execute_statement(&statement);
|
|
}
|
|
}
|
|
|
|
pub fn print_prompt() void {
|
|
std.debug.print("db > ", .{});
|
|
}
|
|
|
|
pub fn read_input(input_buffer: *InputBuffer) !void {
|
|
const stdin = std.io.getStdIn().reader();
|
|
const tempInput = try allocator.alloc(u8, 256);
|
|
|
|
if (stdin.read(tempInput)) |input_size| {
|
|
input_buffer.buffer_length = input_size;
|
|
input_buffer.buffer = tempInput.ptr;
|
|
|
|
input_buffer.input_length = input_buffer.buffer_length - 1;
|
|
input_buffer.buffer[input_buffer.buffer_length - 1] = 0;
|
|
} else |err| {
|
|
return err;
|
|
}
|
|
}
|
|
|
|
pub fn close_input_buffer(input_buffer: *InputBuffer) void {
|
|
allocator.free(input_buffer);
|
|
}
|
|
|
|
pub fn do_meta_command(command: []u8) MetaCommandError!void {
|
|
if (std.mem.eql(u8, command, ".exit")) {
|
|
std.os.exit(0);
|
|
return;
|
|
} else {
|
|
return MetaCommandError.UNRECOGNIZED_COMMAND;
|
|
}
|
|
}
|
|
|
|
pub fn prepare_statement(input_buffer: InputBuffer, statement: *Statement) PrepareResultError!void {
|
|
if (std.mem.eql(u8, input_buffer.buffer[0..6], "insert")) {
|
|
statement.type = StatementType.INSERT;
|
|
|
|
var data = std.mem.split(u8, input_buffer.buffer[7 .. input_buffer.buffer_length - 1], " ");
|
|
|
|
while (data.next()) |field| {
|
|
statement.data_to_insert[statement.data_inserted] = &field;
|
|
statement.data_inserted += 1;
|
|
}
|
|
|
|
return;
|
|
}
|
|
if (std.mem.eql(u8, input_buffer.buffer[0..6], "select")) {
|
|
statement.type = StatementType.SELECT;
|
|
return;
|
|
}
|
|
|
|
return PrepareResultError.UNRECOGNIZED_STATEMENT;
|
|
}
|
|
|
|
pub fn execute_statement(statement: *Statement) void {
|
|
switch (statement.type) {
|
|
StatementType.INSERT => {},
|
|
StatementType.SELECT => {
|
|
select_all();
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn select_all() void {
|
|
std.debug.print("id | username | email\n", .{});
|
|
for (Table) |rowItem| {
|
|
if (rowItem.id == 0) return;
|
|
std.debug.print("{} {s} {s}\n", .{ rowItem.id, rowItem.username[0..], rowItem.email[0..] });
|
|
}
|
|
}
|
|
|
|
pub fn insert() !void {}
|