@Override
  public Optional<ProjectionApplicationResult<ConnectorTableHandle>> applyProjection(
      ConnectorSession session,
      ConnectorTableHandle handle,
      List<ConnectorExpression> projections,
      Map<String, ColumnHandle> assignments) {
    if (!isProjectionPushdownEnabled(session)) {
      return Optional.empty();
    }

    // Create projected column representations for supported sub expressions. Simple column
    // references and chain of
    // dereferences on a variable are supported right now.
    Set<ConnectorExpression> projectedExpressions =
        projections.stream()
            .flatMap(expression -> extractSupportedProjectedColumns(expression).stream())
            .collect(toImmutableSet());

    Map<ConnectorExpression, ProjectedColumnRepresentation> columnProjections =
        projectedExpressions.stream()
            .collect(
                toImmutableMap(
                    identity(), HiveApplyProjectionUtil::createProjectedColumnRepresentation));

    IcebergTableHandle icebergTableHandle = (IcebergTableHandle) handle;

    // all references are simple variables
    if (columnProjections.values().stream().allMatch(ProjectedColumnRepresentation::isVariable)) {
      Set<IcebergColumnHandle> projectedColumns =
          assignments.values().stream()
              .map(IcebergColumnHandle.class::cast)
              .collect(toImmutableSet());
      if (icebergTableHandle.getProjectedColumns().equals(projectedColumns)) {
        return Optional.empty();
      }
      List<Assignment> assignmentsList =
          assignments.entrySet().stream()
              .map(
                  assignment ->
                      new Assignment(
                          assignment.getKey(),
                          assignment.getValue(),
                          ((IcebergColumnHandle) assignment.getValue()).getType()))
              .collect(toImmutableList());

      return Optional.of(
          new ProjectionApplicationResult<>(
              icebergTableHandle.withProjectedColumns(projectedColumns),
              projections,
              assignmentsList,
              false));
    }

    Map<String, Assignment> newAssignments = new HashMap<>();
    ImmutableMap.Builder<ConnectorExpression, Variable> newVariablesBuilder =
        ImmutableMap.builder();
    ImmutableSet.Builder<IcebergColumnHandle> projectedColumnsBuilder = ImmutableSet.builder();

    for (Map.Entry<ConnectorExpression, ProjectedColumnRepresentation> entry :
        columnProjections.entrySet()) {
      ConnectorExpression expression = entry.getKey();
      ProjectedColumnRepresentation projectedColumn = entry.getValue();

      IcebergColumnHandle baseColumnHandle =
          (IcebergColumnHandle) assignments.get(projectedColumn.getVariable().getName());
      IcebergColumnHandle projectedColumnHandle =
          createProjectedColumnHandle(
              baseColumnHandle, projectedColumn.getDereferenceIndices(), expression.getType());
      String projectedColumnName = projectedColumnHandle.getQualifiedName();

      Variable projectedColumnVariable = new Variable(projectedColumnName, expression.getType());
      Assignment newAssignment =
          new Assignment(projectedColumnName, projectedColumnHandle, expression.getType());
      newAssignments.putIfAbsent(projectedColumnName, newAssignment);

      newVariablesBuilder.put(expression, projectedColumnVariable);
      projectedColumnsBuilder.add(projectedColumnHandle);
    }

    // Modify projections to refer to new variables
    Map<ConnectorExpression, Variable> newVariables = newVariablesBuilder.buildOrThrow();
    List<ConnectorExpression> newProjections =
        projections.stream()
            .map(expression -> replaceWithNewVariables(expression, newVariables))
            .collect(toImmutableList());

    List<Assignment> outputAssignments = ImmutableList.copyOf(newAssignments.values());
    return Optional.of(
        new ProjectionApplicationResult<>(
            icebergTableHandle.withProjectedColumns(projectedColumnsBuilder.build()),
            newProjections,
            outputAssignments,
            false));
  }
Iceberg original metadata has some problems for mixed-format table, such as iceberg version,
table type. So copy from IcebergMetadata and made some change
amoro-format-mixed/amoro-mixed-trino/src/main/java/org/apache/amoro/trino/unkeyed/IcebergMetadata.java