/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * 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 VoltDB. If not, see <http://www.gnu.org/licenses/>. */ package org.voltdb.compiler; import org.voltcore.network.Connection; import org.voltdb.AuthSystem; import org.voltdb.CatalogContext; import org.voltdb.ClientInterface.ExplainMode; import org.voltdb.client.BatchTimeoutOverrideType; import org.voltdb.compiler.deploymentfile.DrRoleType; public class AdHocPlannerWork extends AsyncCompilerWork { private static final long serialVersionUID = -6567283432846270119L; final String sqlBatchText; final String[] sqlStatements; final Object[] userParamSet; final CatalogContext catalogContext; final boolean inferPartitioning; // The user partition key is usually null // -- otherwise, it contains one element to support @AdHocSpForTest and // ad hoc statements queued within single-partition stored procs. final Object[] userPartitionKey; public final ExplainMode explainMode; public final int m_batchTimeout; public AdHocPlannerWork(long replySiteId, long clientHandle, long connectionId, boolean adminConnection, Connection clientConnection, String sqlBatchText, String[] sqlStatements, Object[] userParamSet, CatalogContext context, ExplainMode explainMode, boolean inferPartitioning, Object[] userPartitionKey, String invocationName, int batchTimeout, DrRoleType drRole, boolean useAdhocDDL, AsyncCompilerWorkCompletionHandler completionHandler, AuthSystem.AuthUser user) { super(replySiteId, false, clientHandle, connectionId, clientConnection == null ? "" : clientConnection.getHostnameAndIPAndPort(), adminConnection, clientConnection, invocationName, drRole, useAdhocDDL, completionHandler, user); this.sqlBatchText = sqlBatchText; this.sqlStatements = sqlStatements; this.userParamSet = userParamSet; this.catalogContext = context; this.explainMode = explainMode; this.inferPartitioning = inferPartitioning; this.userPartitionKey = userPartitionKey; this.m_batchTimeout = batchTimeout; } /** * A mutated clone method, allowing override of completionHandler and * clearing of (obsolete) catalogContext */ public static AdHocPlannerWork rework(AdHocPlannerWork orig, AsyncCompilerWorkCompletionHandler completionHandler) { return new AdHocPlannerWork(orig.replySiteId, orig.clientHandle, orig.connectionId, orig.adminConnection, (Connection) orig.clientData, orig.sqlBatchText, orig.sqlStatements, orig.userParamSet, null /* context */, orig.explainMode, orig.inferPartitioning, orig.userPartitionKey, orig.invocationName, orig.m_batchTimeout, orig.drRole, orig.useAdhocDDL, completionHandler, orig.user); } /** * Special factory of a mostly mocked up instance for calling from inside a stored proc. * It's also convenient for simple tests that need to mock up a quick planner request to * test related parts of the system. */ public static AdHocPlannerWork makeStoredProcAdHocPlannerWork(long replySiteId, String sql, Object[] userParams, boolean singlePartition, CatalogContext context, AsyncCompilerWorkCompletionHandler completionHandler) { return makeStoredProcAdHocPlannerWork(replySiteId, sql, userParams, singlePartition, context, completionHandler, false); } public static AdHocPlannerWork makeStoredProcAdHocPlannerWork(long replySiteId, String sql, Object[] userParams, boolean singlePartition, CatalogContext context, AsyncCompilerWorkCompletionHandler completionHandler, boolean isAdmin) { return new AdHocPlannerWork(replySiteId, 0, 0, isAdmin, null, sql, new String[] { sql }, userParams, context, ExplainMode.NONE, // ??? The settings passed here for the single partition stored proc caller // denote that the partitioning has already been done so something like the planner // code path for @AdHocSpForTest is called for. // The plan is required to be single-partition regardless of its internal logic // -- EXCEPT that writes to replicated tables are strictly forbdden -- and there // should be no correlation inferred or assumed between the partitioning and the // statement's constants or parameters. false, (singlePartition ? new Object[1] /*any vector element will do, even null*/ : null), "@AdHoc_RW_MP", BatchTimeoutOverrideType.NO_TIMEOUT, DrRoleType.MASTER, false, // don't allow adhoc DDL in this path completionHandler, new AuthSystem.AuthDisabledUser()); } @Override public String toString() { String retval = super.toString(); if (userParamSet == null || (userParamSet.length == 0)) { retval += "\n user params: empty"; } else { int i = 0; for (Object param : userParamSet) { i++; retval += String.format("\n user param[%d]: %s", i, (param == null ? "null" : param.toString())); } } if (userPartitionKey == null) { retval += "\n user partitioning: none"; } else { retval += "\n user partitioning: " + (userPartitionKey[0] == null ? "null" : userPartitionKey[0].toString()); } assert(sqlStatements != null); if (sqlStatements.length == 0) { retval += "\n sql: empty"; } else { int i = 0; for (String sql : sqlStatements) { i++; retval += String.format("\n sql[%d]: %s", i, sql); } } return retval; } public int getStatementCount() { return (this.sqlStatements != null ? this.sqlStatements.length : 0); } public int getParameterCount() { return (this.userParamSet != null ? this.userParamSet.length : 0); } }