fightBoxing opened a new pull request, #4487:
URL: https://github.com/apache/flink-cdc/pull/4487

   ## Purpose
   
   Add support for extracting Oracle **ROWID pseudo-column** as a metadata 
column in Oracle CDC. Users can then access it in Flink SQL via:
   
   ```sql
   CREATE TABLE oracle_source (
       ID INT,
       NAME STRING,
       row_id STRING METADATA FROM 'row_id' VIRTUAL   -- new
   ) WITH (
       'connector' = 'oracle-cdc',
       'scan.incremental.snapshot.enabled' = 'true',
       ...
   );
   ```
   
   Typical use cases: data lineage, exact-row identification, idempotent 
downstream writes, systems that rely on ROWID for reconciliation.
   
   ## What is changed
   
   ### 1. `OracleReadableMetaData` — new `ROW_ID` enum
   Reads the ROWID value from the `SourceRecord` headers (key = `ROWID`).
   
   ### 2. `OracleScanFetchTask` (snapshot phase)
   Oracle's `SELECT *` does **not** include ROWID. So:
   - Rewrite the split-scan SQL: `SELECT * FROM tab` → `SELECT T0.*, ROWID FROM 
tab T0` (ROWID placed at the tail keeps physical column positions unchanged).
   - Manually construct `ColumnArray` from the table's own columns to bypass 
Debezium's `ColumnUtils.toArray(rs, table)` strict validation, which would 
otherwise reject the extra ROWID column.
   - Extract ROWID via `((OracleResultSet) rs).getROWID(N+1)` and inject it 
into `SourceRecord` headers by overriding 
`SnapshotChangeRecordEmitter#getEmitConnectHeaders`.
   
   Streaming phase already carries ROWID in headers through Debezium's 
`LogMinerChangeRecordEmitter` (from `V$LOGMNR_CONTENTS.ROW_ID`), so no changes 
are needed there.
   
   ### 3. `JdbcSourceFetchTaskContext` — headers-loss bug fix ⭐
   
   While implementing the above, we discovered a **latent bug affecting all 
JDBC-based CDC connectors** (MySQL, PostgreSQL, SQL Server, Db2, Oracle):
   
   Both `rewriteOutputBuffer()` (used for PK-update path) and 
`formatMessageTimestamp()` (used for snapshot record normalization) were 
constructing new `SourceRecord`s using the 8-argument constructor, silently 
discarding the **timestamp** and **headers** from the original record.
   
   Any header-based metadata — including the new Oracle `row_id`, and any 
future header-based columns that may be added — would be silently dropped by 
these two rewrite paths.
   
   Fix: switch both call sites to the 10-argument `SourceRecord` constructor so 
`timestamp` and `headers` are preserved.
   
   ## Verification
   
   Compilation:
   ```
   mvn compile -pl 
flink-cdc-connect/flink-cdc-source-connectors/flink-connector-oracle-cdc -am 
-DskipTests
   ```
   ✅ BUILD SUCCESS
   
   Runtime (Oracle Database 12c Standard Edition 12.1.0.2.0, back-ported to 
release-2.4 and verified end-to-end):
   ```
   +I[2, bbb, AABDuHAAGAAAAF3AAA]
   +I[3, ccc, AABDuHAAGAAAAF0AAA]
   +I[4, ddd, AABDuHAAGAAAAF0AAB]
   -D[2, bbb, AABDuHAAGAAAAF3AAA]
   ```
   Both snapshot (READ) and streaming (INSERT/UPDATE/DELETE) rows carry a valid 
ROWID.
   
   ## Data flow
   
   ```
   Snapshot phase:
     OracleScanFetchTask (rs.getROWID)
       → SnapshotChangeRecordEmitter.getEmitConnectHeaders (inject ROWID)
         → BufferingSnapshotChangeRecordReceiver (new SourceRecord with headers)
           → ChangeEventQueue
   
   Streaming phase (already works):
     LogMinerChangeRecordEmitter.getEmitConnectHeaders (inject ROWID)
       → ChangeEventQueue
   
   Reader side (bug fix here):
     IncrementalSourceScanFetcher.pollSplitRecords
       → JdbcSourceFetchTaskContext.formatMessageTimestamp/rewriteOutputBuffer
         (preserve headers)  ⭐
           → OracleReadableMetaData.ROW_ID.read(record.headers())
   ```
   
   ## User requirements
   
   - `scan.incremental.snapshot.enabled=true` (this PR does not touch 
Debezium's native snapshot path).
   - Table supplemental logging enabled for streaming capture:
     ```
     ALTER TABLE <schema>.<table> ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
     ```
   
   ## Compatibility
   
   - No breaking API changes.
   - No new configuration options.
   - Users who don't declare `row_id` metadata column see zero behavioral 
change (SQL rewrite still runs but only adds a single pseudo-column to the JDBC 
query, which is negligible).
   - The `JdbcSourceFetchTaskContext` fix is transparent — records that 
previously had `null`/absent headers still have `null`/absent headers 
afterwards.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to