Skip to content

Commit 2e379be

Browse files
aokolnychyidongjoon-hyun
authored andcommitted
[SPARK-52455][SQL][TESTS] Test expression-based defaults in UPDATE and MERGE
### What changes were proposed in this pull request? This PR adds test for expression-based defaults in UPDATE and MERGE. ### Why are the changes needed? To complete default value support. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? This PR comes with tests. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #51161 from aokolnychyi/spark-52455. Authored-by: Anton Okolnychyi <[email protected]> Signed-off-by: Dongjoon Hyun <[email protected]>
1 parent bbc8043 commit 2e379be

File tree

2 files changed

+102
-4
lines changed

2 files changed

+102
-4
lines changed

sql/core/src/test/scala/org/apache/spark/sql/connector/MergeIntoTableSuiteBase.scala

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import org.apache.spark.SparkRuntimeException
2121
import org.apache.spark.sql.{AnalysisException, Row}
2222
import org.apache.spark.sql.catalyst.expressions.{AttributeReference, EqualTo, In, Not}
2323
import org.apache.spark.sql.catalyst.optimizer.BuildLeft
24-
import org.apache.spark.sql.connector.catalog.{Column, ColumnDefaultValue}
25-
import org.apache.spark.sql.connector.expressions.LiteralValue
24+
import org.apache.spark.sql.connector.catalog.{Column, ColumnDefaultValue, TableInfo}
25+
import org.apache.spark.sql.connector.expressions.{GeneralScalarExpression, LiteralValue}
2626
import org.apache.spark.sql.execution.SparkPlan
2727
import org.apache.spark.sql.execution.joins.{BroadcastHashJoinExec, BroadcastNestedLoopJoinExec, CartesianProductExec}
2828
import org.apache.spark.sql.internal.SQLConf
@@ -32,6 +32,51 @@ abstract class MergeIntoTableSuiteBase extends RowLevelOperationSuiteBase {
3232

3333
import testImplicits._
3434

35+
test("merge into table with expression-based default values") {
36+
val columns = Array(
37+
Column.create("pk", IntegerType),
38+
Column.create("salary", IntegerType),
39+
Column.create("dep", StringType),
40+
Column.create(
41+
"value",
42+
IntegerType,
43+
false, /* not nullable */
44+
null, /* no comment */
45+
new ColumnDefaultValue(
46+
new GeneralScalarExpression(
47+
"+",
48+
Array(LiteralValue(100, IntegerType), LiteralValue(23, IntegerType))),
49+
LiteralValue(123, IntegerType)),
50+
"{}"))
51+
val tableInfo = new TableInfo.Builder().withColumns(columns).build()
52+
catalog.createTable(ident, tableInfo)
53+
54+
withTempView("source") {
55+
val sourceRows = Seq(
56+
(1, 500, "eng"),
57+
(2, 600, "hr"))
58+
sourceRows.toDF("pk", "salary", "dep").createOrReplaceTempView("source")
59+
60+
sql(s"INSERT INTO $tableNameAsString (pk, salary, dep, value) VALUES (1, 200, 'eng', 999)")
61+
62+
sql(
63+
s"""MERGE INTO $tableNameAsString t
64+
|USING source s
65+
|ON t.pk = s.pk
66+
|WHEN MATCHED THEN
67+
| UPDATE SET value = DEFAULT
68+
|WHEN NOT MATCHED THEN
69+
| INSERT (pk, salary, dep) VALUES (s.pk, s.salary, s.dep)
70+
|""".stripMargin)
71+
72+
checkAnswer(
73+
sql(s"SELECT * FROM $tableNameAsString"),
74+
Seq(
75+
Row(1, 200, "eng", 123), // update
76+
Row(2, 600, "hr", 123))) // insert
77+
}
78+
}
79+
3580
test("merge into table containing added column with default value") {
3681
withTempView("source") {
3782
sql(

sql/core/src/test/scala/org/apache/spark/sql/connector/UpdateTableSuiteBase.scala

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ package org.apache.spark.sql.connector
1919

2020
import org.apache.spark.SparkRuntimeException
2121
import org.apache.spark.sql.Row
22-
import org.apache.spark.sql.connector.catalog.{Column, ColumnDefaultValue}
23-
import org.apache.spark.sql.connector.expressions.LiteralValue
22+
import org.apache.spark.sql.connector.catalog.{Column, ColumnDefaultValue, TableChange, TableInfo}
23+
import org.apache.spark.sql.connector.expressions.{GeneralScalarExpression, LiteralValue}
2424
import org.apache.spark.sql.types.{IntegerType, StringType}
2525

2626
abstract class UpdateTableSuiteBase extends RowLevelOperationSuiteBase {
@@ -64,6 +64,59 @@ abstract class UpdateTableSuiteBase extends RowLevelOperationSuiteBase {
6464
Row(5, 500, "hr", null)))
6565
}
6666

67+
test("update table with expression-based default values") {
68+
val columns = Array(
69+
Column.create("pk", IntegerType),
70+
Column.create("salary", IntegerType),
71+
Column.create("dep", StringType))
72+
val tableInfo = new TableInfo.Builder().withColumns(columns).build()
73+
catalog.createTable(ident, tableInfo)
74+
75+
append("pk INT, salary INT, dep STRING",
76+
"""{ "pk": 1, "salary": 100, "dep": "hr" }
77+
|{ "pk": 2, "salary": 200, "dep": "software" }
78+
|{ "pk": 3, "salary": 300, "dep": "hr" }
79+
|""".stripMargin)
80+
81+
val addColumn = TableChange.addColumn(
82+
Array("value"),
83+
IntegerType,
84+
false, /* not nullable */
85+
null, /* no comment */
86+
null, /* no position */
87+
new ColumnDefaultValue(
88+
new GeneralScalarExpression(
89+
"+",
90+
Array(LiteralValue(100, IntegerType), LiteralValue(23, IntegerType))),
91+
LiteralValue(123, IntegerType)))
92+
catalog.alterTable(ident, addColumn)
93+
94+
append("pk INT, salary INT, dep STRING, value INT",
95+
"""{ "pk": 4, "salary": 400, "dep": "hr", "value": -4 }
96+
|{ "pk": 5, "salary": 500, "dep": "hr", "value": -5 }
97+
|""".stripMargin)
98+
99+
checkAnswer(
100+
sql(s"SELECT * FROM $tableNameAsString"),
101+
Seq(
102+
Row(1, 100, "hr", 123),
103+
Row(2, 200, "software", 123),
104+
Row(3, 300, "hr", 123),
105+
Row(4, 400, "hr", -4),
106+
Row(5, 500, "hr", -5)))
107+
108+
sql(s"UPDATE $tableNameAsString SET value = DEFAULT WHERE pk >= 5")
109+
110+
checkAnswer(
111+
sql(s"SELECT * FROM $tableNameAsString"),
112+
Seq(
113+
Row(1, 100, "hr", 123),
114+
Row(2, 200, "software", 123),
115+
Row(3, 300, "hr", 123),
116+
Row(4, 400, "hr", -4),
117+
Row(5, 500, "hr", 123)))
118+
}
119+
67120
test("EXPLAIN only update") {
68121
createAndInitTable("pk INT NOT NULL, dep STRING", """{ "pk": 1, "dep": "hr" }""")
69122

0 commit comments

Comments
 (0)