This is an automated email from the ASF dual-hosted git repository.

gengliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 38a75333db72 [SPARK-55694][SQL] Block constraints in CTAS/RTAS at 
parser level
38a75333db72 is described below

commit 38a75333db72896318177e241b9d0a45d5b99c7b
Author: Yan Yan <[email protected]>
AuthorDate: Wed Feb 25 11:20:49 2026 -0800

    [SPARK-55694][SQL] Block constraints in CTAS/RTAS at parser level
    
    ### What changes were proposed in this pull request?
    The grammar accepts constraint specifications (PRIMARY KEY, UNIQUE, CHECK, 
FOREIGN KEY) in CREATE TABLE AS SELECT and REPLACE TABLE AS SELECT, but the 
execution layer silently drops them. Neither the ANSI SQL standard nor 
PostgreSQL supports this syntax - the SQL standard makes table element lists 
and AS subquery clauses mutually exclusive. Block this at the parser level, 
consistent with existing CTAS/RTAS checks for schema columns and partition 
column types.
    
    ### Why are the changes needed?
    Explicitly throw exception for an unsupported case for clarity
    
    ### Does this PR introduce _any_ user-facing change?
    No
    
    ### How was this patch tested?
    unit test
    
    ### Was this patch authored or co-authored using generative AI tooling?
    Co-Authored-By: Claude Opus 4.6 <noreplyanthropic.com>
    
    Closes #54454 from yyanyy/block-ctas-constraints.
    
    Authored-by: Yan Yan <[email protected]>
    Signed-off-by: Gengliang Wang <[email protected]>
---
 .../spark/sql/catalyst/parser/AstBuilder.scala     | 10 ++++++++
 .../execution/command/PlanResolutionSuite.scala    | 30 ++++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala
index 99d76430c3cd..6fb9cc6799f9 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala
@@ -5238,6 +5238,11 @@ class AstBuilder extends DataTypeAstBuilder
             "Partition column types may not be specified in Create Table As 
Select (CTAS)",
             ctx)
 
+        case Some(_) if constraints.nonEmpty =>
+          operationNotAllowed(
+            "Constraints may not be specified in a Create Table As Select 
(CTAS) statement",
+            ctx)
+
         case Some(query) =>
           CreateTableAsSelect(identifier, partitioning, query, tableSpec, 
Map.empty, ifNotExists)
 
@@ -5317,6 +5322,11 @@ class AstBuilder extends DataTypeAstBuilder
             "Partition column types may not be specified in Replace Table As 
Select (RTAS)",
             ctx)
 
+        case Some(_) if constraints.nonEmpty =>
+          operationNotAllowed(
+            "Constraints may not be specified in a Replace Table As Select 
(RTAS) statement",
+            ctx)
+
         case Some(query) =>
           ReplaceTableAsSelect(identifier, partitioning, query, tableSpec,
             writeOptions = Map.empty, orCreate = orCreate)
diff --git 
a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/PlanResolutionSuite.scala
 
b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/PlanResolutionSuite.scala
index 65028eb1777e..5f5999f67e72 100644
--- 
a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/PlanResolutionSuite.scala
+++ 
b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/PlanResolutionSuite.scala
@@ -3041,6 +3041,36 @@ class PlanResolutionSuite extends SharedSparkSession 
with AnalysisTest {
       ExpectedContext(fragment = sql2, start = 0, stop = 61))
   }
 
+  test("CTAS statement with constraints") {
+    Seq(
+      "CONSTRAINT pk PRIMARY KEY (id)",
+      "CONSTRAINT uk UNIQUE (id)",
+      "CONSTRAINT ck CHECK (id > 0)"
+    ).foreach { constraintDef =>
+      val sql = s"CREATE TABLE ctas1 ($constraintDef) AS SELECT 1 AS id"
+      assertUnsupported(
+        sql,
+        Map("message" ->
+          "Constraints may not be specified in a Create Table As Select (CTAS) 
statement"),
+        ExpectedContext(fragment = sql, start = 0, stop = sql.length - 1))
+    }
+  }
+
+  test("RTAS statement with constraints") {
+    Seq(
+      "CONSTRAINT pk PRIMARY KEY (id)",
+      "CONSTRAINT uk UNIQUE (id)",
+      "CONSTRAINT ck CHECK (id > 0)"
+    ).foreach { constraintDef =>
+      val sql = s"REPLACE TABLE rtas1 ($constraintDef) AS SELECT 1 AS id"
+      assertUnsupported(
+        sql,
+        Map("message" ->
+          "Constraints may not be specified in a Replace Table As Select 
(RTAS) statement"),
+        ExpectedContext(fragment = sql, start = 0, stop = sql.length - 1))
+    }
+  }
+
   test("create table - basic") {
     val query = "CREATE TABLE my_table (id int, name string)"
     val (desc, allowExisting) = extractTableDesc(query)


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

Reply via email to