/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.server.service.dxl;
import com.foundationdb.ais.AISCloner;
import com.foundationdb.ais.model.AkibanInformationSchema;
import com.foundationdb.ais.model.Index;
import com.foundationdb.ais.model.Routine;
import com.foundationdb.ais.model.Sequence;
import com.foundationdb.ais.model.SQLJJar;
import com.foundationdb.ais.model.Table;
import com.foundationdb.ais.model.TableName;
import com.foundationdb.ais.model.View;
import com.foundationdb.ais.util.TableChange;
import com.foundationdb.qp.operator.QueryContext;
import com.foundationdb.server.rowdata.RowDef;
import com.foundationdb.server.api.DDLFunctions;
import com.foundationdb.server.service.dxl.DXLFunctionsHook.DXLFunction;
import com.foundationdb.server.service.session.Session;
import com.foundationdb.server.service.session.SessionService;
import com.foundationdb.server.store.format.StorageFormatRegistry;
import com.foundationdb.server.types.common.types.TypesTranslator;
import com.foundationdb.server.types.service.TypesRegistry;
import com.foundationdb.sql.server.ServerSession;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static com.foundationdb.ais.util.TableChangeValidator.ChangeLevel;
import static com.foundationdb.util.Exceptions.throwAlways;
public final class HookableDDLFunctions implements DDLFunctions {
private final DDLFunctions delegate;
private final DXLFunctionsHook hook;
private final SessionService sessionService;
public HookableDDLFunctions(DDLFunctions delegate, List<DXLFunctionsHook> hooks, SessionService sessionService) {
this.delegate = delegate;
this.sessionService = sessionService;
this.hook = hooks.size() == 1 ? hooks.get(0) : new CompositeHook(hooks);
}
@Override
public void createTable(Session session, Table table) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.CREATE_TABLE);
delegate.createTable(session, table);
}catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.CREATE_TABLE, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.CREATE_TABLE, thrown);
}
}
@Override
public void createTable(Session session, Table table, String queryExpression, QueryContext context, ServerSession server) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.CREATE_TABLE);
delegate.createTable(session, table, queryExpression, context, server);
}catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.CREATE_TABLE, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.CREATE_TABLE, thrown);
}
}
@Override
public void renameTable(Session session, TableName currentName, TableName newName) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.RENAME_TABLE);
delegate.renameTable(session, currentName, newName);
}catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.RENAME_TABLE, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.RENAME_TABLE, thrown);
}
}
@Override
public void dropTable(Session session, TableName tableName) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.DROP_TABLE);
delegate.dropTable(session, tableName);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.DROP_TABLE, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.DROP_TABLE, thrown);
}
}
@Override
public ChangeLevel alterTable(Session session, TableName tableName, Table newDefinition,
List<TableChange> columnChanges, List<TableChange> indexChanges,
QueryContext context) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.ALTER_TABLE);
return delegate.alterTable(session, tableName, newDefinition, columnChanges, indexChanges, context);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.ALTER_TABLE, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.ALTER_TABLE, thrown);
}
}
@Override
public void alterSequence(Session session, TableName sequenceName, Sequence newDefinition) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.ALTER_SEQUENCE);
delegate.alterSequence(session, sequenceName, newDefinition);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.ALTER_SEQUENCE, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.ALTER_SEQUENCE, thrown);
}
}
@Override
public void createView(Session session, View view) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.CREATE_VIEW);
delegate.createView(session, view);
}catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.CREATE_VIEW, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.CREATE_VIEW, thrown);
}
}
@Override
public void dropView(Session session, TableName viewName) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.DROP_VIEW);
delegate.dropView(session, viewName);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.DROP_VIEW, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.DROP_VIEW, thrown);
}
}
@Override
public void createRoutine(Session session, Routine routine, boolean replaceExisting) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.CREATE_ROUTINE);
delegate.createRoutine(session, routine, replaceExisting);
}catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.CREATE_ROUTINE, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.CREATE_ROUTINE, thrown);
}
}
@Override
public void dropRoutine(Session session, TableName routineName) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.DROP_ROUTINE);
delegate.dropRoutine(session, routineName);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.DROP_ROUTINE, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.DROP_ROUTINE, thrown);
}
}
@Override
public void createSQLJJar(Session session, SQLJJar sqljJar) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.CREATE_SQLJ_JAR);
delegate.createSQLJJar(session, sqljJar);
}catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.CREATE_SQLJ_JAR, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.CREATE_SQLJ_JAR, thrown);
}
}
@Override
public void replaceSQLJJar(Session session, SQLJJar sqljJar) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.REPLACE_SQLJ_JAR);
delegate.replaceSQLJJar(session, sqljJar);
}catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.REPLACE_SQLJ_JAR, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.REPLACE_SQLJ_JAR, thrown);
}
}
@Override
public void dropSQLJJar(Session session, TableName jarName) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.DROP_SQLJ_JAR);
delegate.dropSQLJJar(session, jarName);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.DROP_SQLJ_JAR, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.DROP_SQLJ_JAR, thrown);
}
}
@Override
public void dropSchema(Session session, String schemaName) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.DROP_SCHEMA);
delegate.dropSchema(session, schemaName);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.DROP_SCHEMA, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.DROP_SCHEMA, thrown);
}
}
@Override
public void dropNonSystemSchemas(Session session) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.DROP_SCHEMA);
delegate.dropNonSystemSchemas(session);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.DROP_SCHEMA, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.DROP_SCHEMA, thrown);
}
}
@Override
public void dropGroup(Session session, TableName groupName) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.DROP_GROUP);
delegate.dropGroup(session, groupName);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.DROP_GROUP, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.DROP_GROUP, thrown);
}
}
@Override
public AkibanInformationSchema getAIS(final Session session) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.GET_AIS);
return delegate.getAIS(session);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.GET_AIS, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.GET_AIS, thrown);
}
}
@Override
public TypesRegistry getTypesRegistry() {
return delegate.getTypesRegistry();
}
@Override
public TypesTranslator getTypesTranslator() {
return delegate.getTypesTranslator();
}
@Override
public StorageFormatRegistry getStorageFormatRegistry() {
return delegate.getStorageFormatRegistry();
}
@Override
public AISCloner getAISCloner() {
return delegate.getAISCloner();
}
@Override
public int getTableId(Session session, TableName tableName) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.GET_TABLE_ID);
return delegate.getTableId(session, tableName);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.GET_TABLE_ID, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.GET_TABLE_ID, thrown);
}
}
@Override
public Table getTable(Session session, int tableId) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.GET_TABLE_BY_ID);
return delegate.getTable(session, tableId);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.GET_TABLE_BY_ID, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.GET_TABLE_BY_ID, thrown);
}
}
@Override
public Table getTable(Session session, TableName tableName) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.GET_TABLE_BY_NAME);
return delegate.getTable(session, tableName);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.GET_TABLE_BY_NAME, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.GET_TABLE_BY_NAME, thrown);
}
}
@Override
public TableName getTableName(Session session, int tableId) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.GET_USER_TABLE_BY_ID);
return delegate.getTableName(session, tableId);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.GET_USER_TABLE_BY_ID, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.GET_USER_TABLE_BY_ID, thrown);
}
}
@Override
public int getGenerationAsInt(Session session) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.GET_SCHEMA_ID);
return delegate.getGenerationAsInt(session);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.GET_SCHEMA_ID, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.GET_SCHEMA_ID, thrown);
}
}
@Override
public long getGeneration(Session session) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.GET_SCHEMA_TIMESTAMP);
return delegate.getGeneration(session);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.GET_SCHEMA_TIMESTAMP, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.GET_SCHEMA_TIMESTAMP, thrown);
}
}
@Override
public long getOldestActiveGeneration() {
Session session = sessionService.createSession();
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.GET_OLDEST_ACTIVE_GENERATION);
return delegate.getOldestActiveGeneration();
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.GET_OLDEST_ACTIVE_GENERATION, t);
throw throwAlways(t);
} finally {
try {
hook.hookFunctionFinally(session, DXLFunction.GET_OLDEST_ACTIVE_GENERATION, thrown);
} finally {
session.close();
}
}
}
@Override
public Set<Long> getActiveGenerations() {
Session session = sessionService.createSession();
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.GET_ACTIVE_GENERATIONS);
return delegate.getActiveGenerations();
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.GET_ACTIVE_GENERATIONS, t);
throw throwAlways(t);
} finally {
try {
hook.hookFunctionFinally(session, DXLFunction.GET_ACTIVE_GENERATIONS, thrown);
} finally {
session.close();
}
}
}
@Override
public void createIndexes(final Session session, Collection<? extends Index> indexesToAdd) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.CREATE_INDEXES);
delegate.createIndexes(session, indexesToAdd);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.CREATE_INDEXES, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.CREATE_INDEXES, thrown);
}
}
@Override
public void dropTableIndexes(final Session session, TableName tableName, Collection<String> indexNamesToDrop) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.DROP_INDEXES);
delegate.dropTableIndexes(session, tableName, indexNamesToDrop);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.DROP_INDEXES, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.DROP_INDEXES, thrown);
}
}
@Override
public void dropGroupIndexes(Session session, TableName groupName, Collection<String> indexesToDrop) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.DROP_INDEXES);
delegate.dropGroupIndexes(session, groupName, indexesToDrop);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.DROP_INDEXES, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.DROP_INDEXES, thrown);
}
}
@Override
public void updateTableStatistics(Session session, TableName tableName, Collection<String> indexesToUpdate) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.UPDATE_TABLE_STATISTICS);
delegate.updateTableStatistics(session, tableName, indexesToUpdate);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.UPDATE_TABLE_STATISTICS, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.UPDATE_TABLE_STATISTICS, thrown);
}
}
@Override
public void createSequence(Session session, Sequence sequence) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.CREATE_SEQUENCE);
delegate.createSequence(session, sequence);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.CREATE_SEQUENCE, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.CREATE_SEQUENCE, thrown);
}
}
@Override
public void dropSequence(Session session, TableName sequenceName) {
Throwable thrown = null;
try {
hook.hookFunctionIn(session, DXLFunction.DROP_SEQUENCE);
delegate.dropSequence(session, sequenceName);
} catch (Throwable t) {
thrown = t;
hook.hookFunctionCatch(session, DXLFunction.DROP_SEQUENCE, t);
throw throwAlways(t);
} finally {
hook.hookFunctionFinally(session, DXLFunction.DROP_SEQUENCE, thrown);
}
}
/** Test only, not hooked. */
@Override
public void setOnlineDDLMonitor(OnlineDDLMonitor onlineDDLMonitor) {
delegate.setOnlineDDLMonitor(onlineDDLMonitor);
}
}