KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > SchemaManager


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb;
33
34 import org.hsqldb.HsqlNameManager.HsqlName;
35 import org.hsqldb.lib.ArrayUtil;
36 import org.hsqldb.lib.HsqlArrayList;
37 import org.hsqldb.lib.HashMappedList;
38 import org.hsqldb.lib.Iterator;
39 import org.hsqldb.lib.WrapperIterator;
40 import org.hsqldb.persist.Logger;
41
42 /**
43  * Manages all SCHEMA related database objects
44  *
45  * @author fredt@users
46  * @version 1.8.0
47  * @since 1.8.0
48  */

49 public class SchemaManager {
50
51     static final String JavaDoc SYSTEM_SCHEMA = "SYSTEM_SCHEMA";
52     static final String JavaDoc DEFINITION_SCHEMA = "DEFINITION_SCHEMA";
53     static final String JavaDoc INFORMATION_SCHEMA = "INFORMATION_SCHEMA";
54     static final String JavaDoc PUBLIC_SCHEMA = "PUBLIC";
55     static HsqlName INFORMATION_SCHEMA_HSQLNAME =
56         HsqlNameManager.newHsqlSystemObjectName(INFORMATION_SCHEMA);
57     static HsqlName SYSTEM_SCHEMA_HSQLNAME =
58         HsqlNameManager.newHsqlSystemObjectName(SYSTEM_SCHEMA);
59     Database database;
60     HsqlName defaultSchemaHsqlName;
61     HashMappedList schemaMap = new HashMappedList();
62
63     SchemaManager(Database database) {
64
65         this.database = database;
66
67         Schema schema = new Schema(PUBLIC_SCHEMA, false);
68
69         defaultSchemaHsqlName = schema.name;
70
71         schemaMap.put(PUBLIC_SCHEMA, schema);
72     }
73
74     void createSchema(String JavaDoc name, boolean isQuoted) throws HsqlException {
75
76         if (DEFINITION_SCHEMA.equals(name) || INFORMATION_SCHEMA.equals(name)
77                 || SYSTEM_SCHEMA.equals(name)) {
78             throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS);
79         }
80
81         Schema schema = new Schema(name, isQuoted);
82
83         schemaMap.add(name, schema);
84     }
85
86     void dropSchema(String JavaDoc name, boolean cascade) throws HsqlException {
87
88         Schema schema = (Schema) schemaMap.get(name);
89
90         if (schema == null) {
91             throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS);
92         }
93
94         if (!cascade &&!schema.isEmpty()) {
95             throw Trace.error(Trace.DEPENDENT_DATABASE_OBJECT_EXISTS);
96         }
97
98         Iterator tableIterator = schema.tablesIterator();
99
100         while (tableIterator.hasNext()) {
101             Table table = ((Table) tableIterator.next());
102
103             database.getUserManager().removeDbObject(table.getName());
104             table.drop();
105         }
106
107         Iterator sequenceIterator = schema.sequencesIterator();
108
109         while (tableIterator.hasNext()) {
110             NumberSequence sequence =
111                 ((NumberSequence) sequenceIterator.next());
112
113             database.getUserManager().removeDbObject(sequence.getName());
114         }
115
116         schema.clearStructures();
117         schemaMap.remove(name);
118
119         if (defaultSchemaHsqlName.name.equals(name)) {
120             if (schemaMap.isEmpty()) {
121                 schema = new Schema(PUBLIC_SCHEMA, false);
122             } else {
123                 schema = (Schema) schemaMap.get(0);
124             }
125
126             defaultSchemaHsqlName = schema.name;
127
128             schemaMap.put(defaultSchemaHsqlName.name, schema);
129         }
130
131         // these are called last and in this particular order
132
database.getUserManager().removeSchemaReference(schema);
133         database.getSessionManager().removeSchemaReference(schema);
134     }
135
136     void renameSchema(String JavaDoc name, String JavaDoc newName,
137                       boolean isQuoted) throws HsqlException {
138
139         Schema schema = (Schema) schemaMap.get(name);
140         Schema exists = (Schema) schemaMap.get(newName);
141
142         if (schema == null || exists != null
143                 || INFORMATION_SCHEMA.equals(newName)) {
144             throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS,
145                               schema == null ? name
146                                              : newName);
147         }
148
149         schema.name.rename(newName, isQuoted);
150
151         int index = schemaMap.getIndex(name);
152
153         schemaMap.set(index, newName, schema);
154     }
155
156     void clearStructures() {
157
158         Iterator it = schemaMap.values().iterator();
159
160         while (it.hasNext()) {
161             Schema schema = (Schema) it.next();
162
163             schema.clearStructures();
164         }
165     }
166
167     public Iterator userSchemaNameIterator() {
168         return schemaMap.keySet().iterator();
169     }
170
171     HsqlName toSchemaHsqlName(String JavaDoc name) {
172
173         Schema schema = (Schema) schemaMap.get(name);
174
175         return schema == null ? null
176                               : schema.name;
177     }
178
179     HsqlName getDefaultSchemaHsqlName() {
180         return defaultSchemaHsqlName;
181     }
182
183     public String JavaDoc getDefaultSchemaName() {
184         return defaultSchemaHsqlName.name;
185     }
186
187     boolean schemaExists(String JavaDoc name) {
188
189         if (INFORMATION_SCHEMA.equals(name)) {
190             return true;
191         }
192
193         return schemaMap.containsKey(name);
194     }
195
196     /**
197      * If schemaName is null, return the current schema name, else return
198      * the HsqlName object for the schema. If schemaName does not exist,
199      * throw.
200      */

201     HsqlName getSchemaHsqlName(String JavaDoc name) throws HsqlException {
202
203         if (name == null) {
204             return defaultSchemaHsqlName;
205         }
206
207         if (INFORMATION_SCHEMA.equals(name)) {
208             return INFORMATION_SCHEMA_HSQLNAME;
209         }
210
211         Schema schema = ((Schema) schemaMap.get(name));
212
213         if (schema == null) {
214             throw Trace.error(Trace.INVALID_SCHEMA_NAME_NO_SUBCLASS, name);
215         }
216
217         return schema.name;
218     }
219
220     /**
221      * Same as above, but return string
222      */

223     String JavaDoc getSchemaName(String JavaDoc name) throws HsqlException {
224         return getSchemaHsqlName(name).name;
225     }
226
227     /**
228      * Iterator includes INFORMATION_SCHEMA
229      */

230     Iterator fullSchemaNamesIterator() {
231         return new WrapperIterator(new WrapperIterator(INFORMATION_SCHEMA),
232                                    schemaMap.keySet().iterator());
233     }
234
235     /**
236      * is a schema read-only
237      */

238     public boolean isSystemSchema(HsqlName schema) {
239
240         return (INFORMATION_SCHEMA_HSQLNAME.equals(schema) || SYSTEM_SCHEMA_HSQLNAME.equals(schema))
241                ? true
242                : false;
243     }
244
245     public Iterator tablesIterator(String JavaDoc schema) {
246
247         Schema temp = (Schema) schemaMap.get(schema);
248
249         return temp.tablesIterator();
250     }
251
252     public Iterator allTablesIterator() {
253
254         Iterator schemas = userSchemaNameIterator();
255         Iterator tables = new WrapperIterator();
256
257         while (schemas.hasNext()) {
258             String JavaDoc name = (String JavaDoc) schemas.next();
259             Iterator t = tablesIterator(name);
260
261             tables = new WrapperIterator(tables, t);
262         }
263
264         return tables;
265     }
266
267     Iterator sequenceIterator(String JavaDoc schema) {
268
269         Schema temp = (Schema) schemaMap.get(schema);
270
271         return temp.sequencesIterator();
272     }
273
274     public Iterator allSequencesIterator() {
275
276         Iterator it = schemaMap.values().iterator();
277         Iterator sequences = new WrapperIterator();
278
279         while (it.hasNext()) {
280             Schema temp = (Schema) it.next();
281
282             sequences = new WrapperIterator(sequences,
283                                             temp.sequencesIterator());
284         }
285
286         return sequences;
287     }
288
289     /**
290      * Returns an HsqlArrayList containing references to all non-system
291      * tables and views. This includes all tables and views registered with
292      * this Database.
293      */

294     public HsqlArrayList getAllTables() {
295
296         Iterator schemas = userSchemaNameIterator();
297         HsqlArrayList alltables = new HsqlArrayList();
298
299         while (schemas.hasNext()) {
300             String JavaDoc name = (String JavaDoc) schemas.next();
301             HashMappedList current = getTables(name);
302
303             alltables.addAll(current.values());
304         }
305
306         return alltables;
307     }
308
309     public HashMappedList getTables(String JavaDoc schema) {
310
311         Schema temp = (Schema) schemaMap.get(schema);
312
313         return temp.tableList;
314     }
315
316     /**
317      * @throws HsqlException if exists.
318      */

319     void checkUserViewNotExists(Session session, String JavaDoc viewName,
320                                 String JavaDoc schema) throws HsqlException {
321
322         boolean exists =
323             database.schemaManager.findUserTable(session, viewName, schema)
324             != null;
325
326         if (exists) {
327             throw Trace.error(Trace.VIEW_ALREADY_EXISTS, viewName);
328         }
329     }
330
331     /**
332      * @throws HsqlException if exists
333      */

334     void checkUserTableNotExists(Session session, String JavaDoc tableName,
335                                  String JavaDoc schema) throws HsqlException {
336
337         boolean exists = findUserTable(session, tableName, schema) != null;
338
339         if (exists) {
340             throw Trace.error(Trace.TABLE_ALREADY_EXISTS, tableName);
341         }
342     }
343
344     /**
345      * Returns the specified user-defined table or view visible within the
346      * context of the specified Session, or any system table of the given
347      * name. It excludes any temp tables created in other Sessions.
348      * Throws if the table does not exist in the context.
349      */

350     public Table getTable(Session session, String JavaDoc name,
351                           String JavaDoc schema) throws HsqlException {
352
353         Table t = findUserTable(session, name, schema);
354
355         if (t == null) {
356             if (!INFORMATION_SCHEMA.equals(schema)) {
357                 throw Trace.error(Trace.TABLE_NOT_FOUND);
358             }
359
360             if (database.dbInfo != null) {
361                 t = database.dbInfo.getSystemTable(session, name);
362             }
363         }
364
365         if (t == null) {
366             throw Trace.error(Trace.TABLE_NOT_FOUND, name);
367         }
368
369         return t;
370     }
371
372     /**
373      * Returns the specified user-defined table or view visible within the
374      * context of the specified Session. It excludes system tables and
375      * any temp tables created in different Sessions.
376      * Throws if the table does not exist in the context.
377      */

378     public Table getUserTable(Session session, String JavaDoc name,
379                               String JavaDoc schema) throws HsqlException {
380
381         Table t = findUserTable(session, name, schema);
382
383         if (t == null) {
384             throw Trace.error(Trace.TABLE_NOT_FOUND, name);
385         }
386
387         return t;
388     }
389
390     /**
391      * Returns the specified user-defined table or view visible within the
392      * context of the specified schema. It excludes system tables.
393      * Returns null if the table does not exist in the context.
394      */

395     Table findUserTable(Session session, String JavaDoc name, String JavaDoc schemaName) {
396
397         Schema schema = (Schema) schemaMap.get(schemaName);
398
399         if (schema == null) {
400             return null;
401         }
402
403         for (int i = 0, tsize = schema.tableList.size(); i < tsize; i++) {
404             Table t = (Table) schema.tableList.get(i);
405
406             if (t.equals(session, name)) {
407                 return t;
408             }
409         }
410
411         return null;
412     }
413
414     /**
415      * Registers the specified table or view with this Database.
416      */

417     void linkTable(Table t) {
418
419         Schema schema = (Schema) schemaMap.get(t.getSchemaName());
420
421         schema.tableList.add(t.getName().name, t);
422     }
423
424     NumberSequence getSequence(String JavaDoc name,
425                                String JavaDoc schemaName) throws HsqlException {
426
427         NumberSequence sequence = findSequence(name, schemaName);
428
429         if (sequence == null) {
430             throw Trace.error(Trace.SEQUENCE_NOT_FOUND, name);
431         }
432
433         return sequence;
434     }
435
436     /**
437      * Returns the specified Sequence visible within the
438      * context of the specified Session.
439      */

