001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.conn.TempTableInfo
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.conn;
023:
024: import org.apache.derby.iapi.error.StandardException;
025: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
026:
027: //this class is for temporary tables. The information kept here is necessary to implement the rollback
028: //and commit behavior for temporary tables.
029:
030: /**
031: The temp tables will have following data structure
032: TableDescriptor
033: Declared in savepoint level
034: Dropped in savepoint level
035: Modified in savepoint level
036:
037: The actual logic
038:
039: LanguageConnectionContext will keep the "current savepoint level". At any point in
040: time, this is the total number of savepoints defined for a transaction.
041: At the start of any new transaction, the "current savepoint level" will be set to 0.
042:
043: Everytime a new user defined savepoint is set, store returns the total number of savepoints
044: for the connection at that point.
045: For eg, in a new transaction,
046: "current savepoint level' will be 0. When the first savepoint is set, store will return
047: 1 and "current savepoint level" will be set to 1. For next savepoint, store will return 2 and so on
048: and so forth.
049:
050: When language calls rollback or release of a savepoint, store will again return the total number of savepoints
051: for the connection after rollback or release and we will set "current savepoint level" to that number. For eg,
052: start tran ("current savepoint level"=0)
053: set savepoint 1 ("current savepoint level"=1)
054: set savepoint 2 ("current savepoint level"=2)
055: set savepoint 3 ("current savepoint level"=3)
056: set savepoint 4 ("current savepoint level"=4)
057: release savepoint 3 ("current savepoint level"=2)
058: rollback savepoint 1 ("current savepoint level"=0)
059:
060: If the temporary table was declared with ON ROLLBACK DELETE ROWS and contents of that temporary table
061: were modified in a transaction or within a savepoint unit, then we keep track of that by saving the
062: savepoint level in dataModifiedInSavepointLevel. This information will be used at rollback of savepoint or transaction.
063: Also, when a savepoint is released, we check if the table was modified in any of the savepoints that
064: are getting released. If yes, then we put the current savepoint level as dataModifiedInSavepointLevel.
065: eg
066: start tran ("current savepoint level"=0)
067: declare temp table 0 ON ROLLBACK DELETE ROWS("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1)
068: commit (temp table 0 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1))
069: start tran ("current savepoint level = 0)
070: temp table 0 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1)
071: set savepoint 1("current savepoint level = 1")
072: temp table 0 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1)
073: set savepoint 2("current savepoint level = 2")
074: delete 1 row from temp table 0
075: temp table 0 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=2)
076: release savepoint 2 ("current savepoint level"=1) and reset the modified in savepoint level as follows
077: temp table 0 ("declared in savepoint level"=-1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=1)
078: rollback ("current savepoint level"=0) All the rows from the temp table 0 will be removed
079: At the time of commit, we set dataModifiedInSavepointLevel to -1.
080: At the time of rollback (transaction / savepoint), first we check if the table was modified in the unit of work
081: getting rolled back. If yes, then we delete all the data from the temp table and we set dataModifiedInSavepointLevel to -1.
082:
083: When language calls release of a savepoint, store will again return the total number of savepoints
084: in the system after release. We will go through all the temp tables and reset their declared or
085: dropped or modified in savepoint level to the value returned by the release savepoint if those tables had their
086: declared or dropped or modified in savepoint levels higher than what was returned by the release savepoint.
087: eg
088: start tran ("current savepoint level"=0)
089: declare temp table 0 ("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1)
090: set savepoint 1("current savepoint level = 1")
091: declare temp table 1 ("declared in savepoint level"=1, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1)
092: set savepoint 2("current savepoint level = 2")
093: declare temp table 2 ("declared in savepoint level"=2, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1)
094: release savepoint 1 ("current savepoint level"=0) and reset the savepoint levels as follows
095: temp table 1 ("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1)
096: temp table 2 ("declared in savepoint level"=0, "dropped in savepoint level"=-1, "dataModifiedInSavepointLevel"=-1)
097: set savepoint 3("current savepoint level = 1")
098: rollback savepoint 3 ("current savepoint level"=0) and temp table info will look as follows
099: 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: private TableDescriptor td;
181: private int declaredInSavepointLevel;
182: private int droppededInSavepointLevel;
183: private int dataModifiedInSavepointLevel;
184:
185: TempTableInfo(TableDescriptor td, int declaredInSavepointLevel) {
186: this .td = td;
187: this .declaredInSavepointLevel = declaredInSavepointLevel;
188: this .droppededInSavepointLevel = -1;
189: this .dataModifiedInSavepointLevel = -1;
190: }
191:
192: /**
193: * Return the table descriptor
194: */
195: TableDescriptor getTableDescriptor() {
196: return td;
197: }
198:
199: /**
200: * Set the table descriptor. Will be called while temporary is being restored
201: */
202: void setTableDescriptor(TableDescriptor td) {
203: this .td = td;
204: }
205:
206: /**
207: * Matches by name and only temp tables that have not been dropped (that's when droppededInSavepointLevel will be -1)
208: */
209: boolean matches(String tableName) {
210: return (td.getName().equals(tableName) && droppededInSavepointLevel == -1);
211: }
212:
213: /**
214: * Return the savepoint level when the table was last modified
215: */
216: int getModifiedInSavepointLevel() {
217: return dataModifiedInSavepointLevel;
218: }
219:
220: /**
221: * Set the savepoint level when the table was last modified
222: */
223: void setModifiedInSavepointLevel(int dataModifiedInSavepointLevel) {
224: this .dataModifiedInSavepointLevel = dataModifiedInSavepointLevel;
225: }
226:
227: /**
228: * Return the savepoint level when the table was declared
229: */
230: int getDeclaredInSavepointLevel() {
231: return declaredInSavepointLevel;
232: }
233:
234: /**
235: * Set the savepoint level when the table was declared
236: */
237: void setDeclaredInSavepointLevel(int declaredInSavepointLevel) {
238: this .declaredInSavepointLevel = declaredInSavepointLevel;
239: }
240:
241: /**
242: * Return the savepoint level when the table was dropped
243: */
244: int getDroppedInSavepointLevel() {
245: return droppededInSavepointLevel;
246: }
247:
248: /**
249: * Return the savepoint level when the table was dropped
250: */
251: public void setDroppedInSavepointLevel(int droppededInSavepointLevel) {
252: this.droppededInSavepointLevel = droppededInSavepointLevel;
253: }
254: }
|