use of io.crate.statistics.TableStats in project crate by crate.
the class Rename method rewriteToFetch.
@Nullable
@Override
public FetchRewrite rewriteToFetch(TableStats tableStats, Collection<Symbol> usedColumns) {
IdentityHashMap<Symbol, Symbol> parentToChildMap = new IdentityHashMap<>(outputs.size());
IdentityHashMap<Symbol, Symbol> childToParentMap = new IdentityHashMap<>(outputs.size());
for (int i = 0; i < outputs.size(); i++) {
parentToChildMap.put(outputs.get(i), source.outputs().get(i));
childToParentMap.put(source.outputs().get(i), outputs.get(i));
}
ArrayList<Symbol> mappedUsedColumns = new ArrayList<>();
for (Symbol usedColumn : usedColumns) {
SymbolVisitors.intersection(usedColumn, outputs, s -> {
Symbol childSymbol = parentToChildMap.get(s);
assert childSymbol != null : "There must be a mapping available for symbol " + s;
mappedUsedColumns.add(childSymbol);
});
}
FetchRewrite fetchRewrite = source.rewriteToFetch(tableStats, mappedUsedColumns);
if (fetchRewrite == null) {
return null;
}
LogicalPlan newSource = fetchRewrite.newPlan();
ArrayList<Symbol> newOutputs = new ArrayList<>();
for (Symbol output : newSource.outputs()) {
if (output instanceof FetchMarker) {
FetchMarker marker = (FetchMarker) output;
FetchMarker newMarker = new FetchMarker(name, marker.fetchRefs(), marker.fetchId());
newOutputs.add(newMarker);
childToParentMap.put(marker, newMarker);
} else {
Symbol mappedOutput = requireNonNull(childToParentMap.get(output), () -> "Mapping must exist for output from source. `" + output + "` is missing in " + childToParentMap);
newOutputs.add(mappedOutput);
}
}
LinkedHashMap<Symbol, Symbol> replacedOutputs = new LinkedHashMap<>();
Function<Symbol, Symbol> convertChildrenToScopedSymbols = s -> MapBackedSymbolReplacer.convert(s, childToParentMap);
for (var entry : fetchRewrite.replacedOutputs().entrySet()) {
Symbol key = entry.getKey();
Symbol value = entry.getValue();
Symbol parentSymbolForKey = requireNonNull(childToParentMap.get(key), () -> "Mapping must exist for output from source. `" + key + "` is missing in " + childToParentMap);
replacedOutputs.put(parentSymbolForKey, convertChildrenToScopedSymbols.apply(value));
}
Rename newRename = new Rename(newOutputs, name, fieldResolver, newSource);
return new FetchRewrite(replacedOutputs, newRename);
}
use of io.crate.statistics.TableStats in project crate by crate.
the class MoveFilterBeneathWindowAgg method apply.
@Override
public LogicalPlan apply(Filter filter, Captures captures, TableStats tableStats, TransactionContext txnCtx, NodeContext nodeCtx) {
WindowAgg windowAgg = captures.get(windowAggCapture);
WindowDefinition windowDefinition = windowAgg.windowDefinition();
List<WindowFunction> windowFunctions = windowAgg.windowFunctions();
Predicate<Symbol> containsWindowFunction = symbol -> symbol instanceof WindowFunction && windowFunctions.contains(symbol);
Symbol predicate = filter.query();
List<Symbol> filterParts = AndOperator.split(predicate);
ArrayList<Symbol> remainingFilterSymbols = new ArrayList<>();
ArrayList<Symbol> windowPartitionedBasedFilters = new ArrayList<>();
for (Symbol part : filterParts) {
if (SymbolVisitors.any(containsWindowFunction, part) == false && windowDefinition.partitions().containsAll(extractColumns(part))) {
windowPartitionedBasedFilters.add(part);
} else {
remainingFilterSymbols.add(part);
}
}
assert remainingFilterSymbols.size() > 0 || windowPartitionedBasedFilters.size() > 0 : "Splitting the filter symbol must result in at least one group";
/* SELECT ROW_NUMBER() OVER(PARTITION BY id)
* WHERE `x = 1`
*
* `x` is not the window partition column.
* We cannot push down the filter as it would change the window aggregation value
*
*/
if (windowPartitionedBasedFilters.isEmpty()) {
return null;
}
/* SELECT ROW_NUMBER() OVER(PARTITION BY id)
* WHERE `id = 1`
* remainingFilterSymbols: []
* windowPartitionedBasedFilters: [id = 1]
*
* Filter
* |
* WindowsAgg
*
* transforms to
*
* WindowAgg
* |
* Filter (id = 1)
*/
if (remainingFilterSymbols.isEmpty()) {
return transpose(filter, windowAgg);
}
/* WHERE `ROW_NUMBER() OVER(PARTITION BY id) = 2 AND id = 1`
* remainingFilterSymbols: [ROW_NUMBER() OVER(PARTITION BY id) = 2]
* windowPartitionedBasedFilters: [id = 1]
*
* Filter
* |
* WindowsAgg
*
* transforms to
*
* Filter (ROW_NUMBER() OVER(PARTITION BY id) = 2)
* |
* WindowAgg
* |
* Filter (id = 1)
*/
LogicalPlan newWindowAgg = windowAgg.replaceSources(List.of(new Filter(windowAgg.source(), AndOperator.join(windowPartitionedBasedFilters))));
return new Filter(newWindowAgg, AndOperator.join(remainingFilterSymbols));
}
use of io.crate.statistics.TableStats in project crate by crate.
the class SubSelectIntegrationTest method testSingleRowSubSelectWorksWithJoins.
@Test
public void testSingleRowSubSelectWorksWithJoins() throws Exception {
execute("create table t (x long primary key)");
ensureYellow();
execute("insert into t (x) values (1), (2)");
execute("refresh table t");
for (TableStats tableStats : internalCluster().getInstances(TableStats.class)) {
Map<RelationName, Stats> newStats = new HashMap<>();
newStats.put(new RelationName(sqlExecutor.getCurrentSchema(), "t"), new Stats(100, 64, Map.of()));
tableStats.updateTableStats(newStats);
}
// Left table is expected to be one row, due to the single row subselect in the where clause.
execute("select * from t as t1, t as t2 where t1.x = (select 1) order by t2.x");
assertThat(printedTable(response.rows()), is("1| 1\n1| 2\n"));
// Left table is expected to be bigger due to the table stats stating it being 100 rows
execute("select * from t as t2, t as t1 where t1.x = (select 1) order by t2.x");
assertThat(printedTable(response.rows()), is("1| 1\n2| 1\n"));
}
use of io.crate.statistics.TableStats in project crate by crate.
the class CollectTest method test_prune_output_of_collect_updates_estimated_row_size.
@Test
public void test_prune_output_of_collect_updates_estimated_row_size() throws Exception {
var e = SQLExecutor.builder(clusterService).addTable("create table t (x int, y int)").build();
TableStats tableStats = new TableStats();
Symbol x = e.asSymbol("x");
Collect collect = Collect.create(new DocTableRelation(e.resolveTableInfo("t")), List.of(x, e.asSymbol("y")), WhereClause.MATCH_ALL, tableStats, Row.EMPTY);
assertThat(collect.estimatedRowSize(), is(DataTypes.INTEGER.fixedSize() * 2L));
LogicalPlan prunedCollect = collect.pruneOutputsExcept(tableStats, List.of(x));
assertThat(prunedCollect.estimatedRowSize(), is((long) DataTypes.INTEGER.fixedSize()));
}
use of io.crate.statistics.TableStats in project crate by crate.
the class FetchRewriteTest method test_fetchrewrite_on_eval_with_nested_source_outputs.
@Test
public void test_fetchrewrite_on_eval_with_nested_source_outputs() throws Exception {
SQLExecutor e = SQLExecutor.builder(clusterService).addTable("create table tbl (x int)").build();
DocTableInfo tableInfo = e.resolveTableInfo("tbl");
var x = new AliasSymbol("x_alias", e.asSymbol("x"));
var relation = new DocTableRelation(tableInfo);
var collect = new Collect(relation, List.of(x), WhereClause.MATCH_ALL, 1L, DataTypes.INTEGER.fixedSize());
var eval = new Eval(collect, List.of(x));
FetchRewrite fetchRewrite = eval.rewriteToFetch(new TableStats(), List.of());
assertThat(fetchRewrite, Matchers.notNullValue());
assertThat(fetchRewrite.newPlan(), isPlan("Collect[doc.tbl | [_fetchid] | true]"));
assertThat(fetchRewrite.replacedOutputs(), Matchers.hasEntry(is(x), isAlias("x_alias", isFetchStub("_doc['x']"))));
}
Aggregations