diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 271cec48cf4..27939d6381a 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -265,6 +265,8 @@ Other Changes * SOLR-8385: Narrow StreamFactory.withFunctionName clazz parameter to prevent misconfiguration (Jason Gerlowski, Kevin Risden) +* SOLR-8969: SQLHandler causes NPE in non-cloud mode (Markus Jelsma, Kevin Risden) + ================== 6.2.1 ================== Bug Fixes diff --git a/solr/core/src/java/org/apache/solr/handler/SQLHandler.java b/solr/core/src/java/org/apache/solr/handler/SQLHandler.java index f0240c627cd..5fcf93828e3 100644 --- a/solr/core/src/java/org/apache/solr/handler/SQLHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/SQLHandler.java @@ -88,6 +88,7 @@ public class SQLHandler extends RequestHandlerBase implements SolrCoreAware , Pe } private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + static final String sqlNonCloudErrorMsg = "/sql handler only works in Solr Cloud mode"; public void inform(SolrCore core) { @@ -111,7 +112,7 @@ public class SQLHandler extends RequestHandlerBase implements SolrCoreAware , Pe String sql = params.get("stmt"); int numWorkers = params.getInt("numWorkers", 1); String workerCollection = params.get("workerCollection", defaultWorkerCollection); - String workerZkhost = params.get("workerZkhost",defaultZkhost); + String workerZkhost = params.get("workerZkhost", defaultZkhost); String mode = params.get("aggregationMode", "map_reduce"); StreamContext context = new StreamContext(); @@ -120,6 +121,10 @@ public class SQLHandler extends RequestHandlerBase implements SolrCoreAware , Pe try { + if(workerZkhost == null) { + throw new IllegalStateException(sqlNonCloudErrorMsg); + } + if(sql == null) { throw new Exception("stmt parameter cannot be null"); } diff --git a/solr/core/src/test/org/apache/solr/handler/TestSQLHandlerNonCloud.java b/solr/core/src/test/org/apache/solr/handler/TestSQLHandlerNonCloud.java new file mode 100644 index 00000000000..8623290844d --- /dev/null +++ b/solr/core/src/test/org/apache/solr/handler/TestSQLHandlerNonCloud.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.handler; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.solr.SolrJettyTestBase; +import org.apache.solr.client.solrj.io.Tuple; +import org.apache.solr.client.solrj.io.stream.SolrStream; +import org.apache.solr.client.solrj.io.stream.TupleStream; +import org.apache.solr.common.params.CommonParams; +import org.apache.solr.common.params.ModifiableSolrParams; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.IOUtils; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestSQLHandlerNonCloud extends SolrJettyTestBase { + + private static File createSolrHome() throws Exception { + File workDir = createTempDir().toFile(); + setupJettyTestHome(workDir, DEFAULT_TEST_COLLECTION_NAME); + return workDir; + } + + @BeforeClass + public static void beforeClass() throws Exception { + File solrHome = createSolrHome(); + solrHome.deleteOnExit(); + createJetty(solrHome.getAbsolutePath()); + } + + @Test + public void testSQLHandler() throws Exception { + String sql = "select id, field_i, str_s from " + DEFAULT_TEST_COLLECTION_NAME + " limit 10"; + SolrParams sParams = mapParams(CommonParams.QT, "/sql", "stmt", sql); + String url = jetty.getBaseUrl() + "/" + DEFAULT_TEST_COLLECTION_NAME; + + SolrStream solrStream = new SolrStream(url, sParams); + try { + getTuples(solrStream); + fail(SQLHandler.sqlNonCloudErrorMsg); + } catch (IOException e) { + assertTrue(e.getMessage().contains(SQLHandler.sqlNonCloudErrorMsg)); + } + } + + private List getTuples(TupleStream tupleStream) throws IOException { + List tuples = new ArrayList<>(); + try { + tupleStream.open(); + for (; ; ) { + Tuple t = tupleStream.read(); + if (t.EOF) { + break; + } else { + tuples.add(t); + } + } + } finally { + IOUtils.closeQuietly(tupleStream); + } + return tuples; + } + + public static SolrParams mapParams(String... vals) { + ModifiableSolrParams params = new ModifiableSolrParams(); + assertEquals("Parameters passed in here must be in pairs!", 0, (vals.length % 2)); + for (int idx = 0; idx < vals.length; idx += 2) { + params.add(vals[idx], vals[idx + 1]); + } + + return params; + } +}