1 | /* |
2 | |
3 | Derby - Class org.apache.derby.impl.sql.conn.TempTableInfo |
4 | |
5 | Copyright 2003, 2004 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.impl.sql.conn; |
22 | |
23 | import org.apache.derby.iapi.error.StandardException; |
24 | import org.apache.derby.iapi.sql.dictionary.TableDescriptor; |
25 | |
26 | //this class is for temporary tables. The information kept here is necessary to implement the rollback |
27 | //and commit behavior for temporary tables. |
28 | |
29 | /** |
30 | The temp tables will have following data structure |
31 | TableDescriptor |
32 | Declared in savepoint level |
33 | Dropped in savepoint level |
34 | Modified in savepoint level |
35 | |
36 | The actual logic |
37 | |
38 | LanguageConnectionContext will keep the "current savepoint level". At any point in |
39 | time, this is the total number of savepoints defined for a transaction. |
40 | At the start of any new transaction, the "current savepoint level" will be set to 0. |
41 | |
42 | Everytime a new user defined savepoint is set, store returns the total number of savepoints |
43 | for the connection at that point. |
44 | For eg, in a new transaction, |
45 | "current savepoint level' will be 0. When the first savepoint is set, store will return |
46 | 1 and "current savepoint level" will be set to 1. For next savepoint, store will return 2 and so on |
47 | and so forth. |
48 | |
49 | When language calls rollback or release of a savepoint, store will again return the total number of savepoints |
50 | for the connection after rollback or release and we will set "current savepoint level" to that number. For eg, |
51 | start tran ("current savepoint level"=0) |
52 | set savepoint 1 ("current savepoint level"=1) |
53 | set savepoint 2 ("current savepoint level"=2) |
54 | set savepoint 3 ("current savepoint level"=3) |
55 | set savepoint 4 ("current savepoint level"=4) |
56 | release savepoint 3 ("current savepoint level"=2) |
57 | rollback savepoint 1 ("current savepoint level"=0) |
58 | |
59 | If the temporary table was declared with ON ROLLBACK DELETE ROWS and contents of that temporary table |
60 | were modified in a transaction or within a savepoint unit, then we keep track of that by saving the |
61 | savepoint level in dataModifiedInSavepointLevel. This information will be used at rollback of savepoint or transaction. |
62 | Also, when a savepoint is released, we check if the table was modified in any of the savepoints that |
63 | are getting released. If yes, then we put the current savepoint level as dataModifiedInSavepointLevel. |
64 | eg |
65 | start tran ("current savepoint level"=0) |
66 | declare temp table 0 ON ROLLBACK DELETE ROWS("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
67 | commit (temp table 0 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1)) |
68 | start tran ("current savepoint level = 0) |
69 | temp table 0 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
70 | set savepoint 1("current savepoint level = 1") |
71 | temp table 0 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
72 | set savepoint 2("current savepoint level = 2") |
73 | delete 1 row from temp table 0 |
74 | temp table 0 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=2) |
75 | release savepoint 2 ("current savepoint level"=1) and reset the modified in savepoint level as follows |
76 | temp table 0 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=1) |
77 | rollback ("current savepoint level"=0) All the rows from the temp table 0 will be removed |
78 | At the time of commit, we set dataModifiedInSavepointLevel to -1. |
79 | At the time of rollback (transaction / savepoint), first we check if the table was modified in the unit of work |
80 | getting rolled back. If yes, then we delete all the data from the temp table and we set dataModifiedInSavepointLevel to -1. |
81 | |
82 | When language calls release of a savepoint, store will again return the total number of savepoints |
83 | in the system after release. We will go through all the temp tables and reset their declared or |
84 | dropped or modified in savepoint level to the value returned by the release savepoint if those tables had their |
85 | declared or dropped or modified in savepoint levels higher than what was returned by the release savepoint. |
86 | eg |
87 | start tran ("current savepoint level"=0) |
88 | declare temp table 0 ("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
89 | set savepoint 1("current savepoint level = 1") |
90 | declare temp table 1 ("declared in savepoint level"=1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
91 | set savepoint 2("current savepoint level = 2") |
92 | declare temp table 2 ("declared in savepoint level"=2, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
93 | release savepoint 1 ("current savepoint level"=0) and reset the savepoint levels as follows |
94 | temp table 1 ("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
95 | temp table 2 ("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
96 | set savepoint 3("current savepoint level = 1") |
97 | rollback savepoint 3 ("current savepoint level"=0) and temp table info will look as follows |
98 | temp table 0 ("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
99 | temp table 1 ("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
100 | temp table 2 ("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1) |
101 | |
102 | When you declare a temp table, it will have "declared in savepoint level" as the current savepoint |
103 | level of the LanguageConnectionContext (which will be 0 in a transaction with no user-defined savepoints). |
104 | The "dropped in savepoint level" for new temp tables will be set to -1. |
105 | The "dataModifiedInSavepointLevel" for new temp tables will be set to -1 as well. |
106 | |
107 | When a temp table is dropped, we will first check if the table was declared in a savepoint level |
108 | equal to the current savepoint level. |
109 | If yes, then we will remove it from the temp tables list for the LanguageConnectionContext . |
110 | eg |
111 | start tran ("current savepoint level = 0") |
112 | set savepoint 1("current savepoint level = 1") |
113 | declare temp table 1 ("declared in savepoint level"=1, "dropped in savepoint level"=-1) |
114 | drop temp table 1 (declared in savepoint level same as current savepoint level and hence will remove it from list of temp tables) |
115 | If no, then we will set the dropped in savepoint level as the current savepoint level of the |
116 | LanguageConnectionContext (which will be 0 in a transaction without savepoints and it also means |
117 | that the table was declared in a previous transaction). |
118 | |
119 | At the time of commit, go through all the temp tables with "dropped in savepoint level" != -1 (meaning dropped in this transaction) |
120 | and remove them from the temp tables list for the LanguageConnectionContext. All the rest of the temp tables with |
121 | "dropped in savepoint level" = -1, we will set their "declared in savepoint level" to -1 and , "dataModifiedInSavepointLevel" to -1. |
122 | eg |
123 | start tran ("current savepoint level = 0) |
124 | declare temp table t1("declared in savepoint level" = 0, "dropped in savepoint level"=-1) |
125 | commit (temp table 1 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1)) |
126 | start tran ("current savepoint level = 0) |
127 | drop temp table t1 ("declared in savepoint level" = -1, "dropped in savepoint level"=0) |
128 | commit (temp table t1 will be removed from list of temp tables) |
129 | |
130 | At the time of rollback |
131 | if rolling back transaction, first set the "current savepoint level" to 0 |
132 | if rolling back to a savepoint, first set the "current savepoint level" to savepoint level returned by Store |
133 | for the rollback to savepoint command |
134 | Now go through all the temp tables. |
135 | If "declared in savepoint level" of temp table is greater than or equal to "current savepoint level" |
136 | (ie table was declared in this unit of work) |
137 | And if table was not dropped in this unit of work ie "dropped in savepoint level" = -1 |
138 | Then we should remove the table from the list of temp tables and drop the conglomerate created for it |
139 | eg |
140 | start tran ("current savepoint level = 0) |
141 | declare temp table t2("declared in savepoint level" = 0, "dropped in savepoint level"=-1) |
142 | rollback tran |
143 | (temp table t2 will be removed from list of tables and conglomerate associated with it will be dropped) |
144 | And if table was dropped in this unit of work ie "dropped in savepoint level" >= "current savepoint level" |
145 | Then we should remove the table from the list of temp tables |
146 | eg |
147 | start tran ("current savepoint level = 0) |
148 | set savepoint 1("current savepoint level = 1") |
149 | declare temp table t2("declared in savepoint level" = 1, "dropped in savepoint level"=-1) |
150 | set savepoint 2("current savepoint level = 2") |
151 | drop temp table t1 ("declared in savepoint level" = 1, "dropped in savepoint level"=2) |
152 | rollback savepoint 1 ("current savepoint level = 0) temp table t1 will be removed from the list of temp tables |
153 | Else if the "dropped in savepoint level" of temp table is greate than or equal to "current savepoint level" |
154 | it mean that table was dropped in this unit of work (and was declared in an earlier savepoint unit / transaction) and we will |
155 | restore it as part of rollback ie replace the existing entry for this table in valid temp tables list with restored temp table. |
156 | At the end of restoring, "declared in savepoint level" will remain unchanged and "dropped in savepoint level" will be -1. |
157 | eg |
158 | start tran ("current savepoint level = 0) |
159 | declare temp table t1 with definition 1("declared in savepoint level" = 0, "dropped in savepoint level"=-1, definition 1(stored in table descriptor)) |
160 | commit (temp table t1 "declared in savepoint level" = -1, "dropped in savepoint level"=-1) |
161 | start tran ("current savepoint level = 0) |
162 | set savepoint 1("current savepoint level = 1") |
163 | drop temp table t1 ("declared in savepoint level" = -1, "dropped in savepoint level"=1, definition 1(stored in table descriptor)) |
164 | declare temp table t1 with definition 2(say different than definition 1) |
165 | ("declared in savepoint level" = -1, "dropped in savepoint level"=1, definition 1(stored in table descriptor)) , |
166 | ("declared in savepoint level" = 1, "dropped in savepoint level"=-1, definition 2(stored in table descriptor)) |
167 | set savepoint 2("current savepoint level = 2") |
168 | drop temp table t1("declared in savepoint level" = -1, "dropped in savepoint level"=1, definition 1(stored in table descriptor)) , |
169 | ("declared in savepoint level" = 1, "dropped in savepoint level"=2, definition 2(stored in table descriptor)) |
170 | rollback tran |
171 | (Remove : temp table t1("declared in savepoint level" = 1, "dropped in savepoint level"=2, definition 2(stored in table descriptor) |
172 | (Restore : temp table t1"declared in savepoint level" = -1, "dropped in savepoint level"=-1, definition 1(stored in table descriptor)) |
173 | Else if the "dataModifiedInSavepointLevel" of temp table is greate than or equal to "current savepoint level" |
174 | it means that table was declared in an earlier savepoint unit / transaction and was modified in the current UOW. And hence we will delete all the |
175 | data from it. |
176 | */ |
177 | class TempTableInfo |
178 | { |
179 | |
180 | private TableDescriptor td; |
181 | private int declaredInSavepointLevel; |
182 | private int droppededInSavepointLevel; |
183 | private int dataModifiedInSavepointLevel; |
184 | |
185 | TempTableInfo(TableDescriptor td, int declaredInSavepointLevel) |
186 | { |
187 | this.td = td; |
188 | this.declaredInSavepointLevel = declaredInSavepointLevel; |
189 | this.droppededInSavepointLevel = -1; |
190 | this.dataModifiedInSavepointLevel = -1; |
191 | } |
192 | |
193 | /** |
194 | * Return the table descriptor |
195 | */ |
196 | TableDescriptor getTableDescriptor() { |
197 | return td; |
198 | } |
199 | |
200 | /** |
201 | * Set the table descriptor. Will be called while temporary is being restored |
202 | */ |
203 | void setTableDescriptor(TableDescriptor td) { |
204 | this.td = td; |
205 | } |
206 | |
207 | /** |
208 | * Matches by name and only temp tables that have not been dropped (that's when droppededInSavepointLevel will be -1) |
209 | */ |
210 | boolean matches(String tableName) { |
211 | return (td.getName().equals(tableName) && droppededInSavepointLevel == -1); |
212 | } |
213 | |
214 | /** |
215 | * Return the savepoint level when the table was last modified |
216 | */ |
217 | int getModifiedInSavepointLevel() { |
218 | return dataModifiedInSavepointLevel; |
219 | } |
220 | |
221 | /** |
222 | * Set the savepoint level when the table was last modified |
223 | */ |
224 | void setModifiedInSavepointLevel(int dataModifiedInSavepointLevel) { |
225 | this.dataModifiedInSavepointLevel = dataModifiedInSavepointLevel; |
226 | } |
227 | |
228 | /** |
229 | * Return the savepoint level when the table was declared |
230 | */ |
231 | int getDeclaredInSavepointLevel() { |
232 | return declaredInSavepointLevel; |
233 | } |
234 | |
235 | /** |
236 | * Set the savepoint level when the table was declared |
237 | */ |
238 | void setDeclaredInSavepointLevel(int declaredInSavepointLevel) { |
239 | this.declaredInSavepointLevel = declaredInSavepointLevel; |
240 | } |
241 | |
242 | /** |
243 | * Return the savepoint level when the table was dropped |
244 | */ |
245 | int getDroppedInSavepointLevel() { |
246 | return droppededInSavepointLevel; |
247 | } |
248 | |
249 | /** |
250 | * Return the savepoint level when the table was dropped |
251 | */ |
252 | public void setDroppedInSavepointLevel(int droppededInSavepointLevel) { |
253 | this.droppededInSavepointLevel = droppededInSavepointLevel; |
254 | } |
255 | } |