This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch branch-3.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-3.1 by this push:
new e9750282d9b branch-3.1: [fix](pkfk) Fix drop table not drop constraint
related info #58958 (#59233)
e9750282d9b is described below
commit e9750282d9b578cf7ca382b19896ba0972f9f099
Author: feiniaofeiafei <[email protected]>
AuthorDate: Mon Dec 22 15:11:38 2025 +0800
branch-3.1: [fix](pkfk) Fix drop table not drop constraint related info
#58958 (#59233)
picked from #58958
---
.../java/org/apache/doris/catalog/TableIf.java | 58 +++++++++++++++++++--
.../catalog/constraint/ForeignKeyConstraint.java | 11 ++++
.../catalog/constraint/PrimaryKeyConstraint.java | 4 ++
.../doris/catalog/constraint/TableIdentifier.java | 2 +-
.../apache/doris/datasource/InternalCatalog.java | 1 +
.../plans/commands/DropConstraintCommand.java | 22 ++++----
.../nereids_p0/pkfk/test_pk_fk_drop_table.groovy | 59 ++++++++++++++++++++++
7 files changed, 143 insertions(+), 14 deletions(-)
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/TableIf.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/TableIf.java
index 1ca51e2d394..d8a25872d41 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/TableIf.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/TableIf.java
@@ -22,11 +22,13 @@ import org.apache.doris.analysis.TableValuedFunctionRef;
import org.apache.doris.catalog.constraint.Constraint;
import org.apache.doris.catalog.constraint.ForeignKeyConstraint;
import org.apache.doris.catalog.constraint.PrimaryKeyConstraint;
+import org.apache.doris.catalog.constraint.TableIdentifier;
import org.apache.doris.catalog.constraint.UniqueConstraint;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.MetaNotFoundException;
import org.apache.doris.common.Pair;
+import org.apache.doris.common.util.MetaLockUtils;
import org.apache.doris.datasource.systable.SysTable;
import org.apache.doris.nereids.exceptions.AnalysisException;
import
org.apache.doris.nereids.trees.expressions.functions.table.TableValuedFunction;
@@ -47,6 +49,7 @@ import org.apache.logging.log4j.Logger;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -334,6 +337,56 @@ public interface TableIf {
dropConstraint(name, true);
}
+ // when table has foreign key constraint referencing to primary key of
other table,
+ // need to remove this table identifier from primary table's foreign table
set when drop this
+ // when table has primary key constraint, when drop table(this), need to
remove the foreign key referenced this
+ default void removeTableIdentifierFromPrimaryTable() {
+ Map<String, Constraint> constraintMap = getConstraintsMapUnsafe();
+ for (Constraint constraint : constraintMap.values()) {
+ dropConstraintRefWithLock(constraint);
+ }
+ }
+
+ default void dropConstraintRefWithLock(Constraint constraint) {
+ List<TableIf> tables = getConstraintRelatedTables(constraint);
+ tables.sort((Comparator.comparing(TableIf::getId)));
+ MetaLockUtils.writeLockTables(tables);
+ try {
+ dropConstraintRef(constraint);
+ } finally {
+ MetaLockUtils.writeUnlockTables(tables);
+ }
+ }
+
+ default void dropConstraintRef(Constraint constraint) {
+ if (constraint instanceof PrimaryKeyConstraint) {
+ ((PrimaryKeyConstraint) constraint).getForeignTables()
+ .forEach(t -> t.dropFKReferringPK(this,
(PrimaryKeyConstraint) constraint));
+ } else if (constraint instanceof ForeignKeyConstraint) {
+ ForeignKeyConstraint foreignKeyConstraint = (ForeignKeyConstraint)
constraint;
+ Optional<TableIf> primaryTableIf =
foreignKeyConstraint.getReferencedTableOrNull();
+ if (primaryTableIf.isPresent()) {
+ Map<String, Constraint> refTableConstraintMap =
primaryTableIf.get().getConstraintsMapUnsafe();
+ for (Constraint refTableConstraint :
refTableConstraintMap.values()) {
+ if (refTableConstraint instanceof PrimaryKeyConstraint) {
+ PrimaryKeyConstraint primaryKeyConstraint =
(PrimaryKeyConstraint) refTableConstraint;
+ primaryKeyConstraint.removeForeignTable(new
TableIdentifier(this));
+ }
+ }
+ }
+ }
+ }
+
+ default List<TableIf> getConstraintRelatedTables(Constraint constraint) {
+ List<TableIf> tables = Lists.newArrayList();
+ if (constraint instanceof PrimaryKeyConstraint) {
+ tables.addAll(((PrimaryKeyConstraint)
constraint).getForeignTables());
+ } else if (constraint instanceof ForeignKeyConstraint) {
+ tables.add(((ForeignKeyConstraint)
constraint).getReferencedTable());
+ }
+ return tables;
+ }
+
default void dropConstraint(String name, boolean replay) {
Map<String, Constraint> constraintMap = getConstraintsMapUnsafe();
if (!constraintMap.containsKey(name)) {
@@ -342,10 +395,7 @@ public interface TableIf {
}
Constraint constraint = constraintMap.get(name);
constraintMap.remove(name);
- if (constraint instanceof PrimaryKeyConstraint) {
- ((PrimaryKeyConstraint) constraint).getForeignTables()
- .forEach(t -> t.dropFKReferringPK(this,
(PrimaryKeyConstraint) constraint));
- }
+ dropConstraintRefWithLock(constraint);
if (!replay) {
Env.getCurrentEnv().getEditLog().logDropConstraint(new
AlterConstraintLog(constraint, this));
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/ForeignKeyConstraint.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/ForeignKeyConstraint.java
index 69d16c07532..db6d9131dc6 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/ForeignKeyConstraint.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/ForeignKeyConstraint.java
@@ -29,6 +29,7 @@ import com.google.gson.annotations.SerializedName;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
public class ForeignKeyConstraint extends Constraint {
@@ -90,6 +91,16 @@ public class ForeignKeyConstraint extends Constraint {
return referencedTable.toTableIf();
}
+ public Optional<TableIf> getReferencedTableOrNull() {
+ TableIf res = null;
+ try {
+ res = referencedTable.toTableIf();
+ } catch (Exception ignored) {
+ // do nothing
+ }
+ return Optional.ofNullable(res);
+ }
+
public Boolean isReferringPK(TableIf table, PrimaryKeyConstraint
constraint) {
return constraint.getPrimaryKeyNames().equals(getPrimaryKeyNames())
&& getReferencedTable().equals(table);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/PrimaryKeyConstraint.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/PrimaryKeyConstraint.java
index 47c822ad597..28f90a4a03a 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/PrimaryKeyConstraint.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/PrimaryKeyConstraint.java
@@ -60,6 +60,10 @@ public class PrimaryKeyConstraint extends Constraint {
.collect(ImmutableList.toImmutableList());
}
+ public void removeForeignTable(TableIdentifier tableIdentifier) {
+ foreignTables.remove(tableIdentifier);
+ }
+
@Override
public String toString() {
return "PRIMARY KEY (" + String.join(", ", columns) + ")";
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/TableIdentifier.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/TableIdentifier.java
index 8e510ec7a93..3022da31e91 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/TableIdentifier.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/TableIdentifier.java
@@ -56,7 +56,7 @@ public class TableIdentifier {
}
TableIf tableIf = databaseIf.getTableNullable(tableId);
if (tableIf == null) {
- throw new MetaNotFoundException(String.format("Can not find table
%s in constraint", databaseId));
+ throw new MetaNotFoundException(String.format("Can not find table
%s in constraint", tableId));
}
return tableIf;
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
index 3522aad64a2..ecc9da236f5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
@@ -1061,6 +1061,7 @@ public class InternalCatalog implements
CatalogIf<Database> {
}
Env.getCurrentEnv().getAnalysisManager().removeTableStats(table.getId());
+ table.removeTableIdentifierFromPrimaryTable();
db.unregisterTable(table.getId());
StopWatch watch = StopWatch.createStarted();
Env.getCurrentRecycleBin().recycleTable(db.getId(), table, isReplay,
isForceDrop, recycleTime);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropConstraintCommand.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropConstraintCommand.java
index 63d43212159..93acf494eea 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropConstraintCommand.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropConstraintCommand.java
@@ -19,8 +19,8 @@ package org.apache.doris.nereids.trees.plans.commands;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.catalog.constraint.Constraint;
+import org.apache.doris.catalog.constraint.ForeignKeyConstraint;
import org.apache.doris.catalog.constraint.PrimaryKeyConstraint;
-import org.apache.doris.common.util.MetaLockUtils;
import org.apache.doris.nereids.NereidsPlanner;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.properties.PhysicalProperties;
@@ -37,7 +37,6 @@ import com.google.common.collect.Lists;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import java.util.Comparator;
import java.util.List;
import java.util.Set;
@@ -59,10 +58,19 @@ public class DropConstraintCommand extends Command
implements ForwardWithSync {
this.plan = plan;
}
+ private static List<TableIf> getConstraintRelatedTables(Constraint
constraint) {
+ List<TableIf> tables = Lists.newArrayList();
+ if (constraint instanceof PrimaryKeyConstraint) {
+ tables.addAll(((PrimaryKeyConstraint)
constraint).getForeignTables());
+ } else if (constraint instanceof ForeignKeyConstraint) {
+ tables.add(((ForeignKeyConstraint)
constraint).getReferencedTable());
+ }
+ return tables;
+ }
+
@Override
public void run(ConnectContext ctx, StmtExecutor executor) throws
Exception {
TableIf table = extractTable(ctx, plan);
- List<TableIf> tables = Lists.newArrayList(table);
table.readLock();
try {
Constraint constraint = table.getConstraintsMapUnsafe().get(name);
@@ -70,18 +78,14 @@ public class DropConstraintCommand extends Command
implements ForwardWithSync {
throw new AnalysisException(
String.format("Unknown constraint %s on table %s.",
name, table.getName()));
}
- if (constraint instanceof PrimaryKeyConstraint) {
- tables.addAll(((PrimaryKeyConstraint)
constraint).getForeignTables());
- }
} finally {
table.readUnlock();
}
- tables.sort((Comparator.comparing(TableIf::getId)));
- MetaLockUtils.writeLockTables(tables);
+ table.writeLock();
try {
table.dropConstraint(name, false);
} finally {
- MetaLockUtils.writeUnlockTables(tables);
+ table.writeUnlock();
}
}
diff --git
a/regression-test/suites/nereids_p0/pkfk/test_pk_fk_drop_table.groovy
b/regression-test/suites/nereids_p0/pkfk/test_pk_fk_drop_table.groovy
new file mode 100644
index 00000000000..bed59d7b8dc
--- /dev/null
+++ b/regression-test/suites/nereids_p0/pkfk/test_pk_fk_drop_table.groovy
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_pk_fk_drop_table") {
+ // case 1
+ multi_sql """drop table if exists store_sales_test;
+ drop table if exists customer_test;
+ create table customer_test(c_customer_sk int,c_customer_id int);
+ CREATE TABLE `store_sales_test` (
+ `ss_customer_sk` int NULL,
+ `d_date` date NULL
+ ) ENGINE=OLAP
+ DUPLICATE KEY(`ss_customer_sk`, `d_date`)
+ DISTRIBUTED BY RANDOM BUCKETS AUTO
+ PROPERTIES (
+ "replication_allocation" = "tag.location.default: 1"
+ );
+ alter table customer_test add constraint c_pk primary key(c_customer_sk);
+ alter table store_sales_test add constraint ss_c_fk foreign
key(ss_customer_sk) references customer_test(c_customer_sk);
+ drop table store_sales_test;"""
+ // expect: successful drop
+ sql "alter table customer_test drop constraint c_pk;"
+
+ multi_sql """
+ drop table if exists store_sales_test;
+ drop table if exists customer_test;
+ create table customer_test(c_customer_sk int,c_customer_id int) PROPERTIES
(
+ "replication_allocation" = "tag.location.default: 1"
+ );
+ CREATE TABLE `store_sales_test` (
+ `ss_customer_sk` int NULL,
+ `d_date` date NULL
+ ) ENGINE=OLAP
+ DUPLICATE KEY(`ss_customer_sk`, `d_date`)
+ DISTRIBUTED BY RANDOM BUCKETS AUTO
+ PROPERTIES (
+ "replication_allocation" = "tag.location.default: 1"
+ );
+ alter table customer_test add constraint c_pk primary key(c_customer_sk);
+ alter table store_sales_test add constraint ss_c_fk foreign
key(ss_customer_sk) references customer_test(c_customer_sk);
+ drop table customer_test;
+ """
+ // expect: not throw
+ sql "show constraints from store_sales_test;"
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]