org.apache.solr.handler.sql.SQLHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of solr-sql Show documentation
Show all versions of solr-sql Show documentation
Apache Solr (module: sql)
/*
* 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.sql;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.calcite.config.Lex;
import org.apache.solr.client.solrj.io.Tuple;
import org.apache.solr.client.solrj.io.comp.StreamComparator;
import org.apache.solr.client.solrj.io.stream.ExceptionStream;
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.core.CoreContainer;
import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.handler.StreamHandler;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.security.AuthorizationContext;
import org.apache.solr.security.PermissionNameProvider;
import org.apache.solr.util.plugin.SolrCoreAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SQLHandler extends RequestHandlerBase
implements SolrCoreAware, PermissionNameProvider {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static String defaultZkhost = null;
private static String defaultWorkerCollection = null;
static final String sqlNonCloudErrorMsg = "/sql handler only works in Solr Cloud mode";
private boolean isCloud = false;
@Override
public void inform(SolrCore core) {
CoreContainer coreContainer = core.getCoreContainer();
if (coreContainer.isZooKeeperAware()) {
defaultZkhost = coreContainer.getZkController().getZkServerAddress();
defaultWorkerCollection = core.getCoreDescriptor().getCollectionName();
isCloud = true;
}
CalciteSolrDriver.INSTANCE.setSolrClientCache(coreContainer.getSolrClientCache());
}
@Override
public PermissionNameProvider.Name getPermissionName(AuthorizationContext request) {
return PermissionNameProvider.Name.READ_PERM;
}
@Override
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
ModifiableSolrParams params = new ModifiableSolrParams(req.getParams());
params = adjustParams(params);
req.setParams(params);
String sql = params.get("stmt");
// Set defaults for parameters
params.set("numWorkers", params.getInt("numWorkers", 1));
params.set("workerCollection", params.get("workerCollection", defaultWorkerCollection));
params.set("workerZkhost", params.get("workerZkhost", defaultZkhost));
params.set("aggregationMode", params.get("aggregationMode", "facet"));
TupleStream tupleStream = null;
try {
if (!isCloud) {
throw new IllegalStateException(sqlNonCloudErrorMsg);
}
if (sql == null) {
throw new Exception("stmt parameter cannot be null");
}
String url = CalciteSolrDriver.CONNECT_STRING_PREFIX;
Properties properties = new Properties();
// Add all query parameters
Iterator parameterNamesIterator = params.getParameterNamesIterator();
while (parameterNamesIterator.hasNext()) {
String param = parameterNamesIterator.next();
properties.setProperty(param, params.get(param));
}
// Set these last to ensure that they are set properly
properties.setProperty("lex", Lex.MYSQL.toString());
properties.setProperty("zk", defaultZkhost);
String driverClass = CalciteSolrDriver.class.getCanonicalName();
// JDBC driver requires metadata from the SQLHandler. Default to false since this adds a new
// Metadata stream.
boolean includeMetadata = params.getBool("includeMetadata", false);
tupleStream = new SqlHandlerStream(url, sql, null, properties, driverClass, includeMetadata);
tupleStream = new StreamHandler.TimerStream(new ExceptionStream(tupleStream));
rsp.add("result-set", tupleStream);
} catch (Exception e) {
// Catch the SQL parsing and query transformation exceptions.
if (tupleStream != null) {
tupleStream.close();
}
log.error("Exception while SQL parsing and query transformation", e);
rsp.add("result-set", new StreamHandler.DummyErrorStream(e));
}
}
@Override
public String getDescription() {
return "SQLHandler";
}
public String getSource() {
return null;
}
/*
* Only necessary for SolrJ JDBC driver since metadata has to be passed back
*/
private static class SqlHandlerStream extends CalciteJDBCStream {
private final boolean includeMetadata;
private boolean firstTuple = true;
List metadataFields = new ArrayList<>();
Map metadataAliases = new HashMap<>();
SqlHandlerStream(
String connectionUrl,
String sqlQuery,
StreamComparator definedSort,
Properties connectionProperties,
String driverClassName,
boolean includeMetadata)
throws IOException {
super(connectionUrl, sqlQuery, definedSort, connectionProperties, driverClassName);
this.includeMetadata = includeMetadata;
}
@Override
public Tuple read() throws IOException {
// Return a metadata tuple as the first tuple and then pass through to the JDBCStream.
if (firstTuple) {
try {
Tuple tuple = new Tuple();
firstTuple = false;
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
String columnName = resultSetMetaData.getColumnName(i);
String columnLabel = resultSetMetaData.getColumnLabel(i);
metadataFields.add(columnName);
metadataAliases.put(columnName, columnLabel);
}
if (includeMetadata) {
tuple.put("isMetadata", true);
tuple.put("fields", metadataFields);
tuple.put("aliases", metadataAliases);
return tuple;
}
} catch (SQLException e) {
throw new IOException(e);
}
}
Tuple tuple = super.read();
if (!tuple.EOF) {
tuple.setFieldNames(metadataFields);
tuple.setFieldLabels(metadataAliases);
}
return tuple;
}
}
private ModifiableSolrParams adjustParams(SolrParams params) {
ModifiableSolrParams adjustedParams = new ModifiableSolrParams();
adjustedParams.add(params);
adjustedParams.add(CommonParams.OMIT_HEADER, "true");
return adjustedParams;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy