Search in sources :

Example 1 with SymbolEvaluator

use of io.crate.analyze.SymbolEvaluator in project crate by crate.

the class RewriteFilterOnOuterJoinToInnerJoin method apply.

@Override
public LogicalPlan apply(Filter filter, Captures captures, TableStats tableStats, TransactionContext txnCtx, NodeContext nodeCtx) {
    var symbolEvaluator = new SymbolEvaluator(txnCtx, nodeCtx, SubQueryResults.EMPTY);
    NestedLoopJoin nl = captures.get(nlCapture);
    Symbol query = filter.query();
    Map<Set<RelationName>, Symbol> splitQueries = QuerySplitter.split(query);
    if (splitQueries.size() == 1 && splitQueries.keySet().iterator().next().size() > 1) {
        return null;
    }
    LogicalPlan lhs = nl.sources().get(0);
    LogicalPlan rhs = nl.sources().get(1);
    Set<RelationName> leftName = lhs.getRelationNames();
    Set<RelationName> rightName = rhs.getRelationNames();
    Symbol leftQuery = splitQueries.remove(leftName);
    Symbol rightQuery = splitQueries.remove(rightName);
    final LogicalPlan newLhs;
    final LogicalPlan newRhs;
    final boolean newJoinIsInnerJoin;
    switch(nl.joinType()) {
        case LEFT:
            /* LEFT OUTER JOIN -> NULL rows are generated for the RHS if the join-condition doesn't match
                 *
                 * cr> select t1.x as t1x, t2.x as t2x from t1 left join t2 on t1.x = t2.x;
                 * +-----+------+
                 * | t1x |  t2x |
                 * +-----+------+
                 * |   3 |    3 |
                 * |   2 |    2 |
                 * |   1 | NULL |
                 * +-----+------+
                 */
            newLhs = getNewSource(leftQuery, lhs);
            if (rightQuery == null) {
                newRhs = rhs;
                newJoinIsInnerJoin = false;
            } else if (couldMatchOnNull(rightQuery, symbolEvaluator)) {
                newRhs = rhs;
                newJoinIsInnerJoin = false;
                splitQueries.put(rightName, rightQuery);
            } else {
                newRhs = getNewSource(rightQuery, rhs);
                newJoinIsInnerJoin = true;
            }
            break;
        case RIGHT:
            /* RIGHT OUTER JOIN -> NULL rows are generated for the LHS if the join-condition doesn't match

                 * cr> select t1.x as t1x, t2.x as t2x from t1 right join t2 on t1.x = t2.x;
                 * +------+-----+
                 * |  t1x | t2x |
                 * +------+-----+
                 * |    3 |   3 |
                 * |    2 |   2 |
                 * | NULL |   4 |
                 * +------+-----+
                 */
            if (leftQuery == null) {
                newLhs = lhs;
                newJoinIsInnerJoin = false;
            } else if (couldMatchOnNull(leftQuery, symbolEvaluator)) {
                newLhs = lhs;
                newJoinIsInnerJoin = false;
                splitQueries.put(leftName, leftQuery);
            } else {
                newLhs = getNewSource(leftQuery, lhs);
                newJoinIsInnerJoin = true;
            }
            newRhs = getNewSource(rightQuery, rhs);
            break;
        case FULL:
            if (couldMatchOnNull(leftQuery, symbolEvaluator)) {
                newLhs = lhs;
            } else {
                newLhs = getNewSource(leftQuery, lhs);
                if (leftQuery != null) {
                    splitQueries.put(leftName, leftQuery);
                }
            }
            if (couldMatchOnNull(rightQuery, symbolEvaluator)) {
                newRhs = rhs;
            } else {
                newRhs = getNewSource(rightQuery, rhs);
            }
            /*
                 * Filters on each side must be put back into the Filter as each side can generate NULL's on outer joins
                 * which must be filtered out AFTER the join operation.
                 * In case the filter is only on one side, the join could be rewritten to a LEFT/RIGHT OUTER.
                 * TODO: Create a dedicated rule RewriteFilterOnOuterJoinToLeftOrRight
                 *
                 * cr> select t1.x as t1x, t2.x as t2x, t2.y as t2y from t1 full outer join t2 on t1.x = t2.x where t2y = 1;
                 * +------+------+------+
                 * |  t1x |  t2x |  t2y |
                 * +------+------+------+
                 * |    3 |    3 |    1 |
                 * |    2 |    2 |    1 |
                 * | NULL |    4 |    1 |
                 * +------+------+------+
                 */
            if (leftQuery != null) {
                splitQueries.put(leftName, leftQuery);
            }
            if (rightQuery != null) {
                splitQueries.put(rightName, rightQuery);
            }
            newJoinIsInnerJoin = newLhs != lhs && newRhs != rhs;
            break;
        default:
            throw new UnsupportedOperationException("The Rule to rewrite filter+outer-joins to inner joins must not be run on joins of type=" + nl.joinType());
    }
    if (newLhs == lhs && newRhs == rhs) {
        return null;
    }
    NestedLoopJoin newJoin = new NestedLoopJoin(newLhs, newRhs, newJoinIsInnerJoin ? JoinType.INNER : nl.joinType(), nl.joinCondition(), nl.isFiltered(), nl.topMostLeftRelation(), nl.orderByWasPushedDown(), true);
    assert newJoin.outputs().equals(nl.outputs()) : "Outputs after rewrite must be the same as before";
    return splitQueries.isEmpty() ? newJoin : new Filter(newJoin, AndOperator.join(splitQueries.values()));
}
Also used : Set(java.util.Set) Filter(io.crate.planner.operators.Filter) Symbol(io.crate.expression.symbol.Symbol) NestedLoopJoin(io.crate.planner.operators.NestedLoopJoin) RelationName(io.crate.metadata.RelationName) LogicalPlan(io.crate.planner.operators.LogicalPlan) SymbolEvaluator(io.crate.analyze.SymbolEvaluator)

