@@ -1469,14 +1469,18 @@ class Analyzer(override val catalogManager: CatalogManager)
14691469 case UpdateAction (updateCondition, assignments) =>
14701470 val resolvedUpdateCondition = updateCondition.map(
14711471 resolveExpressionByPlanChildren(_, m))
1472- // The update value can access columns from both target and source tables.
14731472 UpdateAction (
14741473 resolvedUpdateCondition,
1475- resolveAssignments(Some (assignments), m, resolveValuesWithSourceOnly = false ))
1474+ // The update value can access columns from both target and source tables.
1475+ resolveAssignments(assignments, m, resolveValuesWithSourceOnly = false ))
14761476 case UpdateStarAction (updateCondition) =>
1477+ val assignments = targetTable.output.map { attr =>
1478+ Assignment (attr, UnresolvedAttribute (Seq (attr.name)))
1479+ }
14771480 UpdateAction (
14781481 updateCondition.map(resolveExpressionByPlanChildren(_, m)),
1479- resolveAssignments(assignments = None , m, resolveValuesWithSourceOnly = false ))
1482+ // For UPDATE *, the value must from source table.
1483+ resolveAssignments(assignments, m, resolveValuesWithSourceOnly = true ))
14801484 case o => o
14811485 }
14821486 val newNotMatchedActions = m.notMatchedActions.map {
@@ -1487,15 +1491,18 @@ class Analyzer(override val catalogManager: CatalogManager)
14871491 resolveExpressionByPlanChildren(_, Project (Nil , m.sourceTable)))
14881492 InsertAction (
14891493 resolvedInsertCondition,
1490- resolveAssignments(Some ( assignments) , m, resolveValuesWithSourceOnly = true ))
1494+ resolveAssignments(assignments, m, resolveValuesWithSourceOnly = true ))
14911495 case InsertStarAction (insertCondition) =>
14921496 // The insert action is used when not matched, so its condition and value can only
14931497 // access columns from the source table.
14941498 val resolvedInsertCondition = insertCondition.map(
14951499 resolveExpressionByPlanChildren(_, Project (Nil , m.sourceTable)))
1500+ val assignments = targetTable.output.map { attr =>
1501+ Assignment (attr, UnresolvedAttribute (Seq (attr.name)))
1502+ }
14961503 InsertAction (
14971504 resolvedInsertCondition,
1498- resolveAssignments(assignments = None , m, resolveValuesWithSourceOnly = true ))
1505+ resolveAssignments(assignments, m, resolveValuesWithSourceOnly = true ))
14991506 case o => o
15001507 }
15011508 val resolvedMergeCondition = resolveExpressionByPlanChildren(m.mergeCondition, m)
@@ -1513,33 +1520,38 @@ class Analyzer(override val catalogManager: CatalogManager)
15131520 }
15141521
15151522 def resolveAssignments (
1516- assignments : Option [ Seq [Assignment ] ],
1523+ assignments : Seq [Assignment ],
15171524 mergeInto : MergeIntoTable ,
15181525 resolveValuesWithSourceOnly : Boolean ): Seq [Assignment ] = {
1519- if (assignments.isEmpty) {
1520- val expandedColumns = mergeInto.targetTable.output
1521- val expandedValues = mergeInto.sourceTable.output
1522- expandedColumns.zip(expandedValues).map(kv => Assignment (kv._1, kv._2))
1523- } else {
1524- assignments.get.map { assign =>
1525- val resolvedKey = assign.key match {
1526- case c if ! c.resolved =>
1527- resolveExpressionByPlanChildren(c, Project (Nil , mergeInto.targetTable))
1528- case o => o
1529- }
1530- val resolvedValue = assign.value match {
1531- // The update values may contain target and/or source references.
1532- case c if ! c.resolved =>
1533- if (resolveValuesWithSourceOnly) {
1534- resolveExpressionByPlanChildren(c, Project (Nil , mergeInto.sourceTable))
1535- } else {
1536- resolveExpressionByPlanChildren(c, mergeInto)
1537- }
1538- case o => o
1539- }
1540- Assignment (resolvedKey, resolvedValue)
1526+ assignments.map { assign =>
1527+ val resolvedKey = assign.key match {
1528+ case c if ! c.resolved =>
1529+ resolveMergeExprOrFail(c, Project (Nil , mergeInto.targetTable))
1530+ case o => o
15411531 }
1532+ val resolvedValue = assign.value match {
1533+ // The update values may contain target and/or source references.
1534+ case c if ! c.resolved =>
1535+ if (resolveValuesWithSourceOnly) {
1536+ resolveMergeExprOrFail(c, Project (Nil , mergeInto.sourceTable))
1537+ } else {
1538+ resolveMergeExprOrFail(c, mergeInto)
1539+ }
1540+ case o => o
1541+ }
1542+ Assignment (resolvedKey, resolvedValue)
1543+ }
1544+ }
1545+
1546+ private def resolveMergeExprOrFail (e : Expression , p : LogicalPlan ): Expression = {
1547+ val resolved = resolveExpressionByPlanChildren(e, p)
1548+ resolved.references.filter(! _.resolved).foreach { a =>
1549+ // Note: This will throw error only on unresolved attribute issues,
1550+ // not other resolution errors like mismatched data types.
1551+ val cols = p.inputSet.toSeq.map(_.sql).mkString(" , " )
1552+ a.failAnalysis(s " cannot resolve ${a.sql} in MERGE command given columns [ $cols] " )
15421553 }
1554+ resolved
15431555 }
15441556
15451557 // This method is used to trim groupByExpressions/selectedGroupByExpressions's top-level
0 commit comments