mirror of https://github.com/apache/druid.git
Add default configuration for select query 'fromNext' parameter (#3986)
* Add default configuration for select query 'fromNext' parameter * PR comments * Fix PagingSpec config injection * Injection fix for test
This commit is contained in:
parent
23927a3c96
commit
5fb1638534
|
@ -20,6 +20,8 @@
|
|||
package io.druid.benchmark.query;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.io.Files;
|
||||
|
@ -49,6 +51,7 @@ import io.druid.query.dimension.DefaultDimensionSpec;
|
|||
import io.druid.query.select.EventHolder;
|
||||
import io.druid.query.select.PagingSpec;
|
||||
import io.druid.query.select.SelectQuery;
|
||||
import io.druid.query.select.SelectQueryConfig;
|
||||
import io.druid.query.select.SelectQueryEngine;
|
||||
import io.druid.query.select.SelectQueryQueryToolChest;
|
||||
import io.druid.query.select.SelectQueryRunnerFactory;
|
||||
|
@ -227,12 +230,15 @@ public class SelectBenchmark
|
|||
qIndexes.add(qIndex);
|
||||
}
|
||||
|
||||
final Supplier<SelectQueryConfig> selectConfigSupplier = Suppliers.ofInstance(new SelectQueryConfig(true));
|
||||
|
||||
factory = new SelectQueryRunnerFactory(
|
||||
new SelectQueryQueryToolChest(
|
||||
JSON_MAPPER,
|
||||
QueryBenchmarkUtil.NoopIntervalChunkingQueryRunnerDecorator()
|
||||
QueryBenchmarkUtil.NoopIntervalChunkingQueryRunnerDecorator(),
|
||||
selectConfigSupplier
|
||||
),
|
||||
new SelectQueryEngine(),
|
||||
new SelectQueryEngine(selectConfigSupplier),
|
||||
QueryBenchmarkUtil.NOOP_QUERYWATCHER
|
||||
);
|
||||
}
|
||||
|
|
|
@ -152,7 +152,57 @@ The results above include:
|
|||
},
|
||||
```
|
||||
|
||||
This can be used with the next query's pagingSpec:
|
||||
### Result Pagination
|
||||
|
||||
The PagingSpec allows the user to specify that the results of a select query should be returned as a paginated set.
|
||||
|
||||
The `threshold` option controls how many rows are returned in each block of paginated results.
|
||||
|
||||
To initiate a paginated query, the user should specify a PagingSpec with a `threshold` set and a blank `pagingIdentifiers` field, e.g.:
|
||||
|
||||
```json
|
||||
"pagingSpec":{"pagingIdentifiers": {}, "threshold":5}
|
||||
```
|
||||
|
||||
When the query returns, the results will contain a `pagingIndentifers` field indicating the current pagination point in the result set (an identifier and an offset).
|
||||
|
||||
To retrieve the next part of the result set, the user should issue the same select query, but replace the `pagingIdentifiers` field of the query with the `pagingIdentifiers` from the previous result.
|
||||
|
||||
When an empty result set is received, all rows have been returned.
|
||||
|
||||
#### fromNext Backwards Compatibility
|
||||
|
||||
In older versions of Druid, when using paginated select queries, it was necessary for the user to manually increment the paging offset by 1 in each `pagingIdentifiers` before submitting the next query to retrieve the next set of results. This offset increment happens automatically in the current version of Druid by default, the user does not need to modify the `pagingIdentifiers` offset to retrieve the next result set.
|
||||
|
||||
Setting the `fromNext` field of the PagingSpec to false instructs Druid to operate in the older mode where the user must manually increment the offset (or decrement for descending queries).
|
||||
|
||||
For example, suppose the user issues the following initial paginated query, with `fromNext` false:
|
||||
|
||||
```json
|
||||
{
|
||||
"queryType": "select",
|
||||
"dataSource": "wikipedia",
|
||||
"descending": "false",
|
||||
"dimensions":[],
|
||||
"metrics":[],
|
||||
"granularity": "all",
|
||||
"intervals": [
|
||||
"2013-01-01/2013-01-02"
|
||||
],
|
||||
"pagingSpec":{"fromNext": "false", "pagingIdentifiers": {}, "threshold":5}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The paginated query with `fromNext` set to false returns a result set with the following `pagingIdentifiers`:
|
||||
|
||||
```json
|
||||
"pagingIdentifiers" : {
|
||||
"wikipedia_2012-12-29T00:00:00.000Z_2013-01-10T08:00:00.000Z_2013-01-10T08:13:47.830Z_v9" : 4
|
||||
},
|
||||
```
|
||||
|
||||
To retrieve the next result set, the next query must be sent with the paging offset (4) incremented by 1.
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -164,18 +214,16 @@ This can be used with the next query's pagingSpec:
|
|||
"intervals": [
|
||||
"2013-01-01/2013-01-02"
|
||||
],
|
||||
"pagingSpec":{"pagingIdentifiers": {"wikipedia_2012-12-29T00:00:00.000Z_2013-01-10T08:00:00.000Z_2013-01-10T08:13:47.830Z_v9" : 5}, "threshold":5}
|
||||
|
||||
"pagingSpec":{"fromNext": "false", "pagingIdentifiers": {"wikipedia_2012-12-29T00:00:00.000Z_2013-01-10T08:00:00.000Z_2013-01-10T08:13:47.830Z_v9" : 5}, "threshold":5}
|
||||
}
|
||||
```
|
||||
|
||||
Note that in the second query, an offset is specified and that it is 1 greater than the largest offset found in the initial results. To return the next "page", this offset must be incremented by 1 (should be decremented by 1 for descending query), with each new query, but with option `fromNext` enabled, this operation is not needed. When an empty results set is received, the very last page has been returned.
|
||||
Note that specifying the `fromNext` option in the `pagingSpec` overrides the default value set by `druid.query.select.enableFromNextDefault` in the server configuration. See [Server configuration](#server-configuration) for more details.
|
||||
|
||||
`fromNext` options is in pagingSpec:
|
||||
### Server configuration
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"pagingSpec":{"pagingIdentifiers": {}, "threshold":5, "fromNext": true}
|
||||
}
|
||||
```
|
||||
The following runtime properties apply to select queries:
|
||||
|
||||
|Property|Description|Default|
|
||||
|--------|-----------|-------|
|
||||
|`druid.query.select.enableFromNextDefault`|If the `fromNext` property in a query's `pagingSpec` is left unspecified, the system will use the value of this property as the default value for `fromNext`. This option is true by default: the option of setting `fromNext` to false by default is intended to support backwards compatibility for deployments where some users may still expect behavior from older versions of Druid.|true|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package io.druid.segment;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -37,6 +39,7 @@ import io.druid.query.Result;
|
|||
import io.druid.query.select.EventHolder;
|
||||
import io.druid.query.select.PagingSpec;
|
||||
import io.druid.query.select.SelectQuery;
|
||||
import io.druid.query.select.SelectQueryConfig;
|
||||
import io.druid.query.select.SelectQueryEngine;
|
||||
import io.druid.query.select.SelectQueryQueryToolChest;
|
||||
import io.druid.query.select.SelectQueryRunnerFactory;
|
||||
|
@ -69,12 +72,15 @@ public class MapVirtualColumnTest
|
|||
@Parameterized.Parameters
|
||||
public static Iterable<Object[]> constructorFeeder() throws IOException
|
||||
{
|
||||
final Supplier<SelectQueryConfig> selectConfigSupplier = Suppliers.ofInstance(new SelectQueryConfig(true));
|
||||
|
||||
SelectQueryRunnerFactory factory = new SelectQueryRunnerFactory(
|
||||
new SelectQueryQueryToolChest(
|
||||
new DefaultObjectMapper(),
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator()
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator(),
|
||||
selectConfigSupplier
|
||||
),
|
||||
new SelectQueryEngine(),
|
||||
new SelectQueryEngine(selectConfigSupplier),
|
||||
QueryRunnerTestHelper.NOOP_QUERYWATCHER
|
||||
);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package io.druid.query.select;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -59,22 +60,32 @@ public class PagingSpec
|
|||
private final Map<String, Integer> pagingIdentifiers;
|
||||
private final int threshold;
|
||||
private final boolean fromNext;
|
||||
private final SelectQueryConfig config;
|
||||
|
||||
@JsonCreator
|
||||
public PagingSpec(
|
||||
@JsonProperty("pagingIdentifiers") Map<String, Integer> pagingIdentifiers,
|
||||
@JsonProperty("threshold") int threshold,
|
||||
@JsonProperty("fromNext") boolean fromNext
|
||||
@JsonProperty("fromNext") Boolean fromNext,
|
||||
@JacksonInject SelectQueryConfig config
|
||||
)
|
||||
{
|
||||
this.pagingIdentifiers = pagingIdentifiers == null ? Maps.<String, Integer>newHashMap() : pagingIdentifiers;
|
||||
this.threshold = threshold;
|
||||
this.fromNext = fromNext;
|
||||
this.config = config;
|
||||
|
||||
boolean defaultFromNext = config.getEnableFromNextDefault();
|
||||
this.fromNext = fromNext == null ? defaultFromNext : fromNext;
|
||||
}
|
||||
|
||||
public PagingSpec(Map<String, Integer> pagingIdentifiers, int threshold)
|
||||
{
|
||||
this(pagingIdentifiers, threshold, false);
|
||||
this(pagingIdentifiers, threshold, null, new SelectQueryConfig(true));
|
||||
}
|
||||
|
||||
public PagingSpec(Map<String, Integer> pagingIdentifiers, int threshold, Boolean fromNext)
|
||||
{
|
||||
this(pagingIdentifiers, threshold, fromNext, new SelectQueryConfig(true));
|
||||
}
|
||||
|
||||
@JsonProperty
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.select;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class SelectQueryConfig
|
||||
{
|
||||
public static String ENABLE_FROM_NEXT_DEFAULT = "enableFromNextDefault";
|
||||
|
||||
@JsonProperty
|
||||
private boolean enableFromNextDefault = true;
|
||||
|
||||
@JsonCreator
|
||||
public SelectQueryConfig(
|
||||
@JsonProperty("enableFromNextDefault") Boolean enableFromNextDefault
|
||||
)
|
||||
{
|
||||
if (enableFromNextDefault != null) {
|
||||
this.enableFromNextDefault = enableFromNextDefault.booleanValue();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getEnableFromNextDefault()
|
||||
{
|
||||
return enableFromNextDefault;
|
||||
}
|
||||
|
||||
public void setEnableFromNextDefault(boolean enableFromNextDefault)
|
||||
{
|
||||
this.enableFromNextDefault = enableFromNextDefault;
|
||||
}
|
||||
}
|
|
@ -21,9 +21,11 @@ package io.druid.query.select;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.inject.Inject;
|
||||
import io.druid.java.util.common.IAE;
|
||||
import io.druid.java.util.common.ISE;
|
||||
import io.druid.java.util.common.guava.Sequence;
|
||||
|
@ -158,6 +160,16 @@ public class SelectQueryEngine
|
|||
}
|
||||
}
|
||||
|
||||
private final Supplier<SelectQueryConfig> configSupplier;
|
||||
|
||||
@Inject
|
||||
public SelectQueryEngine(
|
||||
Supplier<SelectQueryConfig> configSupplier
|
||||
)
|
||||
{
|
||||
this.configSupplier = configSupplier;
|
||||
}
|
||||
|
||||
public Sequence<Result<SelectResultValue>> process(final SelectQuery query, final Segment segment)
|
||||
{
|
||||
final StorageAdapter adapter = segment.asStorageAdapter();
|
||||
|
|
|
@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -77,15 +78,19 @@ public class SelectQueryQueryToolChest extends QueryToolChest<Result<SelectResul
|
|||
};
|
||||
|
||||
private final ObjectMapper jsonMapper;
|
||||
|
||||
private final IntervalChunkingQueryRunnerDecorator intervalChunkingQueryRunnerDecorator;
|
||||
private final Supplier<SelectQueryConfig> configSupplier;
|
||||
|
||||
@Inject
|
||||
public SelectQueryQueryToolChest(ObjectMapper jsonMapper,
|
||||
IntervalChunkingQueryRunnerDecorator intervalChunkingQueryRunnerDecorator)
|
||||
public SelectQueryQueryToolChest(
|
||||
ObjectMapper jsonMapper,
|
||||
IntervalChunkingQueryRunnerDecorator intervalChunkingQueryRunnerDecorator,
|
||||
Supplier<SelectQueryConfig> configSupplier
|
||||
)
|
||||
{
|
||||
this.jsonMapper = jsonMapper;
|
||||
this.intervalChunkingQueryRunnerDecorator = intervalChunkingQueryRunnerDecorator;
|
||||
this.configSupplier = configSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,12 +23,14 @@ import com.fasterxml.jackson.core.JsonParser;
|
|||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import com.fasterxml.jackson.core.ObjectCodec;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.InjectableValues;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.Module;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -56,6 +58,7 @@ import io.druid.query.QueryToolChest;
|
|||
import io.druid.query.groupby.GroupByQueryConfig;
|
||||
import io.druid.query.groupby.GroupByQueryRunnerFactory;
|
||||
import io.druid.query.groupby.GroupByQueryRunnerTest;
|
||||
import io.druid.query.select.SelectQueryConfig;
|
||||
import io.druid.query.select.SelectQueryEngine;
|
||||
import io.druid.query.select.SelectQueryQueryToolChest;
|
||||
import io.druid.query.select.SelectQueryRunnerFactory;
|
||||
|
@ -164,18 +167,30 @@ public class AggregationTestHelper
|
|||
)
|
||||
{
|
||||
ObjectMapper mapper = new DefaultObjectMapper();
|
||||
mapper.setInjectableValues(
|
||||
new InjectableValues.Std().addValue(
|
||||
SelectQueryConfig.class,
|
||||
new SelectQueryConfig(true)
|
||||
)
|
||||
);
|
||||
|
||||
Supplier<SelectQueryConfig> configSupplier = Suppliers.ofInstance(new SelectQueryConfig(true));
|
||||
|
||||
SelectQueryQueryToolChest toolchest = new SelectQueryQueryToolChest(
|
||||
new DefaultObjectMapper(),
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator()
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator(),
|
||||
configSupplier
|
||||
);
|
||||
|
||||
SelectQueryRunnerFactory factory = new SelectQueryRunnerFactory(
|
||||
new SelectQueryQueryToolChest(
|
||||
new DefaultObjectMapper(),
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator()
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator(),
|
||||
configSupplier
|
||||
),
|
||||
new SelectQueryEngine(
|
||||
configSupplier
|
||||
),
|
||||
new SelectQueryEngine(),
|
||||
QueryRunnerTestHelper.NOOP_QUERYWATCHER
|
||||
);
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package io.druid.query.select;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.io.CharSource;
|
||||
|
@ -65,14 +67,17 @@ import java.util.Map;
|
|||
@RunWith(Parameterized.class)
|
||||
public class MultiSegmentSelectQueryTest
|
||||
{
|
||||
private static final Supplier<SelectQueryConfig> configSupplier = Suppliers.ofInstance(new SelectQueryConfig(true));
|
||||
|
||||
private static final SelectQueryQueryToolChest toolChest = new SelectQueryQueryToolChest(
|
||||
new DefaultObjectMapper(),
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator()
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator(),
|
||||
configSupplier
|
||||
);
|
||||
|
||||
private static final QueryRunnerFactory factory = new SelectQueryRunnerFactory(
|
||||
toolChest,
|
||||
new SelectQueryEngine(),
|
||||
new SelectQueryEngine(configSupplier),
|
||||
QueryRunnerTestHelper.NOOP_QUERYWATCHER
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.select;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.druid.jackson.DefaultObjectMapper;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SelectQueryConfigTest
|
||||
{
|
||||
private final ObjectMapper MAPPER = new DefaultObjectMapper();
|
||||
|
||||
private final ImmutableMap<String, String> CONFIG_MAP = ImmutableMap
|
||||
.<String, String>builder()
|
||||
.put(SelectQueryConfig.ENABLE_FROM_NEXT_DEFAULT, "false")
|
||||
.build();
|
||||
|
||||
private final ImmutableMap<String, String> CONFIG_MAP2 = ImmutableMap
|
||||
.<String, String>builder()
|
||||
.put(SelectQueryConfig.ENABLE_FROM_NEXT_DEFAULT, "true")
|
||||
.build();
|
||||
|
||||
private final ImmutableMap<String, String> CONFIG_MAP_EMPTY = ImmutableMap
|
||||
.<String, String>builder()
|
||||
.build();
|
||||
|
||||
@Test
|
||||
public void testSerde()
|
||||
{
|
||||
final SelectQueryConfig config = MAPPER.convertValue(CONFIG_MAP, SelectQueryConfig.class);
|
||||
Assert.assertEquals(false, config.getEnableFromNextDefault());
|
||||
|
||||
final SelectQueryConfig config2 = MAPPER.convertValue(CONFIG_MAP2, SelectQueryConfig.class);
|
||||
Assert.assertEquals(true, config2.getEnableFromNextDefault());
|
||||
|
||||
final SelectQueryConfig configEmpty = MAPPER.convertValue(CONFIG_MAP_EMPTY, SelectQueryConfig.class);
|
||||
Assert.assertEquals(true, configEmpty.getEnableFromNextDefault());
|
||||
}
|
||||
}
|
|
@ -20,6 +20,8 @@
|
|||
package io.druid.query.select;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -109,9 +111,17 @@ public class SelectQueryRunnerTest
|
|||
);
|
||||
public static final String[] V_0112_0114 = ObjectArrays.concat(V_0112, V_0113, String.class);
|
||||
|
||||
private static final boolean DEFAULT_FROM_NEXT = true;
|
||||
private static final SelectQueryConfig config = new SelectQueryConfig(true);
|
||||
{
|
||||
config.setEnableFromNextDefault(DEFAULT_FROM_NEXT);
|
||||
}
|
||||
private static final Supplier<SelectQueryConfig> configSupplier = Suppliers.ofInstance(config);
|
||||
|
||||
private static final SelectQueryQueryToolChest toolChest = new SelectQueryQueryToolChest(
|
||||
new DefaultObjectMapper(),
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator()
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator(),
|
||||
configSupplier
|
||||
);
|
||||
|
||||
@Parameterized.Parameters(name = "{0}:descending={1}")
|
||||
|
@ -121,14 +131,13 @@ public class SelectQueryRunnerTest
|
|||
QueryRunnerTestHelper.makeQueryRunners(
|
||||
new SelectQueryRunnerFactory(
|
||||
toolChest,
|
||||
new SelectQueryEngine(),
|
||||
new SelectQueryEngine(configSupplier),
|
||||
QueryRunnerTestHelper.NOOP_QUERYWATCHER
|
||||
)
|
||||
),
|
||||
Arrays.asList(false, true)
|
||||
);
|
||||
}
|
||||
|
||||
private final QueryRunner runner;
|
||||
private final boolean descending;
|
||||
|
||||
|
@ -194,7 +203,7 @@ public class SelectQueryRunnerTest
|
|||
Assert.assertEquals(offset, pagingIdentifiers.get(QueryRunnerTestHelper.segmentId).intValue());
|
||||
|
||||
Map<String, Integer> next = PagingSpec.next(pagingIdentifiers, descending);
|
||||
query = query.withPagingSpec(new PagingSpec(next, 3));
|
||||
query = query.withPagingSpec(new PagingSpec(next, 3, false));
|
||||
}
|
||||
|
||||
query = newTestQuery().intervals(I_0112_0114).build();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package io.druid.query.select;
|
||||
|
||||
import com.fasterxml.jackson.databind.InjectableValues;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.druid.jackson.DefaultObjectMapper;
|
||||
import io.druid.query.QueryRunnerTestHelper;
|
||||
|
@ -35,7 +36,15 @@ import java.util.Arrays;
|
|||
*/
|
||||
public class SelectQuerySpecTest
|
||||
{
|
||||
private static final ObjectMapper jsonMapper = new DefaultObjectMapper();
|
||||
private final ObjectMapper objectMapper = new DefaultObjectMapper();
|
||||
{
|
||||
objectMapper.setInjectableValues(
|
||||
new InjectableValues.Std().addValue(
|
||||
SelectQueryConfig.class,
|
||||
new SelectQueryConfig(true)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializationLegacyString() throws Exception
|
||||
|
@ -63,7 +72,7 @@ public class SelectQuerySpecTest
|
|||
+ "{\"type\":\"default\",\"dimension\":\"quality\",\"outputName\":\"quality\",\"outputType\":\"STRING\"}],"
|
||||
+ "\"metrics\":[\"index\"],"
|
||||
+ "\"virtualColumns\":[],"
|
||||
+ "\"pagingSpec\":{\"pagingIdentifiers\":{},\"threshold\":3,\"fromNext\":false},"
|
||||
+ "\"pagingSpec\":{\"pagingIdentifiers\":{},\"threshold\":3,\"fromNext\":true},"
|
||||
+ "\"context\":null}";
|
||||
|
||||
SelectQuery query = new SelectQuery(
|
||||
|
@ -75,13 +84,78 @@ public class SelectQuerySpecTest
|
|||
DefaultDimensionSpec.toSpec(Arrays.<String>asList("market", "quality")),
|
||||
Arrays.<String>asList("index"),
|
||||
null,
|
||||
new PagingSpec(null, 3),
|
||||
new PagingSpec(null, 3, null),
|
||||
null
|
||||
);
|
||||
|
||||
String actual = jsonMapper.writeValueAsString(query);
|
||||
String actual = objectMapper.writeValueAsString(query);
|
||||
Assert.assertEquals(current, actual);
|
||||
Assert.assertEquals(query, jsonMapper.readValue(actual, SelectQuery.class));
|
||||
Assert.assertEquals(query, jsonMapper.readValue(legacy, SelectQuery.class));
|
||||
Assert.assertEquals(query, objectMapper.readValue(actual, SelectQuery.class));
|
||||
Assert.assertEquals(query, objectMapper.readValue(legacy, SelectQuery.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPagingSpecFromNext() throws Exception
|
||||
{
|
||||
String baseQueryJson =
|
||||
"{\"queryType\":\"select\",\"dataSource\":{\"type\":\"table\",\"name\":\"testing\"},"
|
||||
+ "\"intervals\":{\"type\":\"LegacySegmentSpec\",\"intervals\":[\"2011-01-12T00:00:00.000Z/2011-01-14T00:00:00.000Z\"]},"
|
||||
+ "\"descending\":true,"
|
||||
+ "\"filter\":null,"
|
||||
+ "\"granularity\":{\"type\":\"all\"},"
|
||||
+ "\"dimensions\":"
|
||||
+ "[{\"type\":\"default\",\"dimension\":\"market\",\"outputName\":\"market\",\"outputType\":\"STRING\"},"
|
||||
+ "{\"type\":\"default\",\"dimension\":\"quality\",\"outputName\":\"quality\",\"outputType\":\"STRING\"}],"
|
||||
+ "\"metrics\":[\"index\"],"
|
||||
+ "\"virtualColumns\":[],";
|
||||
|
||||
String withNull =
|
||||
baseQueryJson
|
||||
+ "\"pagingSpec\":{\"pagingIdentifiers\":{},\"threshold\":3,\"fromNext\":null},"
|
||||
+ "\"context\":null}";
|
||||
|
||||
String withFalse =
|
||||
baseQueryJson
|
||||
+ "\"pagingSpec\":{\"pagingIdentifiers\":{},\"threshold\":3,\"fromNext\":false},"
|
||||
+ "\"context\":null}";
|
||||
|
||||
String withTrue =
|
||||
baseQueryJson
|
||||
+ "\"pagingSpec\":{\"pagingIdentifiers\":{},\"threshold\":3,\"fromNext\":true},"
|
||||
+ "\"context\":null}";
|
||||
|
||||
SelectQuery queryWithNull = new SelectQuery(
|
||||
new TableDataSource(QueryRunnerTestHelper.dataSource),
|
||||
new LegacySegmentSpec(new Interval("2011-01-12/2011-01-14")),
|
||||
true,
|
||||
null,
|
||||
QueryRunnerTestHelper.allGran,
|
||||
DefaultDimensionSpec.toSpec(Arrays.<String>asList("market", "quality")),
|
||||
Arrays.<String>asList("index"),
|
||||
null,
|
||||
new PagingSpec(null, 3, null),
|
||||
null
|
||||
);
|
||||
|
||||
SelectQuery queryWithFalse = queryWithNull.withPagingSpec(
|
||||
new PagingSpec(null, 3, false)
|
||||
);
|
||||
|
||||
SelectQuery queryWithTrue = queryWithNull.withPagingSpec(
|
||||
new PagingSpec(null, 3, true)
|
||||
);
|
||||
|
||||
String actualWithNull = objectMapper.writeValueAsString(queryWithNull);
|
||||
Assert.assertEquals(withTrue, actualWithNull);
|
||||
|
||||
String actualWithFalse = objectMapper.writeValueAsString(queryWithFalse);
|
||||
Assert.assertEquals(withFalse, actualWithFalse);
|
||||
|
||||
String actualWithTrue = objectMapper.writeValueAsString(queryWithTrue);
|
||||
Assert.assertEquals(withTrue, actualWithTrue);
|
||||
|
||||
Assert.assertEquals(queryWithNull, objectMapper.readValue(actualWithNull, SelectQuery.class));
|
||||
Assert.assertEquals(queryWithFalse, objectMapper.readValue(actualWithFalse, SelectQuery.class));
|
||||
Assert.assertEquals(queryWithTrue, objectMapper.readValue(actualWithTrue, SelectQuery.class));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import io.druid.query.search.SearchQueryQueryToolChest;
|
|||
import io.druid.query.search.search.SearchQuery;
|
||||
import io.druid.query.search.search.SearchQueryConfig;
|
||||
import io.druid.query.select.SelectQuery;
|
||||
import io.druid.query.select.SelectQueryConfig;
|
||||
import io.druid.query.select.SelectQueryQueryToolChest;
|
||||
import io.druid.query.timeboundary.TimeBoundaryQuery;
|
||||
import io.druid.query.timeboundary.TimeBoundaryQueryQueryToolChest;
|
||||
|
@ -82,5 +83,6 @@ public class QueryToolChestModule implements Module
|
|||
JsonConfigProvider.bind(binder, "druid.query.search", SearchQueryConfig.class);
|
||||
JsonConfigProvider.bind(binder, "druid.query.topN", TopNQueryConfig.class);
|
||||
JsonConfigProvider.bind(binder, "druid.query.segmentMetadata", SegmentMetadataQueryConfig.class);
|
||||
JsonConfigProvider.bind(binder, "druid.query.select", SelectQueryConfig.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ import com.fasterxml.jackson.dataformat.smile.SmileFactory;
|
|||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
@ -102,6 +104,7 @@ import io.druid.query.search.search.SearchQueryConfig;
|
|||
import io.druid.query.select.EventHolder;
|
||||
import io.druid.query.select.PagingSpec;
|
||||
import io.druid.query.select.SelectQuery;
|
||||
import io.druid.query.select.SelectQueryConfig;
|
||||
import io.druid.query.select.SelectQueryQueryToolChest;
|
||||
import io.druid.query.select.SelectResultValue;
|
||||
import io.druid.query.spec.MultipleIntervalSegmentSpec;
|
||||
|
@ -247,6 +250,9 @@ public class CachingClusteredClientTest
|
|||
private static final DateTimeZone TIMEZONE = DateTimeZone.forID("America/Los_Angeles");
|
||||
private static final Granularity PT1H_TZ_GRANULARITY = new PeriodGranularity(new Period("PT1H"), null, TIMEZONE);
|
||||
private static final String TOP_DIM = "a_dim";
|
||||
|
||||
private static final Supplier<SelectQueryConfig> selectConfigSupplier = Suppliers.ofInstance(new SelectQueryConfig(true));
|
||||
|
||||
static final QueryToolChestWarehouse WAREHOUSE = new MapQueryToolChestWarehouse(
|
||||
ImmutableMap.<Class<? extends Query>, QueryToolChest>builder()
|
||||
.put(
|
||||
|
@ -271,7 +277,8 @@ public class CachingClusteredClientTest
|
|||
SelectQuery.class,
|
||||
new SelectQueryQueryToolChest(
|
||||
jsonMapper,
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator()
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator(),
|
||||
selectConfigSupplier
|
||||
)
|
||||
)
|
||||
.put(
|
||||
|
@ -1328,7 +1335,8 @@ public class CachingClusteredClientTest
|
|||
client,
|
||||
new SelectQueryQueryToolChest(
|
||||
jsonMapper,
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator()
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator(),
|
||||
selectConfigSupplier
|
||||
)
|
||||
);
|
||||
HashMap<String, Object> context = new HashMap<String, Object>();
|
||||
|
@ -1404,7 +1412,8 @@ public class CachingClusteredClientTest
|
|||
client,
|
||||
new SelectQueryQueryToolChest(
|
||||
jsonMapper,
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator()
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator(),
|
||||
selectConfigSupplier
|
||||
)
|
||||
);
|
||||
HashMap<String, Object> context = new HashMap<String, Object>();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package io.druid.sql.calcite.util;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
@ -58,6 +59,7 @@ import io.druid.query.metadata.SegmentMetadataQueryQueryToolChest;
|
|||
import io.druid.query.metadata.SegmentMetadataQueryRunnerFactory;
|
||||
import io.druid.query.metadata.metadata.SegmentMetadataQuery;
|
||||
import io.druid.query.select.SelectQuery;
|
||||
import io.druid.query.select.SelectQueryConfig;
|
||||
import io.druid.query.select.SelectQueryEngine;
|
||||
import io.druid.query.select.SelectQueryQueryToolChest;
|
||||
import io.druid.query.select.SelectQueryRunnerFactory;
|
||||
|
@ -101,6 +103,7 @@ public class CalciteTests
|
|||
public static final String DATASOURCE2 = "foo2";
|
||||
|
||||
private static final String TIMESTAMP_COLUMN = "t";
|
||||
private static final Supplier<SelectQueryConfig> selectConfigSupplier = Suppliers.ofInstance(new SelectQueryConfig(true));
|
||||
|
||||
private static final QueryRunnerFactoryConglomerate CONGLOMERATE = new DefaultQueryRunnerFactoryConglomerate(
|
||||
ImmutableMap.<Class<? extends Query>, QueryRunnerFactory>builder()
|
||||
|
@ -118,9 +121,10 @@ public class CalciteTests
|
|||
new SelectQueryRunnerFactory(
|
||||
new SelectQueryQueryToolChest(
|
||||
TestHelper.getObjectMapper(),
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator()
|
||||
QueryRunnerTestHelper.NoopIntervalChunkingQueryRunnerDecorator(),
|
||||
selectConfigSupplier
|
||||
),
|
||||
new SelectQueryEngine(),
|
||||
new SelectQueryEngine(selectConfigSupplier),
|
||||
QueryRunnerTestHelper.NOOP_QUERYWATCHER
|
||||
)
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue