Skip to content

Commit 8b6b28b

Browse files
[SPARK-52141][SQL] Display constraints in DESC commands
### What changes were proposed in this pull request? Show constraints in `desc extended table` ### Why are the changes needed? Constraint information is the SQL standard and listed in SPIP change. ### Does this PR introduce _any_ user-facing change? Yes, add constraints information in DESC command output. ### How was this patch tested? 1. For `desc extended table` command, I added a test case in `DescribeTableSuite` 2. It's useless to change SQL in `describe.sql` because it's also using v1 table, and constraints are only supported in v2 table. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #51577 from dengziming/SPARK-52141. Lead-authored-by: dengziming <[email protected]> Co-authored-by: Gengliang Wang <[email protected]> Signed-off-by: Gengliang Wang <[email protected]>
1 parent 90fd991 commit 8b6b28b

File tree

4 files changed

+82
-0
lines changed

4 files changed

+82
-0
lines changed

sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/constraints/BaseConstraint.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ public String toDDL() {
7373
rely ? "RELY" : "NORELY");
7474
}
7575

76+
public String toDescription() {
77+
StringJoiner joiner = new StringJoiner(" ");
78+
joiner.add(definition());
79+
joiner.add(enforced ? "ENFORCED" : "NOT ENFORCED");
80+
if (rely) {
81+
joiner.add("RELY");
82+
}
83+
return joiner.toString();
84+
}
85+
7686
@Override
7787
public String toString() {
7888
return toDDL();

sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/constraints/Constraint.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ public interface Constraint {
5858
*/
5959
String toDDL();
6060

61+
/**
62+
* Returns the constraint description for DESCRIBE TABLE output, excluding the constraint
63+
* name (shown separately).
64+
*/
65+
String toDescription();
66+
6167
/**
6268
* Instantiates a builder for a CHECK constraint.
6369
*

sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DescribeTableExec.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ case class DescribeTableExec(
4545
addMetadataColumns(rows)
4646
addTableDetails(rows)
4747
addTableStats(rows)
48+
addTableConstraints(rows)
4849
}
4950
rows.toSeq
5051
}
@@ -88,6 +89,16 @@ case class DescribeTableExec(
8889
}
8990
}
9091

92+
private def addTableConstraints(rows: ArrayBuffer[InternalRow]): Unit = {
93+
if (table.constraints.nonEmpty) {
94+
rows += emptyRow()
95+
rows += toCatalystRow("# Constraints", "", "")
96+
rows ++= table.constraints().map{ constraint =>
97+
toCatalystRow(constraint.name(), constraint.toDescription, "")
98+
}
99+
}
100+
}
101+
91102
private def addMetadataColumns(rows: ArrayBuffer[InternalRow]): Unit = table match {
92103
case hasMeta: SupportsMetadataColumns if hasMeta.metadataColumns.nonEmpty =>
93104
rows += emptyRow()

sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/DescribeTableSuite.scala

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,59 @@ class DescribeTableSuite extends command.DescribeTableSuiteBase
213213
assert("""\d+\s+bytes,\s+4\s+rows""".r.matches(stats))
214214
}
215215
}
216+
217+
test("desc table constraints") {
218+
withNamespaceAndTable("ns", "pk_table", nonPartitionCatalog) { tbl =>
219+
withTable("fk_table") {
220+
sql(
221+
s"""
222+
|CREATE TABLE fk_table (id INT PRIMARY KEY) USING parquet
223+
""".stripMargin)
224+
sql(
225+
s"""
226+
|CREATE TABLE $tbl (
227+
| id INT,
228+
| a INT,
229+
| b STRING,
230+
| c STRING,
231+
| PRIMARY KEY (id),
232+
| CONSTRAINT fk_a FOREIGN KEY (a) REFERENCES fk_table(id) RELY,
233+
| CONSTRAINT uk_b UNIQUE (b),
234+
| CONSTRAINT uk_a_c UNIQUE (a, c),
235+
| CONSTRAINT c1 CHECK (c IS NOT NULL),
236+
| CONSTRAINT c2 CHECK (id > 0)
237+
|)
238+
|$defaultUsing
239+
""".stripMargin)
240+
241+
// Skipped showing NORELY since it is the default value.
242+
var expectedConstraintsDdl = Array(
243+
"# Constraints,,",
244+
"pk_table_pk,PRIMARY KEY (id) NOT ENFORCED,",
245+
"fk_a,FOREIGN KEY (a) REFERENCES fk_table (id) NOT ENFORCED RELY,",
246+
"uk_b,UNIQUE (b) NOT ENFORCED,",
247+
"uk_a_c,UNIQUE (a, c) NOT ENFORCED,",
248+
"c1,CHECK (c IS NOT NULL) ENFORCED,",
249+
"c2,CHECK (id > 0) ENFORCED,"
250+
)
251+
var descDdL = sql(s"DESCRIBE EXTENDED $tbl").collect().map(_.mkString(","))
252+
.dropWhile(_ != "# Constraints,,")
253+
assert(descDdL === expectedConstraintsDdl)
254+
255+
// Show non-default value for RELY.
256+
sql(s"ALTER TABLE $tbl ADD CONSTRAINT c3 CHECK (b IS NOT NULL) RELY")
257+
descDdL = sql(s"DESCRIBE EXTENDED $tbl").collect().map(_.mkString(","))
258+
.dropWhile(_ != "# Constraints,,")
259+
expectedConstraintsDdl = expectedConstraintsDdl ++
260+
Array("c3,CHECK (b IS NOT NULL) ENFORCED RELY,")
261+
assert(descDdL === expectedConstraintsDdl)
262+
263+
sql(s"ALTER TABLE $tbl DROP CONSTRAINT c1")
264+
descDdL = sql(s"DESCRIBE EXTENDED $tbl").collect().map(_.mkString(","))
265+
.dropWhile(_ != "# Constraints,,")
266+
assert(descDdL === expectedConstraintsDdl
267+
.filter(_ != "c1,CHECK (c IS NOT NULL) ENFORCED,"))
268+
}
269+
}
270+
}
216271
}

0 commit comments

Comments
 (0)