/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ package adhocbenchmark; /** * Configuration that determines what the generated join queries look like. */ class JoinTest extends QueryTestBase { // Number of join levels private final int m_nLevels; private final String m_filterColumn; private final boolean m_replicatedQuery; private final String m_joinColumn; private JoinTest(final String tablePrefix, final int nTables, final String columnPrefix, final int nColumns, final int nLevels, final String filterColumn, final boolean replicatedQuery, final String joinColumn) { super(tablePrefix, columnPrefix, nColumns, nTables); m_nLevels = nLevels; m_filterColumn = filterColumn; m_replicatedQuery = replicatedQuery; m_joinColumn = joinColumn; } @Override public String getQuery(int iQuery, QueryTestHelper helper) { // Generate table lists by grabbing n sequential numbers at a time (wrap around). int iStart = iQuery * m_nLevels; String parentTable; // In the SPChain configuration, replicated tables are used solely for the sake of (allowing) chaining // without having to partition the generated tables on PARENT_ID. // So, the parent table wants to explicitly be a partitioned table, not picked at random from the generated tables. // If we DID switch over to partitioning the generated tables on PARENT_ID, the parent table would still // need to be hard-coded because it would still want to be partitioned on ID, instead. if (m_replicatedQuery || m_joinColumn.equals("ID")) { // By default, choose the parent table randomly from those generated. parentTable = helper.tableName(helper.getShuffledNumber(iStart)); } else { // Force a parent table partitioned by ID // -- at some risk, this name assumes that schema was also generated for a different // configuration of this test (that needed partitioned tables) parentTable = "joinPART_1"; } StringBuilder query = new StringBuilder("SELECT * FROM " + parentTable + " T0"); for (int i = 1; i < m_nLevels; i++) { query.append(", "); query.append(helper.tableName(helper.getShuffledNumber(iStart + i)) + " T" + i); } // For SP, the parent table has a where clause with random constant ID filter // on the assumption that ID is the partition key. // Other cases use the never-partitioning PARENT_ID. query.append(" WHERE T0." + m_filterColumn + " = " + helper.getShuffledNumber(0)); // Each child table has a where clause with an equality join to a prior table. // In "star configuration", the join is a primary-to-primary join, (possibly on a partition key). // In "chain configuration", the join is a foreign-to-primary join, // (requiring the child tables to be replicated -- or IN THEORY, they could be foreign-key-partitioned. for (int i = 1; i < m_nLevels; i++) { query.append(" AND T" + i + "." + m_joinColumn + " = T" + (i-1) + ".ID"); } return query.toString(); } public static class ChainFactory implements QueryTestBase.Factory { @Override public QueryTestBase make(final String tablePrefix, int nVariations, final String columnPrefix, final int nColumns, final int nRandomNumbers) { return new JoinTest(tablePrefix, nVariations, columnPrefix, nColumns, nRandomNumbers, "PARENT_ID", true, "PARENT_ID"); } } public static class SPChainFactory implements QueryTestBase.Factory { @Override public QueryTestBase make(final String tablePrefix, int nVariations, final String columnPrefix, final int nColumns, final int nRandomNumbers) { return new JoinTest(tablePrefix, nVariations, columnPrefix, nColumns, nRandomNumbers, "ID", false, "PARENT_ID"); } } public static class MPChainFactory implements QueryTestBase.Factory { @Override public QueryTestBase make(final String tablePrefix, int nVariations, final String columnPrefix, final int nColumns, final int nRandomNumbers) { return new JoinTest(tablePrefix, nVariations, columnPrefix, nColumns, nRandomNumbers, "PARENT_ID", false, "PARENT_ID"); } } public static class StarFactory implements QueryTestBase.Factory { @Override public QueryTestBase make(final String tablePrefix, int nVariations, final String columnPrefix, final int nColumns, final int nRandomNumbers) { return new JoinTest(tablePrefix, nVariations, columnPrefix, nColumns, nRandomNumbers, "PARENT_ID", true, "ID"); } } public static class SPStarFactory implements QueryTestBase.Factory { @Override public QueryTestBase make(final String tablePrefix, int nVariations, final String columnPrefix, final int nColumns, final int nRandomNumbers) { return new JoinTest(tablePrefix, nVariations, columnPrefix, nColumns, nRandomNumbers, "ID", false, "ID"); } } public static class MPStarFactory implements QueryTestBase.Factory { @Override public QueryTestBase make(final String tablePrefix, int nVariations, final String columnPrefix, final int nColumns, final int nRandomNumbers) { return new JoinTest(tablePrefix, nVariations, columnPrefix, nColumns, nRandomNumbers, "PARENT_ID", false, "ID"); } } }