use of org.apache.flink.table.planner.calcite.FlinkTypeFactory in project flink by apache.
the class PushPartitionIntoTableSourceScanRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
Filter filter = call.rel(0);
LogicalTableScan scan = call.rel(1);
TableSourceTable tableSourceTable = scan.getTable().unwrap(TableSourceTable.class);
RelDataType inputFieldTypes = filter.getInput().getRowType();
List<String> inputFieldNames = inputFieldTypes.getFieldNames();
List<String> partitionFieldNames = tableSourceTable.contextResolvedTable().<ResolvedCatalogTable>getResolvedTable().getPartitionKeys();
// extract partition predicates
RelBuilder relBuilder = call.builder();
RexBuilder rexBuilder = relBuilder.getRexBuilder();
Tuple2<Seq<RexNode>, Seq<RexNode>> allPredicates = RexNodeExtractor.extractPartitionPredicateList(filter.getCondition(), FlinkRelOptUtil.getMaxCnfNodeCount(scan), inputFieldNames.toArray(new String[0]), rexBuilder, partitionFieldNames.toArray(new String[0]));
RexNode partitionPredicate = RexUtil.composeConjunction(rexBuilder, JavaConversions.seqAsJavaList(allPredicates._1));
if (partitionPredicate.isAlwaysTrue()) {
return;
}
// build pruner
LogicalType[] partitionFieldTypes = partitionFieldNames.stream().map(name -> {
int index = inputFieldNames.indexOf(name);
if (index < 0) {
throw new TableException(String.format("Partitioned key '%s' isn't found in input columns. " + "Validator should have checked that.", name));
}
return inputFieldTypes.getFieldList().get(index).getType();
}).map(FlinkTypeFactory::toLogicalType).toArray(LogicalType[]::new);
RexNode finalPartitionPredicate = adjustPartitionPredicate(inputFieldNames, partitionFieldNames, partitionPredicate);
FlinkContext context = ShortcutUtils.unwrapContext(scan);
Function<List<Map<String, String>>, List<Map<String, String>>> defaultPruner = partitions -> PartitionPruner.prunePartitions(context.getTableConfig(), partitionFieldNames.toArray(new String[0]), partitionFieldTypes, partitions, finalPartitionPredicate);
// prune partitions
List<Map<String, String>> remainingPartitions = readPartitionsAndPrune(rexBuilder, context, tableSourceTable, defaultPruner, allPredicates._1(), inputFieldNames);
// apply push down
DynamicTableSource dynamicTableSource = tableSourceTable.tableSource().copy();
PartitionPushDownSpec partitionPushDownSpec = new PartitionPushDownSpec(remainingPartitions);
partitionPushDownSpec.apply(dynamicTableSource, SourceAbilityContext.from(scan));
// build new statistic
TableStats newTableStat = null;
if (tableSourceTable.contextResolvedTable().isPermanent()) {
ObjectIdentifier identifier = tableSourceTable.contextResolvedTable().getIdentifier();
ObjectPath tablePath = identifier.toObjectPath();
Catalog catalog = tableSourceTable.contextResolvedTable().getCatalog().get();
for (Map<String, String> partition : remainingPartitions) {
Optional<TableStats> partitionStats = getPartitionStats(catalog, tablePath, partition);
if (!partitionStats.isPresent()) {
// clear all information before
newTableStat = null;
break;
} else {
newTableStat = newTableStat == null ? partitionStats.get() : newTableStat.merge(partitionStats.get());
}
}
}
FlinkStatistic newStatistic = FlinkStatistic.builder().statistic(tableSourceTable.getStatistic()).tableStats(newTableStat).build();
TableSourceTable newTableSourceTable = tableSourceTable.copy(dynamicTableSource, newStatistic, new SourceAbilitySpec[] { partitionPushDownSpec });
LogicalTableScan newScan = LogicalTableScan.create(scan.getCluster(), newTableSourceTable, scan.getHints());
// transform to new node
RexNode nonPartitionPredicate = RexUtil.composeConjunction(rexBuilder, JavaConversions.seqAsJavaList(allPredicates._2()));
if (nonPartitionPredicate.isAlwaysTrue()) {
call.transformTo(newScan);
} else {
Filter newFilter = filter.copy(filter.getTraitSet(), newScan, nonPartitionPredicate);
call.transformTo(newFilter);
}
}
use of org.apache.flink.table.planner.calcite.FlinkTypeFactory in project flink by apache.
the class PushWatermarkIntoTableSourceScanAcrossCalcRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
FlinkLogicalWatermarkAssigner watermarkAssigner = call.rel(0);
FlinkLogicalCalc calc = call.rel(1);
RexProgram originProgram = calc.getProgram();
List<RexNode> projectList = originProgram.getProjectList().stream().map(originProgram::expandLocalRef).collect(Collectors.toList());
// get watermark expression
RexNode rowTimeColumn = projectList.get(watermarkAssigner.rowtimeFieldIndex());
RexNode newWatermarkExpr = watermarkAssigner.watermarkExpr().accept(new RexShuttle() {
@Override
public RexNode visitInputRef(RexInputRef inputRef) {
return projectList.get(inputRef.getIndex());
}
});
// push watermark assigner into the scan
FlinkLogicalTableSourceScan newScan = getNewScan(watermarkAssigner, newWatermarkExpr, call.rel(2), ShortcutUtils.unwrapContext(calc).getTableConfig(), // useWatermarkAssignerRowType
false);
FlinkTypeFactory typeFactory = ShortcutUtils.unwrapTypeFactory(calc);
RexBuilder builder = call.builder().getRexBuilder();
// cast timestamp/timestamp_ltz type to rowtime type.
RexNode newRowTimeColumn = builder.makeReinterpretCast(typeFactory.createRowtimeIndicatorType(rowTimeColumn.getType().isNullable(), rowTimeColumn.getType().getSqlTypeName() == SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE), rowTimeColumn, null);
// build new calc program
RexProgramBuilder programBuilder = new RexProgramBuilder(newScan.getRowType(), builder);
List<String> outputFieldNames = originProgram.getOutputRowType().getFieldNames();
for (int i = 0; i < projectList.size(); i++) {
if (i == watermarkAssigner.rowtimeFieldIndex()) {
// replace the origin computed column to keep type consistent
programBuilder.addProject(newRowTimeColumn, outputFieldNames.get(i));
} else {
programBuilder.addProject(projectList.get(i), outputFieldNames.get(i));
}
}
if (originProgram.getCondition() != null) {
programBuilder.addCondition(originProgram.expandLocalRef(originProgram.getCondition()));
}
FlinkLogicalCalc newCalc = FlinkLogicalCalc.create(newScan, programBuilder.getProgram());
call.transformTo(newCalc);
}
use of org.apache.flink.table.planner.calcite.FlinkTypeFactory in project flink by apache.
the class PushProjectIntoTableSourceScanRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
final LogicalProject project = call.rel(0);
final LogicalTableScan scan = call.rel(1);
final TableSourceTable sourceTable = scan.getTable().unwrap(TableSourceTable.class);
final boolean supportsNestedProjection = supportsNestedProjection(sourceTable.tableSource());
final int[] refFields = RexNodeExtractor.extractRefInputFields(project.getProjects());
if (!supportsNestedProjection && refFields.length == scan.getRowType().getFieldCount()) {
// There is no top-level projection and nested projections aren't supported.
return;
}
final FlinkTypeFactory typeFactory = unwrapTypeFactory(scan);
final ResolvedSchema schema = sourceTable.contextResolvedTable().getResolvedSchema();
final RowType producedType = createProducedType(schema, sourceTable.tableSource());
final NestedSchema projectedSchema = NestedProjectionUtil.build(getProjections(project, scan), typeFactory.buildRelNodeRowType(producedType));
if (!supportsNestedProjection) {
for (NestedColumn column : projectedSchema.columns().values()) {
column.markLeaf();
}
}
final List<SourceAbilitySpec> abilitySpecs = new ArrayList<>();
final RowType newProducedType = performPushDown(sourceTable, projectedSchema, producedType, abilitySpecs);
final DynamicTableSource newTableSource = sourceTable.tableSource().copy();
final SourceAbilityContext context = SourceAbilityContext.from(scan);
abilitySpecs.forEach(spec -> spec.apply(newTableSource, context));
final RelDataType newRowType = typeFactory.buildRelNodeRowType(newProducedType);
final TableSourceTable newSource = sourceTable.copy(newTableSource, newRowType, abilitySpecs.toArray(new SourceAbilitySpec[0]));
final LogicalTableScan newScan = new LogicalTableScan(scan.getCluster(), scan.getTraitSet(), scan.getHints(), newSource);
final LogicalProject newProject = project.copy(project.getTraitSet(), newScan, rewriteProjections(call, newSource, projectedSchema), project.getRowType());
if (ProjectRemoveRule.isTrivial(newProject)) {
call.transformTo(newScan);
} else {
call.transformTo(newProject);
}
}
use of org.apache.flink.table.planner.calcite.FlinkTypeFactory in project flink by apache.
the class ProjectWindowTableFunctionTransposeRule method createNewTableFunctionScan.
private LogicalTableFunctionScan createNewTableFunctionScan(RelBuilder relBuilder, LogicalTableFunctionScan oldScan, LogicalType timeAttributeType, RelNode newInput, Map<Integer, Integer> mapping) {
relBuilder.push(newInput);
RexNode newCall = rewriteWindowCall((RexCall) oldScan.getCall(), mapping, relBuilder);
RelOptCluster cluster = oldScan.getCluster();
FlinkTypeFactory typeFactory = (FlinkTypeFactory) cluster.getTypeFactory();
RelDataType newScanOutputType = SqlWindowTableFunction.inferRowType(typeFactory, newInput.getRowType(), typeFactory.createFieldTypeFromLogicalType(timeAttributeType));
return LogicalTableFunctionScan.create(cluster, new ArrayList<>(Collections.singleton(newInput)), newCall, oldScan.getElementType(), newScanOutputType, oldScan.getColumnMappings());
}
use of org.apache.flink.table.planner.calcite.FlinkTypeFactory in project flink by apache.
the class CatalogSchemaTable method getRowType.
@Override
public RelDataType getRowType(RelDataTypeFactory typeFactory) {
final FlinkTypeFactory flinkTypeFactory = (FlinkTypeFactory) typeFactory;
final ResolvedSchema schema = contextResolvedTable.getResolvedSchema();
// The following block is a workaround to support tables defined by
// TableEnvironment.connect() and
// the actual table sources implement DefinedProctimeAttribute/DefinedRowtimeAttributes.
// It should be removed after we remove DefinedProctimeAttribute/DefinedRowtimeAttributes.
Optional<TableSource<?>> sourceOpt = findAndCreateTableSource();
if (isStreamingMode && sourceOpt.isPresent() && schema.getColumns().stream().allMatch(Column::isPhysical) && schema.getWatermarkSpecs().isEmpty()) {
TableSchema tableSchema = TableSchema.fromResolvedSchema(schema);
TableSource<?> source = sourceOpt.get();
if (TableSourceValidation.hasProctimeAttribute(source) || TableSourceValidation.hasRowtimeAttribute(source)) {
// If the table is defined by TableEnvironment.connect(), and use the legacy
// proctime and rowtime
// descriptors, the TableSchema should fallback to
// ConnectorCatalogTable#calculateSourceSchema
tableSchema = ConnectorCatalogTable.calculateSourceSchema(source, false);
}
return TableSourceUtil.getSourceRowType(flinkTypeFactory, tableSchema, scala.Option.empty(), true);
}
final List<String> fieldNames = schema.getColumnNames();
final List<LogicalType> fieldTypes = schema.getColumnDataTypes().stream().map(DataType::getLogicalType).map(PlannerTypeUtils::removeLegacyTypes).collect(Collectors.toList());
return flinkTypeFactory.buildRelNodeRowType(fieldNames, fieldTypes);
}
Aggregations