Yanquan Lv created FLINK-40739:
----------------------------------

             Summary: [Bug][pipeline-connector][maxcompute] Partition values 
extracted from wrong column index when partition columns are not contiguous at 
the end of schema
                 Key: FLINK-40739
                 URL: https://issues.apache.org/jira/browse/FLINK-40739
             Project: Flink
          Issue Type: Bug
          Components: Flink CDC
    Affects Versions: cdc-3.5.0, cdc-3.4.0, cdc-3.2.1, cdc-3.3.0, cdc-3.2.0
            Reporter: Yanquan Lv


## Description

 

### Problem

 

In `SessionManageOperator#extractPartition`, the MaxCompute pipeline sink 
computes the index of a partition column by assuming that all partition columns 
are contiguous and located at the end of the schema:

 

https://github.com/apache/flink-cdc/blob/master/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-maxcompute/src/main/java/org/apache/flink/cdc/connectors/maxcompute/coordinator/SessionManageOperator.java#L268

 

```java

for (int i = 0; i < partitionKeyCount; i++) {

    RecordData.FieldGetter fieldGetter =

            fieldGetters.get(columnCount - partitionKeyCount - 1 + i);

    ...

}

```

 

The `-1` offset is incorrect. When partition columns are **not** contiguously 
placed at the end of the column list, the sink reads values from the wrong 
field getters and writes data into the wrong MaxCompute partitions.

 

### Example

 

Consider a table whose columns are ordered as:

 

| Index | Column | Is Partition Key |

|-------|--------|------------------|

| 0     | id     |                  |

| 1     | pt     | yes              |

| 2     | name   |                  |

| 3     | dt     | yes              |

 

Here `columnCount = 4` and `partitionKeyCount = 2`.

 

With the current code:

 

- For `i = 0`: index = `4 - 2 - 1 + 0 = 1` → reads `pt` (correct by coincidence)

- For `i = 1`: index = `4 - 2 - 1 + 1 = 2` → reads `name` (wrong! should read 
`dt` at index 3)

 

As a result, the partition spec will contain `pt=<correct>, dt=<value of 
name>`, which silently corrupts data.

 

### Impact

 

- Data is written into incorrect partitions when the source schema has 
partition columns interleaved with regular columns.

- This can happen after schema evolution (e.g., `ADD COLUMN`) or when the user 
explicitly defines columns in a non-trailing order.

 

### Expected Behavior

 

The sink should resolve each partition column by its name instead of by a fixed 
trailing offset, so that it works regardless of column ordering.

 

### Suggested Fix

 

Locate each partition column via 
`schema.getColumnNames().indexOf(partitionKey)`:

 

```java

for (String partitionKey : schema.partitionKeys()) {

    int partitionColumnIndex = schema.getColumnNames().indexOf(partitionKey);

    if (partitionColumnIndex < 0 || partitionColumnIndex >= columnCount) {

        throw new IllegalStateException(

            String.format("Unable to find partition column \"%s\" in schema %s",

                          partitionKey, schema));

    }

    RecordData.FieldGetter fieldGetter = fieldGetters.get(partitionColumnIndex);

    Object value = fieldGetter.getFieldOrNull(recordData);

    partitionSpec.set(partitionKey, Objects.toString(value));

}

```

 

### Additional Context

 

The same bug has already been fixed internally in the `release-11` branch. A 
test case covering the interleaved partition-column scenario would prevent 
regressions.

 

---

 

如果你需要,我也可以顺便生成对应的中文版,或者把这段内容直接写入一个 `.md` 文件方便你复制粘贴。

可以,下面是可直接用于提交到 Apache Flink CDC 的英文 issue 描述。

---

## Title

`[Bug][pipeline-connector][maxcompute] Partition values extracted from wrong 
column index when partition columns are not contiguous at the end of schema`

## Description

### Problem

In `SessionManageOperator#extractPartition`, the MaxCompute pipeline sink 
computes the index of a partition column by assuming that all partition columns 
are contiguous and located at the end of the schema:

https://github.com/apache/flink-cdc/blob/master/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-maxcompute/src/main/java/org/apache/flink/cdc/connectors/maxcompute/coordinator/SessionManageOperator.java#L268

```java
for (int i = 0; i < partitionKeyCount; i++) {
    RecordData.FieldGetter fieldGetter =
            fieldGetters.get(columnCount - partitionKeyCount - 1 + i);
    ...
}
```

The `-1` offset is incorrect. When partition columns are **not** contiguously 
placed at the end of the column list, the sink reads values from the wrong 
field getters and writes data into the wrong MaxCompute partitions.

### Example

Consider a table whose columns are ordered as:

| Index | Column | Is Partition Key |
|-------|--------|------------------|
| 0     | id     |                  |
| 1     | pt     | yes              |
| 2     | name   |                  |
| 3     | dt     | yes              |

Here `columnCount = 4` and `partitionKeyCount = 2`.

With the current code:

- For `i = 0`: index = `4 - 2 - 1 + 0 = 1` → reads `pt` (correct by coincidence)
- For `i = 1`: index = `4 - 2 - 1 + 1 = 2` → reads `name` (wrong! should read 
`dt` at index 3)

As a result, the partition spec will contain `pt=<correct>, dt=<value of 
name>`, which silently corrupts data.

### Impact

- Data is written into incorrect partitions when the source schema has 
partition columns interleaved with regular columns.
- This can happen after schema evolution (e.g., `ADD COLUMN`) or when the user 
explicitly defines columns in a non-trailing order.

### Expected Behavior

The sink should resolve each partition column by its name instead of by a fixed 
trailing offset, so that it works regardless of column ordering.

### Suggested Fix

Locate each partition column via 
`schema.getColumnNames().indexOf(partitionKey)`:

```java
for (String partitionKey : schema.partitionKeys()) {
    int partitionColumnIndex = schema.getColumnNames().indexOf(partitionKey);
    if (partitionColumnIndex < 0 || partitionColumnIndex >= columnCount) {
        throw new IllegalStateException(
            String.format("Unable to find partition column \"%s\" in schema %s",
                          partitionKey, schema));
    }
    RecordData.FieldGetter fieldGetter = fieldGetters.get(partitionColumnIndex);
    Object value = fieldGetter.getFieldOrNull(recordData);
    partitionSpec.set(partitionKey, Objects.toString(value));
}
```

### Additional Context

The same bug has already been fixed internally in the `release-11` branch. A 
test case covering the interleaved partition-column scenario would prevent 
regressions.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to