Example 2 with SymbolEvaluator

use of io.crate.analyze.SymbolEvaluator in project crate by crate.

the class RewriteFilterOnOuterJoinToInnerJoin method couldMatchOnNull.

private static boolean couldMatchOnNull(@Nullable Symbol query, SymbolEvaluator evaluator) {
    if (query == null) {
        return false;
    }
    Symbol queryWithNulls = RefReplacer.replaceRefs(FieldReplacer.replaceFields(query, ignored -> Literal.NULL), ignored -> Literal.NULL);
    Input<?> input = queryWithNulls.accept(evaluator, ALL_NULL_ROW);
    return WhereClause.canMatch(input);
}
Also used : Input(io.crate.data.Input) TransactionContext(io.crate.metadata.TransactionContext) RelationName(io.crate.metadata.RelationName) RefReplacer(io.crate.expression.symbol.RefReplacer) SymbolEvaluator(io.crate.analyze.SymbolEvaluator) AndOperator(io.crate.expression.operator.AndOperator) TableStats(io.crate.statistics.TableStats) JoinType(io.crate.planner.node.dql.join.JoinType) Map(java.util.Map) Nullable(javax.annotation.Nullable) NodeContext(io.crate.metadata.NodeContext) LogicalPlan(io.crate.planner.operators.LogicalPlan) Captures(io.crate.planner.optimizer.matcher.Captures) WhereClause(io.crate.analyze.WhereClause) Pattern(io.crate.planner.optimizer.matcher.Pattern) Set(java.util.Set) QuerySplitter(io.crate.analyze.relations.QuerySplitter) NestedLoopJoin(io.crate.planner.operators.NestedLoopJoin) Rule(io.crate.planner.optimizer.Rule) Row(io.crate.data.Row) Literal(io.crate.expression.symbol.Literal) Symbol(io.crate.expression.symbol.Symbol) Pattern.typeOf(io.crate.planner.optimizer.matcher.Pattern.typeOf) SubQueryResults(io.crate.planner.operators.SubQueryResults) Patterns.source(io.crate.planner.optimizer.matcher.Patterns.source) FieldReplacer(io.crate.expression.symbol.FieldReplacer) Filter(io.crate.planner.operators.Filter) Capture(io.crate.planner.optimizer.matcher.Capture) FilterOnJoinsUtil.getNewSource(io.crate.planner.optimizer.rule.FilterOnJoinsUtil.getNewSource) Symbol(io.crate.expression.symbol.Symbol)

Example 3 with SymbolEvaluator

use of io.crate.analyze.SymbolEvaluator in project crate by crate.

the class InsertFromValues method evaluateValueTableFunction.

private static Iterator<Row> evaluateValueTableFunction(TableFunctionImplementation<?> funcImplementation, List<Symbol> arguments, List<Reference> allTargetReferences, DocTableInfo tableInfo, Row params, PlannerContext plannerContext, SubQueryResults subQueryResults) {
    SymbolEvaluator symbolEval = new SymbolEvaluator(plannerContext.transactionContext(), plannerContext.nodeContext(), subQueryResults);
    Function<? super Symbol, Input<?>> eval = (symbol) -> symbol.accept(symbolEval, params);
    ArrayList<Input<?>> boundArguments = new ArrayList<>(arguments.size());
    for (int i = 0; i < arguments.size(); i++) {
        boundArguments.add(eval.apply(arguments.get(i)));
    }
    // noinspection unchecked
    Iterable<Row> rows = funcImplementation.evaluate(plannerContext.transactionContext(), plannerContext.nodeContext(), boundArguments.toArray(new Input[0]));
    return StreamSupport.stream(rows.spliterator(), false).map(row -> cast(row, allTargetReferences, tableInfo)).iterator();
}
Also used : GeneratedColumns(io.crate.execution.dml.upsert.GeneratedColumns) IndexParts(io.crate.metadata.IndexParts) INDEX_CLOSED_BLOCK(org.elasticsearch.cluster.metadata.IndexMetadata.INDEX_CLOSED_BLOCK) Arrays(java.util.Arrays) TransportShardUpsertAction(io.crate.execution.dml.upsert.TransportShardUpsertAction) ShardIterator(org.elasticsearch.cluster.routing.ShardIterator) ShardedRequests(io.crate.execution.engine.indexing.ShardedRequests) TableFunctionRelation(io.crate.analyze.relations.TableFunctionRelation) NodeLimits(io.crate.execution.jobs.NodeLimits) TransportCreatePartitionsAction(org.elasticsearch.action.admin.indices.create.TransportCreatePartitionsAction) RetryListener(io.crate.execution.support.RetryListener) DependencyCarrier(io.crate.planner.DependencyCarrier) ClusterState(org.elasticsearch.cluster.ClusterState) RowN(io.crate.data.RowN) SymbolEvaluator(io.crate.analyze.SymbolEvaluator) TableStats(io.crate.statistics.TableStats) ClusterBlock(org.elasticsearch.cluster.block.ClusterBlock) ColumnIndexWriterProjection(io.crate.execution.dsl.projection.ColumnIndexWriterProjection) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) IntArrayList(com.carrotsearch.hppc.IntArrayList) IndexNotFoundException(org.elasticsearch.index.IndexNotFoundException) Map(java.util.Map) TypeGuessEstimateRowSize(io.crate.breaker.TypeGuessEstimateRowSize) ConcurrencyLimit(io.crate.concurrent.limits.ConcurrencyLimit) SelectSymbol(io.crate.expression.symbol.SelectSymbol) GroupRowsByShard(io.crate.execution.engine.indexing.GroupRowsByShard) DocTableInfo(io.crate.metadata.doc.DocTableInfo) Collection(java.util.Collection) InMemoryBatchIterator(io.crate.data.InMemoryBatchIterator) Set(java.util.Set) UUID(java.util.UUID) InputRow(io.crate.expression.InputRow) ShardRequest(io.crate.execution.dml.ShardRequest) ExecutionPlan(io.crate.planner.ExecutionPlan) List(java.util.List) OrderBy(io.crate.analyze.OrderBy) Row(io.crate.data.Row) Symbol(io.crate.expression.symbol.Symbol) RowShardResolver(io.crate.execution.engine.collect.RowShardResolver) Assignments(io.crate.expression.symbol.Assignments) Row1(io.crate.data.Row1) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting) Input(io.crate.data.Input) SENTINEL(io.crate.data.SentinelRow.SENTINEL) ClusterService(org.elasticsearch.cluster.service.ClusterService) CollectExpression(io.crate.execution.engine.collect.CollectExpression) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Operation(io.crate.metadata.table.Operation) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) Supplier(java.util.function.Supplier) InsertSourceFromCells(io.crate.execution.dml.upsert.InsertSourceFromCells) ArrayList(java.util.ArrayList) BackoffPolicy(org.elasticsearch.action.bulk.BackoffPolicy) Metadata(org.elasticsearch.cluster.metadata.Metadata) ClusterBlockException(org.elasticsearch.cluster.block.ClusterBlockException) ShardLocation(io.crate.execution.engine.indexing.ShardLocation) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) StreamSupport(java.util.stream.StreamSupport) ColumnValidationException(io.crate.exceptions.ColumnValidationException) Nullable(javax.annotation.Nullable) FutureActionListener(io.crate.action.FutureActionListener) ProjectionBuilder(io.crate.execution.dsl.projection.builder.ProjectionBuilder) BULK_REQUEST_TIMEOUT_SETTING(io.crate.execution.engine.indexing.ShardingUpsertExecutor.BULK_REQUEST_TIMEOUT_SETTING) Iterator(java.util.Iterator) Reference(io.crate.metadata.Reference) DataType(io.crate.types.DataType) AcknowledgedResponse(org.elasticsearch.action.support.master.AcknowledgedResponse) RamAccounting(io.crate.breaker.RamAccounting) Consumer(java.util.function.Consumer) RowConsumer(io.crate.data.RowConsumer) ShardResponse(io.crate.execution.dml.ShardResponse) ShardUpsertRequest(io.crate.execution.dml.upsert.ShardUpsertRequest) CollectionBucket(io.crate.data.CollectionBucket) TableFunctionImplementation(io.crate.metadata.tablefunctions.TableFunctionImplementation) IndexNameResolver(io.crate.execution.engine.indexing.IndexNameResolver) NotSerializableExceptionWrapper(org.elasticsearch.common.io.stream.NotSerializableExceptionWrapper) AbstractTableRelation(io.crate.analyze.relations.AbstractTableRelation) PlannerContext(io.crate.planner.PlannerContext) InputColumns(io.crate.execution.dsl.projection.builder.InputColumns) SQLExceptions(io.crate.exceptions.SQLExceptions) InputFactory(io.crate.expression.InputFactory) CreatePartitionsRequest(org.elasticsearch.action.admin.indices.create.CreatePartitionsRequest) ActionListener(org.elasticsearch.action.ActionListener) Input(io.crate.data.Input) IntArrayList(com.carrotsearch.hppc.IntArrayList) ArrayList(java.util.ArrayList) InputRow(io.crate.expression.InputRow) Row(io.crate.data.Row) SymbolEvaluator(io.crate.analyze.SymbolEvaluator)