440     public NumberSequence findSequence(String JavaDoc name,
441                                        String JavaDoc schemaName)
442                                        throws HsqlException {
443
444         Schema schema = (Schema) schemaMap.get(schemaName);
445         NumberSequence sequence = schema.sequenceManager.getSequence(name);
446
447         return sequence;
448     }
449
450     /**
451      * Returns the table that has an index with the given name and schema.
452      */

453     Table findUserTableForIndex(Session session, String JavaDoc name,
454                                 String JavaDoc schemaName) {
455
456         Schema schema = (Schema) schemaMap.get(schemaName);
457         HsqlName tablename = schema.indexNameList.getOwner(name);
458
459         if (tablename == null) {
460             return null;
461         }
462
463         return findUserTable(session, tablename.name, schemaName);
464     }
465
466     /**
467      * Returns index of a table or view in the HsqlArrayList that
468      * contains the table objects for this Database.
469      *
470      * @param table the Table object
471      * @return the index of the specified table or view, or -1 if not found
472      */

473     int getTableIndex(Table table) {
474
475         Schema schema = (Schema) schemaMap.get(table.getSchemaName());
476
477         for (int i = 0, tsize = schema.tableList.size(); i < tsize; i++) {
478             Table t = (Table) schema.tableList.get(i);
479
480             if (t == table) {
481                 return i;
482             }
483         }
484
485         return -1;
486     }
487
488     /**
489      * Drops the index with the specified name.
490      */

491     void dropIndex(Session session, String JavaDoc indexname, String JavaDoc schema,
492                    boolean ifExists) throws HsqlException {
493
494         Table t = findUserTableForIndex(session, indexname, schema);
495
496         if (t == null) {
497             if (ifExists) {
498                 return;
499             } else {
500                 throw Trace.error(Trace.INDEX_NOT_FOUND, indexname);
501             }
502         }
503
504         t.checkDropIndex(indexname, null, false);
505         session.commit();
506         session.setScripting(true);
507
508         TableWorks tw = new TableWorks(session, t);
509
510         tw.dropIndex(indexname);
511     }
512
513     //------------ name management
514

515     /**
516      * Checks if a Trigger with given name either exists or does not, based on
517      * the value of the argument, yes.
518      */

