KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > smallsql > database > IndexDescription


1 /* =============================================================
2  * SmallSQL : a free Java DBMS library for the Java(tm) platform
3  * =============================================================
4  *
5  * (C) Copyright 2004-2006, by Volker Berlin.
6  *
7  * Project Info: http://www.smallsql.de/
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * ---------------
28  * IndexDescription.java
29  * ---------------
30  * Author: Volker Berlin
31  *
32  * Created on 19.04.2005
33  */

34 package smallsql.database;
35
36 import java.io.File JavaDoc;
37 import java.io.RandomAccessFile JavaDoc;
38 import java.sql.DriverManager JavaDoc;
39 import java.sql.SQLException JavaDoc;
40
41
42
43 final class IndexDescription {
44
45     static final int MAGIC_INDEX = 'S' << 24 | 'Q' << 16 | 'L' << 8 | 'I';
46     static final int INDEX_VERSION = 1;
47     
48     private final String JavaDoc name;
49     final private int constraintType; //PRIMARY, UNIQUE, FOREIGIN, INDEX
50
final private Strings columns;
51     private int[] matrix;
52     final private Expressions expressions;
53     private Index index;
54     private RandomAccessFile JavaDoc raFile;
55     
56     
57     /**
58      *
59      * @param constraintType one of SQLTokenizer.PRIMARY, SQLTokenizer.UNIQUE, SQLTokenizer.FOREIGN or SQLTokenizer.INDEX.
60      * @param columns the Expressions that build the index. For example one or more database columns.
61      */

62     IndexDescription( String JavaDoc name, String JavaDoc tableName, int constraintType, Expressions expressions, Strings columns){
63         this.constraintType = constraintType;
64         this.expressions = expressions;
65         this.columns = columns;
66         this.name = createName(name, tableName);
67     }
68     
69     
70     private static String JavaDoc createName( String JavaDoc defaultName, String JavaDoc tableName ){
71         if(defaultName == null){
72             defaultName = tableName + "_" + Long.toHexString(System.currentTimeMillis()) + Integer.toHexString(new Object JavaDoc().hashCode());
73         }
74         return defaultName;
75     }
76     
77     
78     final String JavaDoc getName(){
79         return name;
80     }
81     
82     
83     final boolean isPrimary(){
84         return constraintType == SQLTokenizer.PRIMARY;
85     }
86     
87     
88     final boolean isUnique(){
89         return constraintType == SQLTokenizer.PRIMARY || constraintType == SQLTokenizer.UNIQUE;
90     }
91     
92     
93     final Strings getColumns(){
94         return columns;
95     }
96     
97     
98     /**
99      * Descript how well the index match to the column list.
100      * @param strings a list of columns that should match
101      * @return Integer.MAX_VALUE does not match; 0 - 100% match
102      */

103     final int matchFactor(Strings strings){
104         if(strings.size() < columns.size())
105             return Integer.MAX_VALUE; //does not map
106

107         nextColumn:
108         for(int c=0; c<columns.size(); c++){
109             String JavaDoc colName = columns.get(c);
110             for(int s=0; s<strings.size(); s++){
111                 if(colName.equalsIgnoreCase(strings.get(s)) )
112                     continue nextColumn;
113             }
114             return Integer.MAX_VALUE; //No Strin found for colName
115
}
116         return strings.size() - columns.size();
117     }
118     
119     
120     /**
121      * Create a binding of the columns form this index to the columns of the table.
122      * @param database
123      * @param tableView
124      * @see IndexDescriptions#setTableView
125      */

126     final void init(Database database, TableView tableView)/* throws Exception*/{
127         int size = tableView.columns.size();
128         matrix = new int[size];
129         for(int i=0; i<matrix.length; i++){
130             matrix[i] = -1;
131         }
132         
133         for(int i=0; i<columns.size(); i++){
134             matrix[tableView.findColumnIdx(columns.get(i))] = i;
135         }
136     }
137     
138     
139     /**
140      * Create the index. A raFile for storing the index data is saved.
141      */

142     final void create(Database database, TableView tableView) throws Exception JavaDoc{
143         init( database, tableView );
144         raFile = createFile( database );
145     }
146     
147     
148     static File JavaDoc getFile(Database database, String JavaDoc name) throws Exception JavaDoc{
149         return new File JavaDoc( Utils.createIdxFileName( database, name ) );
150     }
151     
152
153     private RandomAccessFile JavaDoc createFile(Database database) throws Exception JavaDoc{
154         File JavaDoc file = getFile( database, name );
155         boolean ok = file.createNewFile();
156         if(!ok) throw Utils.createSQLException("Index '" + name + "' already exists.");
157         RandomAccessFile JavaDoc randomFile = new RandomAccessFile JavaDoc( file, "rw" );
158         writeMagic(randomFile);
159         return randomFile;
160     }
161     
162     
163     private void load(Database database) throws SQLException JavaDoc{
164         try{
165             File JavaDoc file = getFile( database, name );
166             if(!file.exists())
167                 throw Utils.createSQLException("Index '" + name + "' does not exist");
168             raFile = new RandomAccessFile JavaDoc( file, "rw" );
169             int magic = raFile.readInt();
170             int version = raFile.readInt();
171             if(magic != MAGIC_INDEX){
172                 throw Utils.createSQLException("File '" + file.getName() + "' is not a valid Index store.");
173             }
174             if(version > INDEX_VERSION){
175                 throw Utils.createSQLException("File version (" + version + ") of file '" + file.getName() + "' is to new for this runtume.");
176             }
177         }catch(Throwable JavaDoc e){
178             if(raFile != null)
179                 try{
180                     raFile.close();
181                 }catch(Exception JavaDoc e2){
182                     DriverManager.println(e2.toString());
183                 }
184             throw Utils.createSQLException(e);
185         }
186     }
187     
188
189     void drop(Database database) throws Exception JavaDoc {
190         close();
191         boolean ok = getFile( database, name).delete();
192         if(!ok) throw Utils.createSQLException("Table '" + name + "' can't drop.");
193     }
194     
195     
196     void close() throws Exception JavaDoc{
197         if(raFile != null){
198             raFile.close();
199             raFile = null;
200         }
201     }
202     
203
204     private final void writeMagic(RandomAccessFile JavaDoc raFile) throws Exception JavaDoc{
205         raFile.writeInt(MAGIC_INDEX);
206         raFile.writeInt(INDEX_VERSION);
207     }
208
209
210     /**
211      * This is call if a single colum of the table is changed.
212      * @param columnIdx The column position in the table
213      * @param valueExpression the new value of the current row.
214      */

215     final void writeExpression( int columnIdx, Expression valueExpression) {
216         int idx = matrix[columnIdx];
217         if(idx >= 0) //set only if the column part of this index
218
expressions.set(idx, valueExpression);
219     }
220
221
222     /**
223      * This is call if the row is finsch written.
224      * @param con the connection for a later commit or rollback.
225      */

226     final void writeFinsh(SSConnection con) {
227         //TODO
228
//index.addValues(expressions);
229
}
230     
231     
232     /**
233      * Save this IndexDescription in the Table definition.
234      */

235     final void save(StoreImpl store) throws SQLException JavaDoc{
236         store.writeInt(constraintType);
237         store.writeInt(columns.size());
238         for(int c=0; c<columns.size(); c++){
239             store.writeString( columns.get(c) );
240         }
241         store.writeString(name);
242     }
243     
244     
245     /**
246      * Restore a IndexDescription from a saved Table.
247      */

248     final static IndexDescription load(Database database, TableView tableView, StoreImpl store) throws SQLException JavaDoc{
249         int constraintType = store.readInt();
250         int count = store.readInt();
251         Strings columns = new Strings();
252         Expressions expressions = new Expressions();
253         SQLParser sqlParser = new SQLParser();
254         for(int c=0; c<count; c++){
255             String JavaDoc column = store.readString();
256             columns.add( column );
257             expressions.add( sqlParser.parseExpression(column));
258         }
259         IndexDescription indexDesc = new IndexDescription( store.readString(), tableView.name, constraintType, expressions, columns);
260         indexDesc.init( database, tableView );
261         indexDesc.load(database);
262         return indexDesc;
263     }
264
265
266 }
267
Popular Tags