Aggregations

SymbolEvaluator (io.crate.analyze.SymbolEvaluator)3 Input (io.crate.data.Input)2 Row (io.crate.data.Row)2 Symbol (io.crate.expression.symbol.Symbol)2 RelationName (io.crate.metadata.RelationName)2 Filter (io.crate.planner.operators.Filter)2 LogicalPlan (io.crate.planner.operators.LogicalPlan)2 NestedLoopJoin (io.crate.planner.operators.NestedLoopJoin)2 Set (java.util.Set)2 IntArrayList (com.carrotsearch.hppc.IntArrayList)1 FutureActionListener (io.crate.action.FutureActionListener)1 OrderBy (io.crate.analyze.OrderBy)1 WhereClause (io.crate.analyze.WhereClause)1 AbstractTableRelation (io.crate.analyze.relations.AbstractTableRelation)1 QuerySplitter (io.crate.analyze.relations.QuerySplitter)1 TableFunctionRelation (io.crate.analyze.relations.TableFunctionRelation)1 RamAccounting (io.crate.breaker.RamAccounting)1 TypeGuessEstimateRowSize (io.crate.breaker.TypeGuessEstimateRowSize)1 ConcurrencyLimit (io.crate.concurrent.limits.ConcurrencyLimit)1 CollectionBucket (io.crate.data.CollectionBucket)1