[ 
https://issues.apache.org/jira/browse/FLINK-40148?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ASF GitHub Bot updated FLINK-40148:
-----------------------------------
    Labels: pull-request-available  (was: )

> TableIdRouter resolves wrong sink table when source regex has multi-digit 
> suffix and sink-table has no back-reference
> ---------------------------------------------------------------------------------------------------------------------
>
>                 Key: FLINK-40148
>                 URL: https://issues.apache.org/jira/browse/FLINK-40148
>             Project: Flink
>          Issue Type: Bug
>          Components: Flink CDC
>    Affects Versions: cdc-3.6.0
>         Environment: flink 1.20.3
> flinkcdc 3.6.0
>            Reporter: peiyu
>            Priority: Major
>              Labels: pull-request-available
>             Fix For: cdc-3.7.0
>
>
> ## Problem
> TableIdRouter.resolveReplacement can produce incorrect sink table names when 
> the source-table
> regex contains a capturing group whose value may span multiple characters 
> (e.g. multi-digit
> suffixes like `13`, `14`, `16`) and the sink-table does not use a `$N` 
> back-reference.
> In this case the unmatched characters after the captured prefix are appended 
> to the configured
> sink-table, producing wrong sink names. For example, given:
>     route:
>       - source-table: db_6.table_([1-9]|1[0-6])
>         sink-table:   new_db_6.table_merged
> `db_6.table_13` is wrongly routed to `new_db_6.table_merged3` (instead of the 
> configured
> `new_db_6.table_merged`), `db_6.table_14` to `new_db_6.table_merged4`, 
> `db_6.table_16` to
> `new_db_6.table_merged6`, etc. Tables 1-9 are not affected because the regex 
> consumes the
> entire single-digit suffix.
> ## Reproduction
> 1. Configure a pipeline with the route above.
> 2. Run the job against a source that has tables `db_6.table_1` … 
> `db_6.table_16`.
> 3. Observe in the logs / sink database that tables 10-16 are written to sink 
> tables named
>    `new_db_6.table_merged0`, `new_db_6.table_merged1`, 
> `new_db_6.table_merged3`, … instead of
>    the single configured sink table.
> A unit test that reproduces the bug (without the fix) is added in this 
> ticket; it fails before
> the patch and passes after.
> ## Root Cause
> `TableIdRouter.resolveReplacement` builds a `Matcher` against the source 
> table id and calls
> `Matcher.find()` followed by `Matcher.replaceAll(sinkTable)`:
>     Matcher matcher = route.f0.matcher(originalTable.toString());
>     if (matcher.find()) {
>         return TableId.parse(matcher.replaceAll(route.f1));
>     }
> Two issues combine to produce the bug:
> 1. `find()` only matches a *prefix* of the source table id. With the regex
>    `([1-9]|1[0-6])`, the alternation `[1-9]` wins first, matching only `1` 
> from input `13`.
> 2. `Matcher.replaceAll` internally calls `reset()` and iterates with 
> `find()`, so it only
>    replaces the prefix matched in step 1 and leaves the trailing characters 
> of the source
>    table id (`0`, `3`, `4`, `5`, `6`) appended to the sink-table. When the 
> sink-table has no
>    `$N` reference, those trailing characters end up in the result.
> The same root cause also makes `find()`-based capturing groups return only 
> the first matched
> digit when the sink-table *does* use `$1`, so the bug is not strictly limited 
> to back-reference
> free sinks.
> ## Proposed Fix
> Switch to `Matcher.matches()` to ensure the entire source table id is 
> consumed, and use
> `Matcher.appendReplacement` / `Matcher.appendTail` to perform the `$N` 
> substitution on the
> matched region only — this avoids the trailing-characters-left-over problem 
> of `replaceAll`.
> ## Tests
> - Add `TableIdRouterTest#testRouteWithoutBackReferenceWithMultiDigitSuffix` 
> to lock down the
>   reported scenario (sink-table has no back-reference).
> - Add `TableIdRouterTest#testRouteWithBackReferenceAndMultiDigitCapture` to 
> cover the related
>   case where sink-table uses `$1` and the captured group must be the full 
> multi-digit value.
> - All existing tests in `TableIdRouterTest`, `TableIdRouterMatchModeTest`, and
>   `SchemaDerivatorTest` continue to pass (27 tests total).



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

Reply via email to