519     void checkTriggerExists(String JavaDoc name, String JavaDoc schemaName,
520                             boolean yes) throws HsqlException {
521
522         Schema schema = (Schema) schemaMap.get(schemaName);
523         boolean exists = schema.triggerNameList.containsName(name);
524
525         if (exists != yes) {
526             int code = yes ? Trace.TRIGGER_NOT_FOUND
527                            : Trace.TRIGGER_ALREADY_EXISTS;
528
529             throw Trace.error(code, name);
530         }
531     }
532
533     void registerTriggerName(String JavaDoc name,
534                              HsqlName tableName) throws HsqlException {
535
536         Schema schema = (Schema) schemaMap.get(tableName.schema.name);
537
538         schema.triggerNameList.addName(name, tableName,
539                                        Trace.TRIGGER_ALREADY_EXISTS);
540     }
541
542     void checkIndexExists(String JavaDoc name, String JavaDoc schemaName,
543                           boolean yes) throws HsqlException {
544
545         Schema schema = (Schema) schemaMap.get(schemaName);
546         boolean exists = schema.indexNameList.containsName(name);
547
548         if (exists != yes) {
549             int code = yes ? Trace.INDEX_NOT_FOUND
550                            : Trace.INDEX_ALREADY_EXISTS;
551
552             throw Trace.error(code, name);
553         }
554     }
555
556     void registerIndexName(String JavaDoc name,
557                            HsqlName tableName) throws HsqlException {
558
559         Schema schema = (Schema) schemaMap.get(tableName.schema.name);
560
561         schema.indexNameList.addName(name, tableName,
562                                      Trace.INDEX_ALREADY_EXISTS);
563     }
564
565     void removeIndexName(String JavaDoc name,
566                          HsqlName tableName) throws HsqlException {
567
568         Schema schema = (Schema) schemaMap.get(tableName.schema.name);
569
570         schema.indexNameList.removeName(name);
571     }
572
573     void removeIndexNames(HsqlName tableName) {
574
575         Schema schema = (Schema) schemaMap.get(tableName.schema.name);
576
577         schema.indexNameList.removeOwner(tableName);
578     }
579
580     void renameIndex(String JavaDoc oldName, String JavaDoc newName,
581                      HsqlName tableName) throws HsqlException {
582
583         Schema schema = (Schema) schemaMap.get(tableName.schema.name);
584
585         schema.indexNameList.rename(oldName, newName,
586                                     Trace.INDEX_ALREADY_EXISTS);
587     }
588
589     void checkConstraintExists(String JavaDoc name, String JavaDoc schemaName,
590                                boolean yes) throws HsqlException {
591
592         Schema schema = (Schema) schemaMap.get(schemaName);
593         boolean exists = schema.constraintNameList.containsName(name);
594
595         if (exists != yes) {
596             int code = yes ? Trace.CONSTRAINT_NOT_FOUND
597                            : Trace.CONSTRAINT_ALREADY_EXISTS;
598
599             throw Trace.error(code, name);
600         }
601     }
602
603     void registerConstraintName(String JavaDoc name,
604                                 HsqlName tableName) throws HsqlException {
605
606         Schema schema = (Schema) schemaMap.get(tableName.schema.name);
607
608         schema.constraintNameList.addName(name, tableName,
609                                           Trace.CONSTRAINT_ALREADY_EXISTS);
610     }
611
612     void removeConstraintName(String JavaDoc name,
613                               HsqlName tableName) throws HsqlException {
614
615         Schema schema = (Schema) schemaMap.get(tableName.schema.name);
616
617         schema.constraintNameList.removeName(name);
618     }
619
620     void removeConstraintNames(HsqlName tableName) {
621
622         Schema schema = (Schema) schemaMap.get(tableName.schema.name);
623
624         schema.constraintNameList.removeOwner(tableName);
625     }
626
627     // sequence
628
NumberSequence createSequence(HsqlName hsqlname, long start,
629                                   long increment,
630                                   int type) throws HsqlException {
631
632         Schema schema = (Schema) schemaMap.get(hsqlname.schema.name);
633
634         return schema.sequenceManager.createSequence(hsqlname, start,
635                 increment, type);
636     }
637
638     void dropSequence(NumberSequence sequence) throws HsqlException {
639
640         Schema schema = (Schema) schemaMap.get(sequence.getSchemaName());
641
642         schema.sequenceManager.dropSequence(sequence.getName().name);
643     }
644
645     void logSequences(Session session, Logger logger) throws HsqlException {
646
647         for (int i = 0, size = schemaMap.size(); i < size; i++) {
648             Schema schema = (Schema) schemaMap.get(i);
649
650             schema.sequenceManager.logSequences(session, logger);
651         }
652     }
653
654     /**
655      * Clear copies of a temporary table from all sessions apart from one.
656      */

657     void clearTempTables(Session exclude, Table table) {
658
659         Session[] sessions = database.sessionManager.getAllSessions();
660         Index[] indexes = table.getIndexes();
661
662         for (int i = 0; i < sessions.length; i++) {
663             if (sessions[i] != exclude) {
664                 for (int j = 0; j < indexes.length; j++) {
665                     sessions[i].dropIndex(indexes[j].getName(), false);
666                 }
667             }
668         }
669     }
670
671     /**
672      * Drops the specified user-defined view or table from this Database
673      * object. <p>
674      *
675      * The process of dropping a table or view includes:
676      * <OL>
677      * <LI> checking that the specified Session's currently connected User
678      * has the right to perform this operation and refusing to proceed if
679      * not by throwing.
680      * <LI> checking for referential constraints that conflict with this
681      * operation and refusing to proceed if they exist by throwing.</LI>
682      *
683      * <LI> removing the specified Table from this Database object.
684      * <LI> removing any exported foreign keys Constraint objects held by
685      * any tables referenced by the table to be dropped. This is especially
686      * important so that the dropped Table ceases to be referenced,
687      * eventually allowing its full garbage collection.
688      * <LI>
689      * </OL>
690      * <p>
691      *
692      * @param name of the table or view to drop
693      * @param ifExists if true and if the Table to drop does not exist, fail
694      * silently, else throw
695      * @param isView true if the name argument refers to a View
696      * @param session the connected context in which to perform this
697      * operation
698      * @throws HsqlException if any of the checks listed above fail
699      */

