morrySnow commented on code in PR #67891:
URL: https://github.com/apache/doris/pull/67891#discussion_r4057624787


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ForeignKeyContext.java:
##########
@@ -131,32 +130,81 @@ void putAllPrimaryKeys(TableIf table) {
         for (PrimaryKeyConstraint c : 
Env.getCurrentEnv().getConstraintManager()
                 .getPrimaryKeyConstraints(tableNameInfo)) {
             Set<QualifiedColumn> primaryKey = c.getPrimaryKeys(table).stream()
-                    .map(column -> new QualifiedColumn(table, 
column)).collect(Collectors.toSet());
-            primaryKeys.addAll(primaryKey);
+                    .map(column -> new QualifiedColumn(table, column))
+                    .collect(ImmutableSet.toImmutableSet());
+            declaredPrimaryKeys.add(primaryKey);
         }
     }
 
     public boolean isForeignKey(Set<Slot> key) {
-        return foreignKeys.containsAll(
-                key.stream().map(s -> 
slotToColumn.get(s)).collect(Collectors.toSet()));
+        Set<QualifiedColumn> columns = key.stream()
+                .map(slotToColumn::get)
+                .collect(Collectors.toSet());
+        return !key.isEmpty() && !columns.contains(null)
+                && constraints.stream().anyMatch(constraint -> 
constraint.keySet().equals(columns));
     }
 
     public boolean isPrimaryKey(Set<Slot> key) {
-        return primaryKeys.containsAll(
-                key.stream().map(s -> 
slotToColumn.get(s)).collect(Collectors.toSet()));
+        return !key.isEmpty() && activePrimaryKeys.contains(key);
     }
 
