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