700     void dropTable(Session session, String JavaDoc name, String JavaDoc schemaName,
701                    boolean ifExists, boolean isView,
702                    boolean cascade) throws HsqlException {
703
704         Table table = null;
705         int dropIndex = -1;
706         Schema schema = (Schema) schemaMap.get(schemaName);
707
708         for (int i = 0; i < schema.tableList.size(); i++) {
709             table = (Table) schema.tableList.get(i);
710
711             if (table.equals(session, name) && isView == table.isView()) {
712                 dropIndex = i;
713
714                 break;
715             } else {
716                 table = null;
717             }
718         }
719
720         if (dropIndex == -1) {
721             if (ifExists) {
722                 return;
723             } else {
724                 throw Trace.error(isView ? Trace.VIEW_NOT_FOUND
725                                          : Trace.TABLE_NOT_FOUND, name);
726             }
727         }
728
729         session.checkAdmin();
730         session.checkDDLWrite();
731
732 // ft - concurrent
733
session.commit();
734         dropTable(table, cascade);
735         session.setScripting(true);
736     }
737
738     void dropTable(Table table, boolean cascade) throws HsqlException {
739
740         Schema schema = (Schema) schemaMap.get(table.getSchemaName());
741         int dropIndex = schema.tableList.getIndex(table.getName().name);
742
743         if (table.isView()) {
744             checkCascadeDropViews((View) table, cascade);
745         } else {
746             checkCascadeDropReferenced(table, cascade);
747             checkCascadeDropViews(table, cascade);
748         }
749
750         // get it again as table object might be a different one
751
table = (Table) schema.tableList.remove(dropIndex);
752
753         removeExportedKeys(table);
754         database.getUserManager().removeDbObject(table.getName());
755         schema.triggerNameList.removeOwner(table.tableName);
756         schema.indexNameList.removeOwner(table.tableName);
757         schema.constraintNameList.removeOwner(table.tableName);
758         table.dropTriggers();
759         table.drop();
760     }
761
762     void setTable(int index, Table table) {
763
764         Schema schema = (Schema) schemaMap.get(table.getSchemaName());
765
766         schema.tableList.set(index, table.getName().name, table);
767     }
768
769     void renameTable(Session session, Table table, String JavaDoc newName,
770                      boolean isQuoted) throws HsqlException {
771
772         Schema schema = (Schema) schemaMap.get(table.tableName.schema.name);
773         int i = schema.tableList.getIndex(table.tableName.name);
774
775         checkCascadeDropViews(table, false);
776         table.rename(session, newName, isQuoted);
777         schema.tableList.setKey(i, newName);
778     }
779
780     /**
781      * Throws if the table is referenced in a foreign key constraint.
782      */

783     private void checkCascadeDropReferenced(Table table,
784             boolean cascade) throws HsqlException {
785
786         Constraint[] constraints = table.getConstraints();
787         Constraint currentConstraint = null;
788         Table refTable = null;
789         boolean isSelfRef = false;
790
791         for (int i = constraints.length - 1; i >= 0; i--) {
792             currentConstraint = constraints[i];
793
794             if (currentConstraint.getType() != Constraint.MAIN) {
795                 continue;
796             }
797
798             refTable = currentConstraint.getRef();
799             isSelfRef = (refTable != null && table.equals(refTable));
800
801             if (isSelfRef) {
802                 continue;
803             }
804
805             if (cascade) {
806                 Constraint refConst =
807                     refTable.getConstraint(currentConstraint.getFkName());
808                 TableWorks tw = new TableWorks(null, refTable);
809
810                 tw.dropFKConstraint(refConst);
811
812                 constraints = table.constraintList;
813                 i = constraints.length;
814             } else {
815                 throw Trace.error(Trace.TABLE_REFERENCED_CONSTRAINT,
816                                   Trace.Database_dropTable, new Object JavaDoc[] {
817                     currentConstraint.getName().name, refTable.getName().name
818                 });
819             }
820         }
821     }
822
823     /**
824      * Throws if the view is referenced in a view.
825      */

