exec-ddl
CREATE TABLE abcde (
    a INT NOT NULL,
    b INT,
    c INT DEFAULT (10),
    d INT AS (b + c + 1) STORED,
    e INT AS (a) STORED
)
----

exec-ddl
CREATE TABLE xyz (
    x TEXT PRIMARY KEY,
    y INT8,
    z FLOAT8
)
----

exec-ddl
CREATE TABLE uv (
    u DECIMAL,
    v BYTES
)
----

exec-ddl
CREATE TABLE on_update_bare (
    a INT NOT NULL,
    v INT ON UPDATE 5
)
----

exec-ddl
CREATE TABLE on_update_with_default (
    a INT NOT NULL,
    v INT DEFAULT 3 ON UPDATE 10
)
----

exec-ddl
CREATE TABLE mutation (
    m INT PRIMARY KEY,
    n INT,
    "o:write-only" INT DEFAULT(10),
    "p:write-only" INT AS (o + n) STORED,
    "q:delete-only" INT AS (m * p) STORED,
    CHECK (m > 0)
)
----

exec-ddl
CREATE TABLE checks (
    a INT PRIMARY KEY CHECK (a > 0),
    b INT,
    c INT,
    d INT AS (c + 1) STORED,
    CHECK (b < d)
)
----

exec-ddl
CREATE TABLE decimals (
    a DECIMAL(10,0) PRIMARY KEY CHECK (round(a) = a),
    b DECIMAL(5,1)[] CHECK (b[0] > 1),
    c DECIMAL(10,1) DEFAULT (1.23),
    d DECIMAL(10,1) AS (a+c) STORED
)
----

exec-ddl
CREATE TABLE assn_cast (
    c CHAR,
    qc "char",
    i INT DEFAULT 10::INT2,
    s STRING,
    d DECIMAL(10, 0),
    d_comp DECIMAL(10, 0) AS (d + 10.0) STORED
)
----

exec-ddl
CREATE TABLE assn_cast_on_update (
    i INT,
    i2 INT ON UPDATE 1.0::FLOAT,
    d DECIMAL(10, 1) ON UPDATE 1.23,
    d2 DECIMAL(10, 1) ON UPDATE 1.23::DECIMAL(10, 2),
    d_comp DECIMAL(10, 0) AS (d) STORED,
    b BOOL ON UPDATE 1.0::FLOAT
)
----

exec-ddl
CREATE TABLE generated_as_identity (
  a INT,
  b INT GENERATED ALWAYS AS IDENTITY,
  c INT GENERATED BY DEFAULT AS IDENTITY
)
----

# ------------------------------------------------------------------------------
# Basic tests.
# ------------------------------------------------------------------------------

# Set single column.
build
UPDATE abcde SET a=2 WHERE a=1
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:17 => a:1
 │    └── a_new:17 => e:5
 └── project
      ├── columns: d_comp:18 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17!null
      ├── project
      │    ├── columns: a_new:17!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── select
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── scan abcde
      │    │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    │    ├── computed column expressions
      │    │    │    │    ├── d:12
      │    │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    │    └── e:13
      │    │    │    │         └── a:9
      │    │    │    └── flags: avoid-full-scan
      │    │    └── filters
      │    │         └── a:9 = 1
      │    └── projections
      │         └── 2 [as=a_new:17]
      └── projections
           └── (b:10 + c:11) + 1 [as=d_comp:18]

# Set all non-computed columns.
build
UPDATE abcde SET a=1, b=2, c=3, rowid=4
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:17 => a:1
 │    ├── b_new:18 => b:2
 │    ├── c_new:19 => c:3
 │    ├── d_comp:21 => d:4
 │    ├── a_new:17 => e:5
 │    └── rowid_new:20 => rowid:6
 └── project
      ├── columns: d_comp:21!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17!null b_new:18!null c_new:19!null rowid_new:20!null
      ├── project
      │    ├── columns: a_new:17!null b_new:18!null c_new:19!null rowid_new:20!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         ├── 1 [as=a_new:17]
      │         ├── 2 [as=b_new:18]
      │         ├── 3 [as=c_new:19]
      │         └── 4 [as=rowid_new:20]
      └── projections
           └── (b_new:18 + c_new:19) + 1 [as=d_comp:21]

# Set all non-computed columns in reverse order.
build
UPDATE abcde SET rowid=1, c=2, b=3, a=4
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:20 => a:1
 │    ├── b_new:19 => b:2
 │    ├── c_new:18 => c:3
 │    ├── d_comp:21 => d:4
 │    ├── a_new:20 => e:5
 │    └── rowid_new:17 => rowid:6
 └── project
      ├── columns: d_comp:21!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 rowid_new:17!null c_new:18!null b_new:19!null a_new:20!null
      ├── project
      │    ├── columns: rowid_new:17!null c_new:18!null b_new:19!null a_new:20!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         ├── 1 [as=rowid_new:17]
      │         ├── 2 [as=c_new:18]
      │         ├── 3 [as=b_new:19]
      │         └── 4 [as=a_new:20]
      └── projections
           └── (b_new:19 + c_new:18) + 1 [as=d_comp:21]

# Set all non-computed columns to NULL.
build
UPDATE abcde SET a=NULL, b=NULL, c=NULL, rowid=NULL
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:17 => a:1
 │    ├── a_new:17 => b:2
 │    ├── a_new:17 => c:3
 │    ├── d_comp:18 => d:4
 │    ├── a_new:17 => e:5
 │    └── a_new:17 => rowid:6
 └── project
      ├── columns: d_comp:18 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17
      ├── project
      │    ├── columns: a_new:17 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         └── NULL::INT8 [as=a_new:17]
      └── projections
           └── (a_new:17 + a_new:17) + 1 [as=d_comp:18]

# Set columns using variable expressions.
build
UPDATE abcde SET a=a+1, b=b*c WHERE b>e
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:17 => a:1
 │    ├── b_new:18 => b:2
 │    ├── d_comp:19 => d:4
 │    └── a_new:17 => e:5
 └── project
      ├── columns: d_comp:19 a:9!null b:10!null c:11 d:12 e:13!null rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17!null b_new:18
      ├── project
      │    ├── columns: a_new:17!null b_new:18 a:9!null b:10!null c:11 d:12 e:13!null rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── select
      │    │    ├── columns: a:9!null b:10!null c:11 d:12 e:13!null rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── scan abcde
      │    │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    │    ├── computed column expressions
      │    │    │    │    ├── d:12
      │    │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    │    └── e:13
      │    │    │    │         └── a:9
      │    │    │    └── flags: avoid-full-scan
      │    │    └── filters
      │    │         └── b:10 > e:13
      │    └── projections
      │         ├── a:9 + 1 [as=a_new:17]
      │         └── b:10 * c:11 [as=b_new:18]
      └── projections
           └── (b_new:18 + c:11) + 1 [as=d_comp:19]

# Set columns using aliased expressions.
build
UPDATE abcde AS foo SET a=foo.b, b=foo.c
----
update abcde [as=foo]
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── b:10 => a:1
 │    ├── c:11 => b:2
 │    ├── d_comp:17 => d:4
 │    └── b:10 => e:5
 └── project
      ├── columns: d_comp:17 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      ├── scan abcde [as=foo]
      │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── computed column expressions
      │    │    ├── d:12
      │    │    │    └── (b:10 + c:11) + 1
      │    │    └── e:13
      │    │         └── a:9
      │    └── flags: avoid-full-scan
      └── projections
           └── (c:11 + c:11) + 1 [as=d_comp:17]

# Use WHERE, ORDER BY, LIMIT.
build
UPDATE abcde SET b=1 WHERE a>0 ORDER BY a LIMIT 10
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── b_new:17 => b:2
 │    └── d_comp:18 => d:4
 └── project
      ├── columns: d_comp:18 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 b_new:17!null
      ├── project
      │    ├── columns: b_new:17!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── limit
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── internal-ordering: +9
      │    │    ├── sort
      │    │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    │    ├── ordering: +9
      │    │    │    ├── limit hint: 10.00
      │    │    │    └── select
      │    │    │         ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    │         ├── scan abcde
      │    │    │         │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    │         │    ├── computed column expressions
      │    │    │         │    │    ├── d:12
      │    │    │         │    │    │    └── (b:10 + c:11) + 1
      │    │    │         │    │    └── e:13
      │    │    │         │    │         └── a:9
      │    │    │         │    └── flags: avoid-full-scan
      │    │    │         └── filters
      │    │    │              └── a:9 > 0
      │    │    └── 10
      │    └── projections
      │         └── 1 [as=b_new:17]
      └── projections
           └── (b_new:17 + c:11) + 1 [as=d_comp:18]

# UPDATE with index hints.
exec-ddl
CREATE TABLE xyzw (
  x INT PRIMARY KEY,
  y INT,
  z INT,
  w INT,
  INDEX foo (z, y)
)
----

build
UPDATE xyzw@xyzw_pkey SET x=2 WHERE z=1
----
update xyzw
 ├── columns: <none>
 ├── fetch columns: x:7 y:8 z:9 w:10
 ├── update-mapping:
 │    └── x_new:13 => x:1
 └── project
      ├── columns: x_new:13!null x:7!null y:8 z:9!null w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── select
      │    ├── columns: x:7!null y:8 z:9!null w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    ├── scan xyzw
      │    │    ├── columns: x:7!null y:8 z:9 w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    └── flags: force-index=xyzw_pkey avoid-full-scan
      │    └── filters
      │         └── z:9 = 1
      └── projections
           └── 2 [as=x_new:13]

build
UPDATE xyzw@foo SET x=2 WHERE z=1
----
update xyzw
 ├── columns: <none>
 ├── fetch columns: x:7 y:8 z:9 w:10
 ├── update-mapping:
 │    └── x_new:13 => x:1
 └── project
      ├── columns: x_new:13!null x:7!null y:8 z:9!null w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── select
      │    ├── columns: x:7!null y:8 z:9!null w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    ├── scan xyzw
      │    │    ├── columns: x:7!null y:8 z:9 w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    └── flags: force-index=foo avoid-full-scan
      │    └── filters
      │         └── z:9 = 1
      └── projections
           └── 2 [as=x_new:13]

build
UPDATE xyzw@{FORCE_INDEX=foo,ASC} SET x=2 WHERE z=1
----
update xyzw
 ├── columns: <none>
 ├── fetch columns: x:7 y:8 z:9 w:10
 ├── update-mapping:
 │    └── x_new:13 => x:1
 └── project
      ├── columns: x_new:13!null x:7!null y:8 z:9!null w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── select
      │    ├── columns: x:7!null y:8 z:9!null w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    ├── scan xyzw
      │    │    ├── columns: x:7!null y:8 z:9 w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    └── flags: force-index=foo,fwd avoid-full-scan
      │    └── filters
      │         └── z:9 = 1
      └── projections
           └── 2 [as=x_new:13]

build
UPDATE xyzw@{FORCE_INDEX=foo,DESC} SET x=2 WHERE z=1
----
update xyzw
 ├── columns: <none>
 ├── fetch columns: x:7 y:8 z:9 w:10
 ├── update-mapping:
 │    └── x_new:13 => x:1
 └── project
      ├── columns: x_new:13!null x:7!null y:8 z:9!null w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── select
      │    ├── columns: x:7!null y:8 z:9!null w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    ├── scan xyzw,rev
      │    │    ├── columns: x:7!null y:8 z:9 w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    └── flags: force-index=foo,rev avoid-full-scan
      │    └── filters
      │         └── z:9 = 1
      └── projections
           └── 2 [as=x_new:13]

build
UPDATE xyzw@{NO_INDEX_JOIN} SET x=2 WHERE z=1
----
update xyzw
 ├── columns: <none>
 ├── fetch columns: x:7 y:8 z:9 w:10
 ├── update-mapping:
 │    └── x_new:13 => x:1
 └── project
      ├── columns: x_new:13!null x:7!null y:8 z:9!null w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── select
      │    ├── columns: x:7!null y:8 z:9!null w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    ├── scan xyzw
      │    │    ├── columns: x:7!null y:8 z:9 w:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    └── flags: no-index-join avoid-full-scan
      │    └── filters
      │         └── z:9 = 1
      └── projections
           └── 2 [as=x_new:13]

build
UPDATE xyzw@bad_idx SET x=2 WHERE z=1
----
error (42704): index "bad_idx" not found


# Infer types.
build
UPDATE xyz SET y=1, z=1
----
update xyz
 ├── columns: <none>
 ├── fetch columns: x:6 y:7 z:8
 ├── update-mapping:
 │    ├── y_new:11 => y:2
 │    └── z_new:12 => z:3
 └── project
      ├── columns: y_new:11!null z_new:12!null x:6!null y:7 z:8 crdb_internal_mvcc_timestamp:9 tableoid:10
      ├── scan xyz
      │    ├── columns: x:6!null y:7 z:8 crdb_internal_mvcc_timestamp:9 tableoid:10
      │    └── flags: avoid-full-scan
      └── projections
           ├── 1 [as=y_new:11]
           └── 1.0 [as=z_new:12]

