-
Notifications
You must be signed in to change notification settings - Fork 578
/
Copy pathJdbcTransaction.java
151 lines (129 loc) · 4.96 KB
/
JdbcTransaction.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
package com.clickhouse.jdbc.internal;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import com.clickhouse.client.ClickHouseChecker;
import com.clickhouse.client.ClickHouseException;
import com.clickhouse.client.ClickHouseRequestManager;
import com.clickhouse.client.ClickHouseTransaction;
import com.clickhouse.client.ClickHouseUtils;
import com.clickhouse.client.logging.Logger;
import com.clickhouse.jdbc.SqlExceptionUtils;
public class JdbcTransaction {
static final String ACTION_COMMITTED = "committed";
static final String ACTION_ROLLBACK = "rolled back";
static final String ERROR_TX_NOT_STARTED = "Transaction not started";
protected final ClickHouseTransaction tx;
protected final String id;
protected final List<String> queries;
protected final List<JdbcSavepoint> savepoints;
JdbcTransaction() {
this(null);
}
public JdbcTransaction(ClickHouseTransaction tx) {
this.tx = tx;
this.id = tx != null ? tx.getId().asTupleString() : ClickHouseRequestManager.getInstance().createUniqueId();
this.queries = new LinkedList<>();
this.savepoints = new LinkedList<>();
}
public void commit(Logger log) throws SQLException {
if (this.tx != null) {
try {
this.tx.commit();
} catch (ClickHouseException e) {
throw SqlExceptionUtils.handle(e);
}
} else {
logTransactionDetails(log, ACTION_COMMITTED);
}
clear();
}
public void rollback(Logger log) throws SQLException {
if (this.tx != null) {
try {
this.tx.rollback();
} catch (ClickHouseException e) {
throw SqlExceptionUtils.handle(e);
}
} else {
logTransactionDetails(log, JdbcTransaction.ACTION_ROLLBACK);
}
clear();
}
synchronized List<String> getQueries() {
return Collections.unmodifiableList(queries);
}
synchronized List<JdbcSavepoint> getSavepoints() {
return Collections.unmodifiableList(savepoints);
}
synchronized void logSavepointDetails(Logger log, JdbcSavepoint s, String action) {
log.warn(
"[JDBC Compliant Mode] Savepoint(id=%d, name=%s) of transaction [%s](%d queries & %d savepoints) is %s.",
s.id, s.name, id, queries.size(), savepoints.size(), action);
}
synchronized void logTransactionDetails(Logger log, String action) {
if (tx != null) {
log.debug("%s (%d queries & %d savepoints) is %s", tx, queries.size(),
savepoints.size(), action);
} else {
log.warn("[JDBC Compliant Mode] Transaction [%s] (%d queries & %d savepoints) is %s.", id, queries.size(),
savepoints.size(), action);
}
log.debug(() -> {
log.debug("[JDBC Compliant Mode] Transaction [%s] is %s - begin", id, action);
int total = queries.size();
int counter = 1;
for (String queryId : queries) {
log.debug(" '%s', -- query (%d of %d) in transaction [%s]", queryId, counter++, total, id);
}
total = savepoints.size();
counter = 1;
for (JdbcSavepoint savepoint : savepoints) {
log.debug(" %s (%d of %d) in transaction [%s]", savepoint, counter++, total, id);
}
return ClickHouseUtils.format("[JDBC Compliant Mode] Transaction [%s] is %s - end", id, action);
});
}
synchronized String newQuery(String queryId) {
if (ClickHouseChecker.isNullOrEmpty(queryId) || queries.contains(queryId)) {
queryId = ClickHouseRequestManager.getInstance().createQueryId();
}
queries.add(queryId);
return queryId;
}
synchronized JdbcSavepoint newSavepoint(String name) {
JdbcSavepoint savepoint = new JdbcSavepoint(queries.size(), name);
this.savepoints.add(savepoint);
return savepoint;
}
synchronized void toSavepoint(JdbcSavepoint savepoint) throws SQLException {
if (tx != null) {
try {
tx.rollback();
} catch (ClickHouseException e) {
throw SqlExceptionUtils.handle(e);
}
}
boolean found = false;
Iterator<JdbcSavepoint> it = savepoints.iterator();
while (it.hasNext()) {
JdbcSavepoint s = it.next();
if (found) {
it.remove();
} else if (s == savepoint) {
found = true;
it.remove();
}
}
if (!found) {
throw SqlExceptionUtils.clientError("Invalid savepoint: " + savepoint);
}
queries.subList(savepoint.id, queries.size()).clear();
}
synchronized void clear() {
this.queries.clear();
this.savepoints.clear();
}
}