KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > execute > GenericRIChecker


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.GenericRIChecker
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.execute;
23
24 import org.apache.derby.iapi.services.sanity.SanityManager;
25 import org.apache.derby.iapi.error.StandardException;
26
27 import org.apache.derby.iapi.types.DataValueDescriptor;
28 import org.apache.derby.iapi.types.RowLocation;
29 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
30 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
31 import org.apache.derby.iapi.sql.execute.ExecRow;
32 import org.apache.derby.iapi.sql.execute.ExecIndexRow;
33
34 import org.apache.derby.iapi.store.access.ConglomerateController;
35 import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;
36 import org.apache.derby.iapi.store.access.ScanController;
37 import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
38 import org.apache.derby.iapi.store.access.TransactionController;
39
40 import org.apache.derby.iapi.services.io.FormatableBitSet;
41 import java.util.Enumeration JavaDoc;
42 import java.util.Hashtable JavaDoc;
43
44 /**
45  * Generic implementation of a Referential Integrity
46  * checker. Abstract.
47  */

48 public abstract class GenericRIChecker
49 {
50     protected FKInfo fkInfo;
51     protected DynamicCompiledOpenConglomInfo[] fkDcocis;
52     protected StaticCompiledOpenConglomInfo[] fkScocis;
53     protected DynamicCompiledOpenConglomInfo refDcoci;
54     protected StaticCompiledOpenConglomInfo refScoci;
55     protected TransactionController tc;
56
57     private Hashtable JavaDoc scanControllers;
58     private int numColumns;
59     private IndexRow indexQualifierRow;
60
61     /**
62      * @param tc the xact controller
63      * @param fkinfo the foreign key information
64      *
65      * @exception StandardException Thrown on failure
66      */

67     GenericRIChecker(TransactionController tc, FKInfo fkinfo)
68         throws StandardException
69     {
70         this.fkInfo = fkinfo;
71         this.tc = tc;
72         scanControllers = new Hashtable JavaDoc();
73         numColumns = fkInfo.colArray.length;
74         indexQualifierRow = new IndexRow(numColumns);
75
76         fkDcocis = new DynamicCompiledOpenConglomInfo[fkInfo.fkConglomNumbers.length];
77         fkScocis = new StaticCompiledOpenConglomInfo[fkInfo.fkConglomNumbers.length];
78         for (int index = 0; index < fkInfo.fkConglomNumbers.length; index++)
79         {
80             fkDcocis[index] = tc.getDynamicCompiledConglomInfo(fkInfo.fkConglomNumbers[index]);
81             fkScocis[index] = tc.getStaticCompiledConglomInfo(fkInfo.fkConglomNumbers[index]);
82         }
83         refDcoci = tc.getDynamicCompiledConglomInfo(fkInfo.refConglomNumber);
84         refScoci = tc.getStaticCompiledConglomInfo(fkInfo.refConglomNumber);
85     }
86
87     /**
88      * Check the validity of this row
89      *
90      * @param row the row to check
91      *
92      * @exception StandardException on error
93      */

94     abstract void doCheck(ExecRow row, boolean restrictCheckOnly) throws StandardException;
95
96     public void doCheck(ExecRow row) throws StandardException
97     {
98         doCheck(row, false); //Check all the referential Actions
99
}
100
101     /**
102      * Get a scan controller positioned using searchRow as
103      * the start/stop position. The assumption is that searchRow
104      * is of the same format as the index being opened.
105      * The scan is set up to return no columns.
106      * NOTE: We only need an instantaneous lock on the
107      * table that we are probing as we are just checking
108      * for the existance of a row. All updaters, whether
109      * to the primary or foreign key tables, will hold an
110      * X lock on the table that they are updating and will
111      * be probing the other table, so instantaneous locks
112      * will not change the semantics.
113      *
114      * RESOLVE: Due to the current RI implementation
115      * we cannot always get instantaneous locks. We
116      * will call a method to find out what kind of
117      * locking to do until the implementation changes.
118      *
119      * @param conglomNumber the particular conglomerate we
120      * are interested in
121      * @param searchRow the row to match
122      *
123      * @exception StandardException on error
124      */

125     protected ScanController getScanController(long conglomNumber,
126                                                StaticCompiledOpenConglomInfo scoci,
127                                                DynamicCompiledOpenConglomInfo dcoci, ExecRow searchRow)
128         throws StandardException
129     {
130         int isoLevel = getRICheckIsolationLevel();
131         ScanController scan;
132         Long JavaDoc hashKey = new Long JavaDoc(conglomNumber);
133
134         /*
135         ** If we haven't already opened this scan controller,
136         ** we'll open it now and stick it in the hash table.
137         */

138         if ((scan = (ScanController)scanControllers.get(hashKey)) == null)
139         {
140             setupQualifierRow(searchRow);
141             scan =
142                 tc.openCompiledScan(
143                       false, // hold
144
0, // read only
145
TransactionController.MODE_RECORD, // row locking
146
isoLevel,
147                       (FormatableBitSet)null, // retrieve all fields
148
indexQualifierRow.getRowArray(), // startKeyValue
149
ScanController.GE, // startSearchOp
150
null, // qualifier
151
indexQualifierRow.getRowArray(), // stopKeyValue
152
ScanController.GT, // stopSearchOp
153
scoci,
154                       dcoci
155                       );
156             scanControllers.put(hashKey, scan);
157         }
158         else
159         {
160             /*
161             ** If the base row is the same row as the previous
162             ** row, this call to setupQualfierRow is redundant,
163             ** but it is safer this way so we'll take the
164             ** marginal performance hit (marginal relative
165             ** to the index scans that we are making).
166             */

167             setupQualifierRow(searchRow);
168             scan.reopenScan(
169                       indexQualifierRow.getRowArray(), // startKeyValue
170
ScanController.GE, // startSearchOp
171
null, // qualifier
172
indexQualifierRow.getRowArray(), // stopKeyValue
173
ScanController.GT // stopSearchOp
174
);
175         }
176
177         return scan;
178     }
179
180     /*
181     ** Do reference copy for the qualifier row. No cloning.
182     ** So we cannot get another row until we are done with
183     ** this one.
184     */

185     private void setupQualifierRow(ExecRow baseRow)
186     {
187         DataValueDescriptor[] indexColArray = indexQualifierRow.getRowArray();
188         DataValueDescriptor[] baseColArray = baseRow.getRowArray();
189
190         for (int i = 0; i < numColumns; i++)
191         {
192             indexColArray[i] = baseColArray[fkInfo.colArray[i] - 1];
193         }
194     }
195
196     /**
197      * Are any of the fields null in the row passed
198      * in. The only fields that are checked are those
199      * corresponding to the colArray in fkInfo.
200      */

201     boolean isAnyFieldNull(ExecRow baseRow)
202     {
203         DataValueDescriptor[] baseColArray = baseRow.getRowArray();
204
205         for (int i = 0; i < numColumns; i++)
206         {
207             DataValueDescriptor storable = baseColArray[fkInfo.colArray[i] - 1];
208             if (storable.isNull())
209             {
210                 return true;
211             }
212         }
213         return false;
214     }
215         
216             
217     /**
218      * Clean up all scan controllers
219      *
220      * @exception StandardException on error
221      */

222     void close()
223         throws StandardException
224     {
225         Enumeration JavaDoc e = scanControllers.elements();
226         while (e.hasMoreElements())
227         {
228             ScanController scan = (ScanController)e.nextElement();
229             scan.close();
230         }
231         scanControllers.clear();
232     }
233
234     /**
235      * Get the isolation level for the scan for
236      * the RI check.
237      *
238      * NOTE: The level will eventually be instantaneous
239      * locking once the implemenation changes.
240      *
241      * @return The isolation level for the scan for
242      * the RI check.
243      */

244     int getRICheckIsolationLevel()
245     {
246         return TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK;
247     }
248 }
249
Popular Tags