Skip to content

Commit

Permalink
Merge #81863
Browse files Browse the repository at this point in the history
81863: opt: assignment casts of non-equivalent types in DEFAULT and ON UPDATE r=mgartner a=mgartner

This commit allows the optimizer to build assignment casts for `DEFAULT`
and `ON UPDATE` expressions that have types that are not equivalent with
their column's type. If the cast from the `DEFAULT` or `ON UPDATE`
expression type to the column type is not a valid assignment cast, an
error is returned. In practice, this error should never occur because 1)
it is currently impossible to create `DEFAULT` and `ON UPDATE`
expressions that do not match their column's type (the tests here get
around this limitation because they use the optimizer test catalog which
has much looser restrictions) and 2) a future PR will allow creating
`DEFAULT` and `ON UPDATE` expressions that do not match their column's
type only if the cast from the expression type to the column type is a
valid assignment cast.

Unblocks #81071

Release note: None

Co-authored-by: Marcus Gartner <marcus@cockroachlabs.com>
  • Loading branch information
craig[bot] and mgartner committed May 26, 2022
2 parents 4f7d083 + f542e2e commit c50a68a
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 52 deletions.
2 changes: 1 addition & 1 deletion pkg/sql/opt/optbuilder/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ func (pb *projectionBuilder) Add(
pb.outScope = pb.inScope.replace()
pb.outScope.appendColumnsFromScope(pb.inScope)
}
typedExpr := pb.inScope.resolveAndRequireType(expr, desiredType)
typedExpr := pb.inScope.resolveType(expr, desiredType)
scopeCol := pb.outScope.addColumn(name, typedExpr)
scalar := pb.b.buildScalar(typedExpr, pb.inScope, pb.outScope, scopeCol, nil)

Expand Down
69 changes: 41 additions & 28 deletions pkg/sql/opt/optbuilder/testdata/insert
Original file line number Diff line number Diff line change
Expand Up @@ -1333,52 +1333,65 @@ exec-ddl
CREATE TABLE assn_cast_default (
k INT PRIMARY KEY,
i2 INT2 DEFAULT 10::INT,
i3 INT DEFAULT 1.0::FLOAT,
c1 CHAR DEFAULT 'foo',
c2 CHAR DEFAULT 'bar'::TEXT,
d1 DECIMAL(10, 0) DEFAULT 1.23,
d2 DECIMAL(10, 0) DEFAULT 4.56::DECIMAL(10, 2),
b BOOL DEFAULT 1.0::FLOAT,
s TEXT DEFAULT NULL
)
----

build
INSERT INTO assn_cast_default (k) VALUES (1)
INSERT INTO assn_cast_default (k, b) VALUES (1, true)
----
insert assn_cast_default
├── columns: <none>
├── insert-mapping:
│ ├── column1:10 => k:1
│ ├── i2_cast:17 => i2:2
│ ├── c1_cast:18 => c1:3
│ ├── c2_cast:19 => c2:4
│ ├── d1_cast:20 => d1:5
│ ├── d2_cast:21 => d2:6
│ └── s_default:16 => s:7
│ ├── column1:12 => k:1
│ ├── i2_cast:21 => i2:2
│ ├── i3_cast:22 => i3:3
│ ├── c1_cast:23 => c1:4
│ ├── c2_cast:24 => c2:5
│ ├── d1_cast:25 => d1:6
│ ├── d2_cast:26 => d2:7
│ ├── column2:13 => b:8
│ └── s_default:20 => s:9
└── project
├── columns: i2_cast:17!null c1_cast:18!null c2_cast:19!null d1_cast:20!null d2_cast:21!null column1:10!null s_default:16
├── columns: i2_cast:21!null i3_cast:22!null c1_cast:23!null c2_cast:24!null d1_cast:25!null d2_cast:26!null column1:12!null column2:13!null s_default:20
├── project
│ ├── columns: i2_default:11!null c1_default:12!null c2_default:13!null d1_default:14!null d2_default:15!null s_default:16 column1:10!null
│ ├── columns: i2_default:14!null i3_default:15!null c1_default:16!null c2_default:17!null d1_default:18!null d2_default:19!null s_default:20 column1:12!null column2:13!null
│ ├── values
│ │ ├── columns: column1:10!null
│ │ └── (1,)
│ │ ├── columns: column1:12!null column2:13!null
│ │ └── (1, true)
│ └── projections
│ ├── 10 [as=i2_default:11]
│ ├── 'foo' [as=c1_default:12]
│ ├── 'bar' [as=c2_default:13]
│ ├── 1.23 [as=d1_default:14]
│ ├── 4.56::DECIMAL(10,2) [as=d2_default:15]
│ └── NULL::STRING [as=s_default:16]
│ ├── 10 [as=i2_default:14]
│ ├── 1.0 [as=i3_default:15]
│ ├── 'foo' [as=c1_default:16]
│ ├── 'bar' [as=c2_default:17]
│ ├── 1.23 [as=d1_default:18]
│ ├── 4.56::DECIMAL(10,2) [as=d2_default:19]
│ └── NULL::STRING [as=s_default:20]
└── projections
├── assignment-cast: INT2 [as=i2_cast:17]
│ └── i2_default:11
├── assignment-cast: CHAR [as=c1_cast:18]
│ └── c1_default:12
├── assignment-cast: CHAR [as=c2_cast:19]
│ └── c2_default:13
├── assignment-cast: DECIMAL(10) [as=d1_cast:20]
│ └── d1_default:14
└── assignment-cast: DECIMAL(10) [as=d2_cast:21]
└── d2_default:15
├── assignment-cast: INT2 [as=i2_cast:21]
│ └── i2_default:14
├── assignment-cast: INT8 [as=i3_cast:22]
│ └── i3_default:15
├── assignment-cast: CHAR [as=c1_cast:23]
│ └── c1_default:16
├── assignment-cast: CHAR [as=c2_cast:24]
│ └── c2_default:17
├── assignment-cast: DECIMAL(10) [as=d1_cast:25]
│ └── d1_default:18
└── assignment-cast: DECIMAL(10) [as=d2_cast:26]
└── d2_default:19