826     void checkCascadeDropViews(View view,
827                                boolean cascade) throws HsqlException {
828
829         View[] views = getViewsWithView(view);
830
831         if (views != null) {
832             if (cascade) {
833
834                 // drop from end to avoid repeat drop
835
for (int i = views.length - 1; i >= 0; i--) {
836                     dropTable(views[i], cascade);
837                 }
838             } else {
839                 throw Trace.error(Trace.TABLE_REFERENCED_VIEW,
840                                   views[0].getName().name);
841             }
842         }
843     }
844
845     /**
846      * Throws if the table is referenced in a view.
847      */

848     void checkCascadeDropViews(Table table,
849                                boolean cascade) throws HsqlException {
850
851         View[] views = getViewsWithTable(table, null);
852
853         if (views != null) {
854             if (cascade) {
855
856                 // drop from end to avoid repeat drop
857
for (int i = views.length - 1; i >= 0; i--) {
858                     dropTable(views[i], cascade);
859                 }
860             } else {
861                 throw Trace.error(Trace.TABLE_REFERENCED_VIEW,
862                                   views[0].getName().name);
863             }
864         }
865     }
866
867     /**
868      * Throws if the sequence is referenced in a view.
869      */

870     void checkCascadeDropViews(NumberSequence sequence,
871                                boolean cascade) throws HsqlException {
872
873         View[] views = getViewsWithSequence(sequence);
874
875         if (views != null) {
876             if (cascade) {
877
878                 // drop from end to avoid repeat drop
879
for (int i = views.length - 1; i >= 0; i--) {
880                     dropTable(views[i], cascade);
881                 }
882             } else {
883                 throw Trace.error(Trace.SEQUENCE_REFERENCED_BY_VIEW,
884                                   views[0].getName().name);
885             }
886         }
887     }
888
889     /**
890      * Throws if the column is referenced in a view.
891      */

892     void checkColumnIsInView(Table table,
893                              String JavaDoc column) throws HsqlException {
894
895         View[] views = getViewsWithTable(table, column);
896
897         if (views != null) {
898             throw Trace.error(Trace.COLUMN_IS_REFERENCED,
899                               views[0].getName().name);
900         }
901     }
902
903     /**
904      * Returns an array of views that reference another view.
905      */

906     private View[] getViewsWithView(View view) {
907
908         HsqlArrayList list = null;
909         Schema schema = (Schema) schemaMap.get(view.getSchemaName());
910
911         for (int i = 0; i < schema.tableList.size(); i++) {
912             Table t = (Table) schema.tableList.get(i);
913
914             if (t.isView()) {
915                 boolean found = ((View) t).hasView(view);
916
917                 if (found) {
918                     if (list == null) {
919                         list = new HsqlArrayList();
920                     }
921
922                     list.add(t);
923                 }
924             }
925         }
926
927         return list == null ? null
928                             : (View[]) list.toArray(new View[list.size()]);
929     }
930
931     /**
932      * Returns an array of views that reference the specified table or
933      * the specified column if column parameter is not null.
934      */

935     private View[] getViewsWithTable(Table table, String JavaDoc column) {
936
937         HsqlArrayList list = null;
938         Iterator it = allTablesIterator();
939
940         while (it.hasNext()) {
941             Table t = (Table) it.next();
942
943             if (t.isView()) {
944                 boolean found = column == null ? ((View) t).hasTable(table)
945                                                : ((View) t).hasColumn(table,
946                                                    column);
947
948                 if (found) {
949                     if (list == null) {
950                         list = new HsqlArrayList();
951                     }
952
953                     list.add(t);
954                 }
955             }
956         }
957
958         return list == null ? null
959                             : (View[]) list.toArray(new View[list.size()]);
960     }
961
962     /**
963      * Returns an array of views that reference a sequence.
964      */

965     View[] getViewsWithSequence(NumberSequence sequence) {
966
967         HsqlArrayList list = null;
968         Iterator it = allTablesIterator();
969
970         while (it.hasNext()) {
971             Table t = (Table) it.next();
972
973             if (t.isView()) {
974                 boolean found = ((View) t).hasSequence(sequence);
975
976                 if (found) {
977                     if (list == null) {
978                         list = new HsqlArrayList();
979                     }
980
981                     list.add(t);
982                 }
983             }
984         }
985
986         return list == null ? null
987                             : (View[]) list.toArray(new View[list.size()]);
988     }
989
990     /**
991      * After addition or removal of columns and indexes all views that
992      * reference the table should be recompiled.
993      */

