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.command.dml; |
7 | |
8 | import org.h2.command.CommandInterface; |
9 | import org.h2.command.Prepared; |
10 | import org.h2.engine.Database; |
11 | import org.h2.engine.Session; |
12 | import org.h2.message.DbException; |
13 | import org.h2.result.ResultInterface; |
14 | |
15 | /** |
16 | * Represents a transactional statement. |
17 | */ |
18 | public class TransactionCommand extends Prepared { |
19 | |
20 | private final int type; |
21 | private String savepointName; |
22 | private String transactionName; |
23 | |
24 | public TransactionCommand(Session session, int type) { |
25 | super(session); |
26 | this.type = type; |
27 | } |
28 | |
29 | public void setSavepointName(String name) { |
30 | this.savepointName = name; |
31 | } |
32 | |
33 | @Override |
34 | public int update() { |
35 | switch (type) { |
36 | case CommandInterface.SET_AUTOCOMMIT_TRUE: |
37 | session.setAutoCommit(true); |
38 | break; |
39 | case CommandInterface.SET_AUTOCOMMIT_FALSE: |
40 | session.setAutoCommit(false); |
41 | break; |
42 | case CommandInterface.BEGIN: |
43 | session.begin(); |
44 | break; |
45 | case CommandInterface.COMMIT: |
46 | session.commit(false); |
47 | break; |
48 | case CommandInterface.ROLLBACK: |
49 | session.rollback(); |
50 | break; |
51 | case CommandInterface.CHECKPOINT: |
52 | session.getUser().checkAdmin(); |
53 | session.getDatabase().checkpoint(); |
54 | break; |
55 | case CommandInterface.SAVEPOINT: |
56 | session.addSavepoint(savepointName); |
57 | break; |
58 | case CommandInterface.ROLLBACK_TO_SAVEPOINT: |
59 | session.rollbackToSavepoint(savepointName); |
60 | break; |
61 | case CommandInterface.CHECKPOINT_SYNC: |
62 | session.getUser().checkAdmin(); |
63 | session.getDatabase().sync(); |
64 | break; |
65 | case CommandInterface.PREPARE_COMMIT: |
66 | session.prepareCommit(transactionName); |
67 | break; |
68 | case CommandInterface.COMMIT_TRANSACTION: |
69 | session.getUser().checkAdmin(); |
70 | session.setPreparedTransaction(transactionName, true); |
71 | break; |
72 | case CommandInterface.ROLLBACK_TRANSACTION: |
73 | session.getUser().checkAdmin(); |
74 | session.setPreparedTransaction(transactionName, false); |
75 | break; |
76 | case CommandInterface.SHUTDOWN_IMMEDIATELY: |
77 | session.getUser().checkAdmin(); |
78 | session.getDatabase().shutdownImmediately(); |
79 | break; |
80 | case CommandInterface.SHUTDOWN: |
81 | case CommandInterface.SHUTDOWN_COMPACT: |
82 | case CommandInterface.SHUTDOWN_DEFRAG: { |
83 | session.getUser().checkAdmin(); |
84 | session.commit(false); |
85 | if (type == CommandInterface.SHUTDOWN_COMPACT || |
86 | type == CommandInterface.SHUTDOWN_DEFRAG) { |
87 | session.getDatabase().setCompactMode(type); |
88 | } |
89 | // close the database, but don't update the persistent setting |
90 | session.getDatabase().setCloseDelay(0); |
91 | Database db = session.getDatabase(); |
92 | // throttle, to allow testing concurrent |
93 | // execution of shutdown and query |
94 | session.throttle(); |
95 | for (Session s : db.getSessions(false)) { |
96 | if (db.isMultiThreaded()) { |
97 | synchronized (s) { |
98 | s.rollback(); |
99 | } |
100 | } else { |
101 | // if not multi-threaded, the session could already own |
102 | // the lock, which would result in a deadlock |
103 | // the other session can not concurrently do anything |
104 | // because the current session has locked the database |
105 | s.rollback(); |
106 | } |
107 | if (s != session) { |
108 | s.close(); |
109 | } |
110 | } |
111 | session.close(); |
112 | break; |
113 | } |
114 | default: |
115 | DbException.throwInternalError("type=" + type); |
116 | } |
117 | return 0; |
118 | } |
119 | |
120 | @Override |
121 | public boolean isTransactional() { |
122 | return true; |
123 | } |
124 | |
125 | @Override |
126 | public boolean needRecompile() { |
127 | return false; |
128 | } |
129 | |
130 | public void setTransactionName(String string) { |
131 | this.transactionName = string; |
132 | } |
133 | |
134 | @Override |
135 | public ResultInterface queryMeta() { |
136 | return null; |
137 | } |
138 | |
139 | @Override |
140 | public int getType() { |
141 | return type; |
142 | } |
143 | |
144 | @Override |
145 | public boolean isCacheable() { |
146 | return true; |
147 | } |
148 | |
149 | } |