All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hsqldb.SchemaManager Maven / Gradle / Ivy

There is a newer version: 2.7.2
Show newest version
/* Copyright (c) 2001-2019, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.hsqldb.HsqlNameManager.HsqlName;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.lib.HashMappedList;
import org.hsqldb.lib.HsqlArrayList;
import org.hsqldb.lib.Iterator;
import org.hsqldb.lib.MultiValueHashMap;
import org.hsqldb.lib.OrderedHashSet;
import org.hsqldb.lib.StringConverter;
import org.hsqldb.lib.WrapperIterator;
import org.hsqldb.navigator.RowIterator;
import org.hsqldb.rights.Grantee;
import org.hsqldb.types.Charset;
import org.hsqldb.types.Collation;
import org.hsqldb.types.Type;

/**
 * Manages all SCHEMA related database objects
 *
 * @author Fred Toussi (fredt@users dot sourceforge.net)
 * @version 2.5.0
 * @since 1.8.0
 */
public class SchemaManager {

    Database          database;
    HsqlName          defaultSchemaHsqlName;
    HashMappedList    schemaMap        = new HashMappedList();
    MultiValueHashMap referenceMap     = new MultiValueHashMap();
    int               defaultTableType = TableBase.MEMORY_TABLE;
    long              schemaChangeTimestamp;
    HsqlName[]        catalogNameArray;

    //
    ReadWriteLock lock      = new ReentrantReadWriteLock();
    Lock          readLock  = lock.readLock();
    Lock          writeLock = lock.writeLock();

    //
    Table        dualTable;
    public Table dataChangeTable;

    public SchemaManager(Database database) {

        this.database         = database;
        defaultSchemaHsqlName = SqlInvariants.INFORMATION_SCHEMA_HSQLNAME;
        catalogNameArray      = new HsqlName[]{ database.getCatalogName() };

        Schema schema =
            new Schema(SqlInvariants.INFORMATION_SCHEMA_HSQLNAME,
                       SqlInvariants.INFORMATION_SCHEMA_HSQLNAME.owner);

        schemaMap.put(schema.getName().name, schema);

        try {
            schema.charsetLookup.add(Charset.SQL_TEXT, false);
            schema.charsetLookup.add(Charset.SQL_IDENTIFIER_CHARSET, false);
            schema.charsetLookup.add(Charset.SQL_CHARACTER, false);
            schema.collationLookup.add(Collation.getDefaultInstance(), false);
            schema.collationLookup.add(
                Collation.getDefaultIgnoreCaseInstance(), false);
            schema.typeLookup.add(TypeInvariants.CARDINAL_NUMBER, false);
            schema.typeLookup.add(TypeInvariants.YES_OR_NO, false);
            schema.typeLookup.add(TypeInvariants.CHARACTER_DATA, false);
            schema.typeLookup.add(TypeInvariants.SQL_IDENTIFIER, false);
            schema.typeLookup.add(TypeInvariants.TIME_STAMP, false);
            schema.typeLookup.add(TypeInvariants.NCNAME, false);
            schema.typeLookup.add(TypeInvariants.URI, false);
        } catch (HsqlException e) {}
    }

    public void setSchemaChangeTimestamp() {
        schemaChangeTimestamp = database.txManager.getGlobalChangeTimestamp();
    }

    public long getSchemaChangeTimestamp() {
        return schemaChangeTimestamp;
    }

    // pre-defined
    public HsqlName getSQLJSchemaHsqlName() {
        return SqlInvariants.SQLJ_SCHEMA_HSQLNAME;
    }

