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]