@@ -21,7 +21,7 @@ import org.apache.spark.SparkRuntimeException
21
21
import org .apache .spark .sql .{AnalysisException , Row }
22
22
import org .apache .spark .sql .catalyst .expressions .{AttributeReference , EqualTo , In , Not }
23
23
import org .apache .spark .sql .catalyst .optimizer .BuildLeft
24
- import org .apache .spark .sql .connector .catalog .{Column , ColumnDefaultValue , TableInfo }
24
+ import org .apache .spark .sql .connector .catalog .{Column , ColumnDefaultValue , InMemoryTable , TableInfo }
25
25
import org .apache .spark .sql .connector .expressions .{GeneralScalarExpression , LiteralValue }
26
26
import org .apache .spark .sql .execution .SparkPlan
27
27
import org .apache .spark .sql .execution .adaptive .AdaptiveSparkPlanHelper
@@ -1811,6 +1811,17 @@ abstract class MergeIntoTableSuiteBase extends RowLevelOperationSuiteBase
1811
1811
Row (1 , 1000 , " hr" ), // updated
1812
1812
Row (2 , 200 , " software" ),
1813
1813
Row (3 , 300 , " hr" )))
1814
+
1815
+ val table = catalog.loadTable(ident)
1816
+ val commitProps = table.asInstanceOf [InMemoryTable ].commits.last.properties
1817
+ assert(commitProps(" merge.numTargetRowsCopied" ) === (if (deltaMerge) " 0" else " 2" ))
1818
+ assert(commitProps(" merge.numTargetRowsInserted" ) === " 0" )
1819
+ assert(commitProps(" merge.numTargetRowsUpdated" ) === " 1" )
1820
+ assert(commitProps(" merge.numTargetRowsDeleted" ) === " 0" )
1821
+ assert(commitProps(" merge.numTargetRowsMatchedUpdated" ) === " 1" )
1822
+ assert(commitProps(" merge.numTargetRowsMatchedDeleted" ) === " 0" )
1823
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceUpdated" ) === " 0" )
1824
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceDeleted" ) === " 0" )
1814
1825
}
1815
1826
}
1816
1827
@@ -1856,6 +1867,17 @@ abstract class MergeIntoTableSuiteBase extends RowLevelOperationSuiteBase
1856
1867
Row (2 , 200 , " software" ),
1857
1868
Row (3 , 300 , " hr" ),
1858
1869
Row (5 , 400 , " executive" ))) // inserted
1870
+
1871
+ val table = catalog.loadTable(ident)
1872
+ val commitProps = table.asInstanceOf [InMemoryTable ].commits.last.properties
1873
+ assert(commitProps(" merge.numTargetRowsCopied" ) === " 0" )
1874
+ assert(commitProps(" merge.numTargetRowsInserted" ) === " 1" )
1875
+ assert(commitProps(" merge.numTargetRowsUpdated" ) === " 0" )
1876
+ assert(commitProps(" merge.numTargetRowsDeleted" ) === " 0" )
1877
+ assert(commitProps(" merge.numTargetRowsMatchedUpdated" ) === " 0" )
1878
+ assert(commitProps(" merge.numTargetRowsMatchedDeleted" ) === " 0" )
1879
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceUpdated" ) === " 0" )
1880
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceDeleted" ) === " 0" )
1859
1881
}
1860
1882
}
1861
1883
@@ -1883,7 +1905,6 @@ abstract class MergeIntoTableSuiteBase extends RowLevelOperationSuiteBase
1883
1905
| """ .stripMargin
1884
1906
}
1885
1907
1886
-
1887
1908
assertMetric(mergeExec, " numTargetRowsCopied" , if (deltaMerge) 0 else 3 )
1888
1909
assertMetric(mergeExec, " numTargetRowsInserted" , 0 )
1889
1910
assertMetric(mergeExec, " numTargetRowsUpdated" , 2 )
@@ -1901,6 +1922,17 @@ abstract class MergeIntoTableSuiteBase extends RowLevelOperationSuiteBase
1901
1922
Row (3 , 300 , " hr" ),
1902
1923
Row (4 , 400 , " marketing" ),
1903
1924
Row (5 , - 1 , " executive" ))) // updated
1925
+
1926
+ val table = catalog.loadTable(ident)
1927
+ val commitProps = table.asInstanceOf [InMemoryTable ].commits.last.properties
1928
+ assert(commitProps(" merge.numTargetRowsCopied" ) === (if (deltaMerge) " 0" else " 3" ))
1929
+ assert(commitProps(" merge.numTargetRowsInserted" ) === " 0" )
1930
+ assert(commitProps(" merge.numTargetRowsUpdated" ) === " 2" )
1931
+ assert(commitProps(" merge.numTargetRowsDeleted" ) === " 0" )
1932
+ assert(commitProps(" merge.numTargetRowsMatchedUpdated" ) === " 1" )
1933
+ assert(commitProps(" merge.numTargetRowsMatchedDeleted" ) === " 0" )
1934
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceUpdated" ) === " 1" )
1935
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceDeleted" ) === " 0" )
1904
1936
}
1905
1937
}
1906
1938
@@ -1947,6 +1979,17 @@ abstract class MergeIntoTableSuiteBase extends RowLevelOperationSuiteBase
1947
1979
Row (4 , 400 , " marketing" ))
1948
1980
// Row(5, 500, "executive") deleted
1949
1981
)
1982
+
1983
+ val table = catalog.loadTable(ident)
1984
+ val commitProps = table.asInstanceOf [InMemoryTable ].commits.last.properties
1985
+ assert(commitProps(" merge.numTargetRowsCopied" ) === (if (deltaMerge) " 0" else " 3" ))
1986
+ assert(commitProps(" merge.numTargetRowsInserted" ) === " 0" )
1987
+ assert(commitProps(" merge.numTargetRowsUpdated" ) === " 0" )
1988
+ assert(commitProps(" merge.numTargetRowsDeleted" ) === " 2" )
1989
+ assert(commitProps(" merge.numTargetRowsMatchedUpdated" ) === " 0" )
1990
+ assert(commitProps(" merge.numTargetRowsMatchedDeleted" ) === " 1" )
1991
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceUpdated" ) === " 0" )
1992
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceDeleted" ) === " 1" )
1950
1993
}
1951
1994
}
1952
1995
@@ -1994,6 +2037,17 @@ abstract class MergeIntoTableSuiteBase extends RowLevelOperationSuiteBase
1994
2037
Row (4 , 400 , " marketing" ),
1995
2038
Row (5 , - 1 , " executive" ), // updated
1996
2039
Row (6 , - 1 , " dummy" ))) // inserted
2040
+
2041
+ val table = catalog.loadTable(ident)
2042
+ val commitProps = table.asInstanceOf [InMemoryTable ].commits.last.properties
2043
+ assert(commitProps(" merge.numTargetRowsCopied" ) === (if (deltaMerge) " 0" else " 3" ))
2044
+ assert(commitProps(" merge.numTargetRowsInserted" ) === " 1" )
2045
+ assert(commitProps(" merge.numTargetRowsUpdated" ) === " 2" )
2046
+ assert(commitProps(" merge.numTargetRowsDeleted" ) === " 0" )
2047
+ assert(commitProps(" merge.numTargetRowsMatchedUpdated" ) === " 1" )
2048
+ assert(commitProps(" merge.numTargetRowsMatchedDeleted" ) === " 0" )
2049
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceUpdated" ) === " 1" )
2050
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceDeleted" ) === " 0" )
1997
2051
}
1998
2052
}
1999
2053
@@ -2032,7 +2086,6 @@ abstract class MergeIntoTableSuiteBase extends RowLevelOperationSuiteBase
2032
2086
assertMetric(mergeExec, " numTargetRowsNotMatchedBySourceUpdated" , 0 )
2033
2087
assertMetric(mergeExec, " numTargetRowsNotMatchedBySourceDeleted" , 1 )
2034
2088
2035
-
2036
2089
checkAnswer(
2037
2090
sql(s " SELECT * FROM $tableNameAsString" ),
2038
2091
Seq (
@@ -2042,6 +2095,62 @@ abstract class MergeIntoTableSuiteBase extends RowLevelOperationSuiteBase
2042
2095
Row (4 , 400 , " marketing" ),
2043
2096
// Row(5, 500, "executive") deleted
2044
2097
Row (6 , - 1 , " dummy" ))) // inserted
2098
+
2099
+ val table = catalog.loadTable(ident)
2100
+ val commitProps = table.asInstanceOf [InMemoryTable ].commits.last.properties
2101
+ assert(commitProps(" merge.numTargetRowsCopied" ) === (if (deltaMerge) " 0" else " 3" ))
2102
+ assert(commitProps(" merge.numTargetRowsInserted" ) === " 1" )
2103
+ assert(commitProps(" merge.numTargetRowsUpdated" ) === " 0" )
2104
+ assert(commitProps(" merge.numTargetRowsDeleted" ) === " 2" )
2105
+ assert(commitProps(" merge.numTargetRowsMatchedUpdated" ) === " 0" )
2106
+ assert(commitProps(" merge.numTargetRowsMatchedDeleted" ) === " 1" )
2107
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceUpdated" ) === " 0" )
2108
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceDeleted" ) === " 1" )
2109
+ }
2110
+ }
2111
+
2112
+ test(" SPARK-52689: V2 write metrics for merge" ) {
2113
+ Seq (" true" , " false" ).foreach { aqeEnabled : String =>
2114
+ withTempView(" source" ) {
2115
+ withSQLConf(SQLConf .ADAPTIVE_EXECUTION_ENABLED .key -> aqeEnabled) {
2116
+ createAndInitTable(" pk INT NOT NULL, salary INT, dep STRING" ,
2117
+ """ { "pk": 1, "salary": 100, "dep": "hr" }
2118
+ |{ "pk": 2, "salary": 200, "dep": "software" }
2119
+ |{ "pk": 3, "salary": 300, "dep": "hr" }
2120
+ |{ "pk": 4, "salary": 400, "dep": "marketing" }
2121
+ |{ "pk": 5, "salary": 500, "dep": "executive" }
2122
+ |""" .stripMargin)
2123
+
2124
+ val sourceDF = Seq (1 , 2 , 6 , 10 ).toDF(" pk" )
2125
+ sourceDF.createOrReplaceTempView(" source" )
2126
+
2127
+ sql(
2128
+ s """ MERGE INTO $tableNameAsString t
2129
+ |USING source s
2130
+ |ON t.pk = s.pk
2131
+ |WHEN MATCHED AND salary < 200 THEN
2132
+ | DELETE
2133
+ |WHEN NOT MATCHED AND s.pk < 10 THEN
2134
+ | INSERT (pk, salary, dep) VALUES (s.pk, -1, "dummy")
2135
+ |WHEN NOT MATCHED BY SOURCE AND salary > 400 THEN
2136
+ | DELETE
2137
+ | """ .stripMargin
2138
+ )
2139
+
2140
+ val table = catalog.loadTable(ident)
2141
+ val commitProps = table.asInstanceOf [InMemoryTable ].commits.last.properties
2142
+ assert(commitProps(" merge.numTargetRowsCopied" ) === (if (deltaMerge) " 0" else " 3" ))
2143
+ assert(commitProps(" merge.numTargetRowsInserted" ) === " 1" )
2144
+ assert(commitProps(" merge.numTargetRowsUpdated" ) === " 0" )
2145
+ assert(commitProps(" merge.numTargetRowsDeleted" ) === " 2" )
2146
+ assert(commitProps(" merge.numTargetRowsMatchedUpdated" ) === " 0" )
2147
+ assert(commitProps(" merge.numTargetRowsMatchedDeleted" ) === " 1" )
2148
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceUpdated" ) === " 0" )
2149
+ assert(commitProps(" merge.numTargetRowsNotMatchedBySourceDeleted" ) === " 1" )
2150
+
2151
+ sql(s " DROP TABLE $tableNameAsString" )
2152
+ }
2153
+ }
2045
2154
}
2046
2155
}
2047
2156
0 commit comments