facade=False
SQL CREATE TABLE contracts(tenant text,id integer,paid integer,refunded integer,primary key(tenant,id));
SQL INSERT INTO contracts VALUES('A',1,1000,0),('B',1,1000,0);
SQL CREATE TABLE refunds(tenant text,key text,cents integer,primary key(tenant,key));
SQL CREATE TABLE outbox(id integer primary key,tenant text,key text,cents integer,sent integer default 0);
SQL CREATE TABLE inbox(tenant text,key text,cents integer,primary key(tenant,key));
SQL CREATE TABLE ledger(tenant text primary key,cents integer);
SQL INSERT INTO ledger VALUES('A',0),('B',0);
SQL BEGIN IMMEDIATE
SQL select cents from refunds where tenant='A' and key='r1'
SQL update contracts set refunded=refunded+300 where tenant='A' and id=1 and refunded+300<=paid
SQL insert or replace into refunds values('A','r1',300)
SQL insert into outbox(tenant,key,cents) values('A','r1',300)
SQL COMMIT
committed refund A:r1
commit-before-publish-crash=PASS exit=74
SQL BEGIN IMMEDIATE
SQL BEGIN IMMEDIATE
SQL select cents from refunds where tenant='A' and key='r1'
SQL ROLLBACK
SQL select cents from refunds where tenant='A' and key='r1'
SQL ROLLBACK
SQL select refunded from contracts where tenant='A'
observed-refunded=300
rejected=["alice", "B", "x", 100]
SQL BEGIN IMMEDIATE
SQL select cents from refunds where tenant='A' and key='r2'
SQL update contracts set refunded=refunded+800 where tenant='A' and id=1 and refunded+800<=paid
rejected=["alice", "A", "r2", 800]
SQL BEGIN IMMEDIATE
SQL select cents from refunds where tenant='A' and key='r1'
SQL select id,tenant,key,cents from outbox where sent=0 order by id
SQL begin immediate
SQL insert or ignore into inbox values('A','r1',300)
SQL update ledger set cents=cents+300 where tenant='A'
SQL COMMIT
receiver committed, acknowledgement absent
rejected=["alice", "A", "r1", 301]
SQL select id,tenant,key,cents from outbox where sent=0 order by id
SQL begin immediate
SQL insert or ignore into inbox values('A','r1',300)
SQL COMMIT
SQL BEGIN 
SQL update outbox set sent=1 where id=1
SQL COMMIT
SQL select id,tenant,key,cents from outbox where sent=0 order by id
SQL select cents from ledger where tenant='A'
SQL select cents from ledger where tenant='B'
SQL select count(*) from outbox where sent=0
SQL select refunded from contracts where tenant='B'
SQL select count(*) from refunds
recovery-and-no-invalid-effects=PASS refunded=300 ledger=300 pending=0 B=0
PASS chapter23
