1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.jdbc; |
7 | |
8 | import java.sql.SQLException; |
9 | import java.sql.Savepoint; |
10 | |
11 | import org.h2.api.ErrorCode; |
12 | import org.h2.message.DbException; |
13 | import org.h2.message.Trace; |
14 | import org.h2.message.TraceObject; |
15 | import org.h2.util.StringUtils; |
16 | |
17 | /** |
18 | * A savepoint is a point inside a transaction to where a transaction can be |
19 | * rolled back. The tasks that where done before the savepoint are not rolled |
20 | * back in this case. |
21 | */ |
22 | public class JdbcSavepoint extends TraceObject implements Savepoint { |
23 | |
24 | private static final String SYSTEM_SAVEPOINT_PREFIX = "SYSTEM_SAVEPOINT_"; |
25 | |
26 | private final int savepointId; |
27 | private final String name; |
28 | private JdbcConnection conn; |
29 | |
30 | JdbcSavepoint(JdbcConnection conn, int savepointId, String name, |
31 | Trace trace, int id) { |
32 | setTrace(trace, TraceObject.SAVEPOINT, id); |
33 | this.conn = conn; |
34 | this.savepointId = savepointId; |
35 | this.name = name; |
36 | } |
37 | |
38 | /** |
39 | * Release this savepoint. This method only set the connection to null and |
40 | * does not execute a statement. |
41 | */ |
42 | void release() { |
43 | this.conn = null; |
44 | } |
45 | |
46 | /** |
47 | * Get the savepoint name for this name or id. |
48 | * If the name is null, the id is used. |
49 | * |
50 | * @param name the name (may be null) |
51 | * @param id the id |
52 | * @return the savepoint name |
53 | */ |
54 | static String getName(String name, int id) { |
55 | if (name != null) { |
56 | return StringUtils.quoteJavaString(name); |
57 | } |
58 | return SYSTEM_SAVEPOINT_PREFIX + id; |
59 | } |
60 | |
61 | /** |
62 | * Roll back to this savepoint. |
63 | */ |
64 | void rollback() { |
65 | checkValid(); |
66 | conn.prepareCommand( |
67 | "ROLLBACK TO SAVEPOINT " + getName(name, savepointId), |
68 | Integer.MAX_VALUE).executeUpdate(); |
69 | } |
70 | |
71 | private void checkValid() { |
72 | if (conn == null) { |
73 | throw DbException.get(ErrorCode.SAVEPOINT_IS_INVALID_1, |
74 | getName(name, savepointId)); |
75 | } |
76 | } |
77 | |
78 | /** |
79 | * Get the generated id of this savepoint. |
80 | * @return the id |
81 | */ |
82 | @Override |
83 | public int getSavepointId() throws SQLException { |
84 | try { |
85 | debugCodeCall("getSavepointId"); |
86 | checkValid(); |
87 | if (name != null) { |
88 | throw DbException.get(ErrorCode.SAVEPOINT_IS_NAMED); |
89 | } |
90 | return savepointId; |
91 | } catch (Exception e) { |
92 | throw logAndConvert(e); |
93 | } |
94 | } |
95 | |
96 | /** |
97 | * Get the name of this savepoint. |
98 | * @return the name |
99 | */ |
100 | @Override |
101 | public String getSavepointName() throws SQLException { |
102 | try { |
103 | debugCodeCall("getSavepointName"); |
104 | checkValid(); |
105 | if (name == null) { |
106 | throw DbException.get(ErrorCode.SAVEPOINT_IS_UNNAMED); |
107 | } |
108 | return name; |
109 | } catch (Exception e) { |
110 | throw logAndConvert(e); |
111 | } |
112 | } |
113 | |
114 | /** |
115 | * INTERNAL |
116 | */ |
117 | @Override |
118 | public String toString() { |
119 | return getTraceObjectName() + ": id=" + savepointId + " name=" + name; |
120 | } |
121 | |
122 | |
123 | } |