All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.xpack.esql.optimizer.OptimizerRules Maven / Gradle / Ivy

There is a newer version: 8.16.1
Show newest version
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */

package org.elasticsearch.xpack.esql.optimizer;

import org.elasticsearch.xpack.esql.core.common.Failures;
import org.elasticsearch.xpack.esql.core.expression.Attribute;
import org.elasticsearch.xpack.esql.core.expression.AttributeSet;
import org.elasticsearch.xpack.esql.core.expression.Expressions;
import org.elasticsearch.xpack.esql.core.expression.NameId;
import org.elasticsearch.xpack.esql.core.plan.QueryPlan;
import org.elasticsearch.xpack.esql.core.plan.logical.LogicalPlan;
import org.elasticsearch.xpack.esql.plan.GeneratingPlan;
import org.elasticsearch.xpack.esql.plan.logical.Aggregate;
import org.elasticsearch.xpack.esql.plan.logical.Enrich;
import org.elasticsearch.xpack.esql.plan.logical.EsRelation;
import org.elasticsearch.xpack.esql.plan.logical.MvExpand;
import org.elasticsearch.xpack.esql.plan.logical.Row;
import org.elasticsearch.xpack.esql.plan.logical.local.LocalRelation;
import org.elasticsearch.xpack.esql.plan.physical.AggregateExec;
import org.elasticsearch.xpack.esql.plan.physical.EnrichExec;
import org.elasticsearch.xpack.esql.plan.physical.EsQueryExec;
import org.elasticsearch.xpack.esql.plan.physical.EsSourceExec;
import org.elasticsearch.xpack.esql.plan.physical.EsStatsQueryExec;
import org.elasticsearch.xpack.esql.plan.physical.EvalExec;
import org.elasticsearch.xpack.esql.plan.physical.ExchangeExec;
import org.elasticsearch.xpack.esql.plan.physical.ExchangeSourceExec;
import org.elasticsearch.xpack.esql.plan.physical.FieldExtractExec;
import org.elasticsearch.xpack.esql.plan.physical.LocalSourceExec;
import org.elasticsearch.xpack.esql.plan.physical.MvExpandExec;
import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan;
import org.elasticsearch.xpack.esql.plan.physical.RegexExtractExec;
import org.elasticsearch.xpack.esql.plan.physical.RowExec;
import org.elasticsearch.xpack.esql.plan.physical.ShowExec;

import java.util.HashSet;
import java.util.Set;

import static org.elasticsearch.xpack.esql.core.common.Failure.fail;

class OptimizerRules {

    private OptimizerRules() {}

    static class DependencyConsistency

> { void checkPlan(P p, Failures failures) { AttributeSet refs = references(p); AttributeSet input = p.inputSet(); AttributeSet generated = generates(p); AttributeSet missing = refs.subtract(input).subtract(generated); if (missing.isEmpty() == false) { failures.add(fail(p, "Plan [{}] optimized incorrectly due to missing references {}", p.nodeString(), missing)); } Set outputAttributeNames = new HashSet<>(); Set outputAttributeIds = new HashSet<>(); for (Attribute outputAttr : p.output()) { if (outputAttributeNames.add(outputAttr.name()) == false || outputAttributeIds.add(outputAttr.id()) == false) { failures.add( fail( p, "Plan [{}] optimized incorrectly due to duplicate output attribute {}", p.nodeString(), outputAttr.toString() ) ); } } } protected AttributeSet references(P p) { return p.references(); } protected AttributeSet generates(P p) { return AttributeSet.EMPTY; } } static class LogicalPlanDependencyCheck extends DependencyConsistency { @Override protected AttributeSet references(LogicalPlan plan) { if (plan instanceof Enrich enrich) { // The enrichFields are NamedExpressions, so we compute their references as well when just calling enrich.references(). // But they are not actually referring to attributes from the input plan - only the match field does. return enrich.matchField().references(); } return super.references(plan); } @Override protected AttributeSet generates(LogicalPlan logicalPlan) { // source-like operators if (logicalPlan instanceof EsRelation || logicalPlan instanceof LocalRelation || logicalPlan instanceof Row || logicalPlan instanceof Aggregate) { return logicalPlan.outputSet(); } if (logicalPlan instanceof GeneratingPlan generating) { return new AttributeSet(generating.generatedAttributes()); } if (logicalPlan instanceof MvExpand mvExpand) { return new AttributeSet(mvExpand.expanded()); } return AttributeSet.EMPTY; } } static class PhysicalPlanDependencyCheck extends DependencyConsistency { @Override protected AttributeSet generates(PhysicalPlan physicalPlan) { // source-like operators if (physicalPlan instanceof EsSourceExec || physicalPlan instanceof EsStatsQueryExec || physicalPlan instanceof EsQueryExec || physicalPlan instanceof LocalSourceExec || physicalPlan instanceof RowExec || physicalPlan instanceof ExchangeExec || physicalPlan instanceof ExchangeSourceExec || physicalPlan instanceof AggregateExec || physicalPlan instanceof ShowExec) { return physicalPlan.outputSet(); } if (physicalPlan instanceof FieldExtractExec fieldExtractExec) { return new AttributeSet(fieldExtractExec.attributesToExtract()); } if (physicalPlan instanceof EvalExec eval) { return new AttributeSet(Expressions.asAttributes(eval.fields())); } if (physicalPlan instanceof RegexExtractExec extract) { return new AttributeSet(extract.extractedFields()); } if (physicalPlan instanceof MvExpandExec mvExpand) { return new AttributeSet(mvExpand.expanded()); } if (physicalPlan instanceof EnrichExec enrich) { return new AttributeSet(Expressions.asAttributes(enrich.enrichFields())); } return AttributeSet.EMPTY; } @Override protected AttributeSet references(PhysicalPlan plan) { if (plan instanceof AggregateExec aggregate) { if (aggregate.getMode() == AggregateExec.Mode.FINAL) { // lousy hack - need to generate the intermediate aggs yet the intermediateAggs method keep creating new IDs on each // call // in practice, the final aggregate should clearly declare the expected properties not hold on the original ones // as they no longer apply return aggregate.inputSet(); } } return plan.references(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy