Skip to documentation
SLOP

tiny.sql.BranchPage

Reference tiny.sql BranchPage

Defined in page.

API (17)

Actions

Public operations.

Fields and members

Public fields and members.

No direct callersNo direct callspageBranch
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/sql/src/page.zig:414

zig
pub const Branch = struct {    bytes: *[size]u8,    pub fn init(bytes: *[size]u8, page_id: u64) Branch {        var branch = Branch{ .bytes = bytes };        @memset(branch.bytes, 0);        @memcpy(branch.bytes[magic_offset..][0..magic.len], magic[0..]);        branch.bytes[version_offset] = format_version;        branch.bytes[kind_offset] = branch_kind;        branch.writeU16(flags_offset, 0);        branch.writeU64(id_offset, page_id);        branch.writeU64(generation_offset, 0);        branch.writeU16(lower_offset, header_size);        branch.writeU16(upper_offset, size);        branch.writeU16(cells_offset, 0);        branch.writeU16(reserved_offset, 0);        return branch;    }    pub fn load(bytes: *[size]u8) Error!Branch {        const branch = Branch{ .bytes = bytes };        try branch.validate();        return branch;    }    /// Wraps a branch image that `load` validated, without walking its cells    /// again. The image must be unchanged since that `load`.    pub fn fromValidated(bytes: *[size]u8) Branch {        std.debug.assert(bytes[kind_offset] == branch_kind);        return .{ .bytes = bytes };    }    pub fn id(self: *const Branch) u64 {        return self.readU64(id_offset);    }    pub fn generation(self: *const Branch) u64 {        return self.readU64(generation_offset);    }    pub fn cellCount(self: *const Branch) usize {        return self.readU16(cells_offset);    }    pub fn childAt(self: *const Branch, index: usize) u32 {        return self.childPayloadAt(index);    }    pub fn lowerAt(self: *const Branch, index: usize) []const u8 {        return self.keyAt(index);    }    pub fn firstLower(self: *const Branch) ?[]const u8 {        if (self.cellCount() == 0) return null;        return self.keyAt(0);    }    pub fn childIndexFor(self: *const Branch, key: []const u8) usize {        const index = self.lowerBound(key);        if (index < self.cellCount() and std.mem.eql(u8, self.keyAt(index), key)) return index;        if (index == 0) return 0;        return index - 1;    }    pub fn childFor(self: *const Branch, key: []const u8) u32 {        return self.childAt(self.childIndexFor(key));    }    pub fn put(self: *Branch, lower_key: []const u8, child: u32) Error!void {        if (child == 0) return error.InvalidPage;        const child_bytes = childBytes(child);        try checkLengths(lower_key, child_bytes[0..]);        const next_generation = try self.nextGeneration();        const index = self.lowerBound(lower_key);        if (index < self.cellCount() and std.mem.eql(u8, self.keyAt(index), lower_key)) {            const slot = self.slotAt(index);            const child_offset: usize = slot.offset + slot.key_len;            self.bytes[child_offset..][0..child_bytes.len].* = child_bytes;        } else {            try self.cells().insert(index, lower_key, child_bytes[0..]);        }        self.writeU64(generation_offset, next_generation);    }    pub fn splitPut(self: *const Branch, left: *Branch, right: *Branch, lower_key: []const u8, child: u32) Error![]const u8 {        if (child == 0) return error.InvalidPage;        const child_bytes = childBytes(child);        try checkLengths(lower_key, child_bytes[0..]);        const next_generation = try self.nextGeneration();        left.writeU64(generation_offset, next_generation);        right.writeU64(generation_offset, next_generation);        var replacement = false;        var index: usize = 0;        while (index < self.cellCount()) : (index += 1) {            if (std.mem.eql(u8, self.keyAt(index), lower_key)) replacement = true;        }        const total = self.cellCount() + if (replacement) @as(usize, 0) else 1;        const split_index = try splitIndexFor(self, lower_key, child_bytes.len, total);        var ordinal: usize = 0;        var inserted = false;        index = 0;        while (index < self.cellCount()) : (index += 1) {            const entry = self.entryAt(index);            switch (simd.order(Bytes, entry.lower, lower_key)) {                .lt => try appendSplitBranchEntry(left, right, split_index, &ordinal, entry.lower, entry.child),                .eq => {                    if (!inserted) {                        try appendSplitBranchEntry(left, right, split_index, &ordinal, lower_key, child);                        inserted = true;                    }                },                .gt => {                    if (!inserted) {                        try appendSplitBranchEntry(left, right, split_index, &ordinal, lower_key, child);                        inserted = true;                    }                    try appendSplitBranchEntry(left, right, split_index, &ordinal, entry.lower, entry.child);                },            }        }        if (!inserted) try appendSplitBranchEntry(left, right, split_index, &ordinal, lower_key, child);        return right.firstLower() orelse error.InvalidPage;    }    pub fn replace(self: *Branch, index: usize, lower_key: []const u8, child: u32) Error!void {        if (index >= self.cellCount()) return error.InvalidPage;        if (child == 0) return error.InvalidPage;        const child_bytes = childBytes(child);        try checkLengths(lower_key, child_bytes[0..]);        const next_generation = try self.nextGeneration();        var scratch: [size]u8 = undefined;        var rebuilt = Branch.init(&scratch, self.id());        rebuilt.writeU64(generation_offset, next_generation);        var cursor: usize = 0;        while (cursor < self.cellCount()) : (cursor += 1) {            if (cursor == index) {                try rebuilt.appendEntry(lower_key, child);            } else {                const entry = self.entryAt(cursor);                try rebuilt.appendEntry(entry.lower, entry.child);            }        }        self.bytes.* = scratch;    }    pub fn remove(self: *Branch, index: usize) Error!void {        if (index >= self.cellCount()) return error.InvalidPage;        const next_generation = try self.nextGeneration();        self.cells().remove(index);        self.writeU64(generation_offset, next_generation);    }    pub fn copyTo(self: *const Branch, target: *Branch) Error!void {        target.writeU64(generation_offset, self.generation());        var index: usize = 0;        while (index < self.cellCount()) : (index += 1) {            const entry = self.entryAt(index);            try target.appendEntry(entry.lower, entry.child);        }    }    fn validate(self: *const Branch) Error!void {        if (!std.mem.eql(u8, self.bytes[magic_offset..][0..magic.len], magic[0..])) return error.InvalidPage;        if (self.bytes[version_offset] != format_version) return error.InvalidPage;        if (self.bytes[kind_offset] != branch_kind) return error.InvalidPage;        if (self.readU16(flags_offset) != 0) return error.InvalidPage;        if (self.readU16(reserved_offset) != 0) return error.InvalidPage;        const count = self.cellCount();        if (count > (size - header_size) / slot_size) return error.InvalidPage;        const lower_bound = self.lower();        const upper_bound = self.upper();        if (lower_bound != header_size + count * slot_size) return error.InvalidPage;        if (upper_bound < lower_bound or upper_bound > size) return error.InvalidPage;        if (count == 0) return error.InvalidPage;        var index: usize = 0;        while (index < count) : (index += 1) {            const slot = self.slotAt(index);            const offset: usize = slot.offset;            const payload_end = offset + @as(usize, slot.key_len) + @as(usize, slot.value_len);            if (offset < upper_bound or payload_end > size) return error.InvalidPage;            if (slot.flags != 0) return error.InvalidPage;            if (slot.value_len != 4) return error.InvalidPage;            if (self.childPayloadAt(index) == 0) return error.InvalidPage;            if (index > 0 and simd.order(Bytes, self.keyAt(index - 1), self.keyAt(index)) != .lt) return error.InvalidPage;        }    }    fn appendEntry(self: *Branch, lower_key: []const u8, child: u32) Error!void {        const child_bytes = childBytes(child);        try self.cells().insert(self.cellCount(), lower_key, child_bytes[0..]);    }    fn cells(self: *Branch) Cells {        return .{ .bytes = self.bytes };    }    fn entryAt(self: *const Branch, index: usize) BranchEntry {        return .{ .lower = self.keyAt(index), .child = self.childPayloadAt(index) };    }    fn lowerBound(self: *const Branch, key: []const u8) usize {        var low: usize = 0;        var high = self.cellCount();        while (low < high) {            const mid = low + (high - low) / 2;            switch (simd.order(Bytes, self.keyAt(mid), key)) {                .lt => low = mid + 1,                .eq, .gt => high = mid,            }        }        return low;    }    fn nextGeneration(self: *const Branch) Error!u64 {        const current = self.generation();        if (current == std.math.maxInt(u64)) return error.GenerationOverflow;        return current + 1;    }    fn keyAt(self: *const Branch, index: usize) []const u8 {        const slot = self.slotAt(index);        const start: usize = slot.offset;        return self.bytes[start..][0..slot.key_len];    }    fn childPayloadAt(self: *const Branch, index: usize) u32 {        const slot = self.slotAt(index);        const start: usize = slot.offset + slot.key_len;        return std.mem.readInt(u32, self.bytes[start..][0..4], .big);    }    fn slotAt(self: *const Branch, index: usize) Slot {        const offset = header_size + index * slot_size;        return .{            .offset = self.readU16(offset),            .key_len = self.readU16(offset + 2),            .value_len = self.readU16(offset + 4),            .flags = self.readU16(offset + 6),        };    }    fn lower(self: *const Branch) usize {        return self.readU16(lower_offset);    }    fn upper(self: *const Branch) usize {        return self.readU16(upper_offset);    }    fn readU16(self: *const Branch, offset: usize) u16 {        return std.mem.readInt(u16, self.bytes[offset..][0..2], .big);    }    fn readU64(self: *const Branch, offset: usize) u64 {        return std.mem.readInt(u64, self.bytes[offset..][0..8], .big);    }    fn writeU16(self: *Branch, offset: usize, value: u16) void {        std.mem.writeInt(u16, self.bytes[offset..][0..2], value, .big);    }    fn writeU64(self: *Branch, offset: usize, value: u64) void {        std.mem.writeInt(u64, self.bytes[offset..][0..8], value, .big);    }};

Source: lib/sql/src/root.zig:57

zig
pub const BranchPage = page.Branch;
Called byCallsprivate sourcelib.sql.src.page.BranchappendEntryBranchPagechildIndexForBranchPagecopyToBranchPagefirstLowerprivate sourcelib.sql.src.page.BranchlowerBound+6 moreprivate sourcelib.sql.src.page.BranchreadU16BranchPagecellCount
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsBranchPagechildForprivate sourcelib.sql.src.page.BranchchildPayloadAtBranchPagechildAt
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.sql.src.pagetest: branch page inserts replaces ch...BranchPagechildAtBranchPagechildIndexForBranchPagechildFor
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsBranchPagechildForBranchPagecellCountprivate sourcelib.sql.src.page.BranchkeyAtprivate sourcelib.sql.src.page.BranchlowerBoundBranchPagechildIndexFor
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.sql.src.pagetest: pages copy entries into a new p...BranchPagecellCountprivate sourcelib.sql.src.page.BranchentryAtBranchPagegenerationBranchPagecopyTo
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsprivate sourcelib.sql.src.tree.TreeputRootBranchBranchPagecellCountprivate sourcelib.sql.src.page.BranchkeyAtBranchPagefirstLower
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.sql.src.tree.ScanadvanceLeafprivate sourcelib.sql.src.tree.Scandescendprivate sourcelib.sql.src.treetrustedTreePageBranchPagefromValidated
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsBranchPagecopyToprivate sourcelib.sql.src.page.BranchnextGenerationtest sourcelib.sql.src.pagetest: branch page inserts replaces ch...private sourcelib.sql.src.page.BranchreadU64BranchPagegeneration
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsBranchPagereplaceprivate sourcelib.sql.src.page.BranchreadU64BranchPageid
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsBranchPagereplacetest sourcelib.sql.src.pagetest: branch page inserts replaces ch...test sourcelib.sql.src.pagetest: branch page rejects zero child ...test sourcelib.sql.src.pagetest: branch page replacement preserv...test sourcelib.sql.src.pagetest: branch page replaces and remove...+9 moreBranchPageinit
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callstest sourcelib.sql.src.pagetest: branch page inserts replaces ch...test sourcelib.sql.src.pagetest: branch page rejects zero child ...test sourcelib.sql.src.pagetest: branch page replacement preserv...test sourcelib.sql.src.pagetest: branch page replaces and remove...test sourcelib.sql.src.pagetest: branch page split balances unev...+15 moreBranchPageload
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callersprivate sourcelib.sql.src.page.BranchkeyAtBranchPagelowerAt
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.sql.src.pagetest: branch page inserts replaces ch...test sourcelib.sql.src.pagetest: branch page rejects zero child ...test sourcelib.sql.src.pagetest: branch page replacement preserv...test sourcelib.sql.src.pagetest: branch page replaces and remove...test sourcelib.sql.src.pagetest: branch page split balances unev...+6 moreBranchPagecellCountprivate sourcelib.sql.src.page.Branchcellsprivate sourcelib.sql.src.page.BranchkeyAtprivate sourcelib.sql.src.page.BranchlowerBoundprivate sourcelib.sql.src.page.BranchnextGeneration+4 moreBranchPageput
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.sql.src.pagetest: branch page inserts replaces ch...test sourcelib.sql.src.pagetest: branch page replaces and remove...BranchPagecellCountprivate sourcelib.sql.src.page.Branchcellsprivate sourcelib.sql.src.page.BranchnextGenerationprivate sourcelib.sql.src.page.BranchwriteU64BranchPageremove
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.sql.src.pagetest: branch page replaces and remove...private sourcelib.sql.src.page.BranchappendEntryBranchPagecellCountprivate sourcelib.sql.src.page.BranchentryAtBranchPageidBranchPageinit+4 moreBranchPagereplace
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.sql.src.pagetest: branch page split balances unev...test sourcelib.sql.src.pagetest: branch page split returns the f...BranchPagecellCountprivate sourcelib.sql.src.page.BranchentryAtprivate sourcelib.sql.src.page.BranchkeyAtprivate sourcelib.sql.src.page.BranchnextGenerationprivate sourcelib.sql.src.pageappendSplitBranchEntry+3 moreBranchPagesplitPut
Static calls · unresolved targets: 0 · external targets: 4.

Complete caller list for BranchPage.cellCount

11 direct callers.

Complete caller list for BranchPage.init

14 direct callers.

Complete caller list for BranchPage.load

20 direct callers.

Complete caller list for BranchPage.put

11 direct callers.

Complete call list for BranchPage.put

9 direct calls.

Complete call list for BranchPage.replace

9 direct calls.

Complete call list for BranchPage.splitPut

8 direct calls.

Audit

Definitions17
Public names34
Members1
Version26.7.0
Revisiondaab053ee433