-    void putSlot(SlotReference slot, TableIf table) {
-        if (!slot.getOriginalColumn().isPresent()) {
-            return;
+    void putSlots(LogicalCatalogRelation relation, TableIf table) {
+        Map<QualifiedColumn, Slot> columnToSlot = new HashMap<>();
+        for (Slot slot : relation.getOutput()) {
+            if (!(slot instanceof SlotReference) || !((SlotReference) 
slot).getOriginalColumn().isPresent()) {
+                continue;
+            }
+            Column column = ((SlotReference) slot).getOriginalColumn().get();
+            QualifiedColumn qualifiedColumn = new QualifiedColumn(table, 
column);
+            slotToColumn.put(slot, qualifiedColumn);
+            columnToSlot.put(qualifiedColumn, slot);
+        }
+
+        for (Set<QualifiedColumn> declaredPrimaryKey : declaredPrimaryKeys) {
+            if (!columnToSlot.keySet().containsAll(declaredPrimaryKey)) {
+                continue;
+            }
+            Set<Slot> primaryKey = declaredPrimaryKey.stream()
+                    .map(columnToSlot::get)
+                    .collect(ImmutableSet.toImmutableSet());
+            if (canActivatePrimaryKey(relation, primaryKey)) {
+                activePrimaryKeys.add(primaryKey);
+            }
         }
-        Column c = slot.getOriginalColumn().get();
-        slotToColumn.put(slot, new QualifiedColumn(table, c));
+    }
+
+    private boolean canActivatePrimaryKey(LogicalCatalogRelation relation, 
Set<Slot> primaryKey) {
+        if (!relation.getLogicalProperties().getTrait().isUnique(primaryKey)) {
+            return false;
+        }
+        if (!(relation instanceof LogicalOlapScan)) {
+            return true;
+        }
+        LogicalOlapScan scan = (LogicalOlapScan) relation;
+        return new HashSet<>(scan.getSelectedPartitionIds()).equals(
+                        new HashSet<>(scan.getTable().getPartitionIds()))
+                && scan.getSelectedTabletIds().isEmpty()
+                && !scan.getTableSample().isPresent()
+                && !scan.isDirectMvScan();
     }
 
     void putAlias(Slot newSlot, Slot originSlot) {
         if (slotToColumn.containsKey(originSlot)) {
             slotToColumn.put(newSlot, slotToColumn.get(originSlot));
+            Set<Set<Slot>> aliasedPrimaryKeys = activePrimaryKeys.stream()
+                    .filter(primaryKey -> primaryKey.contains(originSlot))

Review Comment:
   Fixed in f87ffc5440c. Active primary-key state is now represented by one 
per-relation proof object with slot-to-proof references, so aliasing a key slot 
copies one map entry instead of materializing key variants. A 16-column alias 
regression asserts 32 slot entries and exactly one proof, bounding growth 
linearly instead of 2^N.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ForeignKeyContext.java:
##########
@@ -131,32 +130,81 @@ void putAllPrimaryKeys(TableIf table) {
         for (PrimaryKeyConstraint c : 
Env.getCurrentEnv().getConstraintManager()
                 .getPrimaryKeyConstraints(tableNameInfo)) {
             Set<QualifiedColumn> primaryKey = c.getPrimaryKeys(table).stream()
-                    .map(column -> new QualifiedColumn(table, 
column)).collect(Collectors.toSet());
-            primaryKeys.addAll(primaryKey);
+                    .map(column -> new QualifiedColumn(table, column))
+                    .collect(ImmutableSet.toImmutableSet());
+            declaredPrimaryKeys.add(primaryKey);
         }
     }
 
     public boolean isForeignKey(Set<Slot> key) {
-        return foreignKeys.containsAll(
-                key.stream().map(s -> 
slotToColumn.get(s)).collect(Collectors.toSet()));
+        Set<QualifiedColumn> columns = key.stream()
+                .map(slotToColumn::get)

Review Comment:
   Fixed in f87ffc5440c. Foreign-key slots now retain their source RelationId 
through direct aliases, and isForeignKey requires every component of a 
composite key to come from the same relation instance. I added a planner 
regression that keeps the top join for f1.fa + f2.fb and a result regression 
that would expose the two extra cross-product rows produced by the old behavior.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ForeignKeyContext.java:
##########
@@ -131,32 +130,81 @@ void putAllPrimaryKeys(TableIf table) {
         for (PrimaryKeyConstraint c : 
Env.getCurrentEnv().getConstraintManager()
                 .getPrimaryKeyConstraints(tableNameInfo)) {
             Set<QualifiedColumn> primaryKey = c.getPrimaryKeys(table).stream()
-                    .map(column -> new QualifiedColumn(table, 
column)).collect(Collectors.toSet());
-            primaryKeys.addAll(primaryKey);
+                    .map(column -> new QualifiedColumn(table, column))
+                    .collect(ImmutableSet.toImmutableSet());
+            declaredPrimaryKeys.add(primaryKey);
         }
     }
 
     public boolean isForeignKey(Set<Slot> key) {
-        return foreignKeys.containsAll(
-                key.stream().map(s -> 
slotToColumn.get(s)).collect(Collectors.toSet()));
+        Set<QualifiedColumn> columns = key.stream()
+                .map(slotToColumn::get)
+                .collect(Collectors.toSet());
+        return !key.isEmpty() && !columns.contains(null)
+                && constraints.stream().anyMatch(constraint -> 
constraint.keySet().equals(columns));
     }
 
     public boolean isPrimaryKey(Set<Slot> key) {
-        return primaryKeys.containsAll(
-                key.stream().map(s -> 
slotToColumn.get(s)).collect(Collectors.toSet()));
+        return !key.isEmpty() && activePrimaryKeys.contains(key);
     }
 
-    void putSlot(SlotReference slot, TableIf table) {
-        if (!slot.getOriginalColumn().isPresent()) {
-            return;
+    void putSlots(LogicalCatalogRelation relation, TableIf table) {
+        Map<QualifiedColumn, Slot> columnToSlot = new HashMap<>();
+        for (Slot slot : relation.getOutput()) {
+            if (!(slot instanceof SlotReference) || !((SlotReference) 
slot).getOriginalColumn().isPresent()) {
+                continue;
+            }
+            Column column = ((SlotReference) slot).getOriginalColumn().get();
+            QualifiedColumn qualifiedColumn = new QualifiedColumn(table, 
column);
+            slotToColumn.put(slot, qualifiedColumn);
+            columnToSlot.put(qualifiedColumn, slot);
+        }
+
+        for (Set<QualifiedColumn> declaredPrimaryKey : declaredPrimaryKeys) {
+            if (!columnToSlot.keySet().containsAll(declaredPrimaryKey)) {
+                continue;
+            }
+            Set<Slot> primaryKey = declaredPrimaryKey.stream()
+                    .map(columnToSlot::get)
+                    .collect(ImmutableSet.toImmutableSet());
+            if (canActivatePrimaryKey(relation, primaryKey)) {
+                activePrimaryKeys.add(primaryKey);
+            }
         }
-        Column c = slot.getOriginalColumn().get();
-        slotToColumn.put(slot, new QualifiedColumn(table, c));
+    }
+
+    private boolean canActivatePrimaryKey(LogicalCatalogRelation relation, 
Set<Slot> primaryKey) {
+        if (!relation.getLogicalProperties().getTrait().isUnique(primaryKey)) {
+            return false;
+        }
+        if (!(relation instanceof LogicalOlapScan)) {
+            return true;

Review Comment:
   Fixed in f87ffc5440c. LogicalFileScan primary keys are now activated only 
for a full selector-free scan: no partial partition selection, TABLESAMPLE, 
snapshot, or scan params. A focused regression exercises the exact activation 
gate for a unique external scan, covering the unrestricted case and each 
selector state.



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


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to