KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > triactive > jdo > store > SchemaTable


1 /*
2  * Copyright 2002 (C) TJDO.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the TJDO License version 1.0.
6  * See the terms of the TJDO License in the documentation provided with this software.
7  *
8  * $Id: SchemaTable.java,v 1.5 2003/10/18 22:05:16 jackknifebarber Exp $
9  */

10
11 package com.triactive.jdo.store;
12
13 import com.triactive.jdo.model.FieldMetaData;
14 import com.triactive.jdo.model.MetaData;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.ListIterator JavaDoc;
19 import java.util.StringTokenizer JavaDoc;
20 import java.sql.Connection JavaDoc;
21 import java.sql.PreparedStatement JavaDoc;
22 import java.sql.ResultSet JavaDoc;
23 import java.sql.SQLException JavaDoc;
24 import java.sql.Statement JavaDoc;
25 import javax.jdo.JDODataStoreException;
26 import org.apache.log4j.Category;
27
28
29 class SchemaTable extends BaseTable
30 {
31     private static final Category LOG = Category.getInstance(SchemaTable.class);
32
33     private ColumnMapping tableIDMapping;
34     private ColumnMapping nextIDMapping;
35     private ColumnMapping javaIDMapping;
36     private ColumnMapping tableNameMapping;
37     private String JavaDoc fetchByJavaIDStmt;
38     private String JavaDoc getMaxTableIDStmt;
39     private String JavaDoc insertStmt;
40     private String JavaDoc fetchByTableIDStmt;
41     private String JavaDoc fetchByTableNameStmt;
42     private String JavaDoc getNextIDStmt;
43     private String JavaDoc incrNextIDStmt;
44     private String JavaDoc fetchAllStmt;
45     private int tableValidationFlags;
46
47
48     public SchemaTable(StoreManager storeMgr)
49     {
50         super(storeMgr);
51
52         name = new TableIdentifier(dba, "jdoTable");
53     }
54
55
56     public void initialize()
57     {
58         assertIsUninitialized();
59
60         Column tableIDColumn = newColumn(int.class, "tableID").setPrimaryKeyPart();
61         Column nextIDColumn = newColumn(int.class, "nextID");
62         Column javaIDColumn = newColumn(String JavaDoc.class, "javaName").setMaximumLength(128).setUnique();
63         Column tableNameColumn = newColumn(String JavaDoc.class, "tableName").setMaximumLength(64).setUnique();
64
65         tableIDMapping = dba.getMapping(tableIDColumn);
66         nextIDMapping = dba.getMapping(nextIDColumn);
67         javaIDMapping = dba.getMapping(javaIDColumn);
68         tableNameMapping = dba.getMapping(tableNameColumn);
69
70         fetchByJavaIDStmt = "SELECT " + tableIDColumn.getName() + "," +
71                                         tableNameColumn.getName() +
72                              " FROM " + name +
73                             " WHERE " + javaIDColumn.getName() + " = ?";
74
75         getMaxTableIDStmt = "SELECT MAX(" + tableIDColumn.getName() + ")" +
76                              " FROM " + name;
77
78         insertStmt = "INSERT INTO " + name +
79                               " (" +
80                                     tableIDColumn.getName() + "," +
81                                     nextIDColumn.getName() + "," +
82                                     javaIDColumn.getName() + "," +
83                                     tableNameColumn.getName() +
84                                ")" +
85                          " VALUES (?,?,?,?)";
86
87         fetchByTableIDStmt = "SELECT " + javaIDColumn.getName() +
88                               " FROM " + name +
89                              " WHERE " + tableIDColumn.getName() + " = ?";
90
91         fetchByTableNameStmt = "SELECT " + tableIDColumn.getName() +
92                                 " FROM " + name +
93                                " WHERE " + tableNameColumn.getName() + " = ?";
94
95         getNextIDStmt = "SELECT " + nextIDColumn.getName() +
96                          " FROM " + name +
97                         " WHERE " + tableIDColumn.getName() + " = ?";
98
99         incrNextIDStmt = "UPDATE " + name +
100                            " SET " + nextIDColumn.getName() + " = ?" +
101                          " WHERE " + tableIDColumn.getName() + " = ?";
102
103         fetchAllStmt = "SELECT " + tableIDColumn.getName() + "," +
104                                    javaIDColumn.getName() + "," +
105                                    tableNameColumn.getName() +
106                         " FROM " + name +
107                     " ORDER BY " + tableIDColumn.getName();
108
109         state = TABLE_STATE_INITIALIZED;
110     }
111
112
113     public boolean validate(int flags, Connection JavaDoc conn) throws SQLException JavaDoc
114     {
115         this.tableValidationFlags = flags;
116
117         return super.validate(flags, conn);
118     }
119
120
121     public boolean exists(Connection JavaDoc conn) throws SQLException JavaDoc
122     {
123         assertIsInitialized();
124
125         try
126         {
127             getNextTableID(conn);
128             return true;
129         }
130         catch (SQLException JavaDoc e)
131         {
132             return false;
133         }
134     }
135
136
137     private SQLIdentifier generateTableName(MetaData md, Connection JavaDoc conn) throws SQLException JavaDoc
138     {
139         ArrayList JavaDoc nameParts = new ArrayList JavaDoc();
140
141         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(md.getJavaName(), ".");
142
143         while (tokens.hasMoreTokens())
144             nameParts.add(tokens.nextToken());
145
146         ListIterator JavaDoc li = nameParts.listIterator(nameParts.size());
147
148         String JavaDoc uniqueName = (String JavaDoc)li.previous();
149
150         if (md instanceof FieldMetaData)
151             uniqueName = (String JavaDoc)li.previous() + '_' + uniqueName;
152
153         TableIdentifier tableName = new TableIdentifier(dba, uniqueName);
154         int n = 1;
155
156         while (tableNameInUse(tableName, conn))
157         {
158             if (li.hasPrevious())
159                 uniqueName = (String JavaDoc)li.previous() + '_' + uniqueName;
160             else
161                 uniqueName = uniqueName + n++;
162
163             tableName = new TableIdentifier(dba, uniqueName);
164         }
165
166         return tableName;
167     }
168
169
170     private boolean tableNameInUse(TableIdentifier tableName, Connection JavaDoc conn) throws SQLException JavaDoc
171     {
172         if (storeMgr.tableExists(tableName, conn))
173             return true;
174         
175         PreparedStatement JavaDoc ps = conn.prepareStatement(fetchByTableNameStmt);
176
177         try
178         {
179             ps.setString(1, tableName.getSQLIdentifier());
180             ResultSet JavaDoc rs = ps.executeQuery();
181
182             try
183             {
184                 return rs.next();
185             }
186             finally
187             {
188                 rs.close();
189             }
190         }
191         finally
192         {
193             ps.close();
194         }
195     }
196
197
198     private TableMetadata fetchByJavaID(String JavaDoc javaName, Connection JavaDoc conn) throws SQLException JavaDoc
199     {
200         TableMetadata tmd = null;
201
202         PreparedStatement JavaDoc ps = conn.prepareStatement(fetchByJavaIDStmt);
203
204         try
205         {
206             javaIDMapping.setString(null, ps, 1, javaName);
207
208             long startTime = System.currentTimeMillis();
209
210             ResultSet JavaDoc rs = ps.executeQuery();
211
212             try
213             {
214                 if (LOG.isDebugEnabled())
215                     LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + fetchByJavaIDStmt);
216
217                 storeMgr.logSQLWarnings(ps);
218
219                 if (rs.next())
220                 {
221                     int tableID = tableIDMapping.getInt(null, rs, 1);
222                     SQLIdentifier tableName = new SQLIdentifier(dba, tableNameMapping.getString(null, rs, 2));
223
224                     storeMgr.logSQLWarnings(rs);
225
226                     tmd = new TableMetadata(tableID, javaName, tableName);
227                 }
228             }
229             finally
230             {
231                 rs.close();
232             }
233         }
234         finally
235         {
236             ps.close();
237         }
238
239         return tmd;
240     }
241
242
243     private int getNextTableID(Connection JavaDoc conn) throws SQLException JavaDoc
244     {
245         int nextTableID;
246         Statement JavaDoc stmt = conn.createStatement();
247
248         try
249         {
250             long startTime = System.currentTimeMillis();
251
252             ResultSet JavaDoc rs = stmt.executeQuery(getMaxTableIDStmt);
253
254             try
255             {
256                 if (LOG.isDebugEnabled())
257                     LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + getMaxTableIDStmt);
258
259                 storeMgr.logSQLWarnings(stmt);
260
261                 if (!rs.next())
262                     throw new JDODataStoreException("Can't find max table ID in " + name + "???");
263
264                 nextTableID = rs.getInt(1) + 1;
265                 storeMgr.logSQLWarnings(rs);
266             }
267             finally
268             {
269                 rs.close();
270             }
271         }
272         finally
273         {
274             stmt.close();
275         }
276
277         return nextTableID;
278     }
279
280
281     private void insert(TableMetadata tmd, Connection JavaDoc conn) throws SQLException JavaDoc
282     {
283         PreparedStatement JavaDoc ps = conn.prepareStatement(insertStmt);
284
285         try
286         {
287             tableIDMapping.setInt(null, ps, 1, tmd.tableID);
288             nextIDMapping.setInt(null, ps, 2, 0);
289             javaIDMapping.setString(null, ps, 3, tmd.javaName);
290             tableNameMapping.setString(null, ps, 4, tmd.tableName.getSQLIdentifier());
291
292             long startTime = System.currentTimeMillis();
293
294             ps.executeUpdate();
295
296             if (LOG.isDebugEnabled())
297                 LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + insertStmt);
298
299             storeMgr.logSQLWarnings(ps);
300         }
301         finally
302         {
303             ps.close();
304         }
305     }
306
307
308     /**
309      * Retrieve the TableMetadata for the given MetaData. If the TableMetaData is
310      * not found in the SchemaTable and <code>tableValidationFlags</code> do not
311      * specify AUTO_CREATE, a <code>MissingSchemaTableEntryException</code> is thrown.
312      *
313      * @param md The MetaData to retrieve the TableMetaData for.
314      * @param conn The Connection to use.
315      *
316      * @return The TableMetadata for the given MetaData.
317      *
318      * @exception SQLException
319      * If inserting the TableMetadata into the SchemaTable failed.
320      * @exception MissingSchemaTableEntryException
321      * The the SchemaTable does not contain a row for the requested MetaData, and
322      * <code>tableValidationFlags</code> does not specifiy AUTO_CREATE.
323      */

