use of org.apache.flink.table.planner.calcite.FlinkTypeFactory in project flink by apache.
the class PushProjectIntoTableSourceScanRule method getPrimaryKeyProjections.
private List<RexNode> getPrimaryKeyProjections(LogicalTableScan scan) {
final TableSourceTable source = scan.getTable().unwrap(TableSourceTable.class);
final ResolvedSchema schema = source.contextResolvedTable().getResolvedSchema();
if (!schema.getPrimaryKey().isPresent()) {
return Collections.emptyList();
}
final FlinkTypeFactory typeFactory = unwrapTypeFactory(scan);
final UniqueConstraint primaryKey = schema.getPrimaryKey().get();
return primaryKey.getColumns().stream().map(columnName -> {
final int idx = scan.getRowType().getFieldNames().indexOf(columnName);
final Column column = schema.getColumn(idx).orElseThrow(() -> new TableException(String.format("Column at index %d not found.", idx)));
return new RexInputRef(idx, typeFactory.createFieldTypeFromLogicalType(column.getDataType().getLogicalType()));
}).collect(Collectors.toList());
}
use of org.apache.flink.table.planner.calcite.FlinkTypeFactory in project flink by apache.
the class DynamicSinkUtils method convertSinkToRel.
private static RelNode convertSinkToRel(FlinkRelBuilder relBuilder, RelNode input, Map<String, String> dynamicOptions, ContextResolvedTable contextResolvedTable, Map<String, String> staticPartitions, boolean isOverwrite, DynamicTableSink sink) {
final DataTypeFactory dataTypeFactory = unwrapContext(relBuilder).getCatalogManager().getDataTypeFactory();
final FlinkTypeFactory typeFactory = unwrapTypeFactory(relBuilder);
final ResolvedSchema schema = contextResolvedTable.getResolvedSchema();
final String tableDebugName = contextResolvedTable.getIdentifier().asSummaryString();
List<SinkAbilitySpec> sinkAbilitySpecs = new ArrayList<>();
// 1. prepare table sink
prepareDynamicSink(tableDebugName, staticPartitions, isOverwrite, sink, contextResolvedTable.getResolvedTable(), sinkAbilitySpecs);
sinkAbilitySpecs.forEach(spec -> spec.apply(sink));
// 2. validate the query schema to the sink's table schema and apply cast if possible
final RelNode query = validateSchemaAndApplyImplicitCast(input, schema, tableDebugName, dataTypeFactory, typeFactory);
relBuilder.push(query);
// 3. convert the sink's table schema to the consumed data type of the sink
final List<Integer> metadataColumns = extractPersistedMetadataColumns(schema);
if (!metadataColumns.isEmpty()) {
pushMetadataProjection(relBuilder, typeFactory, schema, sink);
}
List<RelHint> hints = new ArrayList<>();
if (!dynamicOptions.isEmpty()) {
hints.add(RelHint.builder("OPTIONS").hintOptions(dynamicOptions).build());
}
final RelNode finalQuery = relBuilder.build();
return LogicalSink.create(finalQuery, hints, contextResolvedTable, sink, staticPartitions, sinkAbilitySpecs.toArray(new SinkAbilitySpec[0]));
}
use of org.apache.flink.table.planner.calcite.FlinkTypeFactory in project flink by apache.
the class DynamicSinkUtils method pushMetadataProjection.
/**
* Creates a projection that reorders physical and metadata columns according to the consumed
* data type of the sink. It casts metadata columns into the expected data type.
*
* @see SupportsWritingMetadata
*/
private static void pushMetadataProjection(FlinkRelBuilder relBuilder, FlinkTypeFactory typeFactory, ResolvedSchema schema, DynamicTableSink sink) {
final RexBuilder rexBuilder = relBuilder.getRexBuilder();
final List<Column> columns = schema.getColumns();
final List<Integer> physicalColumns = extractPhysicalColumns(schema);
final Map<String, Integer> keyToMetadataColumn = extractPersistedMetadataColumns(schema).stream().collect(Collectors.toMap(pos -> {
final MetadataColumn metadataColumn = (MetadataColumn) columns.get(pos);
return metadataColumn.getMetadataKey().orElse(metadataColumn.getName());
}, Function.identity()));
final List<Integer> metadataColumns = createRequiredMetadataKeys(schema, sink).stream().map(keyToMetadataColumn::get).collect(Collectors.toList());
final List<String> fieldNames = Stream.concat(physicalColumns.stream().map(columns::get).map(Column::getName), metadataColumns.stream().map(columns::get).map(MetadataColumn.class::cast).map(c -> c.getMetadataKey().orElse(c.getName()))).collect(Collectors.toList());
final Map<String, DataType> metadataMap = extractMetadataMap(sink);
final List<RexNode> fieldNodes = Stream.concat(physicalColumns.stream().map(pos -> {
final int posAdjusted = adjustByVirtualColumns(columns, pos);
return relBuilder.field(posAdjusted);
}), metadataColumns.stream().map(pos -> {
final MetadataColumn metadataColumn = (MetadataColumn) columns.get(pos);
final String metadataKey = metadataColumn.getMetadataKey().orElse(metadataColumn.getName());
final LogicalType expectedType = metadataMap.get(metadataKey).getLogicalType();
final RelDataType expectedRelDataType = typeFactory.createFieldTypeFromLogicalType(expectedType);
final int posAdjusted = adjustByVirtualColumns(columns, pos);
return rexBuilder.makeAbstractCast(expectedRelDataType, relBuilder.field(posAdjusted));
})).collect(Collectors.toList());
relBuilder.projectNamed(fieldNodes, fieldNames, true);
}
Aggregations