Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import org.apache.calcite.plan.ConventionTraitDef;
import org.apache.calcite.plan.RelTraitDef;
import org.apache.calcite.rel.RelCollationTraitDef;
import org.apache.calcite.rel.core.Correlate;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlDdl;
Expand Down Expand Up @@ -145,8 +144,6 @@ public class CalciteQueryProcessor extends GridProcessorAdapter implements Query
// See Apache Calcite ticket for more information, assertion is incorrect.
// FRAMEWORK_CONFIG initialize SqlToRelConverter class. Assertions should be disabled before class initialization.
SqlToRelConverter.class.getClassLoader().setClassAssertionStatus(SqlToRelConverter.class.getName(), false);
// TODO Workaround for https://issues.apache.org/jira/browse/CALCITE-5421 and https://issues.apache.org/jira/browse/CALCITE-7034
Correlate.class.getClassLoader().setClassAssertionStatus(Correlate.class.getName(), false);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.List;
import java.util.Set;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.volcano.RelSubset;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.core.AggregateCall;
Expand All @@ -33,9 +34,11 @@
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.core.SetOp;
import org.apache.calcite.rel.core.Sort;
import org.apache.calcite.rel.core.Spool;
import org.apache.calcite.rel.core.TableFunctionScan;
import org.apache.calcite.rel.core.TableModify;
import org.apache.calcite.rel.metadata.BuiltInMetadata;
import org.apache.calcite.rel.metadata.CyclicMetadataException;
import org.apache.calcite.rel.metadata.MetadataDef;
import org.apache.calcite.rel.metadata.MetadataHandler;
import org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider;
Expand All @@ -51,8 +54,11 @@
import org.apache.calcite.rex.RexSlot;
import org.apache.calcite.rex.RexVisitor;
import org.apache.calcite.rex.RexVisitorImpl;
import org.apache.calcite.util.BuiltInMethod;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.mapping.Mappings;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteLimit;
import org.apache.ignite.internal.processors.query.calcite.rel.ProjectableFilterableTableScan;
import org.apache.ignite.internal.processors.query.calcite.util.Commons;
import org.jetbrains.annotations.Nullable;

/**
Expand All @@ -61,8 +67,9 @@
*/
public class IgniteMdColumnOrigins implements MetadataHandler<BuiltInMetadata.ColumnOrigin> {
/** */
public static final RelMetadataProvider SOURCE = ReflectiveRelMetadataProvider.reflectiveSource(
BuiltInMethod.COLUMN_ORIGIN.method, new IgniteMdColumnOrigins());
public static final RelMetadataProvider SOURCE =
ReflectiveRelMetadataProvider.reflectiveSource(
new IgniteMdColumnOrigins(), BuiltInMetadata.ColumnOrigin.Handler.class);

/** {@inheritDoc} */
@Override public MetadataDef<BuiltInMetadata.ColumnOrigin> getDef() {
Expand Down Expand Up @@ -261,10 +268,10 @@ public class IgniteMdColumnOrigins implements MetadataHandler<BuiltInMetadata.Co
int iOutputColumn
) {
if (rel.projects() != null) {
RexNode proj = rel.projects().get(iOutputColumn);
RexNode node = rel.projects().get(iOutputColumn);
Set<RexSlot> sources = new HashSet<>();

getOperands(proj, RexSlot.class, sources);
getOperands(node, RexSlot.class, sources);

boolean derived = sources.size() > 1;
Set<RelColumnOrigin> res = new HashSet<>();
Expand All @@ -281,7 +288,19 @@ public class IgniteMdColumnOrigins implements MetadataHandler<BuiltInMetadata.Co
return res;
}

return Collections.singleton(rel.columnOriginsByRelLocalRef(iOutputColumn));
ImmutableBitSet requiredColumns = rel.requiredColumns();
RelOptTable table = rel.getTable();

if (requiredColumns != null) {
Mappings.TargetMapping trimming = Commons.projectedMapping(requiredColumns, table.getRowType().getFieldCount());

iOutputColumn = trimming.getSourceOpt(iOutputColumn);

if (iOutputColumn == -1)
return null;
}

return Set.of(new RelColumnOrigin(table, iOutputColumn, false));
}

/**
Expand All @@ -303,6 +322,38 @@ private <T> void getOperands(RexNode rn, Class<T> cls, Set<T> res) {
}
}

/**
* Provides column origins for a subset.
*
* <p>Origins are resolved through the original (logical) expression of the set rather than through the current best
* plan: the best expression changes during optimization, and metadata depending on it makes row count estimates
* of the same expression unstable, which in turn leads to inconsistent costs and cyclic best plans in Volcano memo.
* Column origins are a property of the logical expression, so the original expression is a stable source of them.
*/
public @Nullable Set<RelColumnOrigin> getColumnOrigins(RelSubset rel,
RelMetadataQuery mq, int outputColumn) {
RelNode original = rel.getOriginal();

try {
return mq.getColumnOrigins(original != null ? original :
rel.stripped(), outputColumn);
}
catch (CyclicMetadataException ignore) {
// Cyclic set (see CALCITE-1048): origins are unknown, callers fall back to generic estimations.
return null;
}
}

/** Spools pass rows of their input through, so column origins are the same as the origins of the input. */
public @Nullable Set<RelColumnOrigin> getColumnOrigins(Spool rel, RelMetadataQuery mq, int iOutputColumn) {
return mq.getColumnOrigins(rel.getInput(), iOutputColumn);
}

/** Limit passes rows of its input through, so column origins are the same as the origins of the input. */
public @Nullable Set<RelColumnOrigin> getColumnOrigins(IgniteLimit rel, RelMetadataQuery mq, int iOutputColumn) {
return mq.getColumnOrigins(rel.getInput(), iOutputColumn);
}

/**
* Catch-all rule when none of the others apply.
*
Expand Down Expand Up @@ -369,15 +420,15 @@ private static Set<RelColumnOrigin> getMultipleColumns(RexNode rexNode, RelNode
final Set<RelColumnOrigin> set = new HashSet<>();

final RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
@Override public Void visitInputRef(RexInputRef inputRef) {
Set<RelColumnOrigin> inputSet = mq.getColumnOrigins(input, inputRef.getIndex());
@Override public Void visitInputRef(RexInputRef inputRef) {
Set<RelColumnOrigin> inputSet = mq.getColumnOrigins(input, inputRef.getIndex());

if (inputSet != null)
set.addAll(inputSet);
if (inputSet != null)
set.addAll(inputSet);

return null;
}
};
return null;
}
};

rexNode.accept(visitor);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@

package org.apache.ignite.internal.processors.query.calcite.metadata;

import org.apache.calcite.plan.volcano.RelSubset;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.core.Join;
import org.apache.calcite.rel.core.Union;
import org.apache.calcite.rel.metadata.BuiltInMetadata;
import org.apache.calcite.rel.metadata.CyclicMetadataException;
import org.apache.calcite.rel.metadata.MetadataDef;
import org.apache.calcite.rel.metadata.MetadataHandler;
import org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider;
import org.apache.calcite.rel.metadata.RelMetadataProvider;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.util.BuiltInMethod;
import org.apache.ignite.internal.processors.query.calcite.rel.ProjectableFilterableTableScan;

/**
* See {@link org.apache.calcite.rel.metadata.RelMdPercentageOriginalRows}
Expand Down Expand Up @@ -105,6 +108,31 @@ public Double getPercentageOriginalRows(Join rel, RelMetadataQuery mq) {
return left * right;
}

/**
* Percentage for a subset.
*
* <p>Resolved through the original (logical) expression of the set rather than through the current best plan,
* consistently with row count, selectivity and column origins: the best expression changes during optimization
* and metadata depending on it makes estimates unstable. Without this handler a subset is treated as a leaf and
* filters pushed down to the join inputs are never accounted.
*/
public Double getPercentageOriginalRows(RelSubset rel, RelMetadataQuery mq) {
RelNode original = rel.getOriginal();

try {
return mq.getPercentageOriginalRows(original != null ? original : rel.stripped());
}
catch (CyclicMetadataException ignore) {
// Cyclic set (see CALCITE-1048): no information.
return null;
}
}

/** A scan with a pushed down condition filters rows by the selectivity of this condition. */
public Double getPercentageOriginalRows(ProjectableFilterableTableScan rel, RelMetadataQuery mq) {
return rel.condition() == null ? 1.0 : mq.getSelectivity(rel, null);
}

/** */
public Double getPercentageOriginalRows(RelNode rel, RelMetadataQuery mq) {
if (rel.getInputs().size() > 1) {
Expand Down
Loading
Loading