feat: add openTemp to expr

This commit is contained in:
dualfroz committed 2026-09-04 11:23:34 +02:00
1 parent d06bc9de07
commit 73c82254f9
1 file changed
+87
+87
View File
@@ -478,3 +478,90 @@ test "in and between reject malformed input" {
try std.testing.expectError(error.InvalidValue, parse(allocator, "age between i:1 and i:notanumber")); try std.testing.expectError(error.InvalidValue, parse(allocator, "age between i:1 and i:notanumber"));
} }
fn openTemp(tmp: *std.testing.TmpDir, allocator: Allocator) !dbmod.Db {
const dbPath = try tmp.dir.realpathAlloc(allocator, ".");
defer allocator.free(dbPath);
return dbmod.Db.open(allocator, dbPath, .{});
}
test "a single-value in reaches Table.select through an index like eq does" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
var db = try openTemp(&tmp, allocator);
defer db.close();
var table = try querymod.Table.open(&db, allocator, "cities");
defer table.deinit();
try table.createIndex("city");
try table.put(.{ .int = 1 }, &.{.{ .name = "city", .value = .{ .text = "oslo" } }});
try table.put(.{ .int = 2 }, &.{.{ .name = "city", .value = .{ .text = "bergen" } }});
var parsed = try parse(allocator, "city in (s:oslo)");
defer parsed.deinit();
var plan = try table.explain(allocator, parsed.predicate);
defer plan.deinit(allocator);
try std.testing.expectEqual(querymod.PlanKind.index_eq, plan.kind);
try std.testing.expectEqualStrings("city", plan.indexName.?);
const results = try table.select(parsed.predicate);
defer querymod.freeRows(allocator, results);
try std.testing.expectEqual(@as(usize, 1), results.len);
try std.testing.expectEqual(@as(i64, 1), results[0].get(querymod.pkField).?.int);
}
test "a multi-value in falls back to a full scan and still matches every listed value" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
var db = try openTemp(&tmp, allocator);
defer db.close();
var table = try querymod.Table.open(&db, allocator, "cities");
defer table.deinit();
try table.createIndex("city");
try table.put(.{ .int = 1 }, &.{.{ .name = "city", .value = .{ .text = "oslo" } }});
try table.put(.{ .int = 2 }, &.{.{ .name = "city", .value = .{ .text = "bergen" } }});
try table.put(.{ .int = 3 }, &.{.{ .name = "city", .value = .{ .text = "trondheim" } }});
var parsed = try parse(allocator, "city in (s:oslo s:trondheim)");
defer parsed.deinit();
var plan = try table.explain(allocator, parsed.predicate);
defer plan.deinit(allocator);
try std.testing.expectEqual(querymod.PlanKind.full_scan, plan.kind);
const results = try table.select(parsed.predicate);
defer querymod.freeRows(allocator, results);
try std.testing.expectEqual(@as(usize, 2), results.len);
}
test "between reaches Table.select through an index range like gte/lte does" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
var db = try openTemp(&tmp, allocator);
defer db.close();
var table = try querymod.Table.open(&db, allocator, "people");
defer table.deinit();
try table.createIndex("age");
var i: i64 = 0;
while (i < 10) : (i += 1) {
try table.put(.{ .int = i }, &.{.{ .name = "age", .value = .{ .int = i * 10 } }});
}
var parsed = try parse(allocator, "age between i:20 and i:50");
defer parsed.deinit();
var plan = try table.explain(allocator, parsed.predicate);
defer plan.deinit(allocator);
try std.testing.expectEqual(querymod.PlanKind.index_range, plan.kind);
try std.testing.expectEqualStrings("age", plan.indexName.?);
const results = try table.select(parsed.predicate);
defer querymod.freeRows(allocator, results);
// ages 20, 30, 40, 50 - inclusive both ends.
try std.testing.expectEqual(@as(usize, 4), results.len);
}