994     void recompileViews(Table table) throws HsqlException {
995
996         View[] viewlist = getViewsWithTable(table, null);
997
998         if (viewlist != null) {
999             for (int i = 0; i < viewlist.length; i++) {
1000                String JavaDoc schema = viewlist[i].compileTimeSchema.name;
1001
1002                if (!schemaExists(schema)) {
1003                    schema = null;
1004                }
1005
1006                Session session =
1007                    database.sessionManager.getSysSession(schema, false);
1008
1009                viewlist[i].compile(session);
1010            }
1011        }
1012    }
1013
1014    /**
1015     * Removes any foreign key Constraint objects (exported keys) held by any
1016     * tables referenced by the specified table. <p>
1017     *
1018     * This method is called as the last step of a successful call to
1019     * dropTable() in order to ensure that the dropped Table ceases to be
1020     * referenced when enforcing referential integrity.
1021     *
1022     * @param toDrop The table to which other tables may be holding keys.
1023     * This is a table that is in the process of being dropped.
1024     */

1025    void removeExportedKeys(Table toDrop) {
1026
1027        Schema schema = (Schema) schemaMap.get(toDrop.getSchemaName());
1028
1029        for (int i = 0; i < schema.tableList.size(); i++) {
1030            Table table = (Table) schema.tableList.get(i);
1031
1032            for (int j = table.constraintList.length - 1; j >= 0; j--) {
1033                Table refTable = table.constraintList[j].getRef();
1034
1035                if (toDrop == refTable) {
1036                    table.constraintList =
1037                        (Constraint[]) ArrayUtil.toAdjustedArray(
1038                            table.constraintList, null, j, -1);
1039                }
1040            }
1041        }
1042    }
1043
1044    /**
1045     * Drops a trigger with the specified name in the given context.
1046     */

1047    void dropTrigger(Session session, String JavaDoc name,
1048                     String JavaDoc schemaName) throws HsqlException {
1049
1050        Schema schema = (Schema) schemaMap.get(schemaName);
1051        boolean found = schema.triggerNameList.containsName(name);
1052
1053        Trace.check(found, Trace.TRIGGER_NOT_FOUND, name);
1054
1055        HsqlName tableName =
1056            (HsqlName) schema.triggerNameList.removeName(name);
1057        Table t = this.findUserTable(session, tableName.name, schemaName);
1058
1059        t.dropTrigger(name);
1060        session.setScripting(true);
1061    }
1062
1063    public class Schema {
1064
1065        HsqlName name;
1066        DatabaseObjectNames triggerNameList;
1067        DatabaseObjectNames constraintNameList;
1068        DatabaseObjectNames indexNameList;
1069        SequenceManager sequenceManager;
1070        HashMappedList tableList;
1071
1072        Schema(String JavaDoc name, boolean isquoted) {
1073
1074            this.name = database.nameManager.newHsqlName(name, isquoted);
1075            triggerNameList = new DatabaseObjectNames();
1076            indexNameList = new DatabaseObjectNames();
1077            constraintNameList = new DatabaseObjectNames();
1078            sequenceManager = new SequenceManager();
1079            tableList = new HashMappedList();
1080        }
1081
1082        boolean isEmpty() {
1083            return sequenceManager.sequenceMap.isEmpty()
1084                   && tableList.isEmpty();
1085        }
1086
1087        Iterator tablesIterator() {
1088            return tableList.values().iterator();
1089        }
1090
1091        Iterator sequencesIterator() {
1092            return sequenceManager.sequenceMap.values().iterator();
1093        }
1094
1095        void clearStructures() {
1096
1097            if (tableList != null) {
1098                for (int i = 0; i < tableList.size(); i++) {
1099                    Table table = (Table) tableList.get(i);
1100
1101                    table.dropTriggers();
1102                }
1103            }
1104
1105            triggerNameList = null;
1106            indexNameList = null;
1107            constraintNameList = null;
1108            sequenceManager = null;
1109            tableList = null;
1110        }
1111    }
1112}
1113
Popular Tags