xuyangzhong commented on code in PR #28090:
URL: https://github.com/apache/flink/pull/28090#discussion_r4559345746


##########
flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/plan/rules/logical/PushFilterIntoSourceScanRuleBase.java:
##########
@@ -87,12 +94,28 @@ protected FilterPushDownResult classifyAndPushFilters(
         boolean supportsMetadataFilter = 
canPushdownMetadataFilter(tableSourceTable);
         List<String> metadataKeys = getReadMetadataKeys(tableSourceTable);
         int firstMetadataIndex = scan.getRowType().getFieldCount() - 
metadataKeys.size();
+        Set<ImmutableBitSet> keys = 
getUpsertKeysOfUpdatingSource(tableSourceTable, scan);
+        boolean changelogNormalized =
+                keys != null
+                        && 
PushProjectIntoTableSourceScanRule.requiresPrimaryKey(

Review Comment:
   nit use `DynamicSourceUtils#changelogNormalizeEnabled`



##########
flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/plan/rules/logical/PushFilterIntoSourceScanRuleBase.java:
##########
@@ -87,12 +94,28 @@ protected FilterPushDownResult classifyAndPushFilters(
         boolean supportsMetadataFilter = 
canPushdownMetadataFilter(tableSourceTable);
         List<String> metadataKeys = getReadMetadataKeys(tableSourceTable);
         int firstMetadataIndex = scan.getRowType().getFieldCount() - 
metadataKeys.size();
+        Set<ImmutableBitSet> keys = 
getUpsertKeysOfUpdatingSource(tableSourceTable, scan);

Review Comment:
   nit maybe we could directly use 
`FlinkRelMetadataQuery.reuseOrCreate(scan.getCluster().getMetadataQuery()).getUpsertKeys(scan)`
 and then use it together with `changelogNormalized` later. What do you think?



##########
flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/plan/stream/sql/join/LookupJoinTest.scala:
##########
@@ -343,6 +343,43 @@ class LookupJoinTest extends TableTestBase with 
Serializable {
     util.verifyExecPlan(sql)
   }
 
+  @Test
+  def testLeftJoinWithNonKeyConditionOnUpsertInput(): Unit = {

Review Comment:
   Could you please add a plan test for inner lookup join?



##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -1744,25 +1750,37 @@ class FlinkChangelogModeInferenceProgram extends 
FlinkOptimizeProgram[StreamOpti
     upsertKeys != null && upsertKeys.exists(!_.isEmpty)
   }
 
+  /**
+   * Whether an inner lookup join drops an update whose row stops matching, 
i.e. a condition reads
+   * columns outside the input's upsert key, or the lookup table is filtered 
and the join key isn't
+   * on the upsert key.
+   */
+  private def isNonUpsertKeyLookupCondition(lookupJoin: 
StreamPhysicalLookupJoin): Boolean = {
+    if (lookupJoin.joinType != JoinRelType.INNER) {
+      return false
+    }
+    val input = lookupJoin.getInput
+    // columns of the looked up row are never in the input's upsert key
+    val conditions = lookupJoin.finalPreFilterCondition ++ 
lookupJoin.finalRemainingCondition
+    conditions.exists(c => !isOnUpsertKey(input, 
RelOptUtil.InputFinder.bits(c))) ||
+    (lookupJoin.calcOnTemporalTable.exists(_.getCondition != null) &&

Review Comment:
   I'd like to discuss this a bit with you. My understanding is that looking up 
the right-side dim table in a lookup join is effectively like invoking a 
non-deterministic function. Since we don't capture UA, UB, or D changes from 
the dim table anyway, checking the Calc condition on that side seems 
unnecessary. What do you think?



-- 
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