# Use placeholders.
build
UPDATE xyz SET x=$1, y=$2, z=$3
----
update xyz
 ├── columns: <none>
 ├── fetch columns: x:6 y:7 z:8
 ├── update-mapping:
 │    ├── x_new:11 => x:1
 │    ├── y_new:12 => y:2
 │    └── z_new:13 => z:3
 └── project
      ├── columns: x_new:11 y_new:12 z_new:13 x:6!null y:7 z:8 crdb_internal_mvcc_timestamp:9 tableoid:10
      ├── scan xyz
      │    ├── columns: x:6!null y:7 z:8 crdb_internal_mvcc_timestamp:9 tableoid:10
      │    └── flags: avoid-full-scan
      └── projections
           ├── $1 [as=x_new:11]
           ├── $2 [as=y_new:12]
           └── $3 [as=z_new:13]

# Duplicate expressions with placeholders.
build
UPDATE abcde SET a=$1 + 1, b=$1 + 1 WHERE c=10
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:17 => a:1
 │    ├── a_new:17 => b:2
 │    ├── d_comp:18 => d:4
 │    └── a_new:17 => e:5
 └── project
      ├── columns: d_comp:18 a:9!null b:10 c:11!null d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17
      ├── project
      │    ├── columns: a_new:17 a:9!null b:10 c:11!null d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── select
      │    │    ├── columns: a:9!null b:10 c:11!null d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── scan abcde
      │    │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    │    ├── computed column expressions
      │    │    │    │    ├── d:12
      │    │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    │    └── e:13
      │    │    │    │         └── a:9
      │    │    │    └── flags: avoid-full-scan
      │    │    └── filters
      │    │         └── c:11 = 10
      │    └── projections
      │         └── $1 + 1 [as=a_new:17]
      └── projections
           └── (a_new:17 + c:11) + 1 [as=d_comp:18]


# Unknown target table.
build
UPDATE unknown SET x=1
----
error (42P01): no data source matches prefix: "unknown"

# Unknown target column.
build
UPDATE abcde SET f=1
----
error (42703): column "f" does not exist

# Test SET type checking.
build
UPDATE xyz SET x=1, y=1, z=1
----
update xyz
 ├── columns: <none>
 ├── fetch columns: x:6 y:7 z:8
 ├── update-mapping:
 │    ├── x_cast:13 => x:1
 │    ├── x_new:11 => y:2
 │    └── z_new:12 => z:3
 └── project
      ├── columns: x_cast:13!null x:6!null y:7 z:8 crdb_internal_mvcc_timestamp:9 tableoid:10 x_new:11!null z_new:12!null
      ├── project
      │    ├── columns: x_new:11!null z_new:12!null x:6!null y:7 z:8 crdb_internal_mvcc_timestamp:9 tableoid:10
      │    ├── scan xyz
      │    │    ├── columns: x:6!null y:7 z:8 crdb_internal_mvcc_timestamp:9 tableoid:10
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         ├── 1 [as=x_new:11]
      │         └── 1.0 [as=z_new:12]
      └── projections
           └── assignment-cast: STRING [as=x_cast:13]
                └── x_new:11

build
UPDATE xyz SET y='1'::TEXT
----
error (42804): value type string doesn't match type int of column "y"

# Try to use non-returning UPDATE as expression.
build
SELECT * FROM [UPDATE abcde SET a=1]
----
error (42703): statement source "UPDATE abcde SET a = 1" does not return any columns

# Non-referenced CTE with mutation.
build
WITH cte AS (SELECT y FROM [UPDATE xyz SET y = y + 1 RETURNING *]) UPDATE abcde SET a=b
----
with &1
 ├── update xyz
 │    ├── columns: xyz.x:1!null xyz.y:2 xyz.z:3
 │    ├── fetch columns: xyz.x:6 xyz.y:7 xyz.z:8
 │    ├── update-mapping:
 │    │    └── y_new:11 => xyz.y:2
 │    ├── return-mapping:
 │    │    ├── xyz.x:6 => xyz.x:1
 │    │    ├── y_new:11 => xyz.y:2
 │    │    └── xyz.z:8 => xyz.z:3
 │    └── project
 │         ├── columns: y_new:11 xyz.x:6!null xyz.y:7 xyz.z:8 xyz.crdb_internal_mvcc_timestamp:9 xyz.tableoid:10
 │         ├── scan xyz
 │         │    ├── columns: xyz.x:6!null xyz.y:7 xyz.z:8 xyz.crdb_internal_mvcc_timestamp:9 xyz.tableoid:10
 │         │    └── flags: avoid-full-scan
 │         └── projections
 │              └── xyz.y:7 + 1 [as=y_new:11]
 └── with &2 (cte)
      ├── project
      │    ├── columns: y:13
      │    └── with-scan &1
      │         ├── columns: x:12!null y:13 z:14
      │         └── mapping:
      │              ├──  xyz.x:1 => x:12
      │              ├──  xyz.y:2 => y:13
      │              └──  xyz.z:3 => z:14
      └── update abcde
           ├── columns: <none>
           ├── fetch columns: a:23 b:24 c:25 d:26 e:27 rowid:28
           ├── update-mapping:
           │    ├── b:24 => a:15
           │    ├── d_comp:31 => d:18
           │    └── b:24 => e:19
           └── project
                ├── columns: d_comp:31 a:23!null b:24 c:25 d:26 e:27 rowid:28!null abcde.crdb_internal_mvcc_timestamp:29 abcde.tableoid:30
                ├── scan abcde
                │    ├── columns: a:23!null b:24 c:25 d:26 e:27 rowid:28!null abcde.crdb_internal_mvcc_timestamp:29 abcde.tableoid:30
                │    ├── computed column expressions
                │    │    ├── d:26
                │    │    │    └── (b:24 + c:25) + 1
                │    │    └── e:27
                │    │         └── a:23
                │    └── flags: avoid-full-scan
                └── projections
                     └── (b:24 + c:25) + 1 [as=d_comp:31]

# With alias, original table name should be inaccessible.
build
UPDATE abcde AS foo SET a=abcde.b
----
error (42P01): no data source matches prefix: abcde in this context

# ORDER BY can only be used with LIMIT.
build
UPDATE abcde SET b=1 ORDER BY c
----
error (42601): UPDATE statement requires LIMIT when ORDER BY is used

# Aggregate functions are not allowed in ORDER BY.
build
UPDATE abcde SET b=1 ORDER BY sum(c) LIMIT 1
----
error (42803): sum(): aggregate functions are not allowed in ORDER BY in UPDATE

# ------------------------------------------------------------------------------
# Test RETURNING.
# ------------------------------------------------------------------------------

# Return values from update.
build
UPDATE abcde SET a=2 WHERE a=1 RETURNING *
----
project
 ├── columns: a:1!null b:2 c:3 d:4 e:5!null
 └── update abcde
      ├── columns: a:1!null b:2 c:3 d:4 e:5!null rowid:6!null
      ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
      ├── update-mapping:
      │    ├── a_new:17 => a:1
      │    └── a_new:17 => e:5
      ├── return-mapping:
      │    ├── a_new:17 => a:1
      │    ├── b:10 => b:2
      │    ├── c:11 => c:3
      │    ├── d:12 => d:4
      │    ├── a_new:17 => e:5
      │    └── rowid:14 => rowid:6
      └── project
           ├── columns: d_comp:18 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17!null
           ├── project
           │    ├── columns: a_new:17!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
           │    ├── select
           │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
           │    │    ├── scan abcde
           │    │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
           │    │    │    ├── computed column expressions
           │    │    │    │    ├── d:12
           │    │    │    │    │    └── (b:10 + c:11) + 1
           │    │    │    │    └── e:13
           │    │    │    │         └── a:9
           │    │    │    └── flags: avoid-full-scan
           │    │    └── filters
           │    │         └── a:9 = 1
           │    └── projections
           │         └── 2 [as=a_new:17]
           └── projections
                └── (b:10 + c:11) + 1 [as=d_comp:18]

# Return values from aliased table.
build
UPDATE abcde AS foo SET a=2 WHERE a=1 RETURNING foo.a+1, foo.b * foo.d
----
project
 ├── columns: "?column?":19!null "?column?":20
 ├── update abcde [as=foo]
 │    ├── columns: a:1!null b:2 c:3 d:4 e:5!null rowid:6!null
 │    ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 │    ├── update-mapping:
 │    │    ├── a_new:17 => a:1
 │    │    └── a_new:17 => e:5
 │    ├── return-mapping:
 │    │    ├── a_new:17 => a:1
 │    │    ├── b:10 => b:2
 │    │    ├── c:11 => c:3
 │    │    ├── d:12 => d:4
 │    │    ├── a_new:17 => e:5
 │    │    └── rowid:14 => rowid:6
 │    └── project
 │         ├── columns: d_comp:18 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17!null
 │         ├── project
 │         │    ├── columns: a_new:17!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
 │         │    ├── select
 │         │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
 │         │    │    ├── scan abcde [as=foo]
 │         │    │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
 │         │    │    │    ├── computed column expressions
 │         │    │    │    │    ├── d:12
 │         │    │    │    │    │    └── (b:10 + c:11) + 1
 │         │    │    │    │    └── e:13
 │         │    │    │    │         └── a:9
 │         │    │    │    └── flags: avoid-full-scan
 │         │    │    └── filters
 │         │    │         └── a:9 = 1
 │         │    └── projections
 │         │         └── 2 [as=a_new:17]
 │         └── projections
 │              └── (b:10 + c:11) + 1 [as=d_comp:18]
 └── projections
      ├── a:1 + 1 [as="?column?":19]
      └── b:2 * d:4 [as="?column?":20]

# Use returning UPDATE as a FROM expression.
build
SELECT a, d FROM [UPDATE abcde SET a=2 WHERE a>0 ORDER BY b LIMIT 10 RETURNING *]
----
with &1
 ├── columns: a:19!null d:22
 ├── project
 │    ├── columns: abcde.a:1!null abcde.b:2 abcde.c:3 abcde.d:4 abcde.e:5!null
 │    └── update abcde
 │         ├── columns: abcde.a:1!null abcde.b:2 abcde.c:3 abcde.d:4 abcde.e:5!null rowid:6!null
 │         ├── fetch columns: abcde.a:9 abcde.b:10 abcde.c:11 abcde.d:12 abcde.e:13 rowid:14
 │         ├── update-mapping:
 │         │    ├── a_new:17 => abcde.a:1
 │         │    └── a_new:17 => abcde.e:5
 │         ├── return-mapping:
 │         │    ├── a_new:17 => abcde.a:1
 │         │    ├── abcde.b:10 => abcde.b:2
 │         │    ├── abcde.c:11 => abcde.c:3
 │         │    ├── abcde.d:12 => abcde.d:4
 │         │    ├── a_new:17 => abcde.e:5
 │         │    └── rowid:14 => rowid:6
 │         └── project
 │              ├── columns: d_comp:18 abcde.a:9!null abcde.b:10 abcde.c:11 abcde.d:12 abcde.e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17!null
 │              ├── project
 │              │    ├── columns: a_new:17!null abcde.a:9!null abcde.b:10 abcde.c:11 abcde.d:12 abcde.e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
 │              │    ├── limit
 │              │    │    ├── columns: abcde.a:9!null abcde.b:10 abcde.c:11 abcde.d:12 abcde.e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
 │              │    │    ├── internal-ordering: +10
 │              │    │    ├── sort
 │              │    │    │    ├── columns: abcde.a:9!null abcde.b:10 abcde.c:11 abcde.d:12 abcde.e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
 │              │    │    │    ├── ordering: +10
 │              │    │    │    ├── limit hint: 10.00
 │              │    │    │    └── select
 │              │    │    │         ├── columns: abcde.a:9!null abcde.b:10 abcde.c:11 abcde.d:12 abcde.e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
 │              │    │    │         ├── scan abcde
 │              │    │    │         │    ├── columns: abcde.a:9!null abcde.b:10 abcde.c:11 abcde.d:12 abcde.e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
 │              │    │    │         │    ├── computed column expressions
 │              │    │    │         │    │    ├── abcde.d:12
 │              │    │    │         │    │    │    └── (abcde.b:10 + abcde.c:11) + 1
 │              │    │    │         │    │    └── abcde.e:13
 │              │    │    │         │    │         └── abcde.a:9
 │              │    │    │         │    └── flags: avoid-full-scan
 │              │    │    │         └── filters
 │              │    │    │              └── abcde.a:9 > 0
 │              │    │    └── 10
 │              │    └── projections
 │              │         └── 2 [as=a_new:17]
 │              └── projections
 │                   └── (abcde.b:10 + abcde.c:11) + 1 [as=d_comp:18]
 └── project
      ├── columns: a:19!null d:22
      └── with-scan &1
           ├── columns: a:19!null b:20 c:21 d:22 e:23!null
           └── mapping:
                ├──  abcde.a:1 => a:19
                ├──  abcde.b:2 => b:20
                ├──  abcde.c:3 => c:21
                ├──  abcde.d:4 => d:22
                └──  abcde.e:5 => e:23

