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);
|
var db = try openTemp(&tmp, allocator);
|
||||||
defer db.close();
|
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