# This fails because the cast from FLOAT to BOOL is not a valid assignment cast.
build
INSERT INTO assn_cast_default (k) VALUES (1)
----
error (42804): value type float doesn't match type bool of column "b"

exec-ddl
CREATE TABLE assn_cast_comp (
Expand Down
60 changes: 37 additions & 23 deletions pkg/sql/opt/optbuilder/testdata/update
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ CREATE TABLE assn_cast (
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
d_comp DECIMAL(10, 0) AS (d) STORED,
b BOOL ON UPDATE 1.0::FLOAT
)
----

Expand Down Expand Up @@ -2218,42 +2220,54 @@ update assn_cast

# Test ON UPDATE columns that require assignment casts.
build
UPDATE assn_cast_on_update SET i=1
UPDATE assn_cast_on_update SET i=1, b=true
----
update assn_cast_on_update
├── columns: <none>
├── fetch columns: i:8 d:9 d2:10 d_comp:11 rowid:12
├── fetch columns: i:10 i2:11 d:12 d2:13 d_comp:14 b:15 rowid:16
├── update-mapping:
│ ├── i_new:15 => i:1
│ ├── d_cast:18 => d:2
│ ├── d2_cast:19 => d2:3
│ └── d_comp_cast:20 => d_comp:4
│ ├── 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:20!null i:8 d:9 d2:10 d_comp:11 rowid:12!null crdb_internal_mvcc_timestamp:13 tableoid:14 i_new:15!null d_cast:18!null d2_cast:19!null
├── 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: d_cast:18!null d2_cast:19!null i:8 d:9 d2:10 d_comp:11 rowid:12!null crdb_internal_mvcc_timestamp:13 tableoid:14 i_new:15!null
│ ├── 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: d_on_update:16!null d2_on_update:17!null i:8 d:9 d2:10 d_comp:11 rowid:12!null crdb_internal_mvcc_timestamp:13 tableoid:14 i_new:15!null
│ │ ├── 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:15!null i:8 d:9 d2:10 d_comp:11 rowid:12!null crdb_internal_mvcc_timestamp:13 tableoid:14
│ │ │ ├── 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:8 d:9 d2:10 d_comp:11 rowid:12!null crdb_internal_mvcc_timestamp:13 tableoid:14
│ │ │ │ ├── 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:11
│ │ │ │ └── d:9
│ │ │ │ └── d_comp:14
│ │ │ │ └── d:12
│ │ │ └── projections
│ │ │ └── 1 [as=i_new:15]
│ │ │ ├── 1 [as=i_new:19]
│ │ │ └── true [as=b_new:20]
│ │ └── projections
│ │ ├── 1.23 [as=d_on_update:16]
│ │ └── 1.23::DECIMAL(10,2) [as=d2_on_update:17]
│ │ ├── 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: DECIMAL(10,1) [as=d_cast:18]
│ │ └── d_on_update:16
│ └── assignment-cast: DECIMAL(10,1) [as=d2_cast:19]
│ └── d2_on_update:17
│ ├── 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:20]
└── d_cast:18
└── 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.
Expand Down

0 comments on commit c50a68a

Please sign in to comment.