# Return hidden column.
build
UPDATE abcde SET rowid=rowid+1 RETURNING rowid
----
project
 ├── columns: rowid:6!null
 └── update abcde
      ├── columns: a:1!null b:2 c:3 d:4 e:5 rowid:6!null
      ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
      ├── update-mapping:
      │    └── rowid_new:17 => rowid:6
      ├── return-mapping:
      │    ├── a:9 => a:1
      │    ├── b:10 => b:2
      │    ├── c:11 => c:3
      │    ├── d:12 => d:4
      │    ├── e:13 => e:5
      │    └── rowid_new:17 => rowid:6
      └── project
           ├── columns: d_comp:18 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 rowid_new:17!null
           ├── project
           │    ├── columns: rowid_new:17!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
           │    ├── scan abcde
           │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
           │    │    ├── computed column expressions
           │    │    │    ├── d:12
           │    │    │    │    └── (b:10 + c:11) + 1
           │    │    │    └── e:13
           │    │    │         └── a:9
           │    │    └── flags: avoid-full-scan
           │    └── projections
           │         └── rowid:14 + 1 [as=rowid_new:17]
           └── projections
                └── (b:10 + c:11) + 1 [as=d_comp:18]

# Try to use aggregate function in RETURNING clause.
build
UPDATE abcde SET b=1 RETURNING sum(a)
----
error (42803): sum(): aggregate functions are not allowed in RETURNING

# Try to use SRF in RETURNING clause.
build
UPDATE abcde SET c=1 RETURNING generate_series(1, 10)
----
error (0A000): generate_series(): set-returning functions are not allowed in RETURNING

# ------------------------------------------------------------------------------
# Test DEFAULT values.
# ------------------------------------------------------------------------------

# Use DEFAULT expressions in RHS of SET expressions.
build
UPDATE abcde SET b=DEFAULT, c=DEFAULT
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── b_new:17 => b:2
 │    ├── c_new:18 => c:3
 │    └── d_comp:19 => d:4
 └── project
      ├── columns: d_comp:19 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 b_new:17 c_new:18!null
      ├── project
      │    ├── columns: b_new:17 c_new:18!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         ├── NULL::INT8 [as=b_new:17]
      │         └── 10 [as=c_new:18]
      └── projections
           └── (b_new:17 + c_new:18) + 1 [as=d_comp:19]

# Allow not-null column to be updated with NULL DEFAULT value (would fail at
# runtime if there are any rows to update).
build
UPDATE abcde SET a=DEFAULT
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:17 => a:1
 │    └── a_new:17 => e:5
 └── project
      ├── columns: d_comp:18 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17
      ├── project
      │    ├── columns: a_new:17 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         └── NULL::INT8 [as=a_new:17]
      └── projections
           └── (b:10 + c:11) + 1 [as=d_comp:18]

build
UPDATE abcde SET c=1+DEFAULT
----
error (42601): DEFAULT can only appear in a VALUES list within INSERT or on the right side of a SET

# ------------------------------------------------------------------------------
# Test tuples.
# ------------------------------------------------------------------------------

build
UPDATE abcde SET (a, b, c) = (1, 2, 3)
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:17 => a:1
 │    ├── b_new:18 => b:2
 │    ├── c_new:19 => c:3
 │    ├── d_comp:20 => d:4
 │    └── a_new:17 => e:5
 └── project
      ├── columns: d_comp:20!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17!null b_new:18!null c_new:19!null
      ├── project
      │    ├── columns: a_new:17!null b_new:18!null c_new:19!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         ├── 1 [as=a_new:17]
      │         ├── 2 [as=b_new:18]
      │         └── 3 [as=c_new:19]
      └── projections
           └── (b_new:18 + c_new:19) + 1 [as=d_comp:20]

build
UPDATE abcde SET (c) = (NULL), (b, a) = (1, 2)
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:19 => a:1
 │    ├── b_new:18 => b:2
 │    ├── c_new:17 => c:3
 │    ├── d_comp:20 => d:4
 │    └── a_new:19 => e:5
 └── project
      ├── columns: d_comp:20 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 c_new:17 b_new:18!null a_new:19!null
      ├── project
      │    ├── columns: c_new:17 b_new:18!null a_new:19!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         ├── NULL::INT8 [as=c_new:17]
      │         ├── 1 [as=b_new:18]
      │         └── 2 [as=a_new:19]
      └── projections
           └── (b_new:18 + c_new:17) + 1 [as=d_comp:20]

# Tuples + DEFAULT.
build
UPDATE abcde SET (b, c)=(DEFAULT, DEFAULT)
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── b_new:17 => b:2
 │    ├── c_new:18 => c:3
 │    └── d_comp:19 => d:4
 └── project
      ├── columns: d_comp:19 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 b_new:17 c_new:18!null
      ├── project
      │    ├── columns: b_new:17 c_new:18!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         ├── NULL::INT8 [as=b_new:17]
      │         └── 10 [as=c_new:18]
      └── projections
           └── (b_new:17 + c_new:18) + 1 [as=d_comp:19]

# Tuples + non-null DEFAULT.
build
UPDATE abcde SET (a, b)=(DEFAULT, DEFAULT)
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:17 => a:1
 │    ├── a_new:17 => b:2
 │    ├── d_comp:18 => d:4
 │    └── a_new:17 => e:5
 └── project
      ├── columns: d_comp:18 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 a_new:17
      ├── project
      │    ├── columns: a_new:17 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         └── NULL::INT8 [as=a_new:17]
      └── projections
           └── (a_new:17 + c:11) + 1 [as=d_comp:18]

build
UPDATE abcde SET (a, b)=(1, 2, 3)
----
error (42601): number of columns (2) does not match number of values (3)

build
UPDATE abcde SET (a, b, a)=(1, 2, 3)
----
error (42601): multiple assignments to the same column "a"

build
UPDATE abcde SET (a, unk)=(1, 2)
----
error (42703): column "unk" does not exist

build
UPDATE abcde SET (a, d)=(1, 2)
----
error (55000): cannot write directly to computed column "d"

# ------------------------------------------------------------------------------
# Test subqueries.
# ------------------------------------------------------------------------------

# Update single column.
build
UPDATE abcde SET (a)=(SELECT 1 AS one)
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── one:17 => a:1
 │    └── one:17 => e:5
 └── project
      ├── columns: d_comp:18 a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 one:17
      ├── left-join-apply
      │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16 one:17
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null crdb_internal_mvcc_timestamp:15 tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    ├── max1-row
      │    │    ├── columns: one:17!null
      │    │    └── project
      │    │         ├── columns: one:17!null
      │    │         ├── values
      │    │         │    └── ()
      │    │         └── projections
      │    │              └── 1 [as=one:17]
      │    └── filters (true)
      └── projections
           └── (b:10 + c:11) + 1 [as=d_comp:18]

# Update all updatable columns.
build
UPDATE abcde SET (a, b, c, rowid)=(SELECT x::int, y, z::int, y+1 AS y1 FROM xyz)
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── x:22 => a:1
 │    ├── y:18 => b:2
 │    ├── z:23 => c:3
 │    ├── d_comp:25 => d:4
 │    ├── x:22 => e:5
 │    └── y1:24 => rowid:6
 └── project
      ├── columns: d_comp:25 a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 x:22 z:23 y1:24
      ├── left-join-apply
      │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 x:22 z:23 y1:24
      │    ├── scan abcde
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16
      │    │    ├── computed column expressions
      │    │    │    ├── d:12
      │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    └── e:13
      │    │    │         └── a:9
      │    │    └── flags: avoid-full-scan
      │    ├── max1-row
      │    │    ├── columns: y:18 x:22!null z:23 y1:24
      │    │    └── project
      │    │         ├── columns: x:22!null z:23 y1:24 y:18
      │    │         ├── scan xyz
      │    │         │    └── columns: xyz.x:17!null y:18 xyz.z:19 xyz.crdb_internal_mvcc_timestamp:20 xyz.tableoid:21
      │    │         └── projections
      │    │              ├── xyz.x:17::INT8 [as=x:22]
      │    │              ├── xyz.z:19::INT8 [as=z:23]
      │    │              └── y:18 + 1 [as=y1:24]
      │    └── filters (true)
      └── projections
           └── (y:18 + z:23) + 1 [as=d_comp:25]

# Update using combination of subquery and tuple SET expressions.
build
UPDATE abcde SET (a, b)=(SELECT y, y+1 AS y1 FROM xyz), (c, rowid)=(1, 2)
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── y:18 => a:1
 │    ├── y1:22 => b:2
 │    ├── c_new:23 => c:3
 │    ├── d_comp:25 => d:4
 │    ├── y:18 => e:5
 │    └── rowid_new:24 => rowid:6
 └── project
      ├── columns: d_comp:25 a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 y1:22 c_new:23!null rowid_new:24!null
      ├── project
      │    ├── columns: c_new:23!null rowid_new:24!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 y1:22
      │    ├── left-join-apply
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 y1:22
      │    │    ├── scan abcde
      │    │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16
      │    │    │    ├── computed column expressions
      │    │    │    │    ├── d:12
      │    │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    │    └── e:13
      │    │    │    │         └── a:9
      │    │    │    └── flags: avoid-full-scan
      │    │    ├── max1-row
      │    │    │    ├── columns: y:18 y1:22
      │    │    │    └── project
      │    │    │         ├── columns: y1:22 y:18
      │    │    │         ├── scan xyz
      │    │    │         │    └── columns: x:17!null y:18 z:19 xyz.crdb_internal_mvcc_timestamp:20 xyz.tableoid:21
      │    │    │         └── projections
      │    │    │              └── y:18 + 1 [as=y1:22]
      │    │    └── filters (true)
      │    └── projections
      │         ├── 1 [as=c_new:23]
      │         └── 2 [as=rowid_new:24]
      └── projections
           └── (y1:22 + c_new:23) + 1 [as=d_comp:25]

# Use subquery SET expression after other expressions.
build
UPDATE abcde SET a=1, (b)=(2), (c, rowid)=(SELECT y, y+1 AS y1 FROM xyz)
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── a_new:23 => a:1
 │    ├── b_new:24 => b:2
 │    ├── y:18 => c:3
 │    ├── d_comp:25 => d:4
 │    ├── a_new:23 => e:5
 │    └── y1:22 => rowid:6
 └── project
      ├── columns: d_comp:25 a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 y1:22 a_new:23!null b_new:24!null
      ├── project
      │    ├── columns: a_new:23!null b_new:24!null a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 y1:22
      │    ├── left-join-apply
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 y1:22
      │    │    ├── scan abcde
      │    │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16
      │    │    │    ├── computed column expressions
      │    │    │    │    ├── d:12
      │    │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    │    └── e:13
      │    │    │    │         └── a:9
      │    │    │    └── flags: avoid-full-scan
      │    │    ├── max1-row
      │    │    │    ├── columns: y:18 y1:22
      │    │    │    └── project
      │    │    │         ├── columns: y1:22 y:18
      │    │    │         ├── scan xyz
      │    │    │         │    └── columns: x:17!null y:18 z:19 xyz.crdb_internal_mvcc_timestamp:20 xyz.tableoid:21
      │    │    │         └── projections
      │    │    │              └── y:18 + 1 [as=y1:22]
      │    │    └── filters (true)
      │    └── projections
      │         ├── 1 [as=a_new:23]
      │         └── 2 [as=b_new:24]
      └── projections
           └── (b_new:24 + y:18) + 1 [as=d_comp:25]

# Multiple subqueries in SET expressions.
build
UPDATE abcde SET (b, a)=(SELECT y, y+1 AS y1 FROM xyz), (c, rowid)=(SELECT 1 AS one, 2 AS two)
----
update abcde
 ├── columns: <none>
 ├── fetch columns: a:9 b:10 c:11 d:12 e:13 rowid:14
 ├── update-mapping:
 │    ├── y1:22 => a:1
 │    ├── y:18 => b:2
 │    ├── one:23 => c:3
 │    ├── d_comp:25 => d:4
 │    ├── y1:22 => e:5
 │    └── two:24 => rowid:6
 └── project
      ├── columns: d_comp:25 a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 y1:22 one:23 two:24
      ├── left-join-apply
      │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 y1:22 one:23 two:24
      │    ├── left-join-apply
      │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16 y:18 y1:22
      │    │    ├── scan abcde
      │    │    │    ├── columns: a:9!null b:10 c:11 d:12 e:13 rowid:14!null abcde.crdb_internal_mvcc_timestamp:15 abcde.tableoid:16
      │    │    │    ├── computed column expressions
      │    │    │    │    ├── d:12
      │    │    │    │    │    └── (b:10 + c:11) + 1
      │    │    │    │    └── e:13
      │    │    │    │         └── a:9
      │    │    │    └── flags: avoid-full-scan
      │    │    ├── max1-row
      │    │    │    ├── columns: y:18 y1:22
      │    │    │    └── project
      │    │    │         ├── columns: y1:22 y:18
      │    │    │         ├── scan xyz
      │    │    │         │    └── columns: x:17!null y:18 z:19 xyz.crdb_internal_mvcc_timestamp:20 xyz.tableoid:21
      │    │    │         └── projections
      │    │    │              └── y:18 + 1 [as=y1:22]
      │    │    └── filters (true)
      │    ├── max1-row
      │    │    ├── columns: one:23!null two:24!null
      │    │    └── project
      │    │         ├── columns: one:23!null two:24!null
      │    │         ├── values
      │    │         │    └── ()
      │    │         └── projections
      │    │              ├── 1 [as=one:23]
      │    │              └── 2 [as=two:24]
      │    └── filters (true)
      └── projections
           └── (y:18 + one:23) + 1 [as=d_comp:25]

