-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBindExample.java
156 lines (126 loc) · 4.99 KB
/
BindExample.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package com.novarto.sanedbc.examples;
import com.novarto.sanedbc.core.interpreter.SyncDbInterpreter;
import com.novarto.sanedbc.core.ops.BatchInsertGenKeysOp;
import com.novarto.sanedbc.core.ops.EffectOp;
import com.novarto.sanedbc.core.ops.SelectOp;
import fj.Unit;
import fj.control.db.DB;
import fj.data.Either;
import fj.data.List;
import org.junit.Test;
import java.sql.DriverManager;
import com.novarto.sanedbc.examples.MapExample1.UserDB;
import static fj.data.List.arrayList;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class BindExample
{
public static final class OrderDb
{
public static final DB<Unit> CREATE_TABLE = new EffectOp(
"CREATE TABLE ORDERS ( USER_EMAIL VARCHAR(200) NOT NULL, ORDER_ID INTEGER PRIMARY KEY IDENTITY," +
"TEXT NVARCHAR(500), FOREIGN KEY (USER_EMAIL) REFERENCES USERS(EMAIL) )"
);
public static DB<Unit> insertOrders(List<CreateOrder> newOrders)
{
// insert all the orders via batch, return the ORDER_ID keys
DB<List<Integer>> insertOrdersGetKeys = new BatchInsertGenKeysOp.FjList<>(
"INSERT INTO ORDERS(USER_EMAIL, TEXT) VALUES(?, ?)",
x -> ps -> {
ps.setString(1, x.userEmail);
ps.setString(2, x.text);
},
newOrders,
rs -> rs.getInt(1)
);
return insertOrdersGetKeys.map(ignore -> Unit.unit());
}
//the operation authenticates the user, and reads their orders
//it returns either an error message (string), in case the login fails; or the list of orders
public static DB<Either<String, List<Order>>> authenticateAndGetOrders(String email, String pass)
{
// with bind we take the result of one operation, and use it to return another operation
return UserDB.login(email, pass).bind(success -> {
if (!success)
{
Either<String, List<Order>> errorMessage = Either.left("auth failure");
// the DB.unit operation returns an immediate result with the passed value, without touching the connection
return DB.unit(errorMessage);
}
return selectOrdersByEmail(email).map(orders -> Either.right(orders));
});
}
public static DB<List<Order>> selectOrdersByEmail(String userEmail)
{
return new SelectOp.FjList<>(
"SELECT ORDER_ID, USER_EMAIL, TEXT FROM ORDERS WHERE USER_EMAIL=?",
ps -> ps.setString(1, userEmail),
rs -> new Order(rs.getInt(1), rs.getString(2), rs.getString(3))
);
}
}
@Test
public void testIt()
{
SyncDbInterpreter dbi = new SyncDbInterpreter(
() -> DriverManager.getConnection("jdbc:hsqldb:mem:bind_example", "sa", "")
);
dbi.submit(UserDB.CREATE_USER_TABLE);
dbi.submit(OrderDb.CREATE_TABLE);
dbi.submit(UserDB.insertUser("[email protected]", "abcd"));
dbi.submit(UserDB.insertUser("[email protected]", "abcd"));
dbi.submit(
OrderDb.insertOrders(
arrayList(new CreateOrder("[email protected]", "Hi there"),
new CreateOrder("[email protected]", "Bye there")
))
);
Either<String, List<Order>> result = dbi.submit(OrderDb.authenticateAndGetOrders("[email protected]", "abcd"));
assertThat(result.isRight(), is(true));
List<Order> orders = result.right().value();
assertThat(orders.isSingle(), is(true));
Order johnOrder = orders.head();
assertThat(johnOrder.text, is("Hi there"));
Either<String, List<Order>> shouldFail = dbi.submit(OrderDb.authenticateAndGetOrders("haxx0r", "abcd"));
assertThat(shouldFail, is(Either.left("auth failure")));
}
public static class Order
{
public final int id;
public final String userEmail;
public final String text;
public Order(int id, String userEmail, String text)
{
this.id = id;
this.userEmail = userEmail;
this.text = text;
}
@Override public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
Order order = (Order) o;
return id == order.id;
}
@Override public int hashCode()
{
return id;
}
}
public static class CreateOrder
{
public final String userEmail;
public final String text;
public CreateOrder(String userEmail, String text)
{
this.userEmail = userEmail;
this.text = text;
}
}
}