feat: grow txn_table
This commit is contained in:
1 parent
697e8c6461
commit
0631d1673d
1 file changed
+77
@@ -950,3 +950,80 @@ test "TableTxn put is restricted from changing a UNIQUE foreign key target a com
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
|
||||
{
|
||||
var products = try querymod.Table.open(&db, allocator, "products");
|
||||
defer products.deinit();
|
||||
try products.createUniqueIndex("sku");
|
||||
try products.put(.{ .int = 1 }, &.{.{ .name = "sku", .value = .{ .text = "WIDGET-1" } }});
|
||||
|
||||
var lineItems = try querymod.Table.open(&db, allocator, "line_items");
|
||||
defer lineItems.deinit();
|
||||
try lineItems.createForeignKey("product_sku", "products", "sku", .restrict);
|
||||
try lineItems.put(.{ .int = 1 }, &.{.{ .name = "product_sku", .value = .{ .text = "WIDGET-1" } }});
|
||||
}
|
||||
|
||||
var txn = Transaction.begin(&db);
|
||||
defer txn.deinit();
|
||||
var t = try TableTxn.open(&txn, allocator, "products");
|
||||
defer t.deinit();
|
||||
|
||||
try std.testing.expectError(error.ForeignKeyInUse, t.put(.{ .int = 1 }, &.{
|
||||
.{ .name = "sku", .value = .{ .text = "WIDGET-2" } },
|
||||
}));
|
||||
// Unchanged is always exempt.
|
||||
try t.put(.{ .int = 1 }, &.{.{ .name = "sku", .value = .{ .text = "WIDGET-1" } }});
|
||||
try txn.commit();
|
||||
|
||||
var plain = try querymod.Table.open(&db, allocator, "products");
|
||||
defer plain.deinit();
|
||||
var stillThere = (try plain.get(.{ .int = 1 })).?;
|
||||
defer stillThere.deinit();
|
||||
try std.testing.expectEqualStrings("WIDGET-1", stillThere.get("sku").?.text);
|
||||
}
|
||||
|
||||
test "TableTxn put update-restrict sees a child row staged earlier in the same uncommitted transaction" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
|
||||
{
|
||||
var products = try querymod.Table.open(&db, allocator, "products");
|
||||
defer products.deinit();
|
||||
try products.createUniqueIndex("sku");
|
||||
try products.put(.{ .int = 1 }, &.{.{ .name = "sku", .value = .{ .text = "WIDGET-1" } }});
|
||||
|
||||
var lineItems = try querymod.Table.open(&db, allocator, "line_items");
|
||||
defer lineItems.deinit();
|
||||
try lineItems.createForeignKey("product_sku", "products", "sku", .restrict);
|
||||
}
|
||||
|
||||
var txn = Transaction.begin(&db);
|
||||
defer txn.deinit();
|
||||
|
||||
// The line item referencing "WIDGET-1" is only staged in this SAME
|
||||
// transaction's write set, never committed - `Transaction.scanPrefix`
|
||||
// is what makes this count as a live reference before commit.
|
||||
var lineItemsTxn = try TableTxn.open(&txn, allocator, "line_items");
|
||||
defer lineItemsTxn.deinit();
|
||||
try lineItemsTxn.put(.{ .int = 1 }, &.{.{ .name = "product_sku", .value = .{ .text = "WIDGET-1" } }});
|
||||
|
||||
var productsTxn = try TableTxn.open(&txn, allocator, "products");
|
||||
defer productsTxn.deinit();
|
||||
try std.testing.expectError(error.ForeignKeyInUse, productsTxn.put(.{ .int = 1 }, &.{
|
||||
.{ .name = "sku", .value = .{ .text = "WIDGET-2" } },
|
||||
}));
|
||||
|
||||
// Once the referencing line item is removed in the same transaction,
|
||||
// the rename goes through.
|
||||
try lineItemsTxn.delete(.{ .int = 1 });
|
||||
try productsTxn.put(.{ .int = 1 }, &.{.{ .name = "sku", .value = .{ .text = "WIDGET-2" } }});
|
||||
try txn.commit();
|
||||
|
||||
var plain = try querymod.Table.open(&db, allocator, "products");
|
||||
defer plain.deinit();
|
||||
var renamed = (try plain.get(.{ .int = 1 })).?;
|
||||
defer renamed.deinit();
|
||||
try std.testing.expectEqualStrings("WIDGET-2", renamed.get("sku").?.text);
|
||||
}
|
||||
Reference in new issue
Block a user