Skip to documentation
SLOP

tiny.sql.Relation

Reference tiny.sql Relation

Defined in relation.

API (23)

Actions

Public operations.

Fields and members

Public fields and members.

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

Source

Source: lib/sql/src/relation.zig:247

zig
pub const Relation = struct {    space: space_mod.Space,    table: table_mod.Table,    indexes: [max_indexes]Indexed = undefined,    index_count: usize,    pub fn open(space: *const space_mod.Space, options: Options) Error!Relation {        if (options.indexes.len > max_indexes) return error.TooManyIndexes;        var relation = Relation{            .space = space.*,            .table = try space.rowidTable(options.table_root),            .index_count = options.indexes.len,        };        for (options.indexes, 0..) |spec, offset| {            if (spec.fields.len > max_index_fields) return error.TooManyIndexFields;            relation.indexes[offset] = .{                .index = try space.index(spec.root_page, spec.columns),                .fields = spec.fields,            };        }        return relation;    }    pub fn reader(self: *const Relation, snapshot: file.Snapshot) Error!Reader {        const opened_space = try self.space.reader(snapshot);        var opened = Reader{            .space = opened_space,            .table = try opened_space.rowidTable(self.table.rows.root_page),            .index_count = self.index_count,        };        for (0..self.index_count) |offset| {            opened.indexes[offset] = .{                .index = try opened_space.index(                    self.indexes[offset].index.entries.root_page,                    self.indexes[offset].index.columns,                ),                .fields = self.indexes[offset].fields,            };        }        return opened;    }    pub fn put(self: *Relation, allocator: Allocator, rowid: i64, values: []const row.Value, options: file.CommitOptions) Error!file.Commit {        const phase = trace.scope("relation.put");        defer phase.end();        const bytes = try allocator.alloc(u8, try row.encodedSize(values));        defer allocator.free(bytes);        const encoded = try row.encode(bytes, values);        return try self.applyEdits(allocator, &.{.{ .put = .{            .rowid = rowid,            .bytes = encoded,        } }}, options);    }    pub fn putEncoded(self: *Relation, allocator: Allocator, rowid: i64, bytes: []const u8, options: file.CommitOptions) Error!file.Commit {        const phase = trace.scope("relation.put_encoded");        defer phase.end();        return try self.applyEdits(allocator, &.{.{ .put = .{            .rowid = rowid,            .bytes = bytes,        } }}, options);    }    pub fn update(self: *Relation, allocator: Allocator, rowid: i64, assignments: []const Edit.Assignment, options: file.CommitOptions) Error!file.Commit {        const phase = trace.scope("relation.update");        defer phase.end();        return try self.applyEdits(allocator, &.{.{ .update = .{            .rowid = rowid,            .assignments = assignments,        } }}, options);    }    pub fn delete(self: *Relation, allocator: Allocator, rowid: i64, options: file.CommitOptions) Error!file.Commit {        const phase = trace.scope("relation.delete");        defer phase.end();        return try self.applyEdits(allocator, &.{.{ .delete = rowid }}, options);    }    pub fn applyEdits(self: *Relation, allocator: Allocator, edits: []const Edit, options: file.CommitOptions) Error!file.Commit {        const phase = trace.scope("relation.apply_edits");        defer phase.end();        var write = try self.space.beginWrite();        defer write.deinit();        try self.applyEditsIn(allocator, &write, edits);        return try write.commit(options);    }    pub fn applyEditsIn(        self: *Relation,        allocator: Allocator,        write: *tree.Write,        edits: []const Edit,    ) Error!void {        const phase = trace.scope("relation.apply_edits_in");        defer phase.end();        try write.claimBatch(self.table.rows.root_page);        var states: std.AutoArrayHashMapUnmanaged(i64, AppliedEdit) = .empty;        defer {            for (states.values()) |*state| state.deinit(allocator);            states.deinit(allocator);        }        const base_reader = try self.reader(write.snapshot);        for (edits) |edit| {            try accumulateEdit(allocator, &base_reader, &states, edit);        }        for (states.values()) |state| try self.applyEditStateIn(write, state);    }    pub fn lastRowId(self: *const Relation) Error!?i64 {        var read = try self.space.database.beginRead();        defer read.deinit();        const opened = try self.reader(read.snapshot());        return try opened.lastRowId();    }    pub fn get(self: *const Relation, allocator: Allocator, rowid: i64) Error!?[]u8 {        var read = try self.space.database.beginRead();        defer read.deinit();        const opened = try self.reader(read.snapshot());        return try opened.get(allocator, rowid);    }    pub fn valueLength(self: *const Relation, rowid: i64) Error!?usize {        var read = try self.space.database.beginRead();        defer read.deinit();        const opened = try self.reader(read.snapshot());        return try opened.valueLength(rowid);    }    pub fn getInto(self: *const Relation, rowid: i64, target: []u8) Error!?[]u8 {        var read = try self.space.database.beginRead();        defer read.deinit();        const opened = try self.reader(read.snapshot());        return try opened.getInto(rowid, target);    }    pub fn scan(        self: *const Relation,        target: *Scan,        allocator: Allocator,        start: ?i64,        end: ?i64,    ) Error!void {        var read = try self.space.database.beginRead();        defer read.deinit();        const opened = try self.reader(read.snapshot());        try opened.scan(target, allocator, start, end);    }    pub fn scanProjected(        self: *const Relation,        target: *Scan,        allocator: Allocator,        start: ?i64,        end: ?i64,        projection: table_mod.Projection,    ) Error!void {        var read = try self.space.database.beginRead();        defer read.deinit();        const opened = try self.reader(read.snapshot());        try opened.scanProjected(target, allocator, start, end, projection);    }    pub fn lookup(        self: *const Relation,        target: *index_mod.Scan,        allocator: Allocator,        index_slot: usize,        prefix: []const row.Value,    ) Error!void {        var read = try self.space.database.beginRead();        defer read.deinit();        const opened = try self.reader(read.snapshot());        try opened.lookup(target, allocator, index_slot, prefix);    }    pub fn indexScan(        self: *const Relation,        target: *index_mod.Scan,        allocator: Allocator,        index_slot: usize,        start: ?[]const row.Value,        end: ?[]const row.Value,    ) Error!void {        var read = try self.space.database.beginRead();        defer read.deinit();        const opened = try self.reader(read.snapshot());        try opened.indexScan(target, allocator, index_slot, start, end);    }    pub fn indexRange(        self: *const Relation,        target: *index_mod.Scan,        allocator: Allocator,        index_slot: usize,        start: ?index_mod.Bound,        end: ?index_mod.Bound,    ) Error!void {        var read = try self.space.database.beginRead();        defer read.deinit();        const opened = try self.reader(read.snapshot());        try opened.indexRange(target, allocator, index_slot, start, end);    }    pub fn summarize(self: *const Relation) Error!Summary {        var read = try self.space.database.beginRead();        defer read.deinit();        const opened = try self.reader(read.snapshot());        return try opened.summarize();    }    pub fn validateIndexes(self: *const Relation, allocator: Allocator) Error!void {        const phase = trace.scope("relation.validate_indexes");        defer phase.end();        var table_scan: Scan = undefined;        try self.scan(&table_scan, allocator, null, null);        defer table_scan.deinit();        while (try table_scan.next()) |entry| {            const view = try entry.view();            var index_offset: usize = 0;            while (index_offset < self.index_count) : (index_offset += 1) {                const indexed = &self.indexes[index_offset];                var projected: [max_index_fields]row.Value = undefined;                const values = try projectView(view, indexed.fields, &projected);                if (!try indexContainsRowid(allocator, &indexed.index, values, entry.rowid)) return error.SecondaryIndexCorrupt;            }        }        var index_offset: usize = 0;        while (index_offset < self.index_count) : (index_offset += 1) {            const indexed = &self.indexes[index_offset];            var index_scan: index_mod.Scan = undefined;            try indexed.index.scan(&index_scan, allocator, null, null);            defer index_scan.deinit();            while (try index_scan.next()) |entry| {                const bytes = (try self.table.get(allocator, entry.rowid)) orelse return error.SecondaryIndexCorrupt;                defer allocator.free(bytes);                const view = try row.View.init(bytes);                var projected: [max_index_fields]row.Value = undefined;                const values = try projectView(view, indexed.fields, &projected);                var decoded_values: [max_index_fields]row.Value = undefined;                var scratch: [page.size]u8 = undefined;                const decoded = try key.decodeIndex(decoded_values[0..], scratch[0..], entry.key);                const valid = decoded.rowid == entry.rowid and valuesEqual(values, decoded.values, indexed.index.columns);                if (!valid) return error.SecondaryIndexCorrupt;            }        }    }    fn putViewIndexesIn(self: *Relation, write: *tree.Write, rowid: i64, view: row.View) Error!void {        var offset: usize = 0;        while (offset < self.index_count) : (offset += 1) {            var projected: [max_index_fields]row.Value = undefined;            const indexed = try projectView(view, self.indexes[offset].fields, &projected);            try self.indexes[offset].index.putIn(write, rowid, indexed);        }    }    fn deleteIndexesIn(self: *Relation, write: *tree.Write, rowid: i64, view: row.View) Error!void {        var offset: usize = 0;        while (offset < self.index_count) : (offset += 1) {            var projected: [max_index_fields]row.Value = undefined;            const indexed = try projectView(view, self.indexes[offset].fields, &projected);            try self.indexes[offset].index.deleteIn(write, rowid, indexed);        }    }    fn accumulateEdit(        allocator: Allocator,        base_reader: *const Reader,        states: *std.AutoArrayHashMapUnmanaged(i64, AppliedEdit),        edit: Edit,    ) Error!void {        const state = try appliedEdit(            allocator,            base_reader,            states,            editRowid(edit),        );        switch (edit) {            .put => |put_edit| {                _ = try row.View.init(put_edit.bytes);                state.current = put_edit.bytes;            },            .update => |update_edit| {                const current = state.current orelse return error.KeyNotFound;                state.adoptMerged(allocator, try applyUpdate(allocator, current, update_edit.assignments));            },            .delete => {                if (state.current == null) return error.KeyNotFound;                state.current = null;            },        }    }    fn appliedEdit(        allocator: Allocator,        base_reader: *const Reader,        states: *std.AutoArrayHashMapUnmanaged(i64, AppliedEdit),        rowid: i64,    ) Error!*AppliedEdit {        if (states.getPtr(rowid)) |state| return state;        const base = try base_reader.get(allocator, rowid);        errdefer if (base) |bytes| allocator.free(bytes);        try states.putNoClobber(allocator, rowid, .{            .rowid = rowid,            .base = base,            .current = if (base) |bytes| bytes else null,        });        return states.getPtr(rowid).?;    }    fn applyEditStateIn(self: *Relation, write: *tree.Write, state: AppliedEdit) Error!void {        if (state.base) |base| {            if (state.current) |current| {                if (std.mem.eql(u8, base, current)) return;                try self.deleteIndexesIn(write, state.rowid, try row.View.init(base));                try self.table.putEncodedIn(write, state.rowid, current);                try self.putViewIndexesIn(write, state.rowid, try row.View.init(current));            } else {                try self.deleteIndexesIn(write, state.rowid, try row.View.init(base));                try self.table.deleteIn(write, state.rowid);            }        } else if (state.current) |current| {            try self.table.putEncodedIn(write, state.rowid, current);            try self.putViewIndexesIn(write, state.rowid, try row.View.init(current));        }    }};

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