    // SCHEMA management
    public void createPublicSchema() {

        writeLock.lock();

        try {
            HsqlName name = database.nameManager.newHsqlName(null,
                SqlInvariants.PUBLIC_SCHEMA, SchemaObject.SCHEMA);
            Schema schema =
                new Schema(name, database.getGranteeManager().getDBARole());

            defaultSchemaHsqlName = schema.getName();

            schemaMap.put(schema.getName().name, schema);
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * Creates a schema belonging to the given grantee.
     */
    public void createSchema(HsqlName name, Grantee owner) {

        writeLock.lock();

        try {
            SqlInvariants.checkSchemaNameNotSystem(name.name);

            Schema schema = new Schema(name, owner);

            schemaMap.add(name.name, schema);
        } finally {
            writeLock.unlock();
        }
    }

    public void dropSchema(Session session, String name, boolean cascade) {

        writeLock.lock();

        try {
            Schema schema = (Schema) schemaMap.get(name);

            if (schema == null) {
                throw Error.error(ErrorCode.X_42501, name);
            }

            if (SqlInvariants.isLobsSchemaName(name)) {
                throw Error.error(ErrorCode.X_42503, name);
            }

            if (!cascade && !schema.isEmpty()) {
                throw Error.error(ErrorCode.X_2B000);
            }

            OrderedHashSet externalReferences = new OrderedHashSet();

            getCascadingReferencesToSchema(schema.getName(),
                                           externalReferences);
            removeSchemaObjects(externalReferences);

            Iterator tableIterator =
                schema.schemaObjectIterator(SchemaObject.TABLE);

            while (tableIterator.hasNext()) {
                Table        table = ((Table) tableIterator.next());
                Constraint[] list  = table.getFKConstraints();

                for (int i = 0; i < list.length; i++) {
                    Constraint constraint = list[i];

                    if (constraint.getMain().getSchemaName()
                            != schema.getName()) {
                        constraint.getMain().removeConstraint(
                            constraint.getMainName().name);
                        removeReferencesFrom(constraint);
                    }
                }

                removeTable(session, table);
            }

            Iterator sequenceIterator =
                schema.schemaObjectIterator(SchemaObject.SEQUENCE);

            while (sequenceIterator.hasNext()) {
                NumberSequence sequence =
                    ((NumberSequence) sequenceIterator.next());

                database.getGranteeManager().removeDbObject(
                    sequence.getName());
            }

            schema.release();
            schemaMap.remove(name);

            if (defaultSchemaHsqlName.name.equals(name)) {
                schema = new Schema(defaultSchemaHsqlName,
                                    database.getGranteeManager().getDBARole());
                defaultSchemaHsqlName = schema.getName();

                schemaMap.put(schema.getName().name, schema);
            } else {
                HsqlName schemaName = schema.getName();

                // these are called last and in this particular order
                database.getUserManager().removeSchemaReference(schemaName);
                database.getSessionManager().removeSchemaReference(schemaName);
            }
        } finally {
            writeLock.unlock();
        }
    }

    public void renameSchema(HsqlName name, HsqlName newName) {

        writeLock.lock();

        try {
            Schema schema = (Schema) schemaMap.get(name.name);
            Schema exists = (Schema) schemaMap.get(newName.name);

            if (schema == null) {
                throw Error.error(ErrorCode.X_42501, name.name);
            }

            if (exists != null) {
                throw Error.error(ErrorCode.X_42504, newName.name);
            }

            SqlInvariants.checkSchemaNameNotSystem(name.name);
            SqlInvariants.checkSchemaNameNotSystem(newName.name);

            int index = schemaMap.getIndex(name.name);

            schema.getName().rename(newName);
            schemaMap.set(index, newName.name, schema);
        } finally {
            writeLock.unlock();
        }
    }

    public void release() {

        writeLock.lock();

        try {
            Iterator it = schemaMap.values().iterator();

            while (it.hasNext()) {
                Schema schema = (Schema) it.next();

                schema.release();
            }
        } finally {
            writeLock.unlock();
        }
    }

    public String[] getSchemaNamesArray() {

        readLock.lock();

        try {
            String[] array = new String[schemaMap.size()];

            schemaMap.toKeysArray(array);

            return array;
        } finally {
            readLock.unlock();
        }
    }

    public Schema[] getAllSchemas() {

        readLock.lock();

        try {
            Schema[] objects = new Schema[schemaMap.size()];

            schemaMap.toValuesArray(objects);

            return objects;
        } finally {
            readLock.unlock();
        }
    }

    public HsqlName getUserSchemaHsqlName(String name) {

        readLock.lock();

        try {
            Schema schema = (Schema) schemaMap.get(name);

            if (schema == null) {
                throw Error.error(ErrorCode.X_3F000, name);
            }

            if (schema.getName()
                    == SqlInvariants.INFORMATION_SCHEMA_HSQLNAME) {
                throw Error.error(ErrorCode.X_3F000, name);
            }

            return schema.getName();
        } finally {
            readLock.unlock();
        }
    }

    public Grantee toSchemaOwner(String name) {

        readLock.lock();

        try {
            Schema schema = (Schema) schemaMap.get(name);

            return schema == null ? null
                                  : schema.getOwner();
        } finally {
            readLock.unlock();
        }
    }

    public HsqlName getDefaultSchemaHsqlName() {
        return defaultSchemaHsqlName;
    }

    public void setDefaultSchemaHsqlName(HsqlName name) {
        defaultSchemaHsqlName = name;
    }

    public boolean schemaExists(String name) {

        readLock.lock();

        try {
            return schemaMap.containsKey(name);
        } finally {
            readLock.unlock();
        }
    }

    public HsqlName findSchemaHsqlName(String name) {

        readLock.lock();

        try {
            Schema schema = ((Schema) schemaMap.get(name));

            if (schema == null) {
                return null;
            }

            return schema.getName();
        } finally {
            readLock.unlock();
        }
    }

    /**
     * If schemaName is null, return the default schema name, else return
     * the HsqlName object for the schema. If schemaName does not exist,
     * throw.
     */
    public HsqlName getSchemaHsqlName(String name) {

        if (name == null) {
            return defaultSchemaHsqlName;
        }

        readLock.lock();

        try {
            Schema schema = ((Schema) schemaMap.get(name));

            if (schema == null) {
                throw Error.error(ErrorCode.X_3F000, name);
            }

            return schema.getName();
        } finally {
            readLock.unlock();
        }
    }

    /**
     * Same as above, but return string
     */
    public String getSchemaName(String name) {
        return getSchemaHsqlName(name).name;
    }

    public Schema findSchema(String name) {

        readLock.lock();

        try {
            return ((Schema) schemaMap.get(name));
        } finally {
            readLock.unlock();
        }
    }

    /**
     * drop all schemas with the given authorisation
     */
    public void dropSchemas(Session session, Grantee grantee,
                            boolean cascade) {

        writeLock.lock();

        try {
            HsqlArrayList list = getSchemas(grantee);
            Iterator      it   = list.iterator();

            while (it.hasNext()) {
                Schema schema = (Schema) it.next();

                dropSchema(session, schema.getName().name, cascade);
            }
        } finally {
            writeLock.unlock();
        }
    }

    public HsqlArrayList getSchemas(Grantee grantee) {

        readLock.lock();

        try {
            HsqlArrayList list = new HsqlArrayList();
            Iterator      it   = schemaMap.values().iterator();

            while (it.hasNext()) {
                Schema schema = (Schema) it.next();

                if (grantee.equals(schema.getOwner())) {
                    list.add(schema);
                }
            }

            return list;
        } finally {
            readLock.unlock();
        }
    }

    public boolean hasSchemas(Grantee grantee) {

        readLock.lock();

        try {
            Iterator it = schemaMap.values().iterator();

            while (it.hasNext()) {
                Schema schema = (Schema) it.next();

                if (grantee.equals(schema.getOwner())) {
                    return true;
                }
            }

            return false;
        } finally {
            readLock.unlock();
        }
    }

    /**
     *  Returns an HsqlArrayList containing references to all non-system
     *  tables and views. This includes all tables and views registered with
     *  this Database.
     */
    public HsqlArrayList getAllTables(boolean withLobTables) {

        readLock.lock();

        try {
            HsqlArrayList alltables = new HsqlArrayList();
            String[]      schemas   = getSchemaNamesArray();

            for (int i = 0; i < schemas.length; i++) {
                String name = schemas[i];

                if (!withLobTables && SqlInvariants.isLobsSchemaName(name)) {
                    continue;
                }

                if (SqlInvariants.isSystemSchemaName(name)) {
                    continue;
                }

                HashMappedList current = getTables(name);

                alltables.addAll(current.values());
            }

            return alltables;
        } finally {
            readLock.unlock();
        }
    }

    public HashMappedList getTables(String schema) {

        readLock.lock();

        try {
            Schema temp = (Schema) schemaMap.get(schema);

            return temp.tableList;
        } finally {
            readLock.unlock();
        }
    }

    public HsqlName[] getCatalogNameArray() {
        return catalogNameArray;
    }

    public HsqlName[] getCatalogAndBaseTableNames() {

        readLock.lock();

        try {
            OrderedHashSet names  = new OrderedHashSet();
            HsqlArrayList  tables = getAllTables(false);

            for (int i = 0; i < tables.size(); i++) {
                Table table = (Table) tables.get(i);

                if (!table.isTemp()) {
                    names.add(table.getName());
                }
            }

            names.add(database.getCatalogName());

            HsqlName[] array = new HsqlName[names.size()];

            names.toArray(array);

            return array;
        } finally {
            readLock.unlock();
        }
    }

    public HsqlName[] getCatalogAndBaseTableNames(HsqlName name) {

        if (name == null) {
            return catalogNameArray;
        }

        readLock.lock();

        try {
            switch (name.type) {

                case SchemaObject.SCHEMA : {
                    if (findSchemaHsqlName(name.name) == null) {
                        return catalogNameArray;
                    }

                    OrderedHashSet names = new OrderedHashSet();

                    names.add(database.getCatalogName());

                    HashMappedList list = getTables(name.name);

                    for (int i = 0; i < list.size(); i++) {
                        names.add(((SchemaObject) list.get(i)).getName());
                    }

                    HsqlName[] array = new HsqlName[names.size()];

                    names.toArray(array);

                    return array;
                }
                case SchemaObject.GRANTEE : {
                    return catalogNameArray;
                }
                case SchemaObject.INDEX :
                case SchemaObject.CONSTRAINT :
                default :
            }

            SchemaObject object = findSchemaObject(name.name,
                                                   name.schema.name,
                                                   name.type);

            if (object == null) {
                return catalogNameArray;
            }

            HsqlName       parent     = object.getName().parent;
            OrderedHashSet references = getReferencesTo(object.getName());
            OrderedHashSet names      = new OrderedHashSet();

            names.add(database.getCatalogName());

            if (parent != null) {
                SchemaObject parentObject = findSchemaObject(parent.name,
                    parent.schema.name, parent.type);

                if (parentObject != null
                        && parentObject.getName().type == SchemaObject.TABLE) {
                    names.add(parentObject.getName());
                }
            }

            if (object.getName().type == SchemaObject.TABLE) {
                names.add(object.getName());
            }

            for (int i = 0; i < references.size(); i++) {
                HsqlName reference = (HsqlName) references.get(i);

                if (reference.type == SchemaObject.TABLE) {
                    Table table = findUserTable(reference.name,
                                                reference.schema.name);

                    if (table != null && !table.isTemp()) {
                        names.add(reference);
                    }
                }
            }

            HsqlName[] array = new HsqlName[names.size()];

            names.toArray(array);

            return array;
        } finally {
            readLock.unlock();
        }
    }

    private SchemaObjectSet getSchemaObjectSet(Schema schema, int type) {

        SchemaObjectSet set = null;

        switch (type) {

            case SchemaObject.SEQUENCE :
                set = schema.sequenceLookup;
                break;

            case SchemaObject.TABLE :
            case SchemaObject.VIEW :
                set = schema.tableLookup;
                break;

            case SchemaObject.CHARSET :
                set = schema.charsetLookup;
                break;

            case SchemaObject.COLLATION :
                set = schema.collationLookup;
                break;

            case SchemaObject.PROCEDURE :
                set = schema.procedureLookup;
                break;

            case SchemaObject.FUNCTION :
                set = schema.functionLookup;
                break;

            case SchemaObject.DOMAIN :
            case SchemaObject.TYPE :
                set = schema.typeLookup;
                break;

            case SchemaObject.INDEX :
                set = schema.indexLookup;
                break;

            case SchemaObject.CONSTRAINT :
                set = schema.constraintLookup;
                break;

            case SchemaObject.TRIGGER :
                set = schema.triggerLookup;
                break;

            case SchemaObject.SPECIFIC_ROUTINE :
                set = schema.specificRoutineLookup;
                break;

            case SchemaObject.REFERENCE :
                set = schema.referenceLookup;
                break;

            default :
                throw Error.runtimeError(ErrorCode.U_S0500, "SchemaObjectSet");
        }

        return set;
    }

    public void checkSchemaObjectNotExists(HsqlName name) {

        readLock.lock();

        try {
            Schema          schema = (Schema) schemaMap.get(name.schema.name);
            SchemaObjectSet set    = getSchemaObjectSet(schema, name.type);

            set.checkAdd(name);
        } finally {
            readLock.unlock();
        }
    }

    public Table getUserTable(HsqlName name) {
        return getUserTable(name.name, name.schema.name);
    }

    /**
     *  Returns the specified user-defined table or view visible within the
     *  context of the specified Session.
     *  Throws if the table does not exist in the context.
     */
    public Table getUserTable(String name, String schema) {

        Table t = findUserTable(name, schema);

        if (t == null) {
            String longName = schema == null ? name
                                             : schema + '.' + name;

            throw Error.error(ErrorCode.X_42501, longName);
        }

        return t;
    }

    /**
     *  Returns the specified user-defined table or view visible within the
     *  context of the specified schema. It excludes system tables.
     *  Returns null if the table does not exist in the context.
     */
    public Table findUserTable(String name, String schemaName) {

        readLock.lock();

        try {
            Schema schema = (Schema) schemaMap.get(schemaName);

            if (schema == null) {
                return null;
            }

            int i = schema.tableList.getIndex(name);

            if (i == -1) {
                return null;
            }

            return (Table) schema.tableList.get(i);
        } finally {
            readLock.unlock();
        }
    }

    /**
     *  Returns the specified session context table.
     *  Returns null if the table does not exist in the context.
     */
    public Table findSessionTable(Session session, String name) {
        return session.sessionContext.findSessionTable(name);
    }

    /**
     * Drops the specified user-defined view or table from this Database object.
     *
     * 

The process of dropping a table or view includes: *

    *
  1. checking that the specified Session's currently connected User has * the right to perform this operation and refusing to proceed if not by * throwing. *
  2. checking for referential constraints that conflict with this * operation and refusing to proceed if they exist by throwing.
  3. *
  4. removing the specified Table from this Database object. *
  5. removing any exported foreign keys Constraint objects held by any * tables referenced by the table to be dropped. This is especially * important so that the dropped Table ceases to be referenced, eventually * allowing its full garbage collection. *
  6. *
* *

* * @param session the connected context in which to perform this operation * @param table if true and if the Table to drop does not exist, fail * silently, else throw * @param cascade true if the name argument refers to a View */ public void dropTableOrView(Session session, Table table, boolean cascade) { writeLock.lock(); try { if (table.isView()) { dropView(table, cascade); } else { dropTable(session, table, cascade); } } finally { writeLock.unlock(); } } private void dropView(Table table, boolean cascade) { Schema schema = (Schema) schemaMap.get(table.getSchemaName().name); removeSchemaObject(table.getName(), cascade); removeTableDependentReferences(table); schema.triggerLookup.removeParent(table.getName()); } private void dropTable(Session session, Table table, boolean cascade) { Schema schema = (Schema) schemaMap.get(table.getSchemaName().name); OrderedHashSet externalConstraints = table.getDependentExternalConstraints(); OrderedHashSet externalReferences = new OrderedHashSet(); getCascadingReferencesTo(table.getName(), externalReferences); if (!cascade) { for (int i = 0; i < externalConstraints.size(); i++) { Constraint c = (Constraint) externalConstraints.get(i); HsqlName refname = c.getRefName(); if (c.getConstraintType() == SchemaObject.ConstraintTypes.MAIN) { throw Error.error( ErrorCode.X_42533, refname.getSchemaQualifiedStatementName()); } } if (!externalReferences.isEmpty()) { int i = 0; for (; i < externalReferences.size(); i++) { HsqlName name = (HsqlName) externalReferences.get(i); if (name.parent == table.getName()) { continue; } throw Error.error(ErrorCode.X_42502, name.getSchemaQualifiedStatementName()); } } } OrderedHashSet tableSet = new OrderedHashSet(); OrderedHashSet constraintNameSet = new OrderedHashSet(); OrderedHashSet indexNameSet = new OrderedHashSet(); for (int i = 0; i < externalConstraints.size(); i++) { Constraint c = (Constraint) externalConstraints.get(i); Table t = c.getMain(); if (t != table) { tableSet.add(t); } t = c.getRef(); if (t != table) { tableSet.add(t); } constraintNameSet.add(c.getMainName()); constraintNameSet.add(c.getRefName()); indexNameSet.add(c.getRefIndex().getName()); } OrderedHashSet uniqueConstraintNames = table.getUniquePKConstraintNames(); TableWorks tw = new TableWorks(session, table); tableSet = tw.dropConstraintsAndIndexes(tableSet, constraintNameSet, indexNameSet); tw.setNewTablesInSchema(tableSet); tw.updateConstraints(tableSet, constraintNameSet); removeSchemaObjects(externalReferences); removeTableDependentReferences(table); removeReferencesTo(uniqueConstraintNames); removeReferencesTo(table.getName()); removeReferencesFrom(table); schema.tableList.remove(table.getName().name); schema.indexLookup.removeParent(table.getName()); schema.constraintLookup.removeParent(table.getName()); schema.triggerLookup.removeParent(table.getName()); removeTable(session, table); recompileDependentObjects(tableSet); } private void removeTable(Session session, Table table) { database.getGranteeManager().removeDbObject(table.getName()); table.releaseTriggers(); if (!table.isView() && table.hasLobColumn()) { RowIterator it = table.rowIterator(session); while (it.next()) { Object[] data = it.getCurrent(); session.sessionData.adjustLobUsageCount(table, data, -1); } } if (table.tableType == TableBase.TEMP_TABLE) { Session[] sessions = database.sessionManager.getAllSessions(); for (int i = 0; i < sessions.length; i++) { sessions[i].sessionData.persistentStoreCollection.removeStore( table); } } else { database.persistentStoreCollection.removeStore(table); } } public void setTable(int index, Table table) { writeLock.lock(); try { Schema schema = (Schema) schemaMap.get(table.getSchemaName().name); schema.tableList.set(index, table.getName().name, table); } finally { writeLock.unlock(); } } /** * Returns index of a table or view in the HashMappedList that * contains the table objects for this Database. * * @param table the Table object * @return the index of the specified table or view, or -1 if not found */ public int getTableIndex(Table table) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(table.getSchemaName().name); if (schema == null) { return -1; } HsqlName name = table.getName(); return schema.tableList.getIndex(name.name); } finally { readLock.unlock(); } } public void recompileDependentObjects(OrderedHashSet tableSet) { writeLock.lock(); try { OrderedHashSet set = new OrderedHashSet(); for (int i = 0; i < tableSet.size(); i++) { Table table = (Table) tableSet.get(i); set.addAll(getReferencesTo(table.getName())); } Session session = database.sessionManager.getSysSession(); for (int i = 0; i < set.size(); i++) { HsqlName name = (HsqlName) set.get(i); switch (name.type) { case SchemaObject.VIEW : case SchemaObject.CONSTRAINT : case SchemaObject.ASSERTION : case SchemaObject.ROUTINE : case SchemaObject.PROCEDURE : case SchemaObject.FUNCTION : case SchemaObject.SPECIFIC_ROUTINE : case SchemaObject.TRIGGER : SchemaObject object = getSchemaObject(name); object.compile(session, null); break; default : } } if (Error.TRACE) { HsqlArrayList list = getAllTables(false); for (int i = 0; i < list.size(); i++) { Table t = (Table) list.get(i); t.verifyConstraintsIntegrity(); } } } finally { writeLock.unlock(); } } /** * After addition or removal of columns and indexes all views that * reference the table should be recompiled. */ public void recompileDependentObjects(Table table) { writeLock.lock(); try { OrderedHashSet set = new OrderedHashSet(); getCascadingReferencesTo(table.getName(), set); Session session = database.sessionManager.getSysSession(); for (int i = 0; i < set.size(); i++) { HsqlName name = (HsqlName) set.get(i); switch (name.type) { case SchemaObject.VIEW : case SchemaObject.CONSTRAINT : case SchemaObject.ASSERTION : case SchemaObject.ROUTINE : case SchemaObject.PROCEDURE : case SchemaObject.FUNCTION : case SchemaObject.SPECIFIC_ROUTINE : case SchemaObject.TRIGGER : SchemaObject object = getSchemaObject(name); object.compile(session, null); break; default : } } if (Error.TRACE) { HsqlArrayList list = getAllTables(false); for (int i = 0; i < list.size(); i++) { Table t = (Table) list.get(i); t.verifyConstraintsIntegrity(); } } } finally { writeLock.unlock(); } } public Collation getCollation(Session session, String name, String schemaName) { Collation collation = null; if (schemaName == null || SqlInvariants.INFORMATION_SCHEMA.equals(schemaName)) { try { collation = Collation.getCollation(name); } catch (HsqlException e) {} } if (collation == null) { schemaName = session.getSchemaName(schemaName); collation = (Collation) getSchemaObject(name, schemaName, SchemaObject.COLLATION); } return collation; } public NumberSequence findSequence(Session session, String name, String schemaName) { NumberSequence seq = getSequence(name, session.getSchemaName(schemaName), false); if (seq == null && schemaName == null) { schemaName = session.getSchemaName(null); ReferenceObject ref = findSynonym(name, schemaName, SchemaObject.SEQUENCE); if (ref != null) { seq = getSequence(ref.target.name, ref.target.schema.name, false); } } return seq; } public NumberSequence getSequence(String name, String schemaName, boolean raise) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(schemaName); if (schema != null) { NumberSequence object = (NumberSequence) schema.sequenceList.get(name); if (object != null) { return object; } } if (raise) { throw Error.error(ErrorCode.X_42501, name); } return null; } finally { readLock.unlock(); } } public Type getUserDefinedType(String name, String schemaName, boolean raise) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(schemaName); if (schema != null) { SchemaObject object = schema.typeLookup.getObject(name); if (object != null) { return (Type) object; } } if (raise) { throw Error.error(ErrorCode.X_42501, name); } return null; } finally { readLock.unlock(); } } public Type findDomainOrUDT(Session session, String name, String prefix, String prePrefix, String prePrePrefix) { readLock.lock(); try { Type type = (Type) findSchemaObject(session, name, prefix, prePrefix, SchemaObject.TYPE); return type; } finally { readLock.unlock(); } } public Type getDomain(String name, String schemaName, boolean raise) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(schemaName); if (schema != null) { SchemaObject object = schema.typeLookup.getObject(name); if (object != null && ((Type) object).isDomainType()) { return (Type) object; } } if (raise) { throw Error.error(ErrorCode.X_42501, name); } return null; } finally { readLock.unlock(); } } public Type getDistinctType(String name, String schemaName, boolean raise) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(schemaName); if (schema != null) { SchemaObject object = schema.typeLookup.getObject(name); if (object != null && ((Type) object).isDistinctType()) { return (Type) object; } } if (raise) { throw Error.error(ErrorCode.X_42501, name); } return null; } finally { readLock.unlock(); } } public SchemaObject getSchemaObject(String name, String schemaName, int type) { readLock.lock(); try { SchemaObject object = findSchemaObject(name, schemaName, type); if (object == null) { throw Error.error(SchemaObjectSet.getGetErrorCode(type), name); } return object; } finally { readLock.unlock(); } } public SchemaObject getCharacterSet(Session session, String name, String schemaName) { if (schemaName == null || SqlInvariants.INFORMATION_SCHEMA.equals(schemaName)) { if (name.equals("SQL_IDENTIFIER")) { return Charset.SQL_IDENTIFIER_CHARSET; } if (name.equals("SQL_TEXT")) { return Charset.SQL_TEXT; } if (name.equals("LATIN1")) { return Charset.LATIN1; } if (name.equals("ASCII_GRAPHIC")) { return Charset.ASCII_GRAPHIC; } } if (schemaName == null) { schemaName = session.getSchemaName(null); } return getSchemaObject(name, schemaName, SchemaObject.CHARSET); } public Table findTable(Session session, String name, String prefix, String prePrefix) { Table t; if (prefix == null) { t = findSessionTable(session, name); if (t != null) { return t; } } if (prePrefix == null) { if (Tokens.T_SESSION.equals(prefix)) { t = findSessionTable(session, name); if (t != null) { return t; } } else if (SqlInvariants.INFORMATION_SCHEMA.equals(prefix) && database.dbInfo != null) { t = database.dbInfo.getSystemTable(session, name); if (t != null) { return t; } } } t = (Table) findSchemaObject(session, name, prefix, prePrefix, SchemaObject.TABLE); return t; } public SchemaObject findSchemaObject(Session session, String name, String prefix, String prePrefix, int type) { SchemaObject object; switch (type) { case SchemaObject.TABLE : case SchemaObject.ROUTINE : case SchemaObject.PROCEDURE : case SchemaObject.FUNCTION : case SchemaObject.TYPE : if (prefix == null) { if (session.database.sqlSyntaxOra || session.database.sqlSyntaxDb2 || session.isProcessingScript()) { if (type == SchemaObject.TABLE && Tokens.T_DUAL.equals(name)) { return dualTable; } } if (type == SchemaObject.TABLE) { // in future there will be a default module for // session tables and variables and anonymous // procedural sql blocks, which can eliminate this code Table t = findSessionTable(session, name); if (t != null) { return t; } } } else if (prePrefix == null) { if (type == SchemaObject.TABLE && Tokens.T_MODULE.equals(prefix)) { Table t = findSessionTable(session, name); if (t != null) { return t; } } if (type == SchemaObject.TABLE && Tokens.T_SESSION.equals(prefix)) { Table t = findSessionTable(session, name); if (t != null) { return t; } } } } if (prefix == null) { prefix = session.getSchemaName(null); } // catalog resolution here if (prePrefix != null && !prePrefix.equals(database.getCatalogName().name)) { return null; } if (type == SchemaObject.TABLE && SqlInvariants.INFORMATION_SCHEMA.equals(prefix) && database.dbInfo != null) { Table t = database.dbInfo.getSystemTable(session, name); if (t != null) { return t; } } return findSchemaObject(name, prefix, type); } public ReferenceObject findSynonym(String name, String schemaName, int type) { Schema schema = (Schema) schemaMap.get(schemaName); if (schema == null) { return null; } ReferenceObject reference = schema.findReference(name, type); return reference; } public SchemaObject findAnySchemaObjectForSynonym(String name, String schemaName) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(schemaName); if (schema == null) { return null; } return schema.findAnySchemaObjectForSynonym(name); } finally { readLock.unlock(); } } public SchemaObject findSchemaObject(String name, String schemaName, int type) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(schemaName); if (schema == null) { return null; } return schema.findSchemaObject(name, type); } finally { readLock.unlock(); } } // INDEX management /** * Returns the table that has an index with the given name and schema. */ Table findUserTableForIndex(Session session, String name, String schemaName) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(schemaName); HsqlName indexName = schema.indexLookup.getName(name); if (indexName == null) { return null; } return findUserTable(indexName.parent.name, schemaName); } finally { readLock.unlock(); } } /** * Drops the index with the specified name. */ void dropIndex(Session session, HsqlName name) { writeLock.lock(); try { Table t = getUserTable(name.parent.name, name.parent.schema.name); TableWorks tw = new TableWorks(session, t); tw.dropIndex(name.name); } finally { writeLock.unlock(); } } /** * Drops the constraint with the specified name. */ void dropConstraint(Session session, HsqlName name, boolean cascade) { writeLock.lock(); try { Table t = getUserTable(name.parent.name, name.parent.schema.name); TableWorks tw = new TableWorks(session, t); tw.dropConstraint(name.name, cascade); } finally { writeLock.unlock(); } } void removeDependentObjects(HsqlName name) { writeLock.lock(); try { Schema schema = (Schema) schemaMap.get(name.schema.name); schema.indexLookup.removeParent(name); schema.constraintLookup.removeParent(name); schema.triggerLookup.removeParent(name); } finally { writeLock.unlock(); } } /** * Removes any foreign key Constraint objects (exported keys) held by any * tables referenced by the specified table.

* * This method is called as the last step of a successful call to * dropTable() in order to ensure that the dropped Table ceases to be * referenced when enforcing referential integrity. * * @param toDrop The table to which other tables may be holding keys. * This is a table that is in the process of being dropped. */ void removeExportedKeys(Table toDrop) { writeLock.lock(); try { // toDrop.schema may be null because it is not registered Schema schema = (Schema) schemaMap.get(toDrop.getSchemaName().name); for (int i = 0; i < schema.tableList.size(); i++) { Table table = (Table) schema.tableList.get(i); Constraint[] constraints = table.getConstraints(); for (int j = constraints.length - 1; j >= 0; j--) { Table refTable = constraints[j].getRef(); if (toDrop == refTable) { table.removeConstraint(j); } } } } finally { writeLock.unlock(); } } public Iterator databaseObjectIterator(String schemaName, int type) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(schemaName); return schema.schemaObjectIterator(type); } finally { readLock.unlock(); } } public Iterator databaseObjectIterator(int type) { readLock.lock(); try { Iterator it = schemaMap.values().iterator(); Iterator objects = new WrapperIterator(); while (it.hasNext()) { int targetType = type; if (type == SchemaObject.ROUTINE) { targetType = SchemaObject.FUNCTION; } Schema temp = (Schema) it.next(); SchemaObjectSet set = temp.getObjectSet(targetType); Object[] values; if (set.map.size() != 0) { values = new Object[set.map.size()]; set.map.valuesToArray(values); objects = new WrapperIterator(objects, new WrapperIterator(values)); } if (type == SchemaObject.ROUTINE) { set = temp.getObjectSet(SchemaObject.PROCEDURE); if (set.map.size() != 0) { values = new Object[set.map.size()]; set.map.valuesToArray(values); objects = new WrapperIterator(objects, new WrapperIterator(values)); } } } return objects; } finally { readLock.unlock(); } } // references private void addReferencesFrom(SchemaObject object) { OrderedHashSet set = object.getReferences(); HsqlName name = object.getName(); if (object instanceof Routine) { name = ((Routine) object).getSpecificName(); } if (set == null) { return; } for (int i = 0; i < set.size(); i++) { HsqlName referenced = (HsqlName) set.get(i); referenceMap.put(referenced, name); } } private void removeReferencesTo(OrderedHashSet set) { for (int i = 0; i < set.size(); i++) { HsqlName referenced = (HsqlName) set.get(i); referenceMap.remove(referenced); } } private void removeReferencesTo(HsqlName referenced) { referenceMap.remove(referenced); } private void removeReferencesFrom(SchemaObject object) { HsqlName name = object.getName(); OrderedHashSet set = object.getReferences(); if (object instanceof Routine) { name = ((Routine) object).getSpecificName(); } if (set == null) { return; } for (int i = 0; i < set.size(); i++) { HsqlName referenced = (HsqlName) set.get(i); referenceMap.remove(referenced, name); } } private void removeTableDependentReferences(Table table) { OrderedHashSet mainSet = table.getReferencesForDependents(); for (int i = 0; i < mainSet.size(); i++) { HsqlName name = (HsqlName) mainSet.get(i); SchemaObject object = null; switch (name.type) { case SchemaObject.CONSTRAINT : object = table.getConstraint(name.name); break; case SchemaObject.TRIGGER : object = table.getTrigger(name.name); break; case SchemaObject.COLUMN : object = table.getColumn(table.getColumnIndex(name.name)); break; default : continue; } removeReferencesFrom(object); } } public OrderedHashSet getReferencesTo(HsqlName object) { readLock.lock(); try { OrderedHashSet set = new OrderedHashSet(); Iterator it = referenceMap.get(object); while (it.hasNext()) { HsqlName name = (HsqlName) it.next(); set.add(name); } return set; } finally { readLock.unlock(); } } public OrderedHashSet getReferencesTo(HsqlName table, HsqlName column) { readLock.lock(); try { OrderedHashSet set = new OrderedHashSet(); Iterator it = referenceMap.get(table); while (it.hasNext()) { HsqlName name = (HsqlName) it.next(); SchemaObject object = getSchemaObject(name); OrderedHashSet references = object.getReferences(); if (references.contains(column)) { set.add(name); } } it = referenceMap.get(column); while (it.hasNext()) { HsqlName name = (HsqlName) it.next(); set.add(name); } return set; } finally { readLock.unlock(); } } private boolean isReferenced(HsqlName object) { writeLock.lock(); try { return referenceMap.containsKey(object); } finally { writeLock.unlock(); } } // public void getCascadingReferencesTo(HsqlName object, OrderedHashSet set) { readLock.lock(); try { OrderedHashSet newSet = new OrderedHashSet(); Iterator it = referenceMap.get(object); while (it.hasNext()) { HsqlName name = (HsqlName) it.next(); boolean added = set.add(name); if (added) { newSet.add(name); } } for (int i = 0; i < newSet.size(); i++) { HsqlName name = (HsqlName) newSet.get(i); getCascadingReferencesTo(name, set); } } finally { readLock.unlock(); } } public void getCascadingReferencesToSchema(HsqlName schema, OrderedHashSet set) { Iterator mainIterator = referenceMap.keySet().iterator(); while (mainIterator.hasNext()) { HsqlName name = (HsqlName) mainIterator.next(); if (name.schema != schema) { continue; } getCascadingReferencesTo(name, set); } for (int i = set.size() - 1; i >= 0; i--) { HsqlName name = (HsqlName) set.get(i); if (name.schema == schema) { set.remove(i); } } } public MultiValueHashMap getReferencesToSchema(String schemaName) { MultiValueHashMap map = new MultiValueHashMap(); Iterator mainIterator = referenceMap.keySet().iterator(); while (mainIterator.hasNext()) { HsqlName name = (HsqlName) mainIterator.next(); if (!name.schema.name.equals(schemaName)) { continue; } Iterator it = referenceMap.get(name); while (it.hasNext()) { map.put(name, it.next()); } } return map; } // public HsqlName getSchemaObjectName(HsqlName schemaName, String name, int type, boolean raise) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(schemaName.name); SchemaObjectSet set = null; if (schema == null) { if (raise) { throw Error.error(SchemaObjectSet.getGetErrorCode(type)); } else { return null; } } if (type == SchemaObject.ROUTINE) { set = schema.functionLookup; SchemaObject object = schema.functionLookup.getObject(name); if (object == null) { set = schema.procedureLookup; object = schema.procedureLookup.getObject(name); } } else { set = getSchemaObjectSet(schema, type); } if (raise) { set.checkExists(name); } return set.getName(name); } finally { readLock.unlock(); } } public SchemaObject getSchemaObject(HsqlName name) { readLock.lock(); try { Schema schema = (Schema) schemaMap.get(name.schema.name); if (schema == null) { return null; } switch (name.type) { case SchemaObject.SEQUENCE : return (SchemaObject) schema.sequenceList.get(name.name); case SchemaObject.TABLE : case SchemaObject.VIEW : return (SchemaObject) schema.tableList.get(name.name); case SchemaObject.CHARSET : return schema.charsetLookup.getObject(name.name); case SchemaObject.COLLATION : return schema.collationLookup.getObject(name.name); case SchemaObject.PROCEDURE : return schema.procedureLookup.getObject(name.name); case SchemaObject.FUNCTION : return schema.functionLookup.getObject(name.name); case RoutineSchema.SPECIFIC_ROUTINE : return schema.specificRoutineLookup.getObject(name.name); case RoutineSchema.ROUTINE : SchemaObject object = schema.functionLookup.getObject(name.name); if (object == null) { object = schema.procedureLookup.getObject(name.name); } return object; case SchemaObject.DOMAIN : case SchemaObject.TYPE : return schema.typeLookup.getObject(name.name); case SchemaObject.TRIGGER : { name = schema.triggerLookup.getName(name.name); if (name == null) { return null; } HsqlName tableName = name.parent; Table table = (Table) schema.tableList.get(tableName.name); return table.getTrigger(name.name); } case SchemaObject.CONSTRAINT : { name = schema.constraintLookup.getName(name.name); if (name == null) { return null; } HsqlName tableName = name.parent; Table table = (Table) schema.tableList.get(tableName.name); return table.getConstraint(name.name); } case SchemaObject.ASSERTION : return null; case SchemaObject.INDEX : name = schema.indexLookup.getName(name.name); if (name == null) { return null; } HsqlName tableName = name.parent; Table table = (Table) schema.tableList.get(tableName.name); return table.getUserIndex(name.name); case SchemaObject.REFERENCE : return schema.referenceLookup.getObject(name.name); } return null; } finally { readLock.unlock(); } } public void checkColumnIsReferenced(HsqlName tableName, HsqlName name) { OrderedHashSet set = getReferencesTo(tableName, name); if (!set.isEmpty()) { HsqlName objectName = (HsqlName) set.get(0); throw Error.error(ErrorCode.X_42502, objectName.getSchemaQualifiedStatementName()); } } public void checkObjectIsReferenced(HsqlName name) { OrderedHashSet set = getReferencesTo(name); HsqlName refName = null; for (int i = 0; i < set.size(); i++) { refName = (HsqlName) set.get(i); // except columns of same table if (refName.parent != name) { break; } refName = null; } if (refName == null) { return; } if (name.type == SchemaObject.CONSTRAINT) { return; } int errorCode = ErrorCode.X_42502; if (refName.type == SchemaObject.ConstraintTypes.FOREIGN_KEY) { errorCode = ErrorCode.X_42533; } throw Error.error(errorCode, refName.getSchemaQualifiedStatementName()); } public void checkSchemaNameCanChange(HsqlName name) { readLock.lock(); try { Iterator it = referenceMap.values().iterator(); HsqlName refName = null; mainLoop: while (it.hasNext()) { refName = (HsqlName) it.next(); switch (refName.type) { case SchemaObject.VIEW : case SchemaObject.ROUTINE : case SchemaObject.FUNCTION : case SchemaObject.PROCEDURE : case SchemaObject.TRIGGER : case SchemaObject.SPECIFIC_ROUTINE : if (refName.schema == name) { break mainLoop; } break; default : } refName = null; } if (refName == null) { return; } throw Error.error(ErrorCode.X_42502, refName.getSchemaQualifiedStatementName()); } finally { readLock.unlock(); } } public void addSchemaObject(SchemaObject object) { writeLock.lock(); try { HsqlName name = object.getName(); Schema schema = (Schema) schemaMap.get(name.schema.name); switch (name.type) { case SchemaObject.TABLE : { OrderedHashSet refs = ((Table) object).getReferencesForDependents(); for (int i = 0; i < refs.size(); i++) { HsqlName ref = (HsqlName) refs.get(i); switch (ref.type) { case SchemaObject.COLUMN : { int index = ((Table) object).findColumn(ref.name); ColumnSchema column = ((Table) object).getColumn(index); addSchemaObject(column); break; } } } break; } case SchemaObject.COLUMN : { OrderedHashSet refs = object.getReferences(); if (refs == null || refs.isEmpty()) { return; } addReferencesFrom(object); return; } } schema.addSchemaObject(database.nameManager, object, false); addReferencesFrom(object); } finally { writeLock.unlock(); } } public void removeSchemaObject(HsqlName name, boolean cascade) { writeLock.lock(); try { OrderedHashSet objectSet = new OrderedHashSet(); switch (name.type) { case SchemaObject.ROUTINE : case SchemaObject.PROCEDURE : case SchemaObject.FUNCTION : { RoutineSchema routine = (RoutineSchema) getSchemaObject(name); if (routine != null) { Routine[] specifics = routine.getSpecificRoutines(); for (int i = 0; i < specifics.length; i++) { getCascadingReferencesTo( specifics[i].getSpecificName(), objectSet); } } } break; case SchemaObject.SEQUENCE : case SchemaObject.TABLE : case SchemaObject.VIEW : case SchemaObject.TYPE : case SchemaObject.CHARSET : case SchemaObject.COLLATION : case SchemaObject.SPECIFIC_ROUTINE : getCascadingReferencesTo(name, objectSet); break; case SchemaObject.DOMAIN : OrderedHashSet set = getReferencesTo(name); Iterator it = set.iterator(); while (it.hasNext()) { HsqlName ref = (HsqlName) it.next(); if (ref.type == SchemaObject.COLUMN) { it.remove(); } } if (!set.isEmpty()) { HsqlName objectName = (HsqlName) set.get(0); throw Error.error( ErrorCode.X_42502, objectName.getSchemaQualifiedStatementName()); } break; } if (objectSet.isEmpty()) { removeSchemaObject(name); return; } if (!cascade) { HsqlName objectName = (HsqlName) objectSet.get(0); throw Error.error( ErrorCode.X_42502, objectName.getSchemaQualifiedStatementName()); } objectSet.add(name); removeSchemaObjects(objectSet); } finally { writeLock.unlock(); } } public void removeSchemaObjects(OrderedHashSet set) { writeLock.lock(); try { for (int i = 0; i < set.size(); i++) { HsqlName name = (HsqlName) set.get(i); if (name.parent != null) { removeSchemaObject(name); } } for (int i = 0; i < set.size(); i++) { HsqlName name = (HsqlName) set.get(i); if (name.parent == null) { removeSchemaObject(name); } } } finally { writeLock.unlock(); } } public void removeSchemaObject(HsqlName name) { writeLock.lock(); try { Schema schema = (Schema) schemaMap.get(name.schema.name); SchemaObject object = null; SchemaObjectSet set = null; switch (name.type) { case SchemaObject.SEQUENCE : set = schema.sequenceLookup; object = set.getObject(name.name); break; case SchemaObject.TABLE : case SchemaObject.VIEW : { set = schema.tableLookup; object = set.getObject(name.name); break; } case SchemaObject.COLUMN : { Table table = (Table) getSchemaObject(name.parent); if (table != null) { object = table.getColumn(table.getColumnIndex(name.name)); } break; } case SchemaObject.CHARSET : set = schema.charsetLookup; object = set.getObject(name.name); break; case SchemaObject.COLLATION : set = schema.collationLookup; object = set.getObject(name.name); break; case SchemaObject.PROCEDURE : { set = schema.procedureLookup; RoutineSchema routine = (RoutineSchema) set.getObject(name.name); object = routine; Routine[] specifics = routine.getSpecificRoutines(); for (int i = 0; i < specifics.length; i++) { removeSchemaObject(specifics[i].getSpecificName()); } break; } case SchemaObject.FUNCTION : { set = schema.functionLookup; RoutineSchema routine = (RoutineSchema) set.getObject(name.name); object = routine; Routine[] specifics = routine.getSpecificRoutines(); for (int i = 0; i < specifics.length; i++) { removeSchemaObject(specifics[i].getSpecificName()); } break; } case SchemaObject.SPECIFIC_ROUTINE : { set = schema.specificRoutineLookup; Routine routine = (Routine) set.getObject(name.name); object = routine; routine.routineSchema.removeSpecificRoutine(routine); if (routine.routineSchema.getSpecificRoutines().length == 0) { removeSchemaObject(routine.getName()); } break; } case SchemaObject.DOMAIN : case SchemaObject.TYPE : set = schema.typeLookup; object = set.getObject(name.name); break; case SchemaObject.INDEX : set = schema.indexLookup; break; case SchemaObject.CONSTRAINT : { set = schema.constraintLookup; if (name.parent.type == SchemaObject.TABLE) { Table table = (Table) schema.tableList.get(name.parent.name); object = table.getConstraint(name.name); table.removeConstraint(name.name); } else if (name.parent.type == SchemaObject.DOMAIN) { Type type = (Type) schema.typeLookup.getObject( name.parent.name); object = type.userTypeModifier.getConstraint(name.name); type.userTypeModifier.removeConstraint(name.name); } break; } case SchemaObject.TRIGGER : { set = schema.triggerLookup; Table table = (Table) schema.tableList.get(name.parent.name); object = table.getTrigger(name.name); if (object != null) { table.removeTrigger((TriggerDef) object); } break; } case SchemaObject.REFERENCE : { set = schema.referenceLookup; object = set.getObject(name.name); break; } default : throw Error.runtimeError(ErrorCode.U_S0500, "SchemaManager"); } if (object != null) { database.getGranteeManager().removeDbObject(name); removeReferencesFrom(object); } if (set != null) { set.remove(name.name); } removeReferencesTo(name); } finally { writeLock.unlock(); } } public void renameSchemaObject(HsqlName name, HsqlName newName) { writeLock.lock(); try { if (name.schema != newName.schema) { throw Error.error(ErrorCode.X_42505, newName.schema.name); } checkObjectIsReferenced(name); Schema schema = (Schema) schemaMap.get(name.schema.name); SchemaObjectSet set = getSchemaObjectSet(schema, name.type); set.rename(name, newName); } finally { writeLock.unlock(); } } public void replaceReferences(SchemaObject oldObject, SchemaObject newObject) { writeLock.lock(); try { removeReferencesFrom(oldObject); addReferencesFrom(newObject); } finally { writeLock.unlock(); } } public String[] getSQLArray() { readLock.lock(); try { OrderedHashSet resolved = new OrderedHashSet(); OrderedHashSet unresolved = new OrderedHashSet(); HsqlArrayList list = new HsqlArrayList(); Iterator schemas = schemaMap.values().iterator(); schemas = schemaMap.values().iterator(); // build up set of simple objects while (schemas.hasNext()) { Schema schema = (Schema) schemas.next(); if (SqlInvariants.isSystemSchemaName(schema.getName().name)) { continue; } if (SqlInvariants.isLobsSchemaName(schema.getName().name)) { continue; } list.add(schema.getSQL()); schema.addSimpleObjects(unresolved); } // list all simple objects in refernece order while (true) { Iterator it = unresolved.iterator(); if (!it.hasNext()) { break; } OrderedHashSet newResolved = new OrderedHashSet(); SchemaObjectSet.addAllSQL(resolved, unresolved, list, it, newResolved); unresolved.removeAll(newResolved); if (newResolved.size() == 0) { break; } } schemas = schemaMap.values().iterator(); // while (schemas.hasNext()) { Schema schema = (Schema) schemas.next(); if (SqlInvariants.isLobsSchemaName(schema.getName().name)) { continue; } if (SqlInvariants.isSystemSchemaName(schema.getName().name)) { continue; } list.addAll(schema.getSQLArray(resolved, unresolved)); } while (true) { Iterator it = unresolved.iterator(); if (!it.hasNext()) { break; } OrderedHashSet newResolved = new OrderedHashSet(); SchemaObjectSet.addAllSQL(resolved, unresolved, list, it, newResolved); unresolved.removeAll(newResolved); if (newResolved.size() == 0) { break; } } Iterator it = unresolved.iterator(); while (it.hasNext()) { SchemaObject object = (SchemaObject) it.next(); if (object instanceof Routine) { list.add(((Routine) object).getSQLDeclaration()); } } it = unresolved.iterator(); while (it.hasNext()) { SchemaObject object = (SchemaObject) it.next(); if (object instanceof Routine) { list.add(((Routine) object).getSQLAlter()); } else { list.add(object.getSQL()); } } it = unresolved.iterator(); while (it.hasNext()) { SchemaObject object = (SchemaObject) it.next(); if (object instanceof ReferenceObject) { list.add(object.getSQL()); } } schemas = schemaMap.values().iterator(); while (schemas.hasNext()) { Schema schema = (Schema) schemas.next(); if (SqlInvariants.isLobsSchemaName(schema.getName().name)) { continue; } if (SqlInvariants.isSystemSchemaName(schema.getName().name)) { continue; } HsqlArrayList t = schema.getTriggerSQL(); if (t.size() > 0) { list.add(Schema.getSetSchemaSQL(schema.getName())); list.addAll(t); } } schemas = schemaMap.values().iterator(); while (schemas.hasNext()) { Schema schema = (Schema) schemas.next(); list.addAll(schema.getSequenceRestartSQL()); } if (defaultSchemaHsqlName != null) { StringBuilder sb = new StringBuilder(); sb.append(Tokens.T_SET).append(' ').append(Tokens.T_DATABASE); sb.append(' ').append(Tokens.T_DEFAULT).append(' '); sb.append(Tokens.T_INITIAL).append(' ').append( Tokens.T_SCHEMA); sb.append(' ').append(defaultSchemaHsqlName.statementName); list.add(sb.toString()); } String[] array = new String[list.size()]; list.toArray(array); return array; } finally { readLock.unlock(); } } public String[] getTablePropsSQL(boolean withHeader) { readLock.lock(); try { HsqlArrayList tableList = getAllTables(false); HsqlArrayList list = new HsqlArrayList(); for (int i = 0; i < tableList.size(); i++) { Table t = (Table) tableList.get(i); if (t.isText()) { String[] ddl = t.getSQLForTextSource(withHeader); list.addAll(ddl); } String ddl = t.getSQLForReadOnly(); if (ddl != null) { list.add(ddl); } if (t.isCached()) { ddl = t.getSQLForClustered(); if (ddl != null) { list.add(ddl); } } } String[] array = new String[list.size()]; list.toArray(array); return array; } finally { readLock.unlock(); } } public String[] getTableSpaceSQL() { readLock.lock(); try { HsqlArrayList tableList = getAllTables(false); HsqlArrayList list = new HsqlArrayList(); for (int i = 0; i < tableList.size(); i++) { Table t = (Table) tableList.get(i); if (t.isCached()) { String ddl = t.getSQLForTableSpace(); if (ddl != null) { list.add(ddl); } } } String[] array = new String[list.size()]; list.toArray(array); return array; } finally { readLock.unlock(); } } public String[] getIndexRootsSQL() { readLock.lock(); try { Session sysSession = database.sessionManager.getSysSession(); long[][] rootsArray = getIndexRoots(sysSession); HsqlArrayList tableList = getAllTables(true); HsqlArrayList list = new HsqlArrayList(); for (int i = 0; i < rootsArray.length; i++) { Table table = (Table) tableList.get(i); if (rootsArray[i] != null && rootsArray[i].length > 0 && rootsArray[i][0] != -1) { String ddl = table.getIndexRootsSQL(rootsArray[i]); list.add(ddl); } } String[] array = new String[list.size()]; list.toArray(array); return array; } finally { readLock.unlock(); } } public String[] getCommentsSQL() { readLock.lock(); try { HsqlArrayList tableList = getAllTables(false); HsqlArrayList list = new HsqlArrayList(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < tableList.size(); i++) { Table table = (Table) tableList.get(i); if (table.getTableType() == Table.INFO_SCHEMA_TABLE) { continue; } int colCount = table.getColumnCount(); for (int j = 0; j < colCount; j++) { ColumnSchema column = table.getColumn(j); if (column.getName().comment == null) { continue; } sb.setLength(0); sb.append(Tokens.T_COMMENT).append(' ').append( Tokens.T_ON); sb.append(' ').append(Tokens.T_COLUMN).append(' '); sb.append( table.getName().getSchemaQualifiedStatementName()); sb.append('.').append(column.getName().statementName); sb.append(' ').append(Tokens.T_IS).append(' '); sb.append( StringConverter.toQuotedString( column.getName().comment, '\'', true)); list.add(sb.toString()); } if (table.getName().comment == null) { continue; } sb.setLength(0); sb.append(Tokens.T_COMMENT).append(' ').append(Tokens.T_ON); sb.append(' ').append(Tokens.T_TABLE).append(' '); sb.append(table.getName().getSchemaQualifiedStatementName()); sb.append(' ').append(Tokens.T_IS).append(' '); sb.append( StringConverter.toQuotedString( table.getName().comment, '\'', true)); list.add(sb.toString()); } Iterator it = databaseObjectIterator(SchemaObject.ROUTINE); while (it.hasNext()) { SchemaObject object = (SchemaObject) it.next(); if (object.getName().comment == null) { continue; } sb.setLength(0); sb.append(Tokens.T_COMMENT).append(' ').append(Tokens.T_ON); sb.append(' ').append(Tokens.T_ROUTINE).append(' '); sb.append(object.getName().getSchemaQualifiedStatementName()); sb.append(' ').append(Tokens.T_IS).append(' '); sb.append( StringConverter.toQuotedString( object.getName().comment, '\'', true)); list.add(sb.toString()); } String[] array = new String[list.size()]; list.toArray(array); return array; } finally { readLock.unlock(); } } long[][] tempIndexRoots; public void setTempIndexRoots(long[][] roots) { tempIndexRoots = roots; } public long[][] getIndexRoots(Session session) { readLock.lock(); try { if (tempIndexRoots != null) { long[][] roots = tempIndexRoots; tempIndexRoots = null; return roots; } HsqlArrayList allTables = getAllTables(true); HsqlArrayList list = new HsqlArrayList(); for (int i = 0, size = allTables.size(); i < size; i++) { Table t = (Table) allTables.get(i); if (t.getTableType() == TableBase.CACHED_TABLE) { long[] roots = t.getIndexRootsArray(); list.add(roots); } else { list.add(null); } } long[][] array = new long[list.size()][]; list.toArray(array); return array; } finally { readLock.unlock(); } } /** * called after the completion of defrag */ public void setIndexRoots(long[][] roots) { readLock.lock(); try { HsqlArrayList allTables = database.schemaManager.getAllTables(true); for (int i = 0, size = allTables.size(); i < size; i++) { Table t = (Table) allTables.get(i); if (t.getTableType() == TableBase.CACHED_TABLE) { long[] rootsArray = roots[i]; if (rootsArray != null) { t.setIndexRoots(rootsArray); } } } } finally { readLock.unlock(); } } public void setDefaultTableType(int type) { defaultTableType = type; } public int getDefaultTableType() { return defaultTableType; } public void createSystemTables() { dualTable = TableUtil.newSingleColumnTable(database, SqlInvariants.DUAL_TABLE_HSQLNAME, TableBase.SYSTEM_TABLE, SqlInvariants.DUAL_COLUMN_HSQLNAME, Type.SQL_VARCHAR); dualTable.insertSys(database.sessionManager.getSysSession(), dualTable.getRowStore(null), new Object[]{ "X" }); dualTable.setDataReadOnly(true); Type[] columnTypes = new Type[] { Type.SQL_BIGINT, Type.SQL_BIGINT, Type.SQL_BIGINT, TypeInvariants.SQL_IDENTIFIER, TypeInvariants.SQL_IDENTIFIER, Type.SQL_BOOLEAN }; HsqlName tableName = database.nameManager.getSubqueryTableName(); HashMappedList columnList = new HashMappedList(); for (int i = 0; i < columnTypes.length; i++) { HsqlName name = HsqlNameManager.getAutoColumnName(i + 1); ColumnSchema column = new ColumnSchema(name, columnTypes[i], true, false, null); columnList.add(name.name, column); } dataChangeTable = new TableDerived(database, tableName, TableBase.CHANGE_SET_TABLE, columnTypes, columnList, new int[]{ 0 }); dataChangeTable.createIndexForColumns(null, new int[]{ 1 }); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy