Skip to content
This repository has been archived by the owner on Jan 5, 2025. It is now read-only.

Commit

Permalink
separate shadow table ddl from dml + queries
Browse files Browse the repository at this point in the history
  • Loading branch information
dgllghr committed Feb 9, 2024
1 parent f0fc136 commit 5a6eb08
Show file tree
Hide file tree
Showing 12 changed files with 390 additions and 355 deletions.
45 changes: 19 additions & 26 deletions src/BlobManager.zig
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
const std = @import("std");
const fmt = std.fmt;
const log = std.log;
const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator;

const sqlite = @import("sqlite3.zig");
const Blob = sqlite.Blob;
const Conn = sqlite.Conn;

const VtabCtxSchemaless = @import("ctx.zig").VtabCtxSchemaless;
const prep_stmt = @import("prepared_stmt.zig");
const MakeShadowTable = @import("shadow_table.zig").ShadowTable;
const VtabCtxSchemaless = @import("ctx.zig").VtabCtxSchemaless;

ctx: *const VtabCtxSchemaless,

Expand All @@ -24,13 +26,7 @@ const StmtCell = prep_stmt.Cell(VtabCtxSchemaless);

const blob_column_name = "blob";

pub fn init(
lifetime_arena: *ArenaAllocator,
tmp_arena: *ArenaAllocator,
ctx: *const VtabCtxSchemaless,
) !Self {
try setup(tmp_arena, ctx.*);

pub fn init(lifetime_arena: *ArenaAllocator, ctx: *const VtabCtxSchemaless) !Self {
const table_name = try fmt.allocPrintZ(
lifetime_arena.allocator(),
"{s}_blobs",
Expand All @@ -45,29 +41,26 @@ pub fn init(
};
}

fn setup(tmp_arena: *ArenaAllocator, ctx: VtabCtxSchemaless) !void {
const query = try fmt.allocPrintZ(tmp_arena.allocator(),
\\CREATE TABLE IF NOT EXISTS "{s}_blobs" (
\\ id INTEGER NOT NULL PRIMARY KEY,
\\ blob BLOB NOT NULL
\\)
, .{ctx.vtabName()});
try ctx.conn().exec(query);
}

pub fn deinit(self: *Self) void {
self.insert_stmt.deinit();
self.delete_stmt.deinit();
}

pub fn destroy(self: *Self, tmp_arena: *ArenaAllocator) !void {
const query = try fmt.allocPrintZ(
tmp_arena.allocator(),
\\DROP TABLE "{s}_blobs"
,
.{self.ctx.vtabName()},
);
try self.ctx.conn().exec(query);
pub const ShadowTable = MakeShadowTable(VtabCtxSchemaless, struct {
pub const suffix: []const u8 = "blobs";

pub fn createTableDdl(ctx: VtabCtxSchemaless, allocator: Allocator) ![:0]const u8 {
return fmt.allocPrintZ(allocator,
\\CREATE TABLE IF NOT EXISTS "{s}_blobs" (
\\ id INTEGER NOT NULL PRIMARY KEY,
\\ blob BLOB NOT NULL
\\)
, .{ctx.vtabName()});
}
});

pub fn table(self: Self) ShadowTable {
return .{ .ctx = self.ctx };
}

pub const Handle = struct {
Expand Down
155 changes: 73 additions & 82 deletions src/PendingInserts.zig
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ const Conn = sqlite.Conn;
const Stmt = sqlite.Stmt;
const ValueRef = sqlite.ValueRef;

const VtabCtx = @import("ctx.zig").VtabCtx;
const prep_stmt = @import("prepared_stmt.zig");
const sql_fmt = @import("sql_fmt.zig");
const MakeShadowTable = @import("shadow_table.zig").ShadowTable;
const VtabCtx = @import("ctx.zig").VtabCtx;

const schema_mod = @import("schema.zig");
const Column = schema_mod.Column;
Expand Down Expand Up @@ -41,17 +42,13 @@ const Self = @This();
const StmtCell = prep_stmt.Cell(VtabCtx);
const StmtPool = prep_stmt.Pool(VtabCtx);

pub fn create(
pub fn init(
allocator: Allocator,
tmp_arena: *ArenaAllocator,
ctx: *const VtabCtx,
table_data: *TableData,
) !Self {
const ddl_formatter = CreateTableDdlFormatter{ .ctx = ctx.* };
const ddl = try fmt.allocPrintZ(tmp_arena.allocator(), "{s}", .{ddl_formatter});
try ctx.conn().exec(ddl);

return .{
var self = Self{
.ctx = ctx,
.table_data = table_data,
.next_rowid = 1,
Expand All @@ -61,76 +58,12 @@ pub fn create(
.delete_from = StmtCell.init(&deleteFromQuery),
.delete_range = StmtCell.init(&deleteRangeQuery),
};
}

const CreateTableDdlFormatter = struct {
ctx: VtabCtx,

pub fn format(
self: @This(),
comptime _: []const u8,
_: std.fmt.FormatOptions,
writer: anytype,
) !void {
try writer.print(
\\CREATE TABLE "{s}_pendinginserts" (
\\rowid INTEGER NOT NULL,
,
.{self.ctx.vtabName()},
);
for (self.ctx.columns(), 0..) |*col, rank| {
const col_type = ColumnType.SqliteFormatter{
.column_type = col.column_type,
};
try writer.print("col_{d} {},", .{ rank, col_type });
}
try writer.print(
\\PRIMARY KEY (
, .{});
for (self.ctx.sortKey()) |col_rank| {
try writer.print("col_{d},", .{col_rank});
}
try writer.print("rowid)", .{});
try writer.print(") WITHOUT ROWID", .{});
// Initialize the rowid to the proper value if the table exists
if (try self.table().checkExists(tmp_arena)) {
try self.loadNextRowid(tmp_arena);
}
};

test "pending inserts: format create table ddl" {
const allocator = testing.allocator;
const datasets = @import("testing/datasets.zig");

const ctx = VtabCtx.init(undefined, "planets", datasets.planets.schema);

const formatter = CreateTableDdlFormatter{ .ctx = ctx };
const ddl = try fmt.allocPrintZ(allocator, "{}", .{formatter});
defer allocator.free(ddl);

const conn = try @import("sqlite3/Conn.zig").openInMemory();
defer conn.close();

conn.exec(ddl) catch |e| {
std.log.err("sqlite error: {s}", .{conn.lastErrMsg()});
return e;
};
}

pub fn open(
allocator: Allocator,
tmp_arena: *ArenaAllocator,
ctx: *const VtabCtx,
table_data: *TableData,
) !Self {
var self = Self{
.ctx = ctx,
.table_data = table_data,
.next_rowid = 0,
.insert_stmt = StmtCell.init(&insertDml),
.cursor_from_start = StmtPool.init(allocator, &cursorFromStartQuery),
.cursor_from_key = StmtPool.init(allocator, &cursorFromKeyQuery),
.delete_from = StmtCell.init(&deleteFromQuery),
.delete_range = StmtCell.init(&deleteRangeQuery),
};
try self.loadNextRowid(tmp_arena);
return self;
}

Expand All @@ -142,14 +75,72 @@ pub fn deinit(self: *Self) void {
self.delete_range.deinit();
}

pub fn drop(self: *Self, tmp_arena: *ArenaAllocator) !void {
const query = try fmt.allocPrintZ(
tmp_arena.allocator(),
\\DROP TABLE "{s}_pendinginserts"
,
.{self.ctx.vtabName()},
);
try self.ctx.conn().exec(query);
pub const ShadowTable = MakeShadowTable(VtabCtx, struct {
pub const suffix: []const u8 = "pendinginserts";

pub fn createTableDdl(ctx: VtabCtx, allocator: Allocator) ![:0]const u8 {
const ddl_formatter = CreateTableDdlFormatter{ .ctx = ctx };
return fmt.allocPrintZ(allocator, "{s}", .{ddl_formatter});
}

const CreateTableDdlFormatter = struct {
ctx: VtabCtx,

pub fn format(
self: @This(),
comptime _: []const u8,
_: std.fmt.FormatOptions,
writer: anytype,
) !void {
try writer.print(
\\CREATE TABLE "{s}_pendinginserts" (
\\rowid INTEGER NOT NULL,
,
.{self.ctx.vtabName()},
);
for (self.ctx.columns(), 0..) |*col, rank| {
const col_type = ColumnType.SqliteFormatter{
.column_type = col.column_type,
};
try writer.print("col_{d} {},", .{ rank, col_type });
}
try writer.print(
\\PRIMARY KEY (
, .{});
for (self.ctx.sortKey()) |col_rank| {
try writer.print("col_{d},", .{col_rank});
}
try writer.print("rowid)", .{});
try writer.print(") WITHOUT ROWID", .{});
}
};

test "pending inserts: format create table ddl" {
const allocator = testing.allocator;
const datasets = @import("testing/datasets.zig");

const ctx = VtabCtx.init(undefined, "planets", datasets.planets.schema);

const formatter = CreateTableDdlFormatter{ .ctx = ctx };
const ddl = try fmt.allocPrintZ(allocator, "{}", .{formatter});
defer allocator.free(ddl);

const conn = try @import("sqlite3/Conn.zig").openInMemory();
defer conn.close();

conn.exec(ddl) catch |e| {
std.log.err("sqlite error: {s}", .{conn.lastErrMsg()});
return e;
};
}
});

test {
_ = ShadowTable;
}

pub fn table(self: Self) ShadowTable {
return .{ .ctx = self.ctx };
}

pub fn insert(self: *Self, tmp_arena: *ArenaAllocator, values: anytype) !i64 {
Expand Down
Loading

0 comments on commit 5a6eb08

Please sign in to comment.