EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.schema]

COVERAGE SUMMARY FOR SOURCE FILE [Schema.java]

nameclass, %method, %block, %line, %
Schema.java100% (1/1)94%  (32/34)87%  (800/917)91%  (188.3/208)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Schema100% (1/1)94%  (32/34)87%  (800/917)91%  (188.3/208)
getCreateSQLForCopy (Table, String): String 0%   (0/1)0%   (0/2)0%   (0/1)
getDropSQL (): String 0%   (0/1)0%   (0/2)0%   (0/1)
rename (SchemaObject, String): void 100% (1/1)69%  (46/67)86%  (12/14)
remove (SchemaObject): void 100% (1/1)69%  (22/32)86%  (6/7)
add (SchemaObject): void 100% (1/1)69%  (29/42)78%  (7/9)
getAllTablesAndViews (): ArrayList 100% (1/1)71%  (12/17)67%  (2/3)
getConstant (String): Constant 100% (1/1)71%  (10/14)75%  (3/4)
getConstraint (String): Constraint 100% (1/1)71%  (10/14)75%  (3/4)
getIndex (String): Index 100% (1/1)71%  (10/14)75%  (3/4)
getSequence (String): Sequence 100% (1/1)71%  (10/14)75%  (3/4)
freeUniqueName (String): void 100% (1/1)76%  (16/21)94%  (4.7/5)
getMap (int): HashMap 100% (1/1)76%  (32/42)94%  (16/17)
removeChildrenAndResources (Session): void 100% (1/1)84%  (150/178)84%  (32/38)
getUniqueName (DbObject, HashMap, String): String 100% (1/1)95%  (93/98)98%  (16.6/17)
Schema (Database, int, String, User, boolean): void 100% (1/1)100% (46/46)100% (13/13)
canDrop (): boolean 100% (1/1)100% (7/7)100% (1/1)
checkRename (): void 100% (1/1)100% (1/1)100% (1/1)
createTable (CreateTableData): Table 100% (1/1)100% (64/64)100% (15/15)
createTableLink (int, String, String, String, String, String, String, String,... 100% (1/1)100% (27/27)100% (3/3)
findConstant (String): Constant 100% (1/1)100% (6/6)100% (1/1)
findConstraint (Session, String): Constraint 100% (1/1)100% (14/14)100% (4/4)
findFunction (String): FunctionAlias 100% (1/1)100% (6/6)100% (1/1)
findIndex (Session, String): Index 100% (1/1)100% (14/14)100% (4/4)
findSequence (String): Sequence 100% (1/1)100% (6/6)100% (1/1)
findTableOrView (Session, String): Table 100% (1/1)100% (16/16)100% (4/4)
findTrigger (String): TriggerObject 100% (1/1)100% (6/6)100% (1/1)
getAll (): ArrayList 100% (1/1)100% (53/53)100% (9/9)
getAll (int): ArrayList 100% (1/1)100% (8/8)100% (2/2)
getCreateSQL (): String 100% (1/1)100% (21/21)100% (3/3)
getOwner (): User 100% (1/1)100% (3/3)100% (1/1)
getTableOrView (Session, String): Table 100% (1/1)100% (22/22)100% (7/7)
getType (): int 100% (1/1)100% (2/2)100% (1/1)
getUniqueConstraintName (Session, Table): String 100% (1/1)100% (19/19)100% (4/4)
getUniqueIndexName (Session, Table, String): String 100% (1/1)100% (19/19)100% (4/4)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.schema;
7 
8import java.util.ArrayList;
9import java.util.HashMap;
10import java.util.HashSet;
11 
12import org.h2.api.ErrorCode;
13import org.h2.api.TableEngine;
14import org.h2.command.ddl.CreateTableData;
15import org.h2.constraint.Constraint;
16import org.h2.engine.Database;
17import org.h2.engine.DbObject;
18import org.h2.engine.DbObjectBase;
19import org.h2.engine.FunctionAlias;
20import org.h2.engine.Session;
21import org.h2.engine.SysProperties;
22import org.h2.engine.User;
23import org.h2.index.Index;
24import org.h2.message.DbException;
25import org.h2.message.Trace;
26import org.h2.mvstore.db.MVTableEngine;
27import org.h2.table.RegularTable;
28import org.h2.table.Table;
29import org.h2.table.TableLink;
30import org.h2.util.JdbcUtils;
31import org.h2.util.New;
32 
33/**
34 * A schema as created by the SQL statement
35 * CREATE SCHEMA
36 */
37public class Schema extends DbObjectBase {
38 
39    private User owner;
40    private final boolean system;
41 
42    private final HashMap<String, Table> tablesAndViews;
43    private final HashMap<String, Index> indexes;
44    private final HashMap<String, Sequence> sequences;
45    private final HashMap<String, TriggerObject> triggers;
46    private final HashMap<String, Constraint> constraints;
47    private final HashMap<String, Constant> constants;
48    private final HashMap<String, FunctionAlias> functions;
49 
50    /**
51     * The set of returned unique names that are not yet stored. It is used to
52     * avoid returning the same unique name twice when multiple threads
53     * concurrently create objects.
54     */
55    private final HashSet<String> temporaryUniqueNames = New.hashSet();
56 
57    /**
58     * Create a new schema object.
59     *
60     * @param database the database
61     * @param id the object id
62     * @param schemaName the schema name
63     * @param owner the owner of the schema
64     * @param system if this is a system schema (such a schema can not be
65     *            dropped)
66     */
67    public Schema(Database database, int id, String schemaName, User owner,
68            boolean system) {
69        tablesAndViews = database.newStringMap();
70        indexes = database.newStringMap();
71        sequences = database.newStringMap();
72        triggers = database.newStringMap();
73        constraints = database.newStringMap();
74        constants = database.newStringMap();
75        functions = database.newStringMap();
76        initDbObjectBase(database, id, schemaName, Trace.SCHEMA);
77        this.owner = owner;
78        this.system = system;
79    }
80 
81    /**
82     * Check if this schema can be dropped. System schemas can not be dropped.
83     *
84     * @return true if it can be dropped
85     */
86    public boolean canDrop() {
87        return !system;
88    }
89 
90    @Override
91    public String getCreateSQLForCopy(Table table, String quotedName) {
92        throw DbException.throwInternalError();
93    }
94 
95    @Override
96    public String getDropSQL() {
97        return null;
98    }
99 
100    @Override
101    public String getCreateSQL() {
102        if (system) {
103            return null;
104        }
105        return "CREATE SCHEMA IF NOT EXISTS " +
106            getSQL() + " AUTHORIZATION " + owner.getSQL();
107    }
108 
109    @Override
110    public int getType() {
111        return DbObject.SCHEMA;
112    }
113 
114    @Override
115    public void removeChildrenAndResources(Session session) {
116        while (triggers != null && triggers.size() > 0) {
117            TriggerObject obj = (TriggerObject) triggers.values().toArray()[0];
118            database.removeSchemaObject(session, obj);
119        }
120        while (constraints != null && constraints.size() > 0) {
121            Constraint obj = (Constraint) constraints.values().toArray()[0];
122            database.removeSchemaObject(session, obj);
123        }
124        // There can be dependencies between tables e.g. using computed columns,
125        // so we might need to loop over them multiple times.
126        boolean runLoopAgain = false;
127        do {
128            runLoopAgain = false;
129            if (tablesAndViews != null) {
130                // Loop over a copy because the map is modified underneath us.
131                for (Table obj : New.arrayList(tablesAndViews.values())) {
132                    // Check for null because multiple tables might be deleted
133                    // in one go underneath us.
134                    if (obj.getName() != null) {
135                        if (database.getDependentTable(obj, obj) == null) {
136                            database.removeSchemaObject(session, obj);
137                        } else {
138                            runLoopAgain = true;
139                        }
140                    }
141                }
142            }
143        } while (runLoopAgain);
144        while (indexes != null && indexes.size() > 0) {
145            Index obj = (Index) indexes.values().toArray()[0];
146            database.removeSchemaObject(session, obj);
147        }
148        while (sequences != null && sequences.size() > 0) {
149            Sequence obj = (Sequence) sequences.values().toArray()[0];
150            database.removeSchemaObject(session, obj);
151        }
152        while (constants != null && constants.size() > 0) {
153            Constant obj = (Constant) constants.values().toArray()[0];
154            database.removeSchemaObject(session, obj);
155        }
156        while (functions != null && functions.size() > 0) {
157            FunctionAlias obj = (FunctionAlias) functions.values().toArray()[0];
158            database.removeSchemaObject(session, obj);
159        }
160        database.removeMeta(session, getId());
161        owner = null;
162        invalidate();
163    }
164 
165    @Override
166    public void checkRename() {
167        // ok
168    }
169 
170    /**
171     * Get the owner of this schema.
172     *
173     * @return the owner
174     */
175    public User getOwner() {
176        return owner;
177    }
178 
179    @SuppressWarnings("unchecked")
180    private HashMap<String, SchemaObject> getMap(int type) {
181        HashMap<String, ? extends SchemaObject> result;
182        switch (type) {
183        case DbObject.TABLE_OR_VIEW:
184            result = tablesAndViews;
185            break;
186        case DbObject.SEQUENCE:
187            result = sequences;
188            break;
189        case DbObject.INDEX:
190            result = indexes;
191            break;
192        case DbObject.TRIGGER:
193            result = triggers;
194            break;
195        case DbObject.CONSTRAINT:
196            result = constraints;
197            break;
198        case DbObject.CONSTANT:
199            result = constants;
200            break;
201        case DbObject.FUNCTION_ALIAS:
202            result = functions;
203            break;
204        default:
205            throw DbException.throwInternalError("type=" + type);
206        }
207        return (HashMap<String, SchemaObject>) result;
208    }
209 
210    /**
211     * Add an object to this schema.
212     * This method must not be called within CreateSchemaObject;
213     * use Database.addSchemaObject() instead
214     *
215     * @param obj the object to add
216     */
217    public void add(SchemaObject obj) {
218        if (SysProperties.CHECK && obj.getSchema() != this) {
219            DbException.throwInternalError("wrong schema");
220        }
221        String name = obj.getName();
222        HashMap<String, SchemaObject> map = getMap(obj.getType());
223        if (SysProperties.CHECK && map.get(name) != null) {
224            DbException.throwInternalError("object already exists: " + name);
225        }
226        map.put(name, obj);
227        freeUniqueName(name);
228    }
229 
230    /**
231     * Rename an object.
232     *
233     * @param obj the object to rename
234     * @param newName the new name
235     */
236    public void rename(SchemaObject obj, String newName) {
237        int type = obj.getType();
238        HashMap<String, SchemaObject> map = getMap(type);
239        if (SysProperties.CHECK) {
240            if (!map.containsKey(obj.getName())) {
241                DbException.throwInternalError("not found: " + obj.getName());
242            }
243            if (obj.getName().equals(newName) || map.containsKey(newName)) {
244                DbException.throwInternalError("object already exists: " + newName);
245            }
246        }
247        obj.checkRename();
248        map.remove(obj.getName());
249        freeUniqueName(obj.getName());
250        obj.rename(newName);
251        map.put(newName, obj);
252        freeUniqueName(newName);
253    }
254 
255    /**
256     * Try to find a table or view with this name. This method returns null if
257     * no object with this name exists. Local temporary tables are also
258     * returned.
259     *
260     * @param session the session
261     * @param name the object name
262     * @return the object or null
263     */
264    public Table findTableOrView(Session session, String name) {
265        Table table = tablesAndViews.get(name);
266        if (table == null && session != null) {
267            table = session.findLocalTempTable(name);
268        }
269        return table;
270    }
271 
272    /**
273     * Try to find an index with this name. This method returns null if
274     * no object with this name exists.
275     *
276     * @param session the session
277     * @param name the object name
278     * @return the object or null
279     */
280    public Index findIndex(Session session, String name) {
281        Index index = indexes.get(name);
282        if (index == null) {
283            index = session.findLocalTempTableIndex(name);
284        }
285        return index;
286    }
287 
288    /**
289     * Try to find a trigger with this name. This method returns null if
290     * no object with this name exists.
291     *
292     * @param name the object name
293     * @return the object or null
294     */
295    public TriggerObject findTrigger(String name) {
296        return triggers.get(name);
297    }
298 
299    /**
300     * Try to find a sequence with this name. This method returns null if
301     * no object with this name exists.
302     *
303     * @param sequenceName the object name
304     * @return the object or null
305     */
306    public Sequence findSequence(String sequenceName) {
307        return sequences.get(sequenceName);
308    }
309 
310    /**
311     * Try to find a constraint with this name. This method returns null if no
312     * object with this name exists.
313     *
314     * @param session the session
315     * @param name the object name
316     * @return the object or null
317     */
318    public Constraint findConstraint(Session session, String name) {
319        Constraint constraint = constraints.get(name);
320        if (constraint == null) {
321            constraint = session.findLocalTempTableConstraint(name);
322        }
323        return constraint;
324    }
325 
326    /**
327     * Try to find a user defined constant with this name. This method returns
328     * null if no object with this name exists.
329     *
330     * @param constantName the object name
331     * @return the object or null
332     */
333    public Constant findConstant(String constantName) {
334        return constants.get(constantName);
335    }
336 
337    /**
338     * Try to find a user defined function with this name. This method returns
339     * null if no object with this name exists.
340     *
341     * @param functionAlias the object name
342     * @return the object or null
343     */
344    public FunctionAlias findFunction(String functionAlias) {
345        return functions.get(functionAlias);
346    }
347 
348    /**
349     * Release a unique object name.
350     *
351     * @param name the object name
352     */
353    public void freeUniqueName(String name) {
354        if (name != null) {
355            synchronized (temporaryUniqueNames) {
356                temporaryUniqueNames.remove(name);
357            }
358        }
359    }
360 
361    private String getUniqueName(DbObject obj,
362            HashMap<String, ? extends SchemaObject> map, String prefix) {
363        String hash = Integer.toHexString(obj.getName().hashCode()).toUpperCase();
364        String name = null;
365        synchronized (temporaryUniqueNames) {
366            for (int i = 1, len = hash.length(); i < len; i++) {
367                name = prefix + hash.substring(0, i);
368                if (!map.containsKey(name) && !temporaryUniqueNames.contains(name)) {
369                    break;
370                }
371                name = null;
372            }
373            if (name == null) {
374                prefix = prefix + hash + "_";
375                for (int i = 0;; i++) {
376                    name = prefix + i;
377                    if (!map.containsKey(name) && !temporaryUniqueNames.contains(name)) {
378                        break;
379                    }
380                }
381            }
382            temporaryUniqueNames.add(name);
383        }
384        return name;
385    }
386 
387    /**
388     * Create a unique constraint name.
389     *
390     * @param session the session
391     * @param table the constraint table
392     * @return the unique name
393     */
394    public String getUniqueConstraintName(Session session, Table table) {
395        HashMap<String, Constraint> tableConstraints;
396        if (table.isTemporary() && !table.isGlobalTemporary()) {
397            tableConstraints = session.getLocalTempTableConstraints();
398        } else {
399            tableConstraints = constraints;
400        }
401        return getUniqueName(table, tableConstraints, "CONSTRAINT_");
402    }
403 
404    /**
405     * Create a unique index name.
406     *
407     * @param session the session
408     * @param table the indexed table
409     * @param prefix the index name prefix
410     * @return the unique name
411     */
412    public String getUniqueIndexName(Session session, Table table, String prefix) {
413        HashMap<String, Index> tableIndexes;
414        if (table.isTemporary() && !table.isGlobalTemporary()) {
415            tableIndexes = session.getLocalTempTableIndexes();
416        } else {
417            tableIndexes = indexes;
418        }
419        return getUniqueName(table, tableIndexes, prefix);
420    }
421 
422    /**
423     * Get the table or view with the given name.
424     * Local temporary tables are also returned.
425     *
426     * @param session the session
427     * @param name the table or view name
428     * @return the table or view
429     * @throws DbException if no such object exists
430     */
431    public Table getTableOrView(Session session, String name) {
432        Table table = tablesAndViews.get(name);
433        if (table == null) {
434            if (session != null) {
435                table = session.findLocalTempTable(name);
436            }
437            if (table == null) {
438                throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, name);
439            }
440        }
441        return table;
442    }
443 
444    /**
445     * Get the index with the given name.
446     *
447     * @param name the index name
448     * @return the index
449     * @throws DbException if no such object exists
450     */
451    public Index getIndex(String name) {
452        Index index = indexes.get(name);
453        if (index == null) {
454            throw DbException.get(ErrorCode.INDEX_NOT_FOUND_1, name);
455        }
456        return index;
457    }
458 
459    /**
460     * Get the constraint with the given name.
461     *
462     * @param name the constraint name
463     * @return the constraint
464     * @throws DbException if no such object exists
465     */
466    public Constraint getConstraint(String name) {
467        Constraint constraint = constraints.get(name);
468        if (constraint == null) {
469            throw DbException.get(ErrorCode.CONSTRAINT_NOT_FOUND_1, name);
470        }
471        return constraint;
472    }
473 
474    /**
475     * Get the user defined constant with the given name.
476     *
477     * @param constantName the constant name
478     * @return the constant
479     * @throws DbException if no such object exists
480     */
481    public Constant getConstant(String constantName) {
482        Constant constant = constants.get(constantName);
483        if (constant == null) {
484            throw DbException.get(ErrorCode.CONSTANT_NOT_FOUND_1, constantName);
485        }
486        return constant;
487    }
488 
489    /**
490     * Get the sequence with the given name.
491     *
492     * @param sequenceName the sequence name
493     * @return the sequence
494     * @throws DbException if no such object exists
495     */
496    public Sequence getSequence(String sequenceName) {
497        Sequence sequence = sequences.get(sequenceName);
498        if (sequence == null) {
499            throw DbException.get(ErrorCode.SEQUENCE_NOT_FOUND_1, sequenceName);
500        }
501        return sequence;
502    }
503 
504    /**
505     * Get all objects.
506     *
507     * @return a (possible empty) list of all objects
508     */
509    public ArrayList<SchemaObject> getAll() {
510        ArrayList<SchemaObject> all = New.arrayList();
511        all.addAll(getMap(DbObject.TABLE_OR_VIEW).values());
512        all.addAll(getMap(DbObject.SEQUENCE).values());
513        all.addAll(getMap(DbObject.INDEX).values());
514        all.addAll(getMap(DbObject.TRIGGER).values());
515        all.addAll(getMap(DbObject.CONSTRAINT).values());
516        all.addAll(getMap(DbObject.CONSTANT).values());
517        all.addAll(getMap(DbObject.FUNCTION_ALIAS).values());
518        return all;
519    }
520 
521    /**
522     * Get all objects of the given type.
523     *
524     * @param type the object type
525     * @return a (possible empty) list of all objects
526     */
527    public ArrayList<SchemaObject> getAll(int type) {
528        HashMap<String, SchemaObject> map = getMap(type);
529        return New.arrayList(map.values());
530    }
531 
532    /**
533     * Get all tables and views.
534     *
535     * @return a (possible empty) list of all objects
536     */
537    public ArrayList<Table> getAllTablesAndViews() {
538        synchronized (database) {
539            return New.arrayList(tablesAndViews.values());
540        }
541    }
542 
543    /**
544     * Remove an object from this schema.
545     *
546     * @param obj the object to remove
547     */
548    public void remove(SchemaObject obj) {
549        String objName = obj.getName();
550        HashMap<String, SchemaObject> map = getMap(obj.getType());
551        if (SysProperties.CHECK && !map.containsKey(objName)) {
552            DbException.throwInternalError("not found: " + objName);
553        }
554        map.remove(objName);
555        freeUniqueName(objName);
556    }
557 
558    /**
559     * Add a table to the schema.
560     *
561     * @param data the create table information
562     * @return the created {@link Table} object
563     */
564    public Table createTable(CreateTableData data) {
565        synchronized (database) {
566            if (!data.temporary || data.globalTemporary) {
567                database.lockMeta(data.session);
568            }
569            data.schema = this;
570            if (data.tableEngine == null) {
571                if (database.getSettings().mvStore) {
572                    data.tableEngine = MVTableEngine.class.getName();
573                }
574            }
575            if (data.tableEngine != null) {
576                TableEngine engine;
577                try {
578                    engine = (TableEngine) JdbcUtils.loadUserClass(data.tableEngine).newInstance();
579                } catch (Exception e) {
580                    throw DbException.convert(e);
581                }
582                return engine.createTable(data);
583            }
584            return new RegularTable(data);
585        }
586    }
587 
588    /**
589     * Add a linked table to the schema.
590     *
591     * @param id the object id
592     * @param tableName the table name of the alias
593     * @param driver the driver class name
594     * @param url the database URL
595     * @param user the user name
596     * @param password the password
597     * @param originalSchema the schema name of the target table
598     * @param originalTable the table name of the target table
599     * @param emitUpdates if updates should be emitted instead of delete/insert
600     * @param force create the object even if the database can not be accessed
601     * @return the {@link TableLink} object
602     */
603    public TableLink createTableLink(int id, String tableName, String driver,
604            String url, String user, String password, String originalSchema,
605            String originalTable, boolean emitUpdates, boolean force) {
606        synchronized (database) {
607            return new TableLink(this, id, tableName,
608                    driver, url, user, password,
609                    originalSchema, originalTable, emitUpdates, force);
610        }
611    }
612 
613}

[all classes][org.h2.schema]
EMMA 2.0.5312 (C) Vladimir Roubtsov