324     public TableMetadata getTableMetadata(MetaData md, Connection JavaDoc conn)
325         throws SQLException JavaDoc, MissingSchemaTableEntryException
326     {
327         assertIsValidated();
328
329         String JavaDoc javaName = md.getJavaName();
330         TableMetadata tmd = fetchByJavaID(javaName, conn);
331
332         if (tmd == null)
333         {
334             if ((tableValidationFlags & AUTO_CREATE) == 0)
335                 throw new MissingSchemaTableEntryException(this, javaName);
336
337             int tableID = getNextTableID(conn);
338             SQLIdentifier tableName = generateTableName(md, conn);
339
340             tmd = new TableMetadata(tableID, javaName, tableName);
341
342             insert(tmd, conn);
343         }
344
345         return tmd;
346     }
347
348
349     public String JavaDoc getJavaName(int tableID, Connection JavaDoc conn) throws SQLException JavaDoc
350     {
351         assertIsValidated();
352
353         String JavaDoc javaName = null;
354
355         PreparedStatement JavaDoc ps = conn.prepareStatement(fetchByTableIDStmt);
356
357         try
358         {
359             tableIDMapping.setInt(null, ps, 1, tableID);
360
361             long startTime = System.currentTimeMillis();
362
363             ResultSet JavaDoc rs = ps.executeQuery();
364
365             try
366             {
367                 if (LOG.isDebugEnabled())
368                     LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + fetchByTableIDStmt);
369
370                 storeMgr.logSQLWarnings(ps);
371
372                 if (rs.next())
373                 {
374                     javaName = javaIDMapping.getString(null, rs, 1);
375
376                     storeMgr.logSQLWarnings(rs);
377                 }
378             }
379             finally
380             {
381                 rs.close();
382             }
383         }
384         finally
385         {
386             ps.close();
387         }
388
389         return javaName;
390     }
391
392
393     public int getNextOIDHiValue(int tableID, Connection JavaDoc conn) throws SQLException JavaDoc
394     {
395         assertIsValidated();
396
397         int nextHiValue;
398         PreparedStatement JavaDoc ps = conn.prepareStatement(getNextIDStmt);
399
400         try
401         {
402             tableIDMapping.setInt(null, ps, 1, tableID);
403
404             long startTime = System.currentTimeMillis();
405
406             ResultSet JavaDoc rs = ps.executeQuery();
407
408             try
409             {
410                 if (LOG.isDebugEnabled())
411                     LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + getNextIDStmt);
412
413                 storeMgr.logSQLWarnings(ps);
414
415                 if (!rs.next())
416                     throw new JDODataStoreException("Can't find table ID " + tableID + " in " + getName() + "???");
417
418                 nextHiValue = nextIDMapping.getInt(null, rs, 1);
419                 storeMgr.logSQLWarnings(rs);
420             }
421             finally
422             {
423                 rs.close();
424             }
425         }
426         finally
427         {
428             ps.close();
429         }
430
431         ps = conn.prepareStatement(incrNextIDStmt);
432
433         try
434         {
435             nextIDMapping.setInt(null, ps, 1, nextHiValue + 1);
436             tableIDMapping.setInt(null, ps, 2, tableID);
437
438             long startTime = System.currentTimeMillis();
439
440             int rowsUpdated = ps.executeUpdate();
441
442             if (LOG.isDebugEnabled())
443                 LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + incrNextIDStmt);
444
445             if (rowsUpdated != 1)
446                 throw new JDODataStoreException("Can't update table ID " + tableID + " in " + getName() + "???");
447
448             storeMgr.logSQLWarnings(ps);
449         }
450         finally
451         {
452             ps.close();
453         }
454
455         return nextHiValue;
456     }
457
458
459     public List JavaDoc getAllTableMetadata(boolean descending, Connection JavaDoc conn) throws SQLException JavaDoc
460     {
461         assertIsValidated();
462
463         ArrayList JavaDoc tmds = new ArrayList JavaDoc();
464         Statement JavaDoc stmt = conn.createStatement();
465
466         try
467         {
468             String JavaDoc stmtText = fetchAllStmt + (descending ? " DESC" : "");
469             long startTime = System.currentTimeMillis();
470
471             ResultSet JavaDoc rs = stmt.executeQuery(stmtText);
472
473             try
474             {
475                 if (LOG.isDebugEnabled())
476                     LOG.debug("Time = " + (System.currentTimeMillis() - startTime) + " ms: " + stmtText);
477
478                 storeMgr.logSQLWarnings(stmt);
479
480                 while (rs.next())
481                 {
482                     int tableID = tableIDMapping.getInt(null, rs, 1);
483                     String JavaDoc javaID = javaIDMapping.getString(null, rs, 2);
484                     SQLIdentifier tableName = new SQLIdentifier(dba, tableNameMapping.getString(null, rs, 3));
485
486                     storeMgr.logSQLWarnings(rs);
487
488                     tmds.add(new TableMetadata(tableID, javaID, tableName));
489                 }
490             }
491             finally
492             {
493                 rs.close();
494             }
495         }
496         finally
497         {
498             stmt.close();
499         }
500
501         return tmds;
502     }
503
504
505     public void dropTablesFor(Class JavaDoc[] classes, Connection JavaDoc conn) throws SQLException JavaDoc
506     {
507         assertIsValidated();
508
509         String JavaDoc[] classNames = new String JavaDoc[classes.length];
510
511         for (int i = 0; i < classes.length; ++i)
512             classNames[i] = classes[i].getName();
513
514         ArrayList JavaDoc toBeRemoved = new ArrayList JavaDoc();
515         Iterator JavaDoc i = getAllTableMetadata(true, conn).iterator();
516
517         while (i.hasNext())
518         {
519             TableMetadata tmd = (TableMetadata)i.next();
520
521             for (int j = 0; j < classNames.length; ++j)
522             {
523                 String JavaDoc name = classNames[j];
524
525                 if (tmd.javaName.equals(name) || tmd.javaName.startsWith(name + '.'))
526                 {
527                     toBeRemoved.add(tmd);
528                     break;
529                 }
530             }
531         }
532
533         dropTables(toBeRemoved, conn);
534     }
535
536
537     public void dropAllTables(Connection JavaDoc conn) throws SQLException JavaDoc
538     {
539         assertIsValidated();
540
541         dropTables(getAllTableMetadata(true, conn), conn);
542     }
543
544
545     private void dropTables(List JavaDoc metadata, Connection JavaDoc conn) throws SQLException JavaDoc
546     {
547         ArrayList JavaDoc allBaseTables = new ArrayList JavaDoc();
548         ArrayList JavaDoc allViews = new ArrayList JavaDoc();
549
550         Iterator JavaDoc i = metadata.iterator();
551
552         while (i.hasNext())
553         {
554             TableMetadata tmd = (TableMetadata)i.next();
555             int tableType = storeMgr.getTableType(tmd.tableName, conn);
556
557             switch (tableType)
558             {
559                 case TABLE_TYPE_BASE_TABLE:
560                     BaseTable t = new JDOBaseTable(tmd, storeMgr);
561                     t.initialize();
562
563                     allBaseTables.add(t);
564                     break;
565
566                 case TABLE_TYPE_VIEW:
567                     View v = new JDOView(tmd, storeMgr);
568                     v.initialize();
569
570                     allViews.add(v);
571                     break;
572
573                 case TABLE_TYPE_MISSING:
574                 case TABLE_TYPE_UNKNOWN:
575                 default:
576                     break;
577             }
578         }
579
580         /*
581          * Tables, table constraints and views get removed in the reverse order
582          * from which they were created.
583          */

584         i = allViews.iterator();
585
586         while (i.hasNext())
587             ((View)i.next()).drop(conn);
588
589         i = allBaseTables.iterator();
590
591         while (i.hasNext())
592             ((BaseTable)i.next()).dropConstraints(conn);
593
594         i = allBaseTables.iterator();
595
596         while (i.hasNext())
597             ((BaseTable)i.next()).drop(conn);
598     }
599 }
600
Popular Tags