diff options
| author | Lucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br> | 2025-12-05 13:48:25 +0000 |
|---|---|---|
| committer | Lucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br> | 2025-12-05 13:48:25 +0000 |
| commit | 1efc65efa0052fa138636d675aba748ecd961bfe (patch) | |
| tree | 32e5a0fdd4edabef7ac6c99592eba0ee8f9e0a9c /src/schema.zig | |
| parent | 8576d34423a784d578da1674f23f491c9443ff37 (diff) | |
| download | sqlite-zig-1efc65efa0052fa138636d675aba748ecd961bfe.tar.gz sqlite-zig-1efc65efa0052fa138636d675aba748ecd961bfe.zip | |
idk
Diffstat (limited to 'src/schema.zig')
| -rw-r--r-- | src/schema.zig | 189 |
1 files changed, 185 insertions, 4 deletions
diff --git a/src/schema.zig b/src/schema.zig index ff1b9cf..1244516 100644 --- a/src/schema.zig +++ b/src/schema.zig @@ -2,6 +2,7 @@ const std = @import("std"); const varint = @import("varint.zig"); const record = @import("record.zig"); +<<<<<<< HEAD fn getIndexRootpage(allocator: std.mem.Allocator, file: *std.fs.File, page_size: u16, table_name: []const u8, column_name: []const u8) !?u32 { var buf: [2]u8 = undefined; _ = try file.seekTo(103); @@ -486,6 +487,8 @@ fn traverseBTree(allocator: std.mem.Allocator, file: *std.fs.File, page_size: u1 } } +======= +>>>>>>> parent of cba3ef1 (codecrafters submit [skip ci]) pub fn getRootpage(allocator: std.mem.Allocator, file: *std.fs.File, page_size: u16, table_name: []const u8) !u32 { var buf: [2]u8 = undefined; _ = try file.seekTo(103); @@ -706,9 +709,73 @@ pub fn parseColumnIndex(sql: []const u8, column_name: []const u8) !usize { pub fn readTableRows(allocator: std.mem.Allocator, file: *std.fs.File, page_size: u16, rootpage: u32, column_idx: usize, stdout: anytype) !void { if (rootpage == 0) return; - // Use the multi-column function with a single column - const column_indices = [_]usize{column_idx}; - try readTableRowsMultiColumnWhere(allocator, file, page_size, rootpage, &column_indices, null, null, stdout); + const page_offset = (rootpage - 1) * @as(u64, page_size); + var page_data = try allocator.alloc(u8, page_size); + defer allocator.free(page_data); + + _ = try file.seekTo(page_offset); + _ = try file.read(page_data); + + const page_type = page_data[0]; + if (page_type != 0x0d) return; + + const num_cells = std.mem.readInt(u16, page_data[3..5], .big); + + var cell_pointers = try allocator.alloc(u16, num_cells); + defer allocator.free(cell_pointers); + + for (0..num_cells) |i| { + const offset = 8 + i * 2; + const cell_ptr_bytes = page_data[offset .. offset + 2]; + cell_pointers[i] = std.mem.readInt(u16, cell_ptr_bytes[0..2], .big); + } + + for (0..num_cells) |i| { + const cell_data = page_data[cell_pointers[i]..]; + + var parsed = varint.parse(cell_data); + var pos = parsed.len; + + parsed = varint.parse(cell_data[pos..]); + pos += parsed.len; + + const record_data = cell_data[pos..]; + parsed = varint.parse(record_data); + const header_size = parsed.value; + var header_pos = parsed.len; + + var serial_types = std.ArrayList(u64){}; + defer serial_types.deinit(allocator); + + while (header_pos < header_size) { + parsed = varint.parse(record_data[header_pos..]); + try serial_types.append(allocator, parsed.value); + header_pos += parsed.len; + } + + var body_pos: usize = header_size; + for (0..column_idx) |col| { + if (col >= serial_types.items.len) break; + const st = serial_types.items[col]; + if (st >= 13 and (st % 2) == 1) { + body_pos += (st - 13) / 2; + } else if (st >= 1 and st <= 6) { + const int_result = record.readInt(record_data[body_pos..], st); + body_pos += int_result.len; + } + } + + if (column_idx < serial_types.items.len) { + const st = serial_types.items[column_idx]; + if (st >= 13 and (st % 2) == 1) { + const str_result = record.readString(record_data[body_pos..], st); + try stdout.print("{s}\n", .{str_result.value}); + } else if (st >= 1 and st <= 6) { + const int_result = record.readInt(record_data[body_pos..], st); + try stdout.print("{}\n", .{int_result.value}); + } + } + } } pub fn readTableRowsMultiColumn(allocator: std.mem.Allocator, file: *std.fs.File, page_size: u16, rootpage: u32, column_indices: []const usize, stdout: anytype) !void { @@ -792,7 +859,121 @@ pub fn readTableRowsMultiColumn(allocator: std.mem.Allocator, file: *std.fs.File pub fn readTableRowsMultiColumnWhere(allocator: std.mem.Allocator, file: *std.fs.File, page_size: u16, rootpage: u32, column_indices: []const usize, where_column_idx: ?usize, where_value: ?[]const u8, stdout: anytype) !void { if (rootpage == 0) return; - try traverseBTree(allocator, file, page_size, rootpage, column_indices, where_column_idx, where_value, stdout); + + const page_offset = (rootpage - 1) * @as(u64, page_size); + var page_data = try allocator.alloc(u8, page_size); + defer allocator.free(page_data); + + _ = try file.seekTo(page_offset); + _ = try file.read(page_data); + + const page_type = page_data[0]; + if (page_type != 0x0d) return; + + const num_cells = std.mem.readInt(u16, page_data[3..5], .big); + + var cell_pointers = try allocator.alloc(u16, num_cells); + defer allocator.free(cell_pointers); + + for (0..num_cells) |i| { + const offset = 8 + i * 2; + const cell_ptr_bytes = page_data[offset .. offset + 2]; + cell_pointers[i] = std.mem.readInt(u16, cell_ptr_bytes[0..2], .big); + } + + for (0..num_cells) |i| { + const cell_data = page_data[cell_pointers[i]..]; + + var parsed = varint.parse(cell_data); + var pos = parsed.len; + + parsed = varint.parse(cell_data[pos..]); + pos += parsed.len; + + const record_data = cell_data[pos..]; + parsed = varint.parse(record_data); + const header_size = parsed.value; + var header_pos = parsed.len; + + var serial_types = std.ArrayList(u64){}; + defer serial_types.deinit(allocator); + + while (header_pos < header_size) { + parsed = varint.parse(record_data[header_pos..]); + try serial_types.append(allocator, parsed.value); + header_pos += parsed.len; + } + + // Check WHERE condition if present + if (where_column_idx) |where_idx| { + if (where_value) |expected_value| { + // Calculate position for WHERE column + var where_body_pos: usize = header_size; + for (0..where_idx) |col| { + if (col >= serial_types.items.len) break; + const st = serial_types.items[col]; + if (st >= 13 and (st % 2) == 1) { + where_body_pos += (st - 13) / 2; + } else if (st >= 1 and st <= 6) { + const int_result = record.readInt(record_data[where_body_pos..], st); + where_body_pos += int_result.len; + } + } + + // Read WHERE column value + var matches = false; + if (where_idx < serial_types.items.len) { + const st = serial_types.items[where_idx]; + if (st >= 13 and (st % 2) == 1) { + const str_result = record.readString(record_data[where_body_pos..], st); + matches = std.mem.eql(u8, str_result.value, expected_value); + } else if (st >= 1 and st <= 6) { + const int_result = record.readInt(record_data[where_body_pos..], st); + // Try to parse expected_value as integer + const expected_int = std.fmt.parseInt(i64, expected_value, 10) catch 0; + matches = int_result.value == expected_int; + } + } + + // Skip this row if it doesn't match + if (!matches) continue; + } + } + + // For each requested column + for (column_indices, 0..) |column_idx, col_num| { + // Calculate position for this column + var body_pos: usize = header_size; + for (0..column_idx) |col| { + if (col >= serial_types.items.len) break; + const st = serial_types.items[col]; + if (st >= 13 and (st % 2) == 1) { + body_pos += (st - 13) / 2; + } else if (st >= 1 and st <= 6) { + const int_result = record.readInt(record_data[body_pos..], st); + body_pos += int_result.len; + } + } + + // Print separator if not first column + if (col_num > 0) { + try stdout.print("|", .{}); + } + + // Read and print the column value + if (column_idx < serial_types.items.len) { + const st = serial_types.items[column_idx]; + if (st >= 13 and (st % 2) == 1) { + const str_result = record.readString(record_data[body_pos..], st); + try stdout.print("{s}", .{str_result.value}); + } else if (st >= 1 and st <= 6) { + const int_result = record.readInt(record_data[body_pos..], st); + try stdout.print("{}", .{int_result.value}); + } + } + } + try stdout.print("\n", .{}); + } } pub fn readTableRowsWithIndex(allocator: std.mem.Allocator, file: *std.fs.File, page_size: u16, table_name: []const u8, table_rootpage: u32, column_indices: []const usize, where_column: []const u8, where_value: []const u8, stdout: anytype) !void { |