zig
pub const Relation = relation.Relation;
Called byCallsRelationdeleteRelationputRelationputEncodedRelationupdateRelationapplyEditsInRelationapplyEdits
Static calls · unresolved targets: 0 · external targets: 5.
Called byCallsRelationapplyEditsprivate sourcelib.sql.src.relation.RelationaccumulateEditprivate sourcelib.sql.src.relation.RelationapplyEditStateInRelationreadertiny.tldrformats.elf.liveness.statedeinitRelationapplyEditsIn
Static calls · unresolved targets: 0 · external targets: 5.
Called byCallsNo direct callersRelationapplyEditsRelationdelete
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callersRelationreaderRelationget
Static calls · unresolved targets: 1 · external targets: 3.
Called byCallsNo direct callersRelationreaderRelationgetInto
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callersRelationreaderRelationindexRange
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callersRelationreaderRelationindexScan
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callersRelationreaderRelationlastRowId
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callersRelationreaderRelationlookup
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callsprivate sourcelib.sql.src.catalogopenPlannedRelationtest sourcelib.sql.src.relationtest: relation applies edit batches t...test sourcelib.sql.src.relationtest: relation applies update edits w...test sourcelib.sql.src.relationtest: relation delete removes table r...test sourcelib.sql.src.relationtest: relation maintains secondary in...+8 moreRelationopen
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callersRelationapplyEditsrowencoderowencodedSizeRelationput
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callersRelationapplyEditsRelationputEncoded
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callsRelationapplyEditsInRelationgetRelationgetIntoRelationindexRangeRelationindexScan+6 moreRelationreader
Static calls · unresolved targets: 0 · external targets: 3.
Called byCallsRelationvalidateIndexesRelationreaderRelationscan
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callersRelationreaderRelationscanProjected
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callersRelationreaderRelationsummarize
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callersRelationapplyEditsRelationupdate
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callerskeydecodeIndexRelationscanprivate sourcelib.sql.src.relationindexContainsRowidprivate sourcelib.sql.src.relationprojectViewprivate sourcelib.sql.src.relationvaluesEqualRowViewinitRelationvalidateIndexes
Static calls · unresolved targets: 3 · external targets: 7.
Called byCallsNo direct callersRelationreaderRelationvalueLength
Static calls · unresolved targets: 0 · external targets: 4.

Complete caller list for Relation.open

13 direct callers.

Complete caller list for Relation.reader

11 direct callers.

Audit

Definitions20
Public names40
Members4
Version26.7.0
Revisiondaab053ee433