# Incorporate desired types when compiling subquery.
build
UPDATE xyz SET x='foo', (z, y)=(SELECT 2 AS two, 3 AS three)
----
update xyz
 ├── columns: <none>
 ├── fetch columns: x:6 y:7 z:8
 ├── update-mapping:
 │    ├── x_new:13 => x:1
 │    ├── three:12 => y:2
 │    └── two:11 => z:3
 └── project
      ├── columns: x_new:13!null x:6!null y:7 z:8 crdb_internal_mvcc_timestamp:9 tableoid:10 two:11 three:12
      ├── left-join-apply
      │    ├── columns: x:6!null y:7 z:8 crdb_internal_mvcc_timestamp:9 tableoid:10 two:11 three:12
      │    ├── scan xyz
      │    │    ├── columns: x:6!null y:7 z:8 crdb_internal_mvcc_timestamp:9 tableoid:10
      │    │    └── flags: avoid-full-scan
      │    ├── max1-row
      │    │    ├── columns: two:11!null three:12!null
      │    │    └── project
      │    │         ├── columns: two:11!null three:12!null
      │    │         ├── values
      │    │         │    └── ()
      │    │         └── projections
      │    │              ├── 2.0 [as=two:11]
      │    │              └── 3 [as=three:12]
      │    └── filters (true)
      └── projections
           └── 'foo' [as=x_new:13]

# SET expression contains correlated subquery + alias.
build
UPDATE abcde AS abcde1 SET b=(SELECT b FROM abcde AS abcde2 WHERE abcde2.rowid=abcde1.a) RETURNING *
----
project
 ├── columns: a:1!null b:2 c:3 d:4 e:5
 └── update abcde [as=abcde1]
      ├── columns: abcde1.a:1!null abcde1.b:2 abcde1.c:3 abcde1.d:4 abcde1.e:5 abcde1.rowid:6!null
      ├── fetch columns: abcde1.a:9 abcde1.b:10 abcde1.c:11 abcde1.d:12 abcde1.e:13 abcde1.rowid:14
      ├── update-mapping:
      │    ├── b_new:25 => abcde1.b:2
      │    └── d_comp:26 => abcde1.d:4
      ├── return-mapping:
      │    ├── abcde1.a:9 => abcde1.a:1
      │    ├── b_new:25 => abcde1.b:2
      │    ├── abcde1.c:11 => abcde1.c:3
      │    ├── d_comp:26 => abcde1.d:4
      │    ├── abcde1.e:13 => abcde1.e:5
      │    └── abcde1.rowid:14 => abcde1.rowid:6
      └── project
           ├── columns: d_comp:26 abcde1.a:9!null abcde1.b:10 abcde1.c:11 abcde1.d:12 abcde1.e:13 abcde1.rowid:14!null abcde1.crdb_internal_mvcc_timestamp:15 abcde1.tableoid:16 b_new:25
           ├── project
           │    ├── columns: b_new:25 abcde1.a:9!null abcde1.b:10 abcde1.c:11 abcde1.d:12 abcde1.e:13 abcde1.rowid:14!null abcde1.crdb_internal_mvcc_timestamp:15 abcde1.tableoid:16
           │    ├── scan abcde [as=abcde1]
           │    │    ├── columns: abcde1.a:9!null abcde1.b:10 abcde1.c:11 abcde1.d:12 abcde1.e:13 abcde1.rowid:14!null abcde1.crdb_internal_mvcc_timestamp:15 abcde1.tableoid:16
           │    │    ├── computed column expressions
           │    │    │    ├── abcde1.d:12
           │    │    │    │    └── (abcde1.b:10 + abcde1.c:11) + 1
           │    │    │    └── abcde1.e:13
           │    │    │         └── abcde1.a:9
           │    │    └── flags: avoid-full-scan
           │    └── projections
           │         └── subquery [as=b_new:25]
           │              └── max1-row
           │                   ├── columns: abcde2.b:18
           │                   └── project
           │                        ├── columns: abcde2.b:18
           │                        └── select
           │                             ├── columns: abcde2.a:17!null abcde2.b:18 abcde2.c:19 abcde2.d:20 abcde2.e:21 abcde2.rowid:22!null abcde2.crdb_internal_mvcc_timestamp:23 abcde2.tableoid:24
           │                             ├── scan abcde [as=abcde2]
           │                             │    ├── columns: abcde2.a:17!null abcde2.b:18 abcde2.c:19 abcde2.d:20 abcde2.e:21 abcde2.rowid:22!null abcde2.crdb_internal_mvcc_timestamp:23 abcde2.tableoid:24
           │                             │    └── computed column expressions
           │                             │         ├── abcde2.d:20
           │                             │         │    └── (abcde2.b:18 + abcde2.c:19) + 1
           │                             │         └── abcde2.e:21
           │                             │              └── abcde2.a:17
           │                             └── filters
           │                                  └── abcde2.rowid:22 = abcde1.a:9
           └── projections
                └── (b_new:25 + abcde1.c:11) + 1 [as=d_comp:26]

# Too many values.
build
UPDATE abcde SET (a, b)=(SELECT y, y+1 AS y1, y+2 AS y2 FROM xyz)
----
error (42601): number of columns (2) does not match number of values (3)

# Too few values.
build
UPDATE abcde SET (a, b, c)=(SELECT y, y+1 AS y1 FROM xyz)
----
error (42601): number of columns (3) does not match number of values (2)

# Try to update same column.
build
UPDATE abcde SET (a, b)=(1, 2), (c, b)=(SELECT y, y+1 AS y1 FROM xyz)
----
error (42601): multiple assignments to the same column "b"

# Target type does not match subquery result.
build
UPDATE abcde SET (a, b)=(SELECT x, y FROM xyz WHERE y>0)
----
error (42804): value type string doesn't match type int of column "a"

# ------------------------------------------------------------------------------
# Test CTEs.
# ------------------------------------------------------------------------------

# Use CTE within WHERE clause.
build
WITH cte AS (SELECT x FROM xyz) UPDATE abcde SET a=b WHERE EXISTS(SELECT * FROM cte)
----
with &1 (cte)
 ├── project
 │    ├── columns: xyz.x:1!null
 │    └── scan xyz
 │         └── columns: xyz.x:1!null y:2 z:3 xyz.crdb_internal_mvcc_timestamp:4 xyz.tableoid:5
 └── update abcde
      ├── columns: <none>
      ├── fetch columns: a:14 b:15 c:16 d:17 e:18 rowid:19
      ├── update-mapping:
      │    ├── b:15 => a:6
      │    ├── d_comp:24 => d:9
      │    └── b:15 => e:10
      └── project
           ├── columns: d_comp:24 a:14!null b:15 c:16 d:17 e:18 rowid:19!null abcde.crdb_internal_mvcc_timestamp:20 abcde.tableoid:21
           ├── select
           │    ├── columns: a:14!null b:15 c:16 d:17 e:18 rowid:19!null abcde.crdb_internal_mvcc_timestamp:20 abcde.tableoid:21
           │    ├── scan abcde
           │    │    ├── columns: a:14!null b:15 c:16 d:17 e:18 rowid:19!null abcde.crdb_internal_mvcc_timestamp:20 abcde.tableoid:21
           │    │    ├── computed column expressions
           │    │    │    ├── d:17
           │    │    │    │    └── (b:15 + c:16) + 1
           │    │    │    └── e:18
           │    │    │         └── a:14
           │    │    └── flags: avoid-full-scan
           │    └── filters
           │         └── exists
           │              └── with-scan &1 (cte)
           │                   ├── columns: x:22!null
           │                   └── mapping:
           │                        └──  xyz.x:1 => x:22
           └── projections
                └── (b:15 + c:16) + 1 [as=d_comp:24]

# Use CTE within SET expression.
build
WITH a AS (SELECT y, y+1 AS y1 FROM xyz) UPDATE abcde SET (a, b) = (SELECT * FROM a)
----
with &1 (a)
 ├── project
 │    ├── columns: y1:6 xyz.y:2
 │    ├── scan xyz
 │    │    └── columns: x:1!null xyz.y:2 z:3 xyz.crdb_internal_mvcc_timestamp:4 xyz.tableoid:5
 │    └── projections
 │         └── xyz.y:2 + 1 [as=y1:6]
 └── update abcde
      ├── columns: <none>
      ├── fetch columns: a:15 b:16 c:17 d:18 e:19 rowid:20
      ├── update-mapping:
      │    ├── y:23 => a:7
      │    ├── y1:24 => b:8
      │    ├── d_comp:25 => d:10
      │    └── y:23 => e:11
      └── project
           ├── columns: d_comp:25 a:15!null b:16 c:17 d:18 e:19 rowid:20!null abcde.crdb_internal_mvcc_timestamp:21 abcde.tableoid:22 y:23 y1:24
           ├── left-join-apply
           │    ├── columns: a:15!null b:16 c:17 d:18 e:19 rowid:20!null abcde.crdb_internal_mvcc_timestamp:21 abcde.tableoid:22 y:23 y1:24
           │    ├── scan abcde
           │    │    ├── columns: a:15!null b:16 c:17 d:18 e:19 rowid:20!null abcde.crdb_internal_mvcc_timestamp:21 abcde.tableoid:22
           │    │    ├── computed column expressions
           │    │    │    ├── d:18
           │    │    │    │    └── (b:16 + c:17) + 1
           │    │    │    └── e:19
           │    │    │         └── a:15
           │    │    └── flags: avoid-full-scan
           │    ├── max1-row
           │    │    ├── columns: y:23 y1:24
           │    │    └── with-scan &1 (a)
           │    │         ├── columns: y:23 y1:24
           │    │         └── mapping:
           │    │              ├──  xyz.y:2 => y:23
           │    │              └──  y1:6 => y1:24
           │    └── filters (true)
           └── projections
                └── (y1:24 + c:17) + 1 [as=d_comp:25]

# ------------------------------------------------------------------------------
# Tests with mutations.
# ------------------------------------------------------------------------------

# Mutation columns should be updated.
build
UPDATE mutation SET m=1
----
update mutation
 ├── columns: <none>
 ├── fetch columns: m:8 n:9 o:10 p:11 q:12
 ├── update-mapping:
 │    ├── m_new:15 => m:1
 │    ├── o_default:16 => o:3
 │    └── p_comp:17 => p:4
 ├── check columns: check1:18
 └── project
      ├── columns: check1:18!null m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14 m_new:15!null o_default:16!null p_comp:17
      ├── project
      │    ├── columns: p_comp:17 m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14 m_new:15!null o_default:16!null
      │    ├── project
      │    │    ├── columns: o_default:16!null m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14 m_new:15!null
      │    │    ├── project
      │    │    │    ├── columns: m_new:15!null m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    │    ├── scan mutation
      │    │    │    │    ├── columns: m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    │    │    ├── check constraint expressions
      │    │    │    │    │    └── m:8 > 0
      │    │    │    │    └── flags: avoid-full-scan
      │    │    │    └── projections
      │    │    │         └── 1 [as=m_new:15]
      │    │    └── projections
      │    │         └── 10 [as=o_default:16]
      │    └── projections
      │         └── o_default:16 + n:9 [as=p_comp:17]
      └── projections
           └── m_new:15 > 0 [as=check1:18]

# Update column that mutation column depends upon.
build
UPDATE mutation SET m=1, n=2
----
update mutation
 ├── columns: <none>
 ├── fetch columns: m:8 n:9 o:10 p:11 q:12
 ├── update-mapping:
 │    ├── m_new:15 => m:1
 │    ├── n_new:16 => n:2
 │    ├── o_default:17 => o:3
 │    └── p_comp:18 => p:4
 ├── check columns: check1:19
 └── project
      ├── columns: check1:19!null m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14 m_new:15!null n_new:16!null o_default:17!null p_comp:18!null
      ├── project
      │    ├── columns: p_comp:18!null m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14 m_new:15!null n_new:16!null o_default:17!null
      │    ├── project
      │    │    ├── columns: o_default:17!null m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14 m_new:15!null n_new:16!null
      │    │    ├── project
      │    │    │    ├── columns: m_new:15!null n_new:16!null m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    │    ├── scan mutation
      │    │    │    │    ├── columns: m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    │    │    ├── check constraint expressions
      │    │    │    │    │    └── m:8 > 0
      │    │    │    │    └── flags: avoid-full-scan
      │    │    │    └── projections
      │    │    │         ├── 1 [as=m_new:15]
      │    │    │         └── 2 [as=n_new:16]
      │    │    └── projections
      │    │         └── 10 [as=o_default:17]
      │    └── projections
      │         └── o_default:17 + n_new:16 [as=p_comp:18]
      └── projections
           └── m_new:15 > 0 [as=check1:19]

