/** * 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.test.mt; import com.foundationdb.ais.model.Index; import com.foundationdb.qp.expression.IndexKeyRange; import com.foundationdb.qp.operator.API; import com.foundationdb.qp.operator.Cursor; import com.foundationdb.qp.operator.Operator; import com.foundationdb.qp.operator.QueryBindings; import com.foundationdb.qp.operator.QueryContext; import com.foundationdb.qp.operator.SimpleQueryContext; import com.foundationdb.qp.operator.StoreAdapter; import com.foundationdb.qp.operator.UpdateFunction; import com.foundationdb.qp.row.Row; import com.foundationdb.qp.rowtype.IndexRowType; import com.foundationdb.qp.rowtype.RowType; import com.foundationdb.qp.rowtype.Schema; import com.foundationdb.qp.rowtype.TableRowType; import com.foundationdb.qp.util.SchemaCache; import com.foundationdb.server.api.DDLFunctions; import com.foundationdb.server.service.session.Session; import com.foundationdb.server.service.transaction.TransactionService; import com.foundationdb.server.store.SchemaManager; import com.foundationdb.server.store.Store; import com.foundationdb.server.test.it.ITBase; import com.foundationdb.server.test.mt.util.ConcurrentTestBuilderImpl; import com.foundationdb.server.test.mt.util.OperatorCreator; import com.foundationdb.server.test.mt.util.ServiceHolder; import org.junit.Rule; import org.junit.rules.TestRule; import org.junit.rules.TestWatcher; import org.junit.runner.Description; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import static com.foundationdb.qp.operator.API.delete_Returning; import static com.foundationdb.qp.operator.API.groupScan_Default; import static com.foundationdb.qp.operator.API.insert_Returning; import static com.foundationdb.qp.operator.API.update_Returning; import static com.foundationdb.qp.operator.API.valuesScan_Default; // Extend ITBase for the miscellaneous Row/Operator test helpers public abstract class MTBase extends ITBase implements ServiceHolder { @Rule public final TestRule FAILED_WATCHMAN = new TestWatcher() { @Override public void failed(Throwable e, Description description) { System.err.printf("Ran with DELAY_BEFORE: %s, DELAY_DDL_STAGE: %s, DELAY_THREAD_STAGE: %s\n", ConcurrentTestBuilderImpl.DELAY_BEFORE, ConcurrentTestBuilderImpl.DELAY_DDL_STAGE, ConcurrentTestBuilderImpl.DELAY_THREAD_STAGE); } }; public MTBase() { super("MT"); } // // MTBase // protected List<Row> runPlanTxn(final OperatorCreator creator) { return txnService().run(session(), new Callable<List<Row>>() { @Override public List<Row> call() throws Exception { Schema schema = SchemaCache.globalSchema(ais()); Operator plan = creator.create(schema); StoreAdapter adapter = store().createAdapter(session()); QueryContext context = new SimpleQueryContext(adapter, serviceManager()); QueryBindings bindings = context.createBindings(); List<Row> rows = new ArrayList<>(); Cursor cursor = API.cursor(plan, context, bindings); cursor.openTopLevel(); try { Row row; while((row = cursor.next()) != null) { rows.add(row); } } finally { cursor.closeTopLevel(); } return rows; } }); } protected static List<Row> remove(List<Row> rows, int index) { return remove(rows, rows.get(index)); } protected static List<Row> remove(List<Row> rows, Row row) { List<Row> newRows = new ArrayList<>(rows); newRows.remove(row); return newRows; } protected static List<Row> combine(List<Row> rows, Row newRow) { List<Row> newRows = new ArrayList<>(rows); newRows.add(newRow); return newRows; } protected static List<Row> insert(List<Row> rows, int index, Row newRow) { List<Row> newRows = new ArrayList<>(rows); newRows.add(index, newRow); return newRows; } protected static List<Row> replace(List<Row> rows, int index, Row newRow) { List<Row> newRows = new ArrayList<>(rows); newRows.set(index, newRow); return newRows; } protected static OperatorCreator groupScanCreator(final int tID) { return new OperatorCreator() { @Override public Operator create(Schema schema) { return groupScan_Default(schema.tableRowType(tID).table().getGroup()); } }; } protected static OperatorCreator indexScanCreator(final int tID, final int iID) { return new OperatorCreator() { @Override public Operator create(Schema schema) { return API.indexScan_Default(schema.tableRowType(tID).indexRowType(iID)); } }; } protected static OperatorCreator indexScanCreator(final int tID, final String indexName) { return new OperatorCreator() { @Override public Operator create(Schema schema) { TableRowType tableRowType = schema.tableRowType(tID); Index index = tableRowType.table().getIndex(indexName); return API.indexScan_Default(tableRowType.indexRowType(index)); } }; } protected static OperatorCreator groupIndexScanCreator(final int tID, final String indexName) { return new OperatorCreator() { @Override public Operator create(Schema schema) { TableRowType tableType = schema.tableRowType(tID); Index index = schema.tableRowType(tID).table().getGroup().getIndex(indexName); IndexRowType indexType = schema.indexRowType(index); return API.indexScan_Default(indexType, false, IndexKeyRange.unbounded(indexType), tableType); } }; } protected static OperatorCreator insertCreator(final int tID, final Row newRow) { return new OperatorCreator() { @Override public Operator create(Schema schema) { RowType rowType = schema.tableRowType(tID); return insert_Returning(valuesScan_Default(bindableRows(newRow), rowType)); } }; } protected static OperatorCreator updateCreator(final int tID, final Row oldRow, final Row newRow) { return new OperatorCreator() { @Override public Operator create(Schema schema) { RowType rowType = schema.tableRowType(tID); return update_Returning( valuesScan_Default(bindableRows(oldRow), rowType), new UpdateFunction() { @Override public Row evaluate(Row original, QueryContext context, QueryBindings bindings) { return newRow; } }); } }; } protected static OperatorCreator deleteCreator(final int tID, final Row row) { return new OperatorCreator() { @Override public Operator create(Schema schema) { RowType rowType = schema.tableRowType(tID); return delete_Returning(valuesScan_Default(bindableRows(row), rowType), false); } }; } // // ServiceHolder // @Override public TransactionService getTransactionService() { return txnService(); } @Override public SchemaManager getSchemaManager() { return serviceManager().getSchemaManager(); } @Override public Store getStore() { return store(); } @Override public DDLFunctions getDDLFunctions() { return ddl(); } @Override public Session createSession() { return createNewSession(); } }