Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (https://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.schema;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.h2.api.ErrorCode;
import org.h2.command.ddl.CreateSynonymData;
import org.h2.command.ddl.CreateTableData;
import org.h2.constraint.Constraint;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.DbObjectBase;
import org.h2.engine.DbSettings;
import org.h2.engine.FunctionAlias;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.engine.SysProperties;
import org.h2.engine.User;
import org.h2.index.Index;
import org.h2.message.DbException;
import org.h2.message.Trace;
import org.h2.mvstore.db.MVTableEngine;
import org.h2.pagestore.db.PageStoreTable;
import org.h2.table.Table;
import org.h2.table.TableLink;
import org.h2.table.TableSynonym;
import org.h2.util.StringUtils;
import org.h2.util.Utils;
/**
* A schema as created by the SQL statement
* CREATE SCHEMA
*/
public class Schema extends DbObjectBase {
private User owner;
private final boolean system;
private ArrayList tableEngineParams;
private final ConcurrentHashMap tablesAndViews;
private final ConcurrentHashMap synonyms;
private final ConcurrentHashMap indexes;
private final ConcurrentHashMap sequences;
private final ConcurrentHashMap triggers;
private final ConcurrentHashMap constraints;
private final ConcurrentHashMap constants;
private final ConcurrentHashMap functions;
/**
* The set of returned unique names that are not yet stored. It is used to
* avoid returning the same unique name twice when multiple threads
* concurrently create objects.
*/
private final HashSet temporaryUniqueNames = new HashSet<>();
/**
* Create a new schema object.
*
* @param database the database
* @param id the object id
* @param schemaName the schema name
* @param owner the owner of the schema
* @param system if this is a system schema (such a schema can not be
* dropped)
*/
public Schema(Database database, int id, String schemaName, User owner,
boolean system) {
super(database, id, schemaName, Trace.SCHEMA);
tablesAndViews = database.newConcurrentStringMap();
synonyms = database.newConcurrentStringMap();
indexes = database.newConcurrentStringMap();
sequences = database.newConcurrentStringMap();
triggers = database.newConcurrentStringMap();
constraints = database.newConcurrentStringMap();
constants = database.newConcurrentStringMap();
functions = database.newConcurrentStringMap();
this.owner = owner;
this.system = system;
}
/**
* Check if this schema can be dropped. System schemas can not be dropped.
*
* @return true if it can be dropped
*/
public boolean canDrop() {
return !system;
}
@Override
public String getCreateSQLForCopy(Table table, String quotedName) {
throw DbException.throwInternalError(toString());
}
@Override
public String getDropSQL() {
return null;
}
@Override
public String getCreateSQL() {
if (system) {
return null;
}
StringBuilder builder = new StringBuilder("CREATE SCHEMA IF NOT EXISTS ");
getSQL(builder, true).append(" AUTHORIZATION ");
owner.getSQL(builder, true);
return builder.toString();
}
@Override
public int getType() {
return DbObject.SCHEMA;
}
/**
* Return whether is this schema is empty (does not contain any objects).
*
* @return {@code true} if this schema is empty, {@code false} otherwise
*/
public boolean isEmpty() {
return tablesAndViews.isEmpty() && synonyms.isEmpty() && indexes.isEmpty() && sequences.isEmpty()
&& triggers.isEmpty() && constraints.isEmpty() && constants.isEmpty() && functions.isEmpty();
}
@Override
public ArrayList getChildren() {
ArrayList children = Utils.newSmallArrayList();
ArrayList rights = database.getAllRights();
for (Right right : rights) {
if (right.getGrantedObject() == this) {
children.add(right);
}
}
return children;
}
@Override
public void removeChildrenAndResources(Session session) {
removeChildrenFromMap(session, triggers);
removeChildrenFromMap(session, constraints);
// There can be dependencies between tables e.g. using computed columns,
// so we might need to loop over them multiple times.
boolean modified = true;
while (!tablesAndViews.isEmpty()) {
boolean newModified = false;
for (Table obj : tablesAndViews.values()) {
if (obj.getName() != null) {
// Database.removeSchemaObject() removes the object from
// the map too, but it is safe for ConcurrentHashMap.
Table dependentTable = database.getDependentTable(obj, obj);
if (dependentTable == null) {
database.removeSchemaObject(session, obj);
newModified = true;
} else if (dependentTable.getSchema() != this) {
throw DbException.get(ErrorCode.CANNOT_DROP_2, //
obj.getSQL(false), dependentTable.getSQL(false));
} else if (!modified) {
dependentTable.removeColumnExpressionsDependencies(session);
dependentTable.setModified();
database.updateMeta(session, dependentTable);
}
}
}
modified = newModified;
}
removeChildrenFromMap(session, indexes);
removeChildrenFromMap(session, sequences);
removeChildrenFromMap(session, constants);
removeChildrenFromMap(session, functions);
for (Right right : database.getAllRights()) {
if (right.getGrantedObject() == this) {
database.removeDatabaseObject(session, right);
}
}
database.removeMeta(session, getId());
owner = null;
invalidate();
}
private void removeChildrenFromMap(Session session, ConcurrentHashMap map) {
if (!map.isEmpty()) {
for (SchemaObject obj : map.values()) {
// Database.removeSchemaObject() removes the object from
// the map too, but it is safe for ConcurrentHashMap.
database.removeSchemaObject(session, obj);
}
}
}
@Override
public void checkRename() {
// ok
}
/**
* Get the owner of this schema.
*
* @return the owner
*/
public User getOwner() {
return owner;
}
/**
* Get table engine params of this schema.
*
* @return default table engine params
*/
public ArrayList getTableEngineParams() {
return tableEngineParams;
}
/**
* Set table engine params of this schema.
* @param tableEngineParams default table engine params
*/
public void setTableEngineParams(ArrayList tableEngineParams) {
this.tableEngineParams = tableEngineParams;
}
@SuppressWarnings("unchecked")
private Map getMap(int type) {
Map result;
switch (type) {
case DbObject.TABLE_OR_VIEW:
result = tablesAndViews;
break;
case DbObject.SYNONYM:
result = synonyms;
break;
case DbObject.SEQUENCE:
result = sequences;
break;
case DbObject.INDEX:
result = indexes;
break;
case DbObject.TRIGGER:
result = triggers;
break;
case DbObject.CONSTRAINT:
result = constraints;
break;
case DbObject.CONSTANT:
result = constants;
break;
case DbObject.FUNCTION_ALIAS:
result = functions;
break;
default:
throw DbException.throwInternalError("type=" + type);
}
return (Map) result;
}
/**
* Add an object to this schema.
* This method must not be called within CreateSchemaObject;
* use Database.addSchemaObject() instead
*
* @param obj the object to add
*/
public void add(SchemaObject obj) {
if (obj.getSchema() != this) {
DbException.throwInternalError("wrong schema");
}
String name = obj.getName();
Map map = getMap(obj.getType());
if (SysProperties.CHECK && map.get(name) != null) {
DbException.throwInternalError("object already exists: " + name);
}
map.put(name, obj);
freeUniqueName(name);
}
/**
* Rename an object.
*
* @param obj the object to rename
* @param newName the new name
*/
public void rename(SchemaObject obj, String newName) {
int type = obj.getType();
Map map = getMap(type);
if (SysProperties.CHECK) {
if (!map.containsKey(obj.getName())) {
DbException.throwInternalError("not found: " + obj.getName());
}
if (obj.getName().equals(newName) || map.containsKey(newName)) {
DbException.throwInternalError("object already exists: " + newName);
}
}
obj.checkRename();
map.remove(obj.getName());
freeUniqueName(obj.getName());
obj.rename(newName);
map.put(newName, obj);
freeUniqueName(newName);
}
/**
* Try to find a table or view with this name. This method returns null if
* no object with this name exists. Local temporary tables are also
* returned. Synonyms are not returned or resolved.
*
* @param session the session
* @param name the object name
* @return the object or null
*/
public Table findTableOrView(Session session, String name) {
Table table = tablesAndViews.get(name);
if (table == null && session != null) {
table = session.findLocalTempTable(name);
}
return table;
}
/**
* Try to find a table or view with this name. This method returns null if
* no object with this name exists. Local temporary tables are also
* returned. If a synonym with this name exists, the backing table of the
* synonym is returned
*
* @param session the session
* @param name the object name
* @return the object or null
*/
public Table resolveTableOrView(Session session, String name) {
Table table = findTableOrView(session, name);
if (table == null) {
TableSynonym synonym = synonyms.get(name);
if (synonym != null) {
return synonym.getSynonymFor();
}
}
return table;
}
/**
* Try to find a synonym with this name. This method returns null if
* no object with this name exists.
*
* @param name the object name
* @return the object or null
*/
public TableSynonym getSynonym(String name) {
return synonyms.get(name);
}
/**
* Try to find an index with this name. This method returns null if
* no object with this name exists.
*
* @param session the session
* @param name the object name
* @return the object or null
*/
public Index findIndex(Session session, String name) {
Index index = indexes.get(name);
if (index == null) {
index = session.findLocalTempTableIndex(name);
}
return index;
}
/**
* Try to find a trigger with this name. This method returns null if
* no object with this name exists.
*
* @param name the object name
* @return the object or null
*/
public TriggerObject findTrigger(String name) {
return triggers.get(name);
}
/**
* Try to find a sequence with this name. This method returns null if
* no object with this name exists.
*
* @param sequenceName the object name
* @return the object or null
*/
public Sequence findSequence(String sequenceName) {
return sequences.get(sequenceName);
}
/**
* Try to find a constraint with this name. This method returns null if no
* object with this name exists.
*
* @param session the session
* @param name the object name
* @return the object or null
*/
public Constraint findConstraint(Session session, String name) {
Constraint constraint = constraints.get(name);
if (constraint == null) {
constraint = session.findLocalTempTableConstraint(name);
}
return constraint;
}
/**
* Try to find a user defined constant with this name. This method returns
* null if no object with this name exists.
*
* @param constantName the object name
* @return the object or null
*/
public Constant findConstant(String constantName) {
return constants.get(constantName);
}
/**
* Try to find a user defined function with this name. This method returns
* null if no object with this name exists.
*
* @param functionAlias the object name
* @return the object or null
*/
public FunctionAlias findFunction(String functionAlias) {
return functions.get(functionAlias);
}
/**
* Release a unique object name.
*
* @param name the object name
*/
public void freeUniqueName(String name) {
if (name != null) {
synchronized (temporaryUniqueNames) {
temporaryUniqueNames.remove(name);
}
}
}
private String getUniqueName(DbObject obj,
Map map, String prefix) {
String hash = StringUtils.toUpperEnglish(Integer.toHexString(obj.getName().hashCode()));
String name = null;
synchronized (temporaryUniqueNames) {
for (int i = 1, len = hash.length(); i < len; i++) {
name = prefix + hash.substring(0, i);
if (!map.containsKey(name) && !temporaryUniqueNames.contains(name)) {
break;
}
name = null;
}
if (name == null) {
prefix = prefix + hash + "_";
for (int i = 0;; i++) {
name = prefix + i;
if (!map.containsKey(name) && !temporaryUniqueNames.contains(name)) {
break;
}
}
}
temporaryUniqueNames.add(name);
}
return name;
}
/**
* Create a unique constraint name.
*
* @param session the session
* @param table the constraint table
* @return the unique name
*/
public String getUniqueConstraintName(Session session, Table table) {
Map tableConstraints;
if (table.isTemporary() && !table.isGlobalTemporary()) {
tableConstraints = session.getLocalTempTableConstraints();
} else {
tableConstraints = constraints;
}
return getUniqueName(table, tableConstraints, "CONSTRAINT_");
}
/**
* Create a unique index name.
*
* @param session the session
* @param table the indexed table
* @param prefix the index name prefix
* @return the unique name
*/
public String getUniqueIndexName(Session session, Table table, String prefix) {
Map tableIndexes;
if (table.isTemporary() && !table.isGlobalTemporary()) {
tableIndexes = session.getLocalTempTableIndexes();
} else {
tableIndexes = indexes;
}
return getUniqueName(table, tableIndexes, prefix);
}
/**
* Get the table or view with the given name.
* Local temporary tables are also returned.
*
* @param session the session
* @param name the table or view name
* @return the table or view
* @throws DbException if no such object exists
*/
public Table getTableOrView(Session session, String name) {
Table table = tablesAndViews.get(name);
if (table == null) {
if (session != null) {
table = session.findLocalTempTable(name);
}
if (table == null) {
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, name);
}
}
return table;
}
/**
* Get the index with the given name.
*
* @param name the index name
* @return the index
* @throws DbException if no such object exists
*/
public Index getIndex(String name) {
Index index = indexes.get(name);
if (index == null) {
throw DbException.get(ErrorCode.INDEX_NOT_FOUND_1, name);
}
return index;
}
/**
* Get the constraint with the given name.
*
* @param name the constraint name
* @return the constraint
* @throws DbException if no such object exists
*/
public Constraint getConstraint(String name) {
Constraint constraint = constraints.get(name);
if (constraint == null) {
throw DbException.get(ErrorCode.CONSTRAINT_NOT_FOUND_1, name);
}
return constraint;
}
/**
* Get the user defined constant with the given name.
*
* @param constantName the constant name
* @return the constant
* @throws DbException if no such object exists
*/
public Constant getConstant(String constantName) {
Constant constant = constants.get(constantName);
if (constant == null) {
throw DbException.get(ErrorCode.CONSTANT_NOT_FOUND_1, constantName);
}
return constant;
}
/**
* Get the sequence with the given name.
*
* @param sequenceName the sequence name
* @return the sequence
* @throws DbException if no such object exists
*/
public Sequence getSequence(String sequenceName) {
Sequence sequence = sequences.get(sequenceName);
if (sequence == null) {
throw DbException.get(ErrorCode.SEQUENCE_NOT_FOUND_1, sequenceName);
}
return sequence;
}
/**
* Get all objects.
*
* @param addTo
* list to add objects to, or {@code null} to allocate a new
* list
* @return the specified list with added objects, or a new (possibly empty) list
* with all objects
*/
public ArrayList getAll(ArrayList addTo) {
if (addTo == null) {
addTo = Utils.newSmallArrayList();
}
addTo.addAll(tablesAndViews.values());
addTo.addAll(synonyms.values());
addTo.addAll(sequences.values());
addTo.addAll(indexes.values());
addTo.addAll(triggers.values());
addTo.addAll(constraints.values());
addTo.addAll(constants.values());
addTo.addAll(functions.values());
return addTo;
}
/**
* Get all objects of the given type.
*
* @param type
* the object type
* @param addTo
* list to add objects to, or {@code null} to allocate a new
* list
* @return the specified list with added objects, or a new (possibly empty) list
* with objects of the given type
*/
public ArrayList getAll(int type, ArrayList addTo) {
Collection values = getMap(type).values();
if (addTo != null) {
addTo.addAll(values);
} else {
addTo = new ArrayList<>(values);
}
return addTo;
}
/**
* Get all tables and views.
*
* @return a (possible empty) list of all objects
*/
public Collection
getAllTablesAndViews() {
return tablesAndViews.values();
}
public Collection getAllSynonyms() {
return synonyms.values();
}
/**
* Get the table with the given name, if any.
*
* @param name the table name
* @return the table or null if not found
*/
public Table getTableOrViewByName(String name) {
return tablesAndViews.get(name);
}
/**
* Remove an object from this schema.
*
* @param obj the object to remove
*/
public void remove(SchemaObject obj) {
String objName = obj.getName();
Map map = getMap(obj.getType());
if (map.remove(objName) == null) {
DbException.throwInternalError("not found: " + objName);
}
freeUniqueName(objName);
}
/**
* Add a table to the schema.
*
* @param data the create table information
* @return the created {@link Table} object
*/
public Table createTable(CreateTableData data) {
synchronized (database) {
if (!data.temporary || data.globalTemporary) {
database.lockMeta(data.session);
}
data.schema = this;
if (data.tableEngine == null) {
DbSettings s = database.getSettings();
if (s.defaultTableEngine != null) {
data.tableEngine = s.defaultTableEngine;
} else if (s.mvStore) {
data.tableEngine = MVTableEngine.class.getName();
}
}
if (data.tableEngine != null) {
if (data.tableEngineParams == null) {
data.tableEngineParams = this.tableEngineParams;
}
return database.getTableEngine(data.tableEngine).createTable(data);
}
return new PageStoreTable(data);
}
}
/**
* Add a table synonym to the schema.
*
* @param data the create synonym information
* @return the created {@link TableSynonym} object
*/
public TableSynonym createSynonym(CreateSynonymData data) {
synchronized (database) {
database.lockMeta(data.session);
data.schema = this;
return new TableSynonym(data);
}
}
/**
* Add a linked table to the schema.
*
* @param id the object id
* @param tableName the table name of the alias
* @param driver the driver class name
* @param url the database URL
* @param user the user name
* @param password the password
* @param originalSchema the schema name of the target table
* @param originalTable the table name of the target table
* @param emitUpdates if updates should be emitted instead of delete/insert
* @param force create the object even if the database can not be accessed
* @return the {@link TableLink} object
*/
public TableLink createTableLink(int id, String tableName, String driver,
String url, String user, String password, String originalSchema,
String originalTable, boolean emitUpdates, boolean force) {
synchronized (database) {
return new TableLink(this, id, tableName,
driver, url, user, password,
originalSchema, originalTable, emitUpdates, force);
}
}
}