# Ensure that ORDER BY wildcard does not select mutation columns.
build
UPDATE mutation SET m=1 ORDER BY mutation.* LIMIT 10
----
update mutation
 ├── columns: <none>
 ├── fetch columns: m:8 n:9 o:10 p:11 q:12
 ├── update-mapping:
 │    ├── m_new:15 => m:1
 │    ├── o_default:16 => o:3
 │    └── p_comp:17 => p:4
 ├── check columns: check1:18
 └── project
      ├── columns: check1:18!null m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14 m_new:15!null o_default:16!null p_comp:17
      ├── project
      │    ├── columns: p_comp:17 m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14 m_new:15!null o_default:16!null
      │    ├── project
      │    │    ├── columns: o_default:16!null m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14 m_new:15!null
      │    │    ├── project
      │    │    │    ├── columns: m_new:15!null m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    │    ├── limit
      │    │    │    │    ├── columns: m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    │    │    ├── internal-ordering: +8,+9
      │    │    │    │    ├── sort (segmented)
      │    │    │    │    │    ├── columns: m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    │    │    │    ├── ordering: +8,+9
      │    │    │    │    │    ├── limit hint: 10.00
      │    │    │    │    │    └── scan mutation
      │    │    │    │    │         ├── columns: m:8!null n:9 o:10 p:11 q:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    │    │    │         ├── check constraint expressions
      │    │    │    │    │         │    └── m:8 > 0
      │    │    │    │    │         ├── flags: avoid-full-scan
      │    │    │    │    │         └── ordering: +8
      │    │    │    │    └── 10
      │    │    │    └── projections
      │    │    │         └── 1 [as=m_new:15]
      │    │    └── projections
      │    │         └── 10 [as=o_default:16]
      │    └── projections
      │         └── o_default:16 + n:9 [as=p_comp:17]
      └── projections
           └── m_new:15 > 0 [as=check1:18]

# Try to return a mutation column.
build
UPDATE mutation SET m=1 RETURNING o
----
error (42703): column "o" does not exist

# Try to update a mutation column.
build
UPDATE mutation SET o=10
----
error (42703): column "o" does not exist

# Try to use mutation column in WHERE clause.
build
UPDATE mutation SET m=1 WHERE o=10
----
error (42P10): column "o" is being backfilled

# Try to use mutation column in SET expression.
build
UPDATE mutation SET m=o
----
error (42P10): column "o" is being backfilled

# Try to use mutation column in ORDER BY expression.
build
UPDATE mutation SET m=1 ORDER BY o LIMIT 2
----
error (42P10): column "o" is being backfilled

# ------------------------------------------------------------------------------
# Test check constraints
# ------------------------------------------------------------------------------

# Update all columns to be constant.
build
UPDATE checks SET a=1, b=2, c=3
----
update checks
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 d:10
 ├── update-mapping:
 │    ├── a_new:13 => a:1
 │    ├── b_new:14 => b:2
 │    ├── c_new:15 => c:3
 │    └── d_comp:16 => d:4
 ├── check columns: check1:17 check2:18
 └── project
      ├── columns: check1:17!null check2:18!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_new:13!null b_new:14!null c_new:15!null d_comp:16!null
      ├── project
      │    ├── columns: d_comp:16!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_new:13!null b_new:14!null c_new:15!null
      │    ├── project
      │    │    ├── columns: a_new:13!null b_new:14!null c_new:15!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    ├── scan checks
      │    │    │    ├── columns: a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    ├── check constraint expressions
      │    │    │    │    └── a:7 > 0
      │    │    │    ├── computed column expressions
      │    │    │    │    └── d:10
      │    │    │    │         └── c:9 + 1
      │    │    │    └── flags: avoid-full-scan
      │    │    └── projections
      │    │         ├── 1 [as=a_new:13]
      │    │         ├── 2 [as=b_new:14]
      │    │         └── 3 [as=c_new:15]
      │    └── projections
      │         └── c_new:15 + 1 [as=d_comp:16]
      └── projections
           ├── b_new:14 < d_comp:16 [as=check1:17]
           └── a_new:13 > 0 [as=check2:18]

# Do not update columns for one of the constraints.
build
UPDATE checks SET a=1
----
update checks
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 d:10
 ├── update-mapping:
 │    └── a_new:13 => a:1
 ├── check columns: check2:16
 └── project
      ├── columns: check1:15 check2:16!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_new:13!null d_comp:14
      ├── project
      │    ├── columns: d_comp:14 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_new:13!null
      │    ├── project
      │    │    ├── columns: a_new:13!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    ├── scan checks
      │    │    │    ├── columns: a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    ├── check constraint expressions
      │    │    │    │    └── a:7 > 0
      │    │    │    ├── computed column expressions
      │    │    │    │    └── d:10
      │    │    │    │         └── c:9 + 1
      │    │    │    └── flags: avoid-full-scan
      │    │    └── projections
      │    │         └── 1 [as=a_new:13]
      │    └── projections
      │         └── c:9 + 1 [as=d_comp:14]
      └── projections
           ├── b:8 < d:10 [as=check1:15]
           └── a_new:13 > 0 [as=check2:16]

# Update one column in constraint, but not the other.
build
UPDATE checks SET b=2
----
update checks
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 d:10
 ├── update-mapping:
 │    └── b_new:13 => b:2
 ├── check columns: check1:15
 └── project
      ├── columns: check1:15 check2:16!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 b_new:13!null d_comp:14
      ├── project
      │    ├── columns: d_comp:14 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 b_new:13!null
      │    ├── project
      │    │    ├── columns: b_new:13!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    ├── scan checks
      │    │    │    ├── columns: a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    ├── check constraint expressions
      │    │    │    │    └── a:7 > 0
      │    │    │    ├── computed column expressions
      │    │    │    │    └── d:10
      │    │    │    │         └── c:9 + 1
      │    │    │    └── flags: avoid-full-scan
      │    │    └── projections
      │    │         └── 2 [as=b_new:13]
      │    └── projections
      │         └── c:9 + 1 [as=d_comp:14]
      └── projections
           ├── b_new:13 < d:10 [as=check1:15]
           └── a:7 > 0 [as=check2:16]

# Update using tuple and subquery.
build
UPDATE checks SET (a, b)=(SELECT a, b FROM abcde WHERE abcde.a=checks.a)
----
update checks
 ├── columns: <none>
 ├── fetch columns: checks.a:7 checks.b:8 checks.c:9 checks.d:10
 ├── update-mapping:
 │    ├── abcde.a:13 => checks.a:1
 │    └── abcde.b:14 => checks.b:2
 ├── check columns: check1:22 check2:23
 └── project
      ├── columns: check1:22 check2:23 checks.a:7!null checks.b:8 checks.c:9 checks.d:10 checks.crdb_internal_mvcc_timestamp:11 checks.tableoid:12 abcde.a:13 abcde.b:14 d_comp:21
      ├── project
      │    ├── columns: d_comp:21 checks.a:7!null checks.b:8 checks.c:9 checks.d:10 checks.crdb_internal_mvcc_timestamp:11 checks.tableoid:12 abcde.a:13 abcde.b:14
      │    ├── left-join-apply
      │    │    ├── columns: checks.a:7!null checks.b:8 checks.c:9 checks.d:10 checks.crdb_internal_mvcc_timestamp:11 checks.tableoid:12 abcde.a:13 abcde.b:14
      │    │    ├── scan checks
      │    │    │    ├── columns: checks.a:7!null checks.b:8 checks.c:9 checks.d:10 checks.crdb_internal_mvcc_timestamp:11 checks.tableoid:12
      │    │    │    ├── check constraint expressions
      │    │    │    │    └── checks.a:7 > 0
      │    │    │    ├── computed column expressions
      │    │    │    │    └── checks.d:10
      │    │    │    │         └── checks.c:9 + 1
      │    │    │    └── flags: avoid-full-scan
      │    │    ├── max1-row
      │    │    │    ├── columns: abcde.a:13!null abcde.b:14
      │    │    │    └── project
      │    │    │         ├── columns: abcde.a:13!null abcde.b:14
      │    │    │         └── select
      │    │    │              ├── columns: abcde.a:13!null abcde.b:14 abcde.c:15 abcde.d:16 e:17 rowid:18!null abcde.crdb_internal_mvcc_timestamp:19 abcde.tableoid:20
      │    │    │              ├── scan abcde
      │    │    │              │    ├── columns: abcde.a:13!null abcde.b:14 abcde.c:15 abcde.d:16 e:17 rowid:18!null abcde.crdb_internal_mvcc_timestamp:19 abcde.tableoid:20
      │    │    │              │    └── computed column expressions
      │    │    │              │         ├── abcde.d:16
      │    │    │              │         │    └── (abcde.b:14 + abcde.c:15) + 1
      │    │    │              │         └── e:17
      │    │    │              │              └── abcde.a:13
      │    │    │              └── filters
      │    │    │                   └── abcde.a:13 = checks.a:7
      │    │    └── filters (true)
      │    └── projections
      │         └── checks.c:9 + 1 [as=d_comp:21]
      └── projections
           ├── abcde.b:14 < checks.d:10 [as=check1:22]
           └── abcde.a:13 > 0 [as=check2:23]

# Test multi-column-family checks under read committed. If a check constraint
# contains multiple column families but only some of them are updated, the
# query should fail under read committed.

exec-ddl
CREATE TABLE multi_col_fam_checks (
  a INT PRIMARY KEY,
  b INT,
  c INT,
  d INT,
  e INT,
  FAMILY (a),
  FAMILY (b, d),
  FAMILY (c, e),
  CHECK (a < b),
  CHECK (c != d)
)
----

# Only a is updated, but b must be read to check the constraint. Should fail
# under read committed.
build isolation=ReadCommitted
UPDATE multi_col_fam_checks SET a = 5
----
error (0A000): unimplemented: multi-column-family check constraints are not yet supported under read committed isolation

# The same query should succeed under serializable isolation.
build isolation=Serializable
UPDATE multi_col_fam_checks SET a = 5
----
update multi_col_fam_checks
 ├── columns: <none>
 ├── fetch columns: a:8 b:9 c:10 d:11 e:12
 ├── update-mapping:
 │    └── a_new:15 => a:1
 ├── check columns: check1:16
 └── project
      ├── columns: check1:16 check2:17 a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14 a_new:15!null
      ├── project
      │    ├── columns: a_new:15!null a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    ├── scan multi_col_fam_checks
      │    │    ├── columns: a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         └── 5 [as=a_new:15]
      └── projections
           ├── a_new:15 < b:9 [as=check1:16]
           └── c:10 != d:11 [as=check2:17]

# Only a is updated, but b is read. Should fail under read committed.
build isolation=ReadCommitted
UPDATE multi_col_fam_checks SET a = 5 WHERE b = 6 AND c = 3
----
error (0A000): unimplemented: multi-column-family check constraints are not yet supported under read committed isolation

# The same query should succeed under serializable isolation.
build isolation=Serializable
UPDATE multi_col_fam_checks SET a = 5 WHERE b = 6 AND c = 3
----
update multi_col_fam_checks
 ├── columns: <none>
 ├── fetch columns: a:8 b:9 c:10 d:11 e:12
 ├── update-mapping:
 │    └── a_new:15 => a:1
 ├── check columns: check1:16
 └── project
      ├── columns: check1:16!null check2:17 a:8!null b:9!null c:10!null d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14 a_new:15!null
      ├── project
      │    ├── columns: a_new:15!null a:8!null b:9!null c:10!null d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    ├── select
      │    │    ├── columns: a:8!null b:9!null c:10!null d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    ├── scan multi_col_fam_checks
      │    │    │    ├── columns: a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    │    └── flags: avoid-full-scan
      │    │    └── filters
      │    │         └── (b:9 = 6) AND (c:10 = 3)
      │    └── projections
      │         └── 5 [as=a_new:15]
      └── projections
           ├── a_new:15 < b:9 [as=check1:16]
           └── c:10 != d:11 [as=check2:17]

# Both a and b are updated, so this should succeed.
build isolation=ReadCommitted
UPDATE multi_col_fam_checks SET a = 5, b = 6
----
update multi_col_fam_checks
 ├── columns: <none>
 ├── fetch columns: a:8 b:9 c:10 d:11 e:12
 ├── update-mapping:
 │    ├── a_new:15 => a:1
 │    └── b_new:16 => b:2
 ├── check columns: check1:17
 └── project
      ├── columns: check1:17!null check2:18 a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14 a_new:15!null b_new:16!null
      ├── project
      │    ├── columns: a_new:15!null b_new:16!null a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    ├── scan multi_col_fam_checks
      │    │    ├── columns: a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         ├── 5 [as=a_new:15]
      │         └── 6 [as=b_new:16]
      └── projections
           ├── a_new:15 < b_new:16 [as=check1:17]
           └── c:10 != d:11 [as=check2:18]

# Both a and b are updated, so this should succeed.
build isolation=ReadCommitted
UPDATE multi_col_fam_checks SET a = 5, b = 6, e = 3
----
update multi_col_fam_checks
 ├── columns: <none>
 ├── fetch columns: a:8 b:9 c:10 d:11 e:12
 ├── update-mapping:
 │    ├── a_new:15 => a:1
 │    ├── b_new:16 => b:2
 │    └── e_new:17 => e:5
 ├── check columns: check1:18
 └── project
      ├── columns: check1:18!null check2:19 a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14 a_new:15!null b_new:16!null e_new:17!null
      ├── project
      │    ├── columns: a_new:15!null b_new:16!null e_new:17!null a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    ├── scan multi_col_fam_checks
      │    │    ├── columns: a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         ├── 5 [as=a_new:15]
      │         ├── 6 [as=b_new:16]
      │         └── 3 [as=e_new:17]
      └── projections
           ├── a_new:15 < b_new:16 [as=check1:18]
           └── c:10 != d:11 [as=check2:19]

# Neither a nor b is updated, so this should succeed.
build isolation=ReadCommitted
UPDATE multi_col_fam_checks SET e = 3 WHERE a = 5
----
update multi_col_fam_checks
 ├── columns: <none>
 ├── fetch columns: a:8 b:9 c:10 d:11 e:12
 ├── update-mapping:
 │    └── e_new:15 => e:5
 └── project
      ├── columns: check1:16 check2:17 a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14 e_new:15!null
      ├── project
      │    ├── columns: e_new:15!null a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    ├── select
      │    │    ├── columns: a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    ├── scan multi_col_fam_checks
      │    │    │    ├── columns: a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    │    └── flags: avoid-full-scan
      │    │    └── filters
      │    │         └── a:8 = 5
      │    └── projections
      │         └── 3 [as=e_new:15]
      └── projections
           ├── a:8 < b:9 [as=check1:16]
           └── c:10 != d:11 [as=check2:17]

# Neither a nor b is updated, so this should succeed.
build isolation=ReadCommitted
UPDATE multi_col_fam_checks SET e = 3
----
update multi_col_fam_checks
 ├── columns: <none>
 ├── fetch columns: a:8 b:9 c:10 d:11 e:12
 ├── update-mapping:
 │    └── e_new:15 => e:5
 └── project
      ├── columns: check1:16 check2:17 a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14 e_new:15!null
      ├── project
      │    ├── columns: e_new:15!null a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    ├── scan multi_col_fam_checks
      │    │    ├── columns: a:8!null b:9 c:10 d:11 e:12 crdb_internal_mvcc_timestamp:13 tableoid:14
      │    │    └── flags: avoid-full-scan
      │    └── projections
      │         └── 3 [as=e_new:15]
      └── projections
           ├── a:8 < b:9 [as=check1:16]
           └── c:10 != d:11 [as=check2:17]

# Test failure due to a different constraint on c and d.
build isolation=ReadCommitted
UPDATE multi_col_fam_checks SET d = 4, e = 5
----
error (0A000): unimplemented: multi-column-family check constraints are not yet supported under read committed isolation

# ------------------------------------------------------------------------------
# Test assignment casts.
# ------------------------------------------------------------------------------

# Test standard update with decimal types that require assignment casts.
build
UPDATE decimals SET a=1.1, b=ARRAY[0.95, NULL, 15::DECIMAL(10, 2)]
----
update decimals
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 d:10
 ├── update-mapping:
 │    ├── a_cast:15 => a:1
 │    ├── b_cast:16 => b:2
 │    └── d_cast:18 => d:4
 ├── check columns: check1:19 check2:20
 └── project
      ├── columns: check1:19 check2:20 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16 d_cast:18
      ├── project
      │    ├── columns: d_cast:18 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16
      │    ├── project
      │    │    ├── columns: d_comp:17 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16
      │    │    ├── project
      │    │    │    ├── columns: a_cast:15!null b_cast:16 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    ├── project
      │    │    │    │    ├── columns: a_new:13!null b_new:14 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    │    ├── scan decimals
      │    │    │    │    │    ├── columns: a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    │    │    ├── computed column expressions
      │    │    │    │    │    │    └── d:10
      │    │    │    │    │    │         └── assignment-cast: DECIMAL(10,1)
      │    │    │    │    │    │              └── a:7 + c:9
      │    │    │    │    │    └── flags: avoid-full-scan
      │    │    │    │    └── projections
      │    │    │    │         ├── 1.1 [as=a_new:13]
      │    │    │    │         └── ARRAY[0.95, NULL, 15::DECIMAL(10,2)] [as=b_new:14]
      │    │    │    └── projections
      │    │    │         ├── assignment-cast: DECIMAL(10) [as=a_cast:15]
      │    │    │         │    └── a_new:13
      │    │    │         └── assignment-cast: DECIMAL(5,1)[] [as=b_cast:16]
      │    │    │              └── b_new:14
      │    │    └── projections
      │    │         └── a_cast:15 + c:9 [as=d_comp:17]
      │    └── projections
      │         └── assignment-cast: DECIMAL(10,1) [as=d_cast:18]
      │              └── d_comp:17
      └── projections
           ├── round(a_cast:15) = a_cast:15 [as=check1:19]
           └── b_cast:16[0] > 1 [as=check2:20]

# Test standard prepared update with decimal types that require assignment
# casts.
assign-placeholders-build query-args=(1.1, (ARRAY[0.95, NULL, 15::DECIMAL(10, 2)]))
UPDATE decimals SET a=$1, b=$2
----
update decimals
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 d:10
 ├── update-mapping:
 │    ├── a_cast:15 => a:1
 │    ├── b_cast:16 => b:2
 │    └── d_cast:18 => d:4
 ├── check columns: check1:19 check2:20
 └── project
      ├── columns: check1:19 check2:20 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16!null d_cast:18
      ├── project
      │    ├── columns: d_cast:18 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16!null
      │    ├── project
      │    │    ├── columns: d_comp:17 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16!null
      │    │    ├── project
      │    │    │    ├── columns: a_cast:15!null b_cast:16!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    ├── project
      │    │    │    │    ├── columns: a_new:13!null b_new:14!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    │    ├── scan decimals
      │    │    │    │    │    ├── columns: a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    │    │    ├── computed column expressions
      │    │    │    │    │    │    └── d:10
      │    │    │    │    │    │         └── assignment-cast: DECIMAL(10,1)
      │    │    │    │    │    │              └── a:7 + c:9
      │    │    │    │    │    └── flags: avoid-full-scan
      │    │    │    │    └── projections
      │    │    │    │         ├── 1.1 [as=a_new:13]
      │    │    │    │         └── ARRAY[0.95,NULL,15.00] [as=b_new:14]
      │    │    │    └── projections
      │    │    │         ├── assignment-cast: DECIMAL(10) [as=a_cast:15]
      │    │    │         │    └── a_new:13
      │    │    │         └── assignment-cast: DECIMAL(5,1)[] [as=b_cast:16]
      │    │    │              └── b_new:14
      │    │    └── projections
      │    │         └── a_cast:15 + c:9 [as=d_comp:17]
      │    └── projections
      │         └── assignment-cast: DECIMAL(10,1) [as=d_cast:18]
      │              └── d_comp:17
      └── projections
           ├── round(a_cast:15) = a_cast:15 [as=check1:19]
           └── b_cast:16[0] > 1 [as=check2:20]

# Test standard update with some types that require assignment casts.
build
UPDATE assn_cast SET c=' ', qc='foo', i='1', s=2
----
update assn_cast
 ├── columns: <none>
 ├── fetch columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16
 ├── update-mapping:
 │    ├── c_cast:23 => c:1
 │    ├── qc_cast:24 => qc:2
 │    ├── i_new:21 => i:3
 │    └── s_cast:25 => s:4
 └── project
      ├── columns: d_comp_comp:26 c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 i_new:21!null c_cast:23!null qc_cast:24!null s_cast:25!null
      ├── project
      │    ├── columns: c_cast:23!null qc_cast:24!null s_cast:25!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 i_new:21!null
      │    ├── project
      │    │    ├── columns: c_new:19!null qc_new:20!null i_new:21!null s_new:22!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    ├── scan assn_cast
      │    │    │    ├── columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    ├── computed column expressions
      │    │    │    │    └── d_comp:15
      │    │    │    │         └── assignment-cast: DECIMAL(10)
      │    │    │    │              └── d:14 + 10.0
      │    │    │    └── flags: avoid-full-scan
      │    │    └── projections
      │    │         ├── '' [as=c_new:19]
      │    │         ├── 'foo' [as=qc_new:20]
      │    │         ├── 1 [as=i_new:21]
      │    │         └── 2 [as=s_new:22]
      │    └── projections
      │         ├── assignment-cast: CHAR [as=c_cast:23]
      │         │    └── c_new:19
      │         ├── assignment-cast: "char" [as=qc_cast:24]
      │         │    └── qc_new:20
      │         └── assignment-cast: STRING [as=s_cast:25]
      │              └── s_new:22
      └── projections
           └── d:14 + 10.0 [as=d_comp_comp:26]

# Test standard prepared update with some types that require assignment casts.
assign-placeholders-build query-args=(' ', 'foo', '1')
UPDATE assn_cast SET c=$1, qc=$2, i=$3
----
update assn_cast
 ├── columns: <none>
 ├── fetch columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16
 ├── update-mapping:
 │    ├── c_cast:22 => c:1
 │    ├── qc_cast:23 => qc:2
 │    └── i_new:21 => i:3
 └── project
      ├── columns: d_comp_comp:24 c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 i_new:21!null c_cast:22!null qc_cast:23!null
      ├── project
      │    ├── columns: c_cast:22!null qc_cast:23!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 i_new:21!null
      │    ├── project
      │    │    ├── columns: c_new:19!null qc_new:20!null i_new:21!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    ├── scan assn_cast
      │    │    │    ├── columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    ├── computed column expressions
      │    │    │    │    └── d_comp:15
      │    │    │    │         └── assignment-cast: DECIMAL(10)
      │    │    │    │              └── d:14 + 10.0
      │    │    │    └── flags: avoid-full-scan
      │    │    └── projections
      │    │         ├── '' [as=c_new:19]
      │    │         ├── 'foo' [as=qc_new:20]
      │    │         └── 1 [as=i_new:21]
      │    └── projections
      │         ├── assignment-cast: CHAR [as=c_cast:22]
      │         │    └── c_new:19
      │         └── assignment-cast: "char" [as=qc_cast:23]
      │              └── qc_new:20
      └── projections
           └── d:14 + 10.0 [as=d_comp_comp:24]

# Test update to DEFAULT that requires an assignment cast.
build
UPDATE assn_cast SET i=DEFAULT
----
update assn_cast
 ├── columns: <none>
 ├── fetch columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16
 ├── update-mapping:
 │    └── i_cast:20 => i:3
 └── project
      ├── columns: d_comp_comp:21 c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 i_cast:20!null
      ├── project
      │    ├── columns: i_cast:20!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    ├── project
      │    │    ├── columns: i_new:19!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    ├── scan assn_cast
      │    │    │    ├── columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    ├── computed column expressions
      │    │    │    │    └── d_comp:15
      │    │    │    │         └── assignment-cast: DECIMAL(10)
      │    │    │    │              └── d:14 + 10.0
      │    │    │    └── flags: avoid-full-scan
      │    │    └── projections
      │    │         └── 10::INT2 [as=i_new:19]
      │    └── projections
      │         └── assignment-cast: INT8 [as=i_cast:20]
      │              └── i_new:19
      └── projections
           └── d:14 + 10.0 [as=d_comp_comp:21]

# Test update to a column that requires an assignment cast and a computed column
# that depends on the new value.
build
UPDATE assn_cast SET d=1.45::DECIMAL(10, 2)
----
update assn_cast
 ├── columns: <none>
 ├── fetch columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16
 ├── update-mapping:
 │    ├── d_cast:20 => d:5
 │    └── d_comp_cast:22 => d_comp:6
 └── project
      ├── columns: d_comp_cast:22!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 d_cast:20!null
      ├── project
      │    ├── columns: d_comp_comp:21!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 d_cast:20!null
      │    ├── project
      │    │    ├── columns: d_cast:20!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    ├── project
      │    │    │    ├── columns: d_new:19!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    ├── scan assn_cast
      │    │    │    │    ├── columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    │    ├── computed column expressions
      │    │    │    │    │    └── d_comp:15
      │    │    │    │    │         └── assignment-cast: DECIMAL(10)
      │    │    │    │    │              └── d:14 + 10.0
      │    │    │    │    └── flags: avoid-full-scan
      │    │    │    └── projections
      │    │    │         └── 1.45::DECIMAL(10,2) [as=d_new:19]
      │    │    └── projections
      │    │         └── assignment-cast: DECIMAL(10) [as=d_cast:20]
      │    │              └── d_new:19
      │    └── projections
      │         └── d_cast:20 + 10.0 [as=d_comp_comp:21]
      └── projections
           └── assignment-cast: DECIMAL(10) [as=d_comp_cast:22]
                └── d_comp_comp:21

# Test prepared update to a column that requires an assignment cast and a
# computed column that depends on the new value.
assign-placeholders-build query-args=(1.45::DECIMAL(10, 2))
UPDATE assn_cast SET d=$1
----
update assn_cast
 ├── columns: <none>
 ├── fetch columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16
 ├── update-mapping:
 │    ├── d_cast:20 => d:5
 │    └── d_comp_cast:22 => d_comp:6
 └── project
      ├── columns: d_comp_cast:22!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 d_cast:20!null
      ├── project
      │    ├── columns: d_comp_comp:21!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 d_cast:20!null
      │    ├── project
      │    │    ├── columns: d_cast:20!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    ├── project
      │    │    │    ├── columns: d_new:19!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    ├── scan assn_cast
      │    │    │    │    ├── columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    │    ├── computed column expressions
      │    │    │    │    │    └── d_comp:15
      │    │    │    │    │         └── assignment-cast: DECIMAL(10)
      │    │    │    │    │              └── d:14 + 10.0
      │    │    │    │    └── flags: avoid-full-scan
      │    │    │    └── projections
      │    │    │         └── 1.45 [as=d_new:19]
      │    │    └── projections
      │    │         └── assignment-cast: DECIMAL(10) [as=d_cast:20]
      │    │              └── d_new:19
      │    └── projections
      │         └── d_cast:20 + 10.0 [as=d_comp_comp:21]
      └── projections
           └── assignment-cast: DECIMAL(10) [as=d_comp_cast:22]
                └── d_comp_comp:21

# Test tuple-syntax update with assignment casts required.
build
UPDATE decimals SET (a, b) = (1.1, ARRAY[0.95, NULL, 15::DECIMAL(10, 2)])
----
update decimals
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 d:10
 ├── update-mapping:
 │    ├── a_cast:15 => a:1
 │    ├── b_cast:16 => b:2
 │    └── d_cast:18 => d:4
 ├── check columns: check1:19 check2:20
 └── project
      ├── columns: check1:19 check2:20 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16 d_cast:18
      ├── project
      │    ├── columns: d_cast:18 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16
      │    ├── project
      │    │    ├── columns: d_comp:17 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16
      │    │    ├── project
      │    │    │    ├── columns: a_cast:15!null b_cast:16 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    ├── project
      │    │    │    │    ├── columns: a_new:13!null b_new:14 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    │    ├── scan decimals
      │    │    │    │    │    ├── columns: a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    │    │    ├── computed column expressions
      │    │    │    │    │    │    └── d:10
      │    │    │    │    │    │         └── assignment-cast: DECIMAL(10,1)
      │    │    │    │    │    │              └── a:7 + c:9
      │    │    │    │    │    └── flags: avoid-full-scan
      │    │    │    │    └── projections
      │    │    │    │         ├── 1.1 [as=a_new:13]
      │    │    │    │         └── ARRAY[0.95, NULL, 15::DECIMAL(10,2)] [as=b_new:14]
      │    │    │    └── projections
      │    │    │         ├── assignment-cast: DECIMAL(10) [as=a_cast:15]
      │    │    │         │    └── a_new:13
      │    │    │         └── assignment-cast: DECIMAL(5,1)[] [as=b_cast:16]
      │    │    │              └── b_new:14
      │    │    └── projections
      │    │         └── a_cast:15 + c:9 [as=d_comp:17]
      │    └── projections
      │         └── assignment-cast: DECIMAL(10,1) [as=d_cast:18]
      │              └── d_comp:17
      └── projections
           ├── round(a_cast:15) = a_cast:15 [as=check1:19]
           └── b_cast:16[0] > 1 [as=check2:20]

# Test tuple-syntax prepared update with assignment casts required.
assign-placeholders-build query-args=(1.1, (ARRAY[0.95, NULL, 15::DECIMAL(10, 2)]))
UPDATE decimals SET (a, b) = ($1, $2)
----
update decimals
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 d:10
 ├── update-mapping:
 │    ├── a_cast:15 => a:1
 │    ├── b_cast:16 => b:2
 │    └── d_cast:18 => d:4
 ├── check columns: check1:19 check2:20
 └── project
      ├── columns: check1:19 check2:20 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16!null d_cast:18
      ├── project
      │    ├── columns: d_cast:18 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16!null
      │    ├── project
      │    │    ├── columns: d_comp:17 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:15!null b_cast:16!null
      │    │    ├── project
      │    │    │    ├── columns: a_cast:15!null b_cast:16!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    ├── project
      │    │    │    │    ├── columns: a_new:13!null b_new:14!null a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    │    ├── scan decimals
      │    │    │    │    │    ├── columns: a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    │    │    ├── computed column expressions
      │    │    │    │    │    │    └── d:10
      │    │    │    │    │    │         └── assignment-cast: DECIMAL(10,1)
      │    │    │    │    │    │              └── a:7 + c:9
      │    │    │    │    │    └── flags: avoid-full-scan
      │    │    │    │    └── projections
      │    │    │    │         ├── 1.1 [as=a_new:13]
      │    │    │    │         └── ARRAY[0.95,NULL,15.00] [as=b_new:14]
      │    │    │    └── projections
      │    │    │         ├── assignment-cast: DECIMAL(10) [as=a_cast:15]
      │    │    │         │    └── a_new:13
      │    │    │         └── assignment-cast: DECIMAL(5,1)[] [as=b_cast:16]
      │    │    │              └── b_new:14
      │    │    └── projections
      │    │         └── a_cast:15 + c:9 [as=d_comp:17]
      │    └── projections
      │         └── assignment-cast: DECIMAL(10,1) [as=d_cast:18]
      │              └── d_comp:17
      └── projections
           ├── round(a_cast:15) = a_cast:15 [as=check1:19]
           └── b_cast:16[0] > 1 [as=check2:20]

# Test tuple-syntax update with DEFAULT that requires assignment cast.
build
UPDATE assn_cast SET (c, i) = (' ', DEFAULT)
----
update assn_cast
 ├── columns: <none>
 ├── fetch columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16
 ├── update-mapping:
 │    ├── c_cast:21 => c:1
 │    └── i_cast:22 => i:3
 └── project
      ├── columns: d_comp_comp:23 c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 c_cast:21!null i_cast:22!null
      ├── project
      │    ├── columns: c_cast:21!null i_cast:22!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    ├── project
      │    │    ├── columns: c_new:19!null i_new:20!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    ├── scan assn_cast
      │    │    │    ├── columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    ├── computed column expressions
      │    │    │    │    └── d_comp:15
      │    │    │    │         └── assignment-cast: DECIMAL(10)
      │    │    │    │              └── d:14 + 10.0
      │    │    │    └── flags: avoid-full-scan
      │    │    └── projections
      │    │         ├── '' [as=c_new:19]
      │    │         └── 10::INT2 [as=i_new:20]
      │    └── projections
      │         ├── assignment-cast: CHAR [as=c_cast:21]
      │         │    └── c_new:19
      │         └── assignment-cast: INT8 [as=i_cast:22]
      │              └── i_new:20
      └── projections
           └── d:14 + 10.0 [as=d_comp_comp:23]

# Test tuple-syntax prepared update with DEFAULT that requires assignment casts.
assign-placeholders-build query-args=(' ')
UPDATE assn_cast SET (c, i) = ($1, DEFAULT)
----
update assn_cast
 ├── columns: <none>
 ├── fetch columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16
 ├── update-mapping:
 │    ├── c_cast:21 => c:1
 │    └── i_cast:22 => i:3
 └── project
      ├── columns: d_comp_comp:23 c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 c_cast:21!null i_cast:22!null
      ├── project
      │    ├── columns: c_cast:21!null i_cast:22!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    ├── project
      │    │    ├── columns: c_new:19!null i_new:20!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    ├── scan assn_cast
      │    │    │    ├── columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    ├── computed column expressions
      │    │    │    │    └── d_comp:15
      │    │    │    │         └── assignment-cast: DECIMAL(10)
      │    │    │    │              └── d:14 + 10.0
      │    │    │    └── flags: avoid-full-scan
      │    │    └── projections
      │    │         ├── '' [as=c_new:19]
      │    │         └── 10::INT2 [as=i_new:20]
      │    └── projections
      │         ├── assignment-cast: CHAR [as=c_cast:21]
      │         │    └── c_new:19
      │         └── assignment-cast: INT8 [as=i_cast:22]
      │              └── i_new:20
      └── projections
           └── d:14 + 10.0 [as=d_comp_comp:23]

# Test update with a subquery that requires an assignment cast.
build
UPDATE decimals SET (a)=(SELECT 1.45 AS n)
----
update decimals
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 d:10
 ├── update-mapping:
 │    ├── a_cast:14 => a:1
 │    └── d_cast:16 => d:4
 ├── check columns: check1:17
 └── project
      ├── columns: check1:17 check2:18 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:14 d_cast:16
      ├── project
      │    ├── columns: d_cast:16 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:14
      │    ├── project
      │    │    ├── columns: d_comp:15 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 a_cast:14
      │    │    ├── project
      │    │    │    ├── columns: a_cast:14 a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    ├── left-join-apply
      │    │    │    │    ├── columns: a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12 n:13
      │    │    │    │    ├── scan decimals
      │    │    │    │    │    ├── columns: a:7!null b:8 c:9 d:10 crdb_internal_mvcc_timestamp:11 tableoid:12
      │    │    │    │    │    ├── computed column expressions
      │    │    │    │    │    │    └── d:10
      │    │    │    │    │    │         └── assignment-cast: DECIMAL(10,1)
      │    │    │    │    │    │              └── a:7 + c:9
      │    │    │    │    │    └── flags: avoid-full-scan
      │    │    │    │    ├── max1-row
      │    │    │    │    │    ├── columns: n:13!null
      │    │    │    │    │    └── project
      │    │    │    │    │         ├── columns: n:13!null
      │    │    │    │    │         ├── values
      │    │    │    │    │         │    └── ()
      │    │    │    │    │         └── projections
      │    │    │    │    │              └── 1.45 [as=n:13]
      │    │    │    │    └── filters (true)
      │    │    │    └── projections
      │    │    │         └── assignment-cast: DECIMAL(10) [as=a_cast:14]
      │    │    │              └── n:13
      │    │    └── projections
      │    │         └── a_cast:14 + c:9 [as=d_comp:15]
      │    └── projections
      │         └── assignment-cast: DECIMAL(10,1) [as=d_cast:16]
      │              └── d_comp:15
      └── projections
           ├── round(a_cast:14) = a_cast:14 [as=check1:17]
           └── b:8[0] > 1 [as=check2:18]

# Test update with a multi-column subquery that requires assignment casts.
build
UPDATE decimals SET (a, c)=(SELECT u, u*10.0 FROM uv WHERE decimals.c = uv.u)
----
update decimals
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 d:10
 ├── update-mapping:
 │    ├── a_cast:19 => a:1
 │    ├── c_cast:20 => c:3
 │    └── d_cast:22 => d:4
 ├── check columns: check1:23
 └── project
      ├── columns: check1:23 check2:24 a:7!null b:8 c:9 d:10 decimals.crdb_internal_mvcc_timestamp:11 decimals.tableoid:12 a_cast:19 c_cast:20 d_cast:22
      ├── project
      │    ├── columns: d_cast:22 a:7!null b:8 c:9 d:10 decimals.crdb_internal_mvcc_timestamp:11 decimals.tableoid:12 a_cast:19 c_cast:20
      │    ├── project
      │    │    ├── columns: d_comp:21 a:7!null b:8 c:9 d:10 decimals.crdb_internal_mvcc_timestamp:11 decimals.tableoid:12 a_cast:19 c_cast:20
      │    │    ├── project
      │    │    │    ├── columns: a_cast:19 c_cast:20 a:7!null b:8 c:9 d:10 decimals.crdb_internal_mvcc_timestamp:11 decimals.tableoid:12
      │    │    │    ├── left-join-apply
      │    │    │    │    ├── columns: a:7!null b:8 c:9 d:10 decimals.crdb_internal_mvcc_timestamp:11 decimals.tableoid:12 u:13 "?column?":18
      │    │    │    │    ├── scan decimals
      │    │    │    │    │    ├── columns: a:7!null b:8 c:9 d:10 decimals.crdb_internal_mvcc_timestamp:11 decimals.tableoid:12
      │    │    │    │    │    ├── computed column expressions
      │    │    │    │    │    │    └── d:10
      │    │    │    │    │    │         └── assignment-cast: DECIMAL(10,1)
      │    │    │    │    │    │              └── a:7 + c:9
      │    │    │    │    │    └── flags: avoid-full-scan
      │    │    │    │    ├── max1-row
      │    │    │    │    │    ├── columns: u:13!null "?column?":18!null
      │    │    │    │    │    └── project
      │    │    │    │    │         ├── columns: "?column?":18!null u:13!null
      │    │    │    │    │         ├── select
      │    │    │    │    │         │    ├── columns: u:13!null v:14 rowid:15!null uv.crdb_internal_mvcc_timestamp:16 uv.tableoid:17
      │    │    │    │    │         │    ├── scan uv
      │    │    │    │    │         │    │    └── columns: u:13 v:14 rowid:15!null uv.crdb_internal_mvcc_timestamp:16 uv.tableoid:17
      │    │    │    │    │         │    └── filters
      │    │    │    │    │         │         └── c:9 = u:13
      │    │    │    │    │         └── projections
      │    │    │    │    │              └── u:13 * 10.0 [as="?column?":18]
      │    │    │    │    └── filters (true)
      │    │    │    └── projections
      │    │    │         ├── assignment-cast: DECIMAL(10) [as=a_cast:19]
      │    │    │         │    └── u:13
      │    │    │         └── assignment-cast: DECIMAL(10,1) [as=c_cast:20]
      │    │    │              └── "?column?":18
      │    │    └── projections
      │    │         └── a_cast:19 + c_cast:20 [as=d_comp:21]
      │    └── projections
      │         └── assignment-cast: DECIMAL(10,1) [as=d_cast:22]
      │              └── d_comp:21
      └── projections
           ├── round(a_cast:19) = a_cast:19 [as=check1:23]
           └── b:8[0] > 1 [as=check2:24]

# Test combined standard and subquery update the requires assignment casts.
build
UPDATE assn_cast SET c=' ', (qc, i)=(SELECT 'foo', '1' FROM uv)
----
update assn_cast
 ├── columns: <none>
 ├── fetch columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 assn_cast.rowid:16
 ├── update-mapping:
 │    ├── c_cast:27 => c:1
 │    ├── qc_cast:28 => qc:2
 │    └── "?column?":25 => i:3
 └── project
      ├── columns: d_comp_comp:29 c:10 qc:11 i:12 s:13 d:14 d_comp:15 assn_cast.rowid:16!null assn_cast.crdb_internal_mvcc_timestamp:17 assn_cast.tableoid:18 "?column?":25 c_cast:27!null qc_cast:28
      ├── project
      │    ├── columns: c_cast:27!null qc_cast:28 c:10 qc:11 i:12 s:13 d:14 d_comp:15 assn_cast.rowid:16!null assn_cast.crdb_internal_mvcc_timestamp:17 assn_cast.tableoid:18 "?column?":25
      │    ├── project
      │    │    ├── columns: c_new:26!null c:10 qc:11 i:12 s:13 d:14 d_comp:15 assn_cast.rowid:16!null assn_cast.crdb_internal_mvcc_timestamp:17 assn_cast.tableoid:18 "?column?":24 "?column?":25
      │    │    ├── left-join-apply
      │    │    │    ├── columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 assn_cast.rowid:16!null assn_cast.crdb_internal_mvcc_timestamp:17 assn_cast.tableoid:18 "?column?":24 "?column?":25
      │    │    │    ├── scan assn_cast
      │    │    │    │    ├── columns: c:10 qc:11 i:12 s:13 d:14 d_comp:15 assn_cast.rowid:16!null assn_cast.crdb_internal_mvcc_timestamp:17 assn_cast.tableoid:18
      │    │    │    │    ├── computed column expressions
      │    │    │    │    │    └── d_comp:15
      │    │    │    │    │         └── assignment-cast: DECIMAL(10)
      │    │    │    │    │              └── d:14 + 10.0
      │    │    │    │    └── flags: avoid-full-scan
      │    │    │    ├── max1-row
      │    │    │    │    ├── columns: "?column?":24!null "?column?":25!null
      │    │    │    │    └── project
      │    │    │    │         ├── columns: "?column?":24!null "?column?":25!null
      │    │    │    │         ├── scan uv
      │    │    │    │         │    └── columns: u:19 v:20 uv.rowid:21!null uv.crdb_internal_mvcc_timestamp:22 uv.tableoid:23
      │    │    │    │         └── projections
      │    │    │    │              ├── 'foo' [as="?column?":24]
      │    │    │    │              └── 1 [as="?column?":25]
      │    │    │    └── filters (true)
      │    │    └── projections
      │    │         └── '' [as=c_new:26]
      │    └── projections
      │         ├── assignment-cast: CHAR [as=c_cast:27]
      │         │    └── c_new:26
      │         └── assignment-cast: "char" [as=qc_cast:28]
      │              └── "?column?":24
      └── projections
           └── d:14 + 10.0 [as=d_comp_comp:29]

# Test ON UPDATE columns that require assignment casts.
build
UPDATE assn_cast_on_update SET i=1, b=true
----
update assn_cast_on_update
 ├── columns: <none>
 ├── fetch columns: i:10 i2:11 d:12 d2:13 d_comp:14 b:15 rowid:16
 ├── update-mapping:
 │    ├── i_new:19 => i:1
 │    ├── i2_cast:24 => i2:2
 │    ├── d_cast:25 => d:3
 │    ├── d2_cast:26 => d2:4
 │    ├── d_comp_cast:27 => d_comp:5
 │    └── b_new:20 => b:6
 └── project
      ├── columns: d_comp_cast:27!null i:10 i2:11 d:12 d2:13 d_comp:14 b:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 i_new:19!null b_new:20!null i2_cast:24!null d_cast:25!null d2_cast:26!null
      ├── project
      │    ├── columns: i2_cast:24!null d_cast:25!null d2_cast:26!null i:10 i2:11 d:12 d2:13 d_comp:14 b:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 i_new:19!null b_new:20!null
      │    ├── project
      │    │    ├── columns: i2_on_update:21!null d_on_update:22!null d2_on_update:23!null i:10 i2:11 d:12 d2:13 d_comp:14 b:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18 i_new:19!null b_new:20!null
      │    │    ├── project
      │    │    │    ├── columns: i_new:19!null b_new:20!null i:10 i2:11 d:12 d2:13 d_comp:14 b:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    ├── scan assn_cast_on_update
      │    │    │    │    ├── columns: i:10 i2:11 d:12 d2:13 d_comp:14 b:15 rowid:16!null crdb_internal_mvcc_timestamp:17 tableoid:18
      │    │    │    │    ├── computed column expressions
      │    │    │    │    │    └── d_comp:14
      │    │    │    │    │         └── assignment-cast: DECIMAL(10)
      │    │    │    │    │              └── d:12
      │    │    │    │    └── flags: avoid-full-scan
      │    │    │    └── projections
      │    │    │         ├── 1 [as=i_new:19]
      │    │    │         └── true [as=b_new:20]
      │    │    └── projections
      │    │         ├── 1.0 [as=i2_on_update:21]
      │    │         ├── 1.23 [as=d_on_update:22]
      │    │         └── 1.23::DECIMAL(10,2) [as=d2_on_update:23]
      │    └── projections
      │         ├── assignment-cast: INT8 [as=i2_cast:24]
      │         │    └── i2_on_update:21
      │         ├── assignment-cast: DECIMAL(10,1) [as=d_cast:25]
      │         │    └── d_on_update:22
      │         └── assignment-cast: DECIMAL(10,1) [as=d2_cast:26]
      │              └── d2_on_update:23
      └── projections
           └── assignment-cast: DECIMAL(10) [as=d_comp_cast:27]
                └── d_cast:25

# This fails because the cast from FLOAT to BOOL is not a valid assignment cast.
build
UPDATE assn_cast_on_update SET i=1
----
error (42804): value type float doesn't match type bool of column "b"

# ------------------------------------------------------------------------------
# ON UPDATE tests.
# ------------------------------------------------------------------------------

build
UPDATE on_update_bare SET a = 1 WHERE a = 2
----
update on_update_bare
 ├── columns: <none>
 ├── fetch columns: a:6 v:7 rowid:8
 ├── update-mapping:
 │    ├── a_new:11 => a:1
 │    └── v_on_update:12 => v:2
 └── project
      ├── columns: v_on_update:12!null a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10 a_new:11!null
      ├── project
      │    ├── columns: a_new:11!null a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    ├── select
      │    │    ├── columns: a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    │    ├── scan on_update_bare
      │    │    │    ├── columns: a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    │    │    └── flags: avoid-full-scan
      │    │    └── filters
      │    │         └── a:6 = 2
      │    └── projections
      │         └── 1 [as=a_new:11]
      └── projections
           └── 5 [as=v_on_update:12]

build
UPDATE on_update_bare SET (a, v) = (1, 4) WHERE a = 2
----
update on_update_bare
 ├── columns: <none>
 ├── fetch columns: a:6 v:7 rowid:8
 ├── update-mapping:
 │    ├── a_new:11 => a:1
 │    └── v_new:12 => v:2
 └── project
      ├── columns: a_new:11!null v_new:12!null a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      ├── select
      │    ├── columns: a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    ├── scan on_update_bare
      │    │    ├── columns: a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    │    └── flags: avoid-full-scan
      │    └── filters
      │         └── a:6 = 2
      └── projections
           ├── 1 [as=a_new:11]
           └── 4 [as=v_new:12]

build
UPDATE on_update_with_default SET a = 1 WHERE a = 2
----
update on_update_with_default
 ├── columns: <none>
 ├── fetch columns: a:6 v:7 rowid:8
 ├── update-mapping:
 │    ├── a_new:11 => a:1
 │    └── v_on_update:12 => v:2
 └── project
      ├── columns: v_on_update:12!null a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10 a_new:11!null
      ├── project
      │    ├── columns: a_new:11!null a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    ├── select
      │    │    ├── columns: a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    │    ├── scan on_update_with_default
      │    │    │    ├── columns: a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    │    │    └── flags: avoid-full-scan
      │    │    └── filters
      │    │         └── a:6 = 2
      │    └── projections
      │         └── 1 [as=a_new:11]
      └── projections
           └── 10 [as=v_on_update:12]

build
UPDATE on_update_with_default SET (a, v) = (1, 4) WHERE a = 2
----
update on_update_with_default
 ├── columns: <none>
 ├── fetch columns: a:6 v:7 rowid:8
 ├── update-mapping:
 │    ├── a_new:11 => a:1
 │    └── v_new:12 => v:2
 └── project
      ├── columns: a_new:11!null v_new:12!null a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      ├── select
      │    ├── columns: a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    ├── scan on_update_with_default
      │    │    ├── columns: a:6!null v:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    │    └── flags: avoid-full-scan
      │    └── filters
      │         └── a:6 = 2
      └── projections
           ├── 1 [as=a_new:11]
           └── 4 [as=v_new:12]


build
UPDATE generated_as_identity SET b=(1+1)
----
error (428C9): column "b" can only be updated to DEFAULT

build
UPDATE generated_as_identity SET a=10, b=(1+1)
----
error (428C9): column "b" can only be updated to DEFAULT

build
UPDATE generated_as_identity SET b=DEFAULT
----
update generated_as_identity
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 rowid:10
 ├── update-mapping:
 │    └── b_new:13 => b:2
 └── project
      ├── columns: b_new:13 a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── scan generated_as_identity
      │    ├── columns: a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      │    └── flags: avoid-full-scan
      └── projections
           └── nextval('t.public.generated_as_identity_b_seq') [as=b_new:13]

build
UPDATE generated_as_identity SET a=10, b=DEFAULT
----
update generated_as_identity
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 rowid:10
 ├── update-mapping:
 │    ├── a_new:13 => a:1
 │    └── b_new:14 => b:2
 └── project
      ├── columns: a_new:13!null b_new:14 a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── scan generated_as_identity
      │    ├── columns: a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      │    └── flags: avoid-full-scan
      └── projections
           ├── 10 [as=a_new:13]
           └── nextval('t.public.generated_as_identity_b_seq') [as=b_new:14]

build
UPDATE generated_as_identity SET c=(1+1)
----
update generated_as_identity
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 rowid:10
 ├── update-mapping:
 │    └── c_new:13 => c:3
 └── project
      ├── columns: c_new:13!null a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── scan generated_as_identity
      │    ├── columns: a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      │    └── flags: avoid-full-scan
      └── projections
           └── 1 + 1 [as=c_new:13]

build
UPDATE generated_as_identity SET a=10, c=(1+1)
----
update generated_as_identity
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 rowid:10
 ├── update-mapping:
 │    ├── a_new:13 => a:1
 │    └── c_new:14 => c:3
 └── project
      ├── columns: a_new:13!null c_new:14!null a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── scan generated_as_identity
      │    ├── columns: a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      │    └── flags: avoid-full-scan
      └── projections
           ├── 10 [as=a_new:13]
           └── 1 + 1 [as=c_new:14]

build
UPDATE generated_as_identity SET c=DEFAULT
----
update generated_as_identity
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 rowid:10
 ├── update-mapping:
 │    └── c_new:13 => c:3
 └── project
      ├── columns: c_new:13 a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── scan generated_as_identity
      │    ├── columns: a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      │    └── flags: avoid-full-scan
      └── projections
           └── nextval('t.public.generated_as_identity_c_seq') [as=c_new:13]

build
UPDATE generated_as_identity SET a=10, c=DEFAULT
----
update generated_as_identity
 ├── columns: <none>
 ├── fetch columns: a:7 b:8 c:9 rowid:10
 ├── update-mapping:
 │    ├── a_new:13 => a:1
 │    └── c_new:14 => c:3
 └── project
      ├── columns: a_new:13!null c_new:14 a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      ├── scan generated_as_identity
      │    ├── columns: a:7 b:8!null c:9!null rowid:10!null crdb_internal_mvcc_timestamp:11 tableoid:12
      │    └── flags: avoid-full-scan
      └── projections
           ├── 10 [as=a_new:13]
           └── nextval('t.public.generated_as_identity_c_seq') [as=c_new:14]

# With SERIAL syntax
exec-ddl
CREATE TABLE serial_t (
  a SERIAL,
  b INT
)
----

build
UPDATE serial_t SET a=(1+2)
----
update serial_t
 ├── columns: <none>
 ├── fetch columns: a:6 b:7 rowid:8
 ├── update-mapping:
 │    └── a_new:11 => a:1
 └── project
      ├── columns: a_new:11!null a:6 b:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      ├── scan serial_t
      │    ├── columns: a:6 b:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    └── flags: avoid-full-scan
      └── projections
           └── 1 + 2 [as=a_new:11]

build
UPDATE serial_t SET a=DEFAULT
----
update serial_t
 ├── columns: <none>
 ├── fetch columns: a:6 b:7 rowid:8
 ├── update-mapping:
 │    └── a_new:11 => a:1
 └── project
      ├── columns: a_new:11 a:6 b:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      ├── scan serial_t
      │    ├── columns: a:6 b:7 rowid:8!null crdb_internal_mvcc_timestamp:9 tableoid:10
      │    └── flags: avoid-full-scan
      └── projections
           └── unique_rowid() [as=a_new:11]
