Merge branch 'master' of https://github.com/dakrone/elasticsearch
This commit is contained in:
commit
e47ec96ca2
|
@ -67,6 +67,7 @@ public class TransportActions {
|
|||
public static final String ANALYZE = "indices/analyze";
|
||||
public static final String PUT_INDEX_TEMPLATE = "indices/putIndexTemplate";
|
||||
public static final String DELETE_INDEX_TEMPLATE = "indices/deleteIndexTemplate";
|
||||
public static final String VALIDATE_QUERY = "indices/validateQuery";
|
||||
|
||||
public static class Gateway {
|
||||
public static final String SNAPSHOT = "indices/gateway/snapshot";
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.action.admin.indices.validate.query;
|
||||
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationRequest;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Internal validate request executed directly against a specific index shard.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class ShardValidateQueryRequest extends BroadcastShardOperationRequest {
|
||||
|
||||
private byte[] querySource;
|
||||
private int querySourceOffset;
|
||||
private int querySourceLength;
|
||||
|
||||
private String[] types = Strings.EMPTY_ARRAY;
|
||||
|
||||
@Nullable
|
||||
private String[] filteringAliases;
|
||||
|
||||
ShardValidateQueryRequest() {
|
||||
|
||||
}
|
||||
|
||||
public ShardValidateQueryRequest(String index, int shardId, @Nullable String[] filteringAliases, ValidateQueryRequest request) {
|
||||
super(index, shardId);
|
||||
this.querySource = request.querySource();
|
||||
this.querySourceOffset = request.querySourceOffset();
|
||||
this.querySourceLength = request.querySourceLength();
|
||||
this.types = request.types();
|
||||
this.filteringAliases = filteringAliases;
|
||||
}
|
||||
|
||||
public byte[] querySource() {
|
||||
return querySource;
|
||||
}
|
||||
|
||||
public int querySourceOffset() {
|
||||
return querySourceOffset;
|
||||
}
|
||||
|
||||
public int querySourceLength() {
|
||||
return querySourceLength;
|
||||
}
|
||||
|
||||
public String[] types() {
|
||||
return this.types;
|
||||
}
|
||||
|
||||
public String[] filteringAliases() {
|
||||
return filteringAliases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
querySourceLength = in.readVInt();
|
||||
querySourceOffset = 0;
|
||||
querySource = new byte[querySourceLength];
|
||||
in.readFully(querySource);
|
||||
int typesSize = in.readVInt();
|
||||
if (typesSize > 0) {
|
||||
types = new String[typesSize];
|
||||
for (int i = 0; i < typesSize; i++) {
|
||||
types[i] = in.readUTF();
|
||||
}
|
||||
}
|
||||
int aliasesSize = in.readVInt();
|
||||
if (aliasesSize > 0) {
|
||||
filteringAliases = new String[aliasesSize];
|
||||
for (int i = 0; i < aliasesSize; i++) {
|
||||
filteringAliases[i] = in.readUTF();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeVInt(querySourceLength);
|
||||
out.writeBytes(querySource, querySourceOffset, querySourceLength);
|
||||
out.writeVInt(types.length);
|
||||
for (String type : types) {
|
||||
out.writeUTF(type);
|
||||
}
|
||||
if (filteringAliases != null) {
|
||||
out.writeVInt(filteringAliases.length);
|
||||
for (String alias : filteringAliases) {
|
||||
out.writeUTF(alias);
|
||||
}
|
||||
} else {
|
||||
out.writeVInt(0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.action.admin.indices.validate.query;
|
||||
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Internal validate response of a shard validate request executed directly against a specific shard.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class ShardValidateQueryResponse extends BroadcastShardOperationResponse {
|
||||
|
||||
private boolean valid;
|
||||
|
||||
ShardValidateQueryResponse() {
|
||||
|
||||
}
|
||||
|
||||
public ShardValidateQueryResponse(String index, int shardId, boolean valid) {
|
||||
super(index, shardId);
|
||||
this.valid = valid;
|
||||
}
|
||||
|
||||
boolean valid() {
|
||||
return this.valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
valid = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeBoolean(valid);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.action.admin.indices.validate.query;
|
||||
|
||||
import org.elasticsearch.ElasticSearchException;
|
||||
import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.action.TransportActions;
|
||||
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.broadcast.TransportBroadcastOperationAction;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||
import org.elasticsearch.cluster.routing.GroupShardsIterator;
|
||||
import org.elasticsearch.cluster.routing.ShardRouting;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.query.IndexQueryParserService;
|
||||
import org.elasticsearch.index.query.QueryParsingException;
|
||||
import org.elasticsearch.index.shard.service.IndexShard;
|
||||
import org.elasticsearch.indices.IndicesService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class TransportValidateQueryAction extends TransportBroadcastOperationAction<ValidateQueryRequest, ValidateQueryResponse, ShardValidateQueryRequest, ShardValidateQueryResponse> {
|
||||
|
||||
private final IndicesService indicesService;
|
||||
|
||||
@Inject
|
||||
public TransportValidateQueryAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, IndicesService indicesService) {
|
||||
super(settings, threadPool, clusterService, transportService);
|
||||
this.indicesService = indicesService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String executor() {
|
||||
return ThreadPool.Names.SEARCH;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String transportAction() {
|
||||
return TransportActions.Admin.Indices.VALIDATE_QUERY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String transportShardAction() {
|
||||
return "indices/validateQuery/shard";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ValidateQueryRequest newRequest() {
|
||||
return new ValidateQueryRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShardValidateQueryRequest newShardRequest() {
|
||||
return new ShardValidateQueryRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShardValidateQueryRequest newShardRequest(ShardRouting shard, ValidateQueryRequest request) {
|
||||
String[] filteringAliases = clusterService.state().metaData().filteringAliases(shard.index(), request.indices());
|
||||
return new ShardValidateQueryRequest(shard.index(), shard.id(), filteringAliases, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShardValidateQueryResponse newShardResponse() {
|
||||
return new ShardValidateQueryResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GroupShardsIterator shards(ValidateQueryRequest request, String[] concreteIndices, ClusterState clusterState) {
|
||||
// Hard-code routing to limit request to a single shard.
|
||||
Map<String, Set<String>> routingMap = clusterState.metaData().resolveSearchRouting("0", request.indices());
|
||||
return clusterService.operationRouting().searchShards(clusterState, request.indices(), concreteIndices, null, routingMap, "_local");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkBlock(ValidateQueryRequest request, String[] concreteIndices, ClusterState state) {
|
||||
for (String index : concreteIndices) {
|
||||
state.blocks().indexBlocked(ClusterBlockLevel.READ, index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ValidateQueryResponse newResponse(ValidateQueryRequest request, AtomicReferenceArray shardsResponses, ClusterState clusterState) {
|
||||
int successfulShards = 0;
|
||||
int failedShards = 0;
|
||||
boolean valid = true;
|
||||
List<ShardOperationFailedException> shardFailures = null;
|
||||
for (int i = 0; i < shardsResponses.length(); i++) {
|
||||
Object shardResponse = shardsResponses.get(i);
|
||||
if (shardResponse == null) {
|
||||
failedShards++;
|
||||
} else if (shardResponse instanceof BroadcastShardOperationFailedException) {
|
||||
failedShards++;
|
||||
if (shardFailures == null) {
|
||||
shardFailures = newArrayList();
|
||||
}
|
||||
shardFailures.add(new DefaultShardOperationFailedException((BroadcastShardOperationFailedException) shardResponse));
|
||||
} else {
|
||||
valid = valid && ((ShardValidateQueryResponse) shardResponse).valid();
|
||||
successfulShards++;
|
||||
}
|
||||
}
|
||||
return new ValidateQueryResponse(valid, shardsResponses.length(), successfulShards, failedShards, shardFailures);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShardValidateQueryResponse shardOperation(ShardValidateQueryRequest request) throws ElasticSearchException {
|
||||
IndexQueryParserService queryParserService = indicesService.indexServiceSafe(request.index()).queryParserService();
|
||||
boolean valid;
|
||||
if (request.querySourceLength() == 0) {
|
||||
valid = true;
|
||||
} else {
|
||||
try {
|
||||
queryParserService.parse(request.querySource(), request.querySourceOffset(), request.querySourceLength());
|
||||
valid = true;
|
||||
} catch (QueryParsingException e) {
|
||||
valid = false;
|
||||
} catch (AssertionError e) {
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
return new ShardValidateQueryResponse(request.index(), request.shardId(), valid);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.action.admin.indices.validate.query;
|
||||
|
||||
import org.apache.lucene.util.UnicodeUtil;
|
||||
import org.elasticsearch.ElasticSearchGenerationException;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastOperationRequest;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastOperationThreading;
|
||||
import org.elasticsearch.client.Requests;
|
||||
import org.elasticsearch.common.Required;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.Unicode;
|
||||
import org.elasticsearch.common.io.BytesStream;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A request to validate a specific query.
|
||||
* <p/>
|
||||
* <p>The request requires the query source to be set either using {@link #query(org.elasticsearch.index.query.QueryBuilder)},
|
||||
* or {@link #query(byte[])}.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ValidateQueryRequest extends BroadcastOperationRequest {
|
||||
|
||||
private static final XContentType contentType = Requests.CONTENT_TYPE;
|
||||
|
||||
private byte[] querySource;
|
||||
private int querySourceOffset;
|
||||
private int querySourceLength;
|
||||
private boolean querySourceUnsafe;
|
||||
|
||||
private String[] types = Strings.EMPTY_ARRAY;
|
||||
|
||||
ValidateQueryRequest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new validate request against the provided indices. No indices provided means it will
|
||||
* run against all indices.
|
||||
*/
|
||||
public ValidateQueryRequest(String... indices) {
|
||||
super(indices);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionRequestValidationException validate() {
|
||||
ActionRequestValidationException validationException = super.validate();
|
||||
return validationException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls the operation threading model.
|
||||
*/
|
||||
@Override
|
||||
public ValidateQueryRequest operationThreading(BroadcastOperationThreading operationThreading) {
|
||||
super.operationThreading(operationThreading);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeStart() {
|
||||
if (querySourceUnsafe) {
|
||||
querySource = Arrays.copyOfRange(querySource, querySourceOffset, querySourceOffset + querySourceLength);
|
||||
querySourceOffset = 0;
|
||||
querySourceUnsafe = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the listener be called on a separate thread if needed.
|
||||
*/
|
||||
@Override
|
||||
public ValidateQueryRequest listenerThreaded(boolean threadedListener) {
|
||||
super.listenerThreaded(threadedListener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValidateQueryRequest indices(String... indices) {
|
||||
this.indices = indices;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The query source to execute.
|
||||
*/
|
||||
byte[] querySource() {
|
||||
return querySource;
|
||||
}
|
||||
|
||||
int querySourceOffset() {
|
||||
return querySourceOffset;
|
||||
}
|
||||
|
||||
int querySourceLength() {
|
||||
return querySourceLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* The query source to execute.
|
||||
*
|
||||
* @see org.elasticsearch.index.query.QueryBuilders
|
||||
*/
|
||||
@Required
|
||||
public ValidateQueryRequest query(QueryBuilder queryBuilder) {
|
||||
BytesStream bos = queryBuilder.buildAsUnsafeBytes();
|
||||
this.querySource = bos.underlyingBytes();
|
||||
this.querySourceOffset = 0;
|
||||
this.querySourceLength = bos.size();
|
||||
this.querySourceUnsafe = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The query source to execute in the form of a map.
|
||||
*/
|
||||
@Required
|
||||
public ValidateQueryRequest query(Map querySource) {
|
||||
try {
|
||||
XContentBuilder builder = XContentFactory.contentBuilder(contentType);
|
||||
builder.map(querySource);
|
||||
return query(builder);
|
||||
} catch (IOException e) {
|
||||
throw new ElasticSearchGenerationException("Failed to generate [" + querySource + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Required
|
||||
public ValidateQueryRequest query(XContentBuilder builder) {
|
||||
try {
|
||||
this.querySource = builder.underlyingBytes();
|
||||
this.querySourceOffset = 0;
|
||||
this.querySourceLength = builder.underlyingBytesLength();
|
||||
this.querySourceUnsafe = false;
|
||||
return this;
|
||||
} catch (IOException e) {
|
||||
throw new ElasticSearchGenerationException("Failed to generate [" + builder + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The query source to validate. It is preferable to use either {@link #query(byte[])}
|
||||
* or {@link #query(org.elasticsearch.index.query.QueryBuilder)}.
|
||||
*/
|
||||
@Required
|
||||
public ValidateQueryRequest query(String querySource) {
|
||||
UnicodeUtil.UTF8Result result = Unicode.fromStringAsUtf8(querySource);
|
||||
this.querySource = result.result;
|
||||
this.querySourceOffset = 0;
|
||||
this.querySourceLength = result.length;
|
||||
this.querySourceUnsafe = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The query source to validate.
|
||||
*/
|
||||
@Required
|
||||
public ValidateQueryRequest query(byte[] querySource) {
|
||||
return query(querySource, 0, querySource.length, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The query source to validate.
|
||||
*/
|
||||
@Required
|
||||
public ValidateQueryRequest query(byte[] querySource, int offset, int length, boolean unsafe) {
|
||||
this.querySource = querySource;
|
||||
this.querySourceOffset = offset;
|
||||
this.querySourceLength = length;
|
||||
this.querySourceUnsafe = unsafe;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The types of documents the query will run against. Defaults to all types.
|
||||
*/
|
||||
String[] types() {
|
||||
return this.types;
|
||||
}
|
||||
|
||||
/**
|
||||
* The types of documents the query will run against. Defaults to all types.
|
||||
*/
|
||||
public ValidateQueryRequest types(String... types) {
|
||||
this.types = types;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
|
||||
querySourceUnsafe = false;
|
||||
querySourceOffset = 0;
|
||||
querySourceLength = in.readVInt();
|
||||
querySource = new byte[querySourceLength];
|
||||
in.readFully(querySource);
|
||||
|
||||
int typesSize = in.readVInt();
|
||||
if (typesSize > 0) {
|
||||
types = new String[typesSize];
|
||||
for (int i = 0; i < typesSize; i++) {
|
||||
types[i] = in.readUTF();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
|
||||
out.writeVInt(querySourceLength);
|
||||
out.writeBytes(querySource, querySourceOffset, querySourceLength);
|
||||
|
||||
out.writeVInt(types.length);
|
||||
for (String type : types) {
|
||||
out.writeUTF(type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + Arrays.toString(indices) + "]" + Arrays.toString(types) + ", querySource[" + Unicode.fromBytes(querySource) + "]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.action.admin.indices.validate.query;
|
||||
|
||||
import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastOperationResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The response of the validate action.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ValidateQueryResponse extends BroadcastOperationResponse {
|
||||
|
||||
private boolean valid;
|
||||
|
||||
ValidateQueryResponse() {
|
||||
|
||||
}
|
||||
|
||||
ValidateQueryResponse(boolean valid, int totalShards, int successfulShards, int failedShards, List<ShardOperationFailedException> shardFailures) {
|
||||
super(totalShards, successfulShards, failedShards, shardFailures);
|
||||
this.valid = valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* A boolean denoting whether the query is valid.
|
||||
*/
|
||||
public boolean valid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* A boolean denoting whether the query is valid.
|
||||
*/
|
||||
public boolean getValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
valid = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeBoolean(valid);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Validate action.
|
||||
*/
|
||||
package org.elasticsearch.action.admin.indices.validate.query;
|
|
@ -61,6 +61,8 @@ import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplat
|
|||
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateResponse;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
|
||||
import org.elasticsearch.client.action.admin.indices.alias.IndicesAliasesRequestBuilder;
|
||||
import org.elasticsearch.client.action.admin.indices.analyze.AnalyzeRequestBuilder;
|
||||
import org.elasticsearch.client.action.admin.indices.cache.clear.ClearIndicesCacheRequestBuilder;
|
||||
|
@ -81,6 +83,7 @@ import org.elasticsearch.client.action.admin.indices.stats.IndicesStatsRequestBu
|
|||
import org.elasticsearch.client.action.admin.indices.status.IndicesStatusRequestBuilder;
|
||||
import org.elasticsearch.client.action.admin.indices.template.delete.DeleteIndexTemplateRequestBuilder;
|
||||
import org.elasticsearch.client.action.admin.indices.template.put.PutIndexTemplateRequestBuilder;
|
||||
import org.elasticsearch.client.action.admin.indices.validate.query.ValidateQueryRequestBuilder;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
|
||||
/**
|
||||
|
@ -537,4 +540,27 @@ public interface IndicesAdminClient {
|
|||
* @param name The name of the template.
|
||||
*/
|
||||
DeleteIndexTemplateRequestBuilder prepareDeleteTemplate(String name);
|
||||
|
||||
/**
|
||||
* Validate a query for correctness.
|
||||
*
|
||||
* @param request The count request
|
||||
* @return The result future
|
||||
* @see Requests#countRequest(String...)
|
||||
*/
|
||||
ActionFuture<ValidateQueryResponse> validateQuery(ValidateQueryRequest request);
|
||||
|
||||
/**
|
||||
* Validate a query for correctness.
|
||||
*
|
||||
* @param request The count request
|
||||
* @param listener A listener to be notified of the result
|
||||
* @see Requests#countRequest(String...)
|
||||
*/
|
||||
void validateQuery(ValidateQueryRequest request, ActionListener<ValidateQueryResponse> listener);
|
||||
|
||||
/**
|
||||
* Validate a query for correctness.
|
||||
*/
|
||||
ValidateQueryRequestBuilder prepareValidateQuery(String... indices);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package org.elasticsearch.client.action.admin.indices.validate.query;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastOperationThreading;
|
||||
import org.elasticsearch.client.IndicesAdminClient;
|
||||
import org.elasticsearch.client.action.admin.indices.support.BaseIndicesRequestBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ValidateQueryRequestBuilder extends BaseIndicesRequestBuilder<ValidateQueryRequest, ValidateQueryResponse> {
|
||||
public ValidateQueryRequestBuilder(IndicesAdminClient client) {
|
||||
super(client, new ValidateQueryRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the indices the query validation will run against.
|
||||
*/
|
||||
public ValidateQueryRequestBuilder setIndices(String... indices) {
|
||||
request.indices(indices);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The types of documents the query will run against. Defaults to all types.
|
||||
*/
|
||||
public ValidateQueryRequestBuilder setTypes(String... types) {
|
||||
request.types(types);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The query source to validate.
|
||||
*
|
||||
* @see org.elasticsearch.index.query.QueryBuilders
|
||||
*/
|
||||
public ValidateQueryRequestBuilder setQuery(QueryBuilder queryBuilder) {
|
||||
request.query(queryBuilder);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The query source to validate.
|
||||
*
|
||||
* @see org.elasticsearch.index.query.QueryBuilders
|
||||
*/
|
||||
public ValidateQueryRequestBuilder setQuery(byte[] querySource) {
|
||||
request.query(querySource);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls the operation threading model.
|
||||
*/
|
||||
public ValidateQueryRequestBuilder setOperationThreading(BroadcastOperationThreading operationThreading) {
|
||||
request.operationThreading(operationThreading);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the listener be called on a separate thread if needed.
|
||||
*/
|
||||
public ValidateQueryRequestBuilder setListenerThreaded(boolean threadedListener) {
|
||||
request.listenerThreaded(threadedListener);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doExecute(ActionListener<ValidateQueryResponse> listener) {
|
||||
client.validateQuery(request, listener);
|
||||
}
|
||||
}
|
|
@ -81,6 +81,9 @@ import org.elasticsearch.action.admin.indices.template.delete.TransportDeleteInd
|
|||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
|
||||
import org.elasticsearch.action.admin.indices.template.put.TransportPutIndexTemplateAction;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.TransportValidateQueryAction;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
|
||||
import org.elasticsearch.client.IndicesAdminClient;
|
||||
import org.elasticsearch.client.support.AbstractIndicesAdminClient;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
|
@ -134,6 +137,8 @@ public class NodeIndicesAdminClient extends AbstractIndicesAdminClient implement
|
|||
|
||||
private final TransportDeleteIndexTemplateAction deleteIndexTemplateAction;
|
||||
|
||||
private final TransportValidateQueryAction validateQueryAction;
|
||||
|
||||
@Inject
|
||||
public NodeIndicesAdminClient(Settings settings, ThreadPool threadPool, TransportIndicesExistsAction indicesExistsAction, TransportIndicesStatsAction indicesStatsAction, TransportIndicesStatusAction indicesStatusAction, TransportIndicesSegmentsAction indicesSegmentsAction,
|
||||
TransportCreateIndexAction createIndexAction, TransportDeleteIndexAction deleteIndexAction,
|
||||
|
@ -142,7 +147,7 @@ public class NodeIndicesAdminClient extends AbstractIndicesAdminClient implement
|
|||
TransportPutMappingAction putMappingAction, TransportDeleteMappingAction deleteMappingAction, TransportGatewaySnapshotAction gatewaySnapshotAction,
|
||||
TransportIndicesAliasesAction indicesAliasesAction, TransportClearIndicesCacheAction clearIndicesCacheAction,
|
||||
TransportUpdateSettingsAction updateSettingsAction, TransportAnalyzeAction analyzeAction,
|
||||
TransportPutIndexTemplateAction putIndexTemplateAction, TransportDeleteIndexTemplateAction deleteIndexTemplateAction) {
|
||||
TransportPutIndexTemplateAction putIndexTemplateAction, TransportDeleteIndexTemplateAction deleteIndexTemplateAction, TransportValidateQueryAction validateQueryAction) {
|
||||
this.threadPool = threadPool;
|
||||
this.indicesExistsAction = indicesExistsAction;
|
||||
this.indicesStatsAction = indicesStatsAction;
|
||||
|
@ -164,6 +169,7 @@ public class NodeIndicesAdminClient extends AbstractIndicesAdminClient implement
|
|||
this.analyzeAction = analyzeAction;
|
||||
this.putIndexTemplateAction = putIndexTemplateAction;
|
||||
this.deleteIndexTemplateAction = deleteIndexTemplateAction;
|
||||
this.validateQueryAction = validateQueryAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -370,4 +376,14 @@ public class NodeIndicesAdminClient extends AbstractIndicesAdminClient implement
|
|||
public void deleteTemplate(DeleteIndexTemplateRequest request, ActionListener<DeleteIndexTemplateResponse> listener) {
|
||||
deleteIndexTemplateAction.execute(request, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFuture<ValidateQueryResponse> validateQuery(ValidateQueryRequest request) {
|
||||
return validateQueryAction.execute(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateQuery(ValidateQueryRequest request, ActionListener<ValidateQueryResponse> listener) {
|
||||
validateQueryAction.execute(request, listener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.elasticsearch.client.action.admin.indices.stats.IndicesStatsRequestBu
|
|||
import org.elasticsearch.client.action.admin.indices.status.IndicesStatusRequestBuilder;
|
||||
import org.elasticsearch.client.action.admin.indices.template.delete.DeleteIndexTemplateRequestBuilder;
|
||||
import org.elasticsearch.client.action.admin.indices.template.put.PutIndexTemplateRequestBuilder;
|
||||
import org.elasticsearch.client.action.admin.indices.validate.query.ValidateQueryRequestBuilder;
|
||||
import org.elasticsearch.client.internal.InternalIndicesAdminClient;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
|
||||
|
@ -151,4 +152,9 @@ public abstract class AbstractIndicesAdminClient implements InternalIndicesAdmin
|
|||
public DeleteIndexTemplateRequestBuilder prepareDeleteTemplate(String name) {
|
||||
return new DeleteIndexTemplateRequestBuilder(this, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidateQueryRequestBuilder prepareValidateQuery(String... indices) {
|
||||
return new ValidateQueryRequestBuilder(this).setIndices(indices);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package org.elasticsearch.client.transport.action.admin.indices.validate.query;
|
||||
|
||||
import org.elasticsearch.action.TransportActions;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
|
||||
import org.elasticsearch.client.transport.action.support.BaseClientTransportAction;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ClientTransportValidateQueryAction extends BaseClientTransportAction<ValidateQueryRequest, ValidateQueryResponse> {
|
||||
|
||||
@Inject
|
||||
public ClientTransportValidateQueryAction(Settings settings, TransportService transportService) {
|
||||
super(settings, transportService, ValidateQueryResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String action() {
|
||||
return TransportActions.Admin.Indices.VALIDATE_QUERY;
|
||||
}
|
||||
}
|
|
@ -62,6 +62,8 @@ import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplat
|
|||
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateResponse;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
|
||||
import org.elasticsearch.client.IndicesAdminClient;
|
||||
import org.elasticsearch.client.support.AbstractIndicesAdminClient;
|
||||
import org.elasticsearch.client.transport.TransportClientNodesService;
|
||||
|
@ -85,6 +87,7 @@ import org.elasticsearch.client.transport.action.admin.indices.stats.ClientTrans
|
|||
import org.elasticsearch.client.transport.action.admin.indices.status.ClientTransportIndicesStatusAction;
|
||||
import org.elasticsearch.client.transport.action.admin.indices.template.delete.ClientTransportDeleteIndexTemplateAction;
|
||||
import org.elasticsearch.client.transport.action.admin.indices.template.put.ClientTransportPutIndexTemplateAction;
|
||||
import org.elasticsearch.client.transport.action.admin.indices.validate.query.ClientTransportValidateQueryAction;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
@ -139,6 +142,8 @@ public class InternalTransportIndicesAdminClient extends AbstractIndicesAdminCli
|
|||
|
||||
private final ClientTransportDeleteIndexTemplateAction deleteIndexTemplateAction;
|
||||
|
||||
private final ClientTransportValidateQueryAction validateQueryAction;
|
||||
|
||||
@Inject
|
||||
public InternalTransportIndicesAdminClient(Settings settings, TransportClientNodesService nodesService, ThreadPool threadPool,
|
||||
ClientTransportIndicesExistsAction indicesExistsAction, ClientTransportIndicesStatusAction indicesStatusAction, ClientTransportIndicesStatsAction indicesStatsAction, ClientTransportIndicesSegmentsAction indicesSegmentsAction,
|
||||
|
@ -147,7 +152,7 @@ public class InternalTransportIndicesAdminClient extends AbstractIndicesAdminCli
|
|||
ClientTransportRefreshAction refreshAction, ClientTransportFlushAction flushAction, ClientTransportOptimizeAction optimizeAction,
|
||||
ClientTransportPutMappingAction putMappingAction, ClientTransportDeleteMappingAction deleteMappingAction, ClientTransportGatewaySnapshotAction gatewaySnapshotAction,
|
||||
ClientTransportIndicesAliasesAction indicesAliasesAction, ClientTransportClearIndicesCacheAction clearIndicesCacheAction,
|
||||
ClientTransportUpdateSettingsAction updateSettingsAction, ClientTransportAnalyzeAction analyzeAction,
|
||||
ClientTransportUpdateSettingsAction updateSettingsAction, ClientTransportAnalyzeAction analyzeAction, ClientTransportValidateQueryAction validateQueryAction,
|
||||
ClientTransportPutIndexTemplateAction putIndexTemplateAction, ClientTransportDeleteIndexTemplateAction deleteIndexTemplateAction) {
|
||||
this.nodesService = nodesService;
|
||||
this.threadPool = threadPool;
|
||||
|
@ -171,6 +176,7 @@ public class InternalTransportIndicesAdminClient extends AbstractIndicesAdminCli
|
|||
this.analyzeAction = analyzeAction;
|
||||
this.putIndexTemplateAction = putIndexTemplateAction;
|
||||
this.deleteIndexTemplateAction = deleteIndexTemplateAction;
|
||||
this.validateQueryAction = validateQueryAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -577,4 +583,24 @@ public class InternalTransportIndicesAdminClient extends AbstractIndicesAdminCli
|
|||
}
|
||||
}, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionFuture<ValidateQueryResponse> validateQuery(final ValidateQueryRequest request) {
|
||||
return nodesService.execute(new TransportClientNodesService.NodeCallback<ActionFuture<ValidateQueryResponse>>() {
|
||||
@Override
|
||||
public ActionFuture<ValidateQueryResponse> doWithNode(DiscoveryNode node) throws ElasticSearchException {
|
||||
return validateQueryAction.execute(node, request);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateQuery(final ValidateQueryRequest request, final ActionListener<ValidateQueryResponse> listener) {
|
||||
nodesService.execute(new TransportClientNodesService.NodeListenerCallback<ValidateQueryResponse>() {
|
||||
@Override
|
||||
public void doWithNode(DiscoveryNode node, ActionListener<ValidateQueryResponse> listener) throws ElasticSearchException {
|
||||
validateQueryAction.execute(node, request, listener);
|
||||
}
|
||||
}, listener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ import org.elasticsearch.rest.action.admin.indices.status.RestIndicesStatusActio
|
|||
import org.elasticsearch.rest.action.admin.indices.template.delete.RestDeleteIndexTemplateAction;
|
||||
import org.elasticsearch.rest.action.admin.indices.template.get.RestGetIndexTemplateAction;
|
||||
import org.elasticsearch.rest.action.admin.indices.template.put.RestPutIndexTemplateAction;
|
||||
import org.elasticsearch.rest.action.admin.indices.validate.query.RestValidateQueryAction;
|
||||
import org.elasticsearch.rest.action.bulk.RestBulkAction;
|
||||
import org.elasticsearch.rest.action.count.RestCountAction;
|
||||
import org.elasticsearch.rest.action.delete.RestDeleteAction;
|
||||
|
@ -149,6 +150,8 @@ public class RestActionModule extends AbstractModule {
|
|||
|
||||
bind(RestSearchAction.class).asEagerSingleton();
|
||||
bind(RestSearchScrollAction.class).asEagerSingleton();
|
||||
|
||||
bind(RestValidateQueryAction.class).asEagerSingleton();
|
||||
|
||||
bind(RestMoreLikeThisAction.class).asEagerSingleton();
|
||||
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch 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.elasticsearch.rest.action.admin.indices.validate.query;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastOperationThreading;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
|
||||
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.rest.*;
|
||||
import org.elasticsearch.rest.action.support.RestActions;
|
||||
import org.elasticsearch.rest.action.support.RestXContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
import static org.elasticsearch.rest.RestStatus.BAD_REQUEST;
|
||||
import static org.elasticsearch.rest.RestStatus.OK;
|
||||
import static org.elasticsearch.rest.action.support.RestActions.buildBroadcastShardsHeader;
|
||||
import static org.elasticsearch.rest.action.support.RestActions.splitTypes;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class RestValidateQueryAction extends BaseRestHandler {
|
||||
|
||||
@Inject
|
||||
public RestValidateQueryAction(Settings settings, Client client, RestController controller) {
|
||||
super(settings, client);
|
||||
controller.registerHandler(GET, "/_validate/query", this);
|
||||
controller.registerHandler(POST, "/_validate/query", this);
|
||||
controller.registerHandler(GET, "/{index}/_validate/query", this);
|
||||
controller.registerHandler(POST, "/{index}/_validate/query", this);
|
||||
controller.registerHandler(GET, "/{index}/{type}/_validate/query", this);
|
||||
controller.registerHandler(POST, "/{index}/{type}/_validate/query", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel) {
|
||||
ValidateQueryRequest validateQueryRequest = new ValidateQueryRequest(RestActions.splitIndices(request.param("index")));
|
||||
// we just send back a response, no need to fork a listener
|
||||
validateQueryRequest.listenerThreaded(false);
|
||||
try {
|
||||
BroadcastOperationThreading operationThreading = BroadcastOperationThreading.fromString(request.param("operation_threading"), BroadcastOperationThreading.SINGLE_THREAD);
|
||||
if (operationThreading == BroadcastOperationThreading.NO_THREADS) {
|
||||
// since we don't spawn, don't allow no_threads, but change it to a single thread
|
||||
operationThreading = BroadcastOperationThreading.SINGLE_THREAD;
|
||||
}
|
||||
validateQueryRequest.operationThreading(operationThreading);
|
||||
if (request.hasContent()) {
|
||||
validateQueryRequest.query(request.contentByteArray(), request.contentByteArrayOffset(), request.contentLength(), true);
|
||||
} else {
|
||||
String source = request.param("source");
|
||||
if (source != null) {
|
||||
validateQueryRequest.query(source);
|
||||
} else {
|
||||
byte[] querySource = RestActions.parseQuerySource(request);
|
||||
if (querySource != null) {
|
||||
validateQueryRequest.query(querySource);
|
||||
}
|
||||
}
|
||||
}
|
||||
validateQueryRequest.types(splitTypes(request.param("type")));
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
|
||||
channel.sendResponse(new XContentRestResponse(request, BAD_REQUEST, builder.startObject().field("error", e.getMessage()).endObject()));
|
||||
} catch (IOException e1) {
|
||||
logger.error("Failed to send failure response", e1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
client.admin().indices().validateQuery(validateQueryRequest, new ActionListener<ValidateQueryResponse>() {
|
||||
@Override
|
||||
public void onResponse(ValidateQueryResponse response) {
|
||||
try {
|
||||
XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
|
||||
builder.startObject();
|
||||
builder.field("valid", response.valid());
|
||||
|
||||
buildBroadcastShardsHeader(builder, response);
|
||||
|
||||
builder.endObject();
|
||||
channel.sendResponse(new XContentRestResponse(request, OK, builder));
|
||||
} catch (Exception e) {
|
||||
onFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
try {
|
||||
channel.sendResponse(new XContentThrowableRestResponse(request, e));
|
||||
} catch (IOException e1) {
|
||||
logger.error("Failed to send failure response", e1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Licensed to Elastic Search and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Elastic Search 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.elasticsearch.test.integration.validate;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.test.integration.AbstractNodesTests;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SimpleValidateQueryTests extends AbstractNodesTests {
|
||||
|
||||
private Client client;
|
||||
|
||||
@BeforeClass
|
||||
public void createNodes() throws Exception {
|
||||
startNode("node1");
|
||||
startNode("node2");
|
||||
client = getClient();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public void closeNodes() {
|
||||
client.close();
|
||||
closeAllNodes();
|
||||
}
|
||||
|
||||
protected Client getClient() {
|
||||
return client("node1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleValidateQuery() throws Exception {
|
||||
client.admin().indices().prepareDelete().execute().actionGet();
|
||||
|
||||
client.admin().indices().prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder().put("index.number_of_shards", 1)).execute().actionGet();
|
||||
client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
|
||||
client.admin().indices().preparePutMapping("test").setType("type1")
|
||||
.setSource(XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
|
||||
.startObject("foo").field("type", "string").endObject()
|
||||
.startObject("bar").field("type", "integer").endObject()
|
||||
.endObject().endObject().endObject())
|
||||
.execute().actionGet();
|
||||
|
||||
client.admin().indices().prepareRefresh().execute().actionGet();
|
||||
|
||||
assertThat(client.admin().indices().prepareValidateQuery("test").setQuery("foo".getBytes()).execute().actionGet().valid(), equalTo(false));
|
||||
assertThat(client.admin().indices().prepareValidateQuery("test").setQuery(QueryBuilders.queryString("_id:1")).execute().actionGet().valid(), equalTo(true));
|
||||
assertThat(client.admin().indices().prepareValidateQuery("test").setQuery(QueryBuilders.queryString("_i:d:1")).execute().actionGet().valid(), equalTo(false));
|
||||
|
||||
assertThat(client.admin().indices().prepareValidateQuery("test").setQuery(QueryBuilders.queryString("foo:1")).execute().actionGet().valid(), equalTo(true));
|
||||
assertThat(client.admin().indices().prepareValidateQuery("test").setQuery(QueryBuilders.queryString("bar:hey")).execute().actionGet().valid(), equalTo(false));
|
||||
|
||||
assertThat(client.admin().indices().prepareValidateQuery("test").setQuery(QueryBuilders.queryString("nonexistent:hello")).execute().actionGet().valid(), equalTo(true));
|
||||
|
||||
assertThat(client.admin().indices().prepareValidateQuery("test").setQuery(QueryBuilders.queryString("foo:1 AND")).execute().actionGet().valid(), equalTo(false));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue