Skip to content

Commit

Permalink
Merge #74180
Browse files Browse the repository at this point in the history
74180: sql: add assignment cast for UPDATEs r=mgartner a=mgartner

#### opt: fix FK WithScan column type

Previously, the WithScan columns of cascade FK updates were given the
type of the child table's target column. This was incorrect when the
parent column type did not match. This commit fixes the issue by given
the WithScan columns the type of the buffered columns used to update the
parent relation.

This did not cause any known bugs, but it is required to implement
assignment casts with FK cascades.

Release note: None

#### sql: add assignment cast for UPDATEs

Fixes #70628

Release note: None

#### opt: give synthesized assignment cast columns descriptive names

Columns synthesized for assignment casts now have more descriptive
metadata names in the form `<target_column_name>_cast`. This is purely
an aesthetic change and has no effect on semantics.

Release note: None

Co-authored-by: Marcus Gartner <[email protected]>
  • Loading branch information
craig[bot] and mgartner committed Dec 31, 2021
2 parents 3471dc5 + 4afae3c commit fa9480a
Show file tree
Hide file tree
Showing 28 changed files with 2,149 additions and 901 deletions.
258 changes: 256 additions & 2 deletions pkg/sql/logictest/testdata/logic_test/cast
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ EXECUTE insert_c('foo'::STRING)
statement ok
DELETE FROM assn_cast

statement
statement ok
EXECUTE insert_c(' ')

statement
statement ok
EXECUTE insert_c(' '::STRING)

query T
Expand Down Expand Up @@ -93,6 +93,8 @@ INSERT INTO assn_cast(qc) VALUES (123) RETURNING qc
----
{

# An integer to "char" cast converts the integer into the corresponding 7-bit
# ASCII character. Anything greater than 127 is out of range.
statement error \"char\" out of range
INSERT INTO assn_cast(qc) VALUES (1234)

Expand Down Expand Up @@ -348,6 +350,258 @@ SELECT d, d_comp, d2, d2_comp FROM assn_cast_comp
----
2 2.00 2.78 3


# Tests for assignment casts in UPDATEs.
subtest assignment_casts_update

statement ok
DELETE FROM assn_cast

statement ok
INSERT INTO assn_cast (c) VALUES (NULL)

statement error value too long for type CHAR
UPDATE assn_cast SET c = 'abc'

query T
UPDATE assn_cast SET c = 1 RETURNING c
----
1

statement error value too long for type CHAR
UPDATE assn_cast SET c = 123

statement ok
UPDATE assn_cast SET c = NULL

statement ok
PREPARE update_c AS UPDATE assn_cast SET c = $1

statement error value too long for type CHAR
EXECUTE update_c('foo')

statement error value too long for type CHAR
EXECUTE update_c('foo'::STRING)

statement ok
EXECUTE update_c(' ')

query T
SELECT concat('"', c, '"') FROM assn_cast
----
""

statement ok
EXECUTE update_c(' '::STRING)

query T
SELECT concat('"', c, '"') FROM assn_cast
----
""

statement ok
UPDATE assn_cast SET qc = 'a'

query T
UPDATE assn_cast SET qc = 'abc' RETURNING qc
----
a

# An integer to "char" cast converts the integer into the corresponding 7-bit
# ASCII character. Anything greater than 127 is out of range.
statement error \"char\" out of range
UPDATE assn_cast SET qc = 1234

statement ok
PREPARE update_qc AS UPDATE assn_cast SET qc = $1

statement ok
EXECUTE update_qc('foo')

query T
SELECT qc FROM assn_cast
----
f

statement ok
EXECUTE update_qc('foo'::STRING)

query T
SELECT qc FROM assn_cast
----
f

statement ok
UPDATE assn_cast SET i = '1'

statement ok
PREPARE update_i AS UPDATE assn_cast SET i = $1

statement ok
EXECUTE update_i('1')

statement error value type string doesn't match type int of column \"i\"
UPDATE assn_cast SET i = '1'::STRING

statement error integer out of range for type int2
UPDATE assn_cast SET i2 = 999999999

statement ok
PREPARE update_i2 AS UPDATE assn_cast SET i2 = $1

statement error integer out of range for type int2
EXECUTE update_i2(99999999)

query F
UPDATE assn_cast SET d = 11.22 RETURNING d
----
11

query F
UPDATE assn_cast SET d = 11.22::DECIMAL(10, 0) RETURNING d
----
11

query F
UPDATE assn_cast SET d = 11.22::DECIMAL(10, 2) RETURNING d
----
11

statement ok
PREPARE update_d AS UPDATE assn_cast SET d = $1

statement ok
EXECUTE update_d(123.45)

query F
SELECT d FROM assn_cast
----
123

statement ok
PREPARE update_d2 AS UPDATE assn_cast SET d = (SELECT * FROM (VALUES ($1::DECIMAL(10, 2))))

statement ok
EXECUTE update_d2(67.89)

query F
SELECT d FROM assn_cast
----
68

query T
UPDATE assn_cast SET a = ARRAY[] RETURNING a
----
{}

query T
UPDATE assn_cast SET a = ARRAY[NULL] RETURNING a
----
{NULL}

query T
UPDATE assn_cast SET a = ARRAY[1.1] RETURNING a
----
{1}

query T
UPDATE assn_cast SET a = ARRAY[2.88, NULL, 15] RETURNING a
----
{3,NULL,15}

query T
UPDATE assn_cast SET a = ARRAY[3.99, NULL, 16]::DECIMAL(10, 2)[] RETURNING a
----
{4,NULL,16}

query T
UPDATE assn_cast SET a = ARRAY[5.55, 6.66::DECIMAL(10, 2)] RETURNING a
----
{6,7}

statement ok
PREPARE update_a AS UPDATE assn_cast SET a = $1

statement ok
EXECUTE update_a(ARRAY[7.77, 8.88::DECIMAL(10, 2)])

query T
SELECT a FROM assn_cast
----
{8,9}

statement ok
PREPARE update_a2 AS UPDATE assn_cast SET a = ARRAY[$1]

statement ok
EXECUTE update_a2(20.2)

query T
SELECT a FROM assn_cast
----
{20}

statement ok
PREPARE update_a3 AS UPDATE assn_cast SET a = ARRAY[30.12, $1, 32.1]

statement ok
EXECUTE update_a3(30.9)

query T
SELECT a FROM assn_cast
----
{30,31,32}

statement error value type tuple{int, int} doesn't match type timestamp of column "t"
UPDATE assn_cast SET t = (SELECT (10, 11))

statement error value type decimal doesn't match type timestamp of column "t"
UPDATE assn_cast SET t = 3.2

statement error value type decimal doesn't match type timestamp of column "t"
UPDATE assn_cast SET (i, t) = (1, 3.2)

# Tests for assignment casts in cascading UPDATEs.
subtest assignment_casts_update_cascade

statement ok
CREATE TABLE assn_cast_p (p DECIMAL(10, 2) PRIMARY KEY);
INSERT INTO assn_cast_p VALUES (1.0);

# Test ON UPDATE CASCADE.
statement ok
CREATE TABLE assn_cast_c (c INT PRIMARY KEY, p DECIMAL(10, 0) REFERENCES assn_cast_p(p) ON UPDATE CASCADE);
INSERT INTO assn_cast_c VALUES (1, 1.0);

statement error update on table "assn_cast_c" violates foreign key constraint "assn_cast_c_p_fkey"
UPDATE assn_cast_p SET p = 1.2

statement ok
UPDATE assn_cast_p SET p = 2.0

query IF
SELECT * FROM assn_cast_c
----
1 2

# Test ON UPDATE SET DEFAULT.
statement ok
DROP TABLE assn_cast_c;
CREATE TABLE assn_cast_c (c INT PRIMARY KEY, p DECIMAL(10, 0) DEFAULT 3.1 REFERENCES assn_cast_p(p) ON UPDATE SET DEFAULT);
INSERT INTO assn_cast_c VALUES (2, 2.0);

statement error update on table "assn_cast_c" violates foreign key constraint "assn_cast_c_p_fkey"
UPDATE assn_cast_p SET p = 1.2

statement ok
UPDATE assn_cast_p SET p = 3.0

query IF
SELECT * FROM assn_cast_c
----
2 3


# Regression tests.
subtest regressions

Expand Down
15 changes: 12 additions & 3 deletions pkg/sql/logictest/testdata/logic_test/update
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@ CREATE TABLE kv (
statement error value type tuple{int, int} doesn't match type int of column "v"
UPDATE kv SET v = (SELECT (10, 11))

statement error value type decimal doesn't match type int of column "v"
statement ok
UPDATE kv SET v = 3.2

statement error value type decimal doesn't match type int of column "v"
statement ok
UPDATE kv SET (k, v) = (3, 3.2)

statement error value type decimal doesn't match type int of column "v"
statement ok
UPDATE kv SET (k, v) = (SELECT 3, 3.2)

statement error value type string doesn't match type int of column "v"
UPDATE kv SET v = '3.2'::STRING

statement error value type string doesn't match type int of column "v"
UPDATE kv SET (k, v) = (3, '3.2'::STRING)

statement error value type string doesn't match type int of column "v"
UPDATE kv SET (k, v) = (SELECT 3, '3.2'::STRING)

statement count 4
INSERT INTO kv VALUES (1, 2), (3, 4), (5, 6), (7, 8)

Expand Down
20 changes: 10 additions & 10 deletions pkg/sql/opt/exec/execbuilder/testdata/hash_sharded_index
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ vectorized: true
│ auto commit
└── • render
│ columns: (column7, column1, check1)
│ columns: (crdb_internal_a_shard_11_cast, column1, check1)
│ estimated row count: 2
│ render check1: column7 IN (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
│ render check1: crdb_internal_a_shard_11_cast IN (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
│ render column1: column1
│ render column7: column7
│ render crdb_internal_a_shard_11_cast: crdb_internal_a_shard_11_cast
└── • render
│ columns: (column7, column1)
│ columns: (crdb_internal_a_shard_11_cast, column1)
│ estimated row count: 2
│ render column7: crdb_internal.assignment_cast(mod(fnv32(crdb_internal.datums_to_bytes(column1)), 11), NULL::INT4)
│ render crdb_internal_a_shard_11_cast: crdb_internal.assignment_cast(mod(fnv32(crdb_internal.datums_to_bytes(column1)), 11), NULL::INT4)
│ render column1: column1
└── • values
Expand All @@ -53,17 +53,17 @@ vectorized: true
│ auto commit
└── • render
│ columns: (column1, column9, rowid_default, check1)
│ columns: (column1, crdb_internal_a_shard_12_cast, rowid_default, check1)
│ estimated row count: 2
│ render check1: column9 IN (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
│ render check1: crdb_internal_a_shard_12_cast IN (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
│ render column1: column1
│ render rowid_default: rowid_default
│ render column9: column9
│ render crdb_internal_a_shard_12_cast: crdb_internal_a_shard_12_cast
└── • render
│ columns: (column9, rowid_default, column1)
│ columns: (crdb_internal_a_shard_12_cast, rowid_default, column1)
│ estimated row count: 2
│ render column9: crdb_internal.assignment_cast(mod(fnv32(crdb_internal.datums_to_bytes(column1)), 12), NULL::INT4)
│ render crdb_internal_a_shard_12_cast: crdb_internal.assignment_cast(mod(fnv32(crdb_internal.datums_to_bytes(column1)), 12), NULL::INT4)
│ render rowid_default: unique_rowid()
│ render column1: column1
Expand Down
4 changes: 2 additions & 2 deletions pkg/sql/opt/exec/explain/testdata/gists_tpce
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ explain(shape):
│ │
│ └── • lookup join (anti)
│ │ table: status_type@status_type_pkey
│ │ equality: (column62) = (st_id)
│ │ equality: (th_st_id_cast) = (st_id)
│ │ equality cols are key
│ │
│ └── • scan buffer
Expand All @@ -361,7 +361,7 @@ explain(shape):
└── • lookup join (anti)
│ table: status_type@status_type_pkey
│ equality: (t_st_id_new) = (st_id)
│ equality: (t_st_id_cast) = (st_id)
│ equality cols are key
└── • scan buffer
Expand Down
Loading

0 comments on commit fa9480a

Please sign in to comment.