Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql: add assignment casts for INSERTs #70722

Merged
merged 4 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/generated/sql/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2829,6 +2829,8 @@ may increase either contention or retry errors, or both.</p>
</span></td></tr>
<tr><td><a name="crdb_internal.approximate_timestamp"></a><code>crdb_internal.approximate_timestamp(timestamp: <a href="decimal.html">decimal</a>) &rarr; <a href="timestamp.html">timestamp</a></code></td><td><span class="funcdesc"><p>Converts the crdb_internal_mvcc_timestamp column into an approximate timestamp.</p>
</span></td></tr>
<tr><td><a name="crdb_internal.assignment_cast"></a><code>crdb_internal.assignment_cast(val: anyelement, type: anyelement) &rarr; anyelement</code></td><td><span class="funcdesc"><p>This function is used internally to perform assignment casts during mutations.</p>
</span></td></tr>
<tr><td><a name="crdb_internal.check_consistency"></a><code>crdb_internal.check_consistency(stats_only: <a href="bool.html">bool</a>, start_key: <a href="bytes.html">bytes</a>, end_key: <a href="bytes.html">bytes</a>) &rarr; tuple{int AS range_id, bytes AS start_key, string AS start_key_pretty, string AS status, string AS detail}</code></td><td><span class="funcdesc"><p>Runs a consistency check on ranges touching the specified key range. an empty start or end key is treated as the minimum and maximum possible, respectively. stats_only should only be set to false when targeting a small number of ranges to avoid overloading the cluster. Each returned row contains the range ID, the status (a roachpb.CheckConsistencyResponse_Status), and verbose detail.</p>
<p>Example usage:
SELECT * FROM crdb_internal.check_consistency(true, ‘\x02’, ‘\x04’)</p>
Expand Down
7 changes: 6 additions & 1 deletion pkg/sql/colexec/builtin_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/execinfra"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/sql/types"
"github.com/cockroachdb/errors"
)

type defaultBuiltinFuncOperator struct {
Expand Down Expand Up @@ -118,7 +119,11 @@ func NewBuiltinFunctionOperator(
outputIdx int,
input colexecop.Operator,
) (colexecop.Operator, error) {
switch funcExpr.ResolvedOverload().SpecializedVecBuiltin {
overload := funcExpr.ResolvedOverload()
if overload.FnWithExprs != nil {
return nil, errors.New("builtins with FnWithExprs are not supported in the vectorized engine")
}
switch overload.SpecializedVecBuiltin {
case tree.SubstringStringIntInt:
input = colexecutils.NewVectorTypeEnforcer(allocator, input, types.String, outputIdx)
return newSubstringOperator(
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func (r *insertRun) initRowContainer(params runParams, columns colinfo.ResultCol
// processSourceRow processes one row from the source for insertion and, if
// result rows are needed, saves it in the result row container.
func (r *insertRun) processSourceRow(params runParams, rowVals tree.Datums) error {
if err := enforceLocalColumnConstraints(rowVals, r.insertCols); err != nil {
if err := enforceLocalColumnConstraints(rowVals, r.insertCols, false /* isUpdate */); err != nil {
return err
}

Expand Down
3 changes: 0 additions & 3 deletions pkg/sql/logictest/testdata/logic_test/alter_column_type
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,6 @@ rowid INT8 false unique_rowid() · {primary} true
statement ok
INSERT INTO t2 VALUES ('5')

statement error pq: value type int doesn't match type string of column "id"
INSERT INTO t2 VALUES (6)

# Verify ALTER COLUMN TYPE from INT to STRING works correctly.
# Column order should stay the same.
statement ok
Expand Down
4 changes: 2 additions & 2 deletions pkg/sql/logictest/testdata/logic_test/array
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ SELECT * FROM a
{hello}
{goodbye}

statement error value type collatedstring{fr}\[\] doesn't match type collatedstring{en}\[\] of column "b"
statement ok
INSERT INTO a VALUES (ARRAY['hello' COLLATE fr])

statement ok
Expand Down Expand Up @@ -841,7 +841,7 @@ CREATE TABLE a (b STRING[])
statement ok
INSERT INTO a VALUES (ARRAY['foo'])

statement error value type collatedstring{en}\[\] doesn't match type string\[\] of column "b"
statement ok
INSERT INTO a VALUES (ARRAY['foo' COLLATE en])

statement ok
Expand Down
180 changes: 180 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/cast
Original file line number Diff line number Diff line change
@@ -1,3 +1,183 @@
# Tests for assignment casts.
subtest assignment_casts

statement ok
CREATE TABLE assn_cast (
c CHAR,
vc VARCHAR(1),
qc "char",
b BIT,
i INT,
t timestamp,
d DECIMAL(10, 0),
s STRING
)

statement ok
INSERT INTO assn_cast(c) VALUES ('a')

statement ok
INSERT INTO assn_cast(c) VALUES (null), ('b')

statement error value too long for type CHAR
INSERT INTO assn_cast(c) VALUES ('abc')

query T
INSERT INTO assn_cast(c) VALUES (1) RETURNING c
----
1

statement error value too long for type CHAR
INSERT INTO assn_cast(c) VALUES (123)

statement ok
PREPARE insert_c AS INSERT INTO assn_cast(c) VALUES ($1)

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

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

statement ok
DELETE FROM assn_cast

statement
EXECUTE insert_c(' ')

statement
EXECUTE insert_c(' '::STRING)

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

statement ok
INSERT INTO assn_cast(vc) VALUES ('a')

statement ok
INSERT INTO assn_cast(vc) VALUES (null), ('b')

statement error value too long for type VARCHAR\(1\)
INSERT INTO assn_cast(vc) VALUES ('abc')

query T
INSERT INTO assn_cast(vc) VALUES (1) RETURNING vc
----
1

statement error value too long for type VARCHAR\(1\)
INSERT INTO assn_cast(vc) VALUES (123)

statement ok
INSERT INTO assn_cast(qc) VALUES ('a')

statement ok
INSERT INTO assn_cast(qc) VALUES (null), ('b')

query T
INSERT INTO assn_cast(qc) VALUES ('abc') RETURNING qc
----
a

# Note: This statement fails in Postgres because the default integer type is an
# INT4, and the INT4 -> "char" cast is explicit. Our default integer type
# is an INT8 and INT8 -> "char" is an assignment cast.
query T
INSERT INTO assn_cast(qc) VALUES (123) RETURNING qc
----
{

statement error \"char\" out of range
INSERT INTO assn_cast(qc) VALUES (1234)

statement ok
PREPARE insert_qc AS INSERT INTO assn_cast(qc) VALUES ($1)

statement ok
DELETE FROM assn_cast

statement ok
EXECUTE insert_qc('foo')

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

query T
SELECT qc FROM assn_cast
----
f
f

statement ok
INSERT into assn_cast(b) VALUES ('1')

statement ok
INSERT INTO assn_cast(b) VALUES (null), ('1')

# TODO(mgartner): To match Postgres behavior, this statement should fail with
# the message "value too long for type BIT".
statement ok
INSERT into assn_cast(b) VALUES ('01')

statement error value type int doesn't match type bit of column \"b\"
INSERT into assn_cast(b) VALUES (1)

statement ok
INSERT INTO assn_cast(i) VALUES ('1')

statement ok
INSERT INTO assn_cast(i) VALUES (null), ('1')

statement ok
PREPARE insert_i AS INSERT INTO assn_cast(i) VALUES ($1)

statement ok
EXECUTE insert_i('1')

statement error value type string doesn't match type int of column \"i\"
INSERT INTO assn_cast(i) VALUES ('1'::STRING)

statement ok
INSERT INTO assn_cast(t) VALUES ('1970-01-01'::timestamptz)

statement ok
INSERT INTO assn_cast(d) VALUES (11.22), (88.99)

statement ok
PREPARE insert_d AS INSERT INTO assn_cast(d) VALUES ($1)

statement ok
EXECUTE insert_d(123.45)

statement ok
PREPARE insert_d2 AS INSERT INTO assn_cast(d) SELECT * FROM (VALUES ($1::DECIMAL(10, 2)))

statement ok
EXECUTE insert_d2(67.89)

query F rowsort
SELECT d FROM assn_cast WHERE d IS NOT NULL
----
11
89
123
68

statement ok
INSERT INTO assn_cast(s) VALUES (1)

statement ok
PREPARE insert_s AS INSERT INTO assn_cast(s) VALUES ($1)

# TODO(mgartner): This should succeed to match the behavior of Postgres.
statement error expected EXECUTE parameter expression to have type string, but \'1\' has type int
EXECUTE insert_s(1)

subtest regressions

statement ok
CREATE TABLE t45837 AS SELECT 1.25::decimal AS d

Expand Down
10 changes: 8 additions & 2 deletions pkg/sql/logictest/testdata/logic_test/collatedstring
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,10 @@ INSERT INTO t VALUES
('x' COLLATE en),
('ü' COLLATE en)

statement error value type collatedstring{de} doesn't match type collatedstring{en} of column "a"
INSERT INTO t VALUES ('X' COLLATE de)
statement ok
INSERT INTO t VALUES
('X' COLLATE de),
('y' COLLATE de)

query T
SELECT a FROM t ORDER BY t.a
Expand All @@ -243,6 +245,8 @@ b
B
ü
x
X
y

query T
SELECT a FROM t ORDER BY t.a COLLATE da
Expand All @@ -252,6 +256,8 @@ A
b
B
x
X
y
ü

query T
Expand Down
40 changes: 39 additions & 1 deletion pkg/sql/logictest/testdata/logic_test/computed
Original file line number Diff line number Diff line change
Expand Up @@ -883,9 +883,17 @@ CREATE TABLE x (
b INT AS (a+1) STORED
)

query error value type decimal doesn't match type int of column "a"
statement ok
INSERT INTO x VALUES(1.4)

query II
SELECT * FROM x
----
1 2

query error value type date doesn't match type int of column "a"
INSERT INTO x VALUES('1970-01-01'::date)

# Regression test for #34901: verify that builtins can be used in computed
# column expressions without a "memory budget exceeded" error while backfilling
statement ok
Expand Down Expand Up @@ -1025,3 +1033,33 @@ SET experimental_computed_column_rewrites = "bad"

statement error invalid column rewrites expression
SET CLUSTER SETTING sql.defaults.experimental_computed_column_rewrites = "bad"

# Regression test for #69327. Computed columns should be evaluated after
# assignment casts have been performed.
statement ok
CREATE TABLE t69327 (
c "char",
v STRING AS (c) STORED
);
INSERT INTO t69327 VALUES ('foo'::STRING)

# Both columns should have a value of "f".
query TT
SELECT * FROM t69327
----
f f

# Regression test for #69665.Computed columns should be evaluated after
# assignment casts have been performed.
statement ok
CREATE TABLE t69665 (
c CHAR,
v STRING AS (c) STORED
);
INSERT INTO t69665 VALUES (' '::STRING)

# Both columns should be empty values.
query II
SELECT length(c), length(v) FROM t69665
----
0 0
2 changes: 1 addition & 1 deletion pkg/sql/logictest/testdata/logic_test/information_schema
Original file line number Diff line number Diff line change
Expand Up @@ -2367,7 +2367,7 @@ char_len dc 1 4
char_len ec 12 48
char_len dv NULL NULL
char_len ev 12 48
char_len dq NULL NULL
char_len dq 1 4
char_len f NULL NULL
char_len g 1 NULL
char_len h 12 NULL
Expand Down
21 changes: 13 additions & 8 deletions pkg/sql/logictest/testdata/logic_test/insert
Original file line number Diff line number Diff line change
Expand Up @@ -129,26 +129,31 @@ INSERT INTO kv4 (int, bool) VALUES (3, 'a')
statement ok
INSERT INTO kv4 (int, bool) VALUES (3, true)

statement error value type int doesn't match type char of column "char"
statement error value too long for type CHAR
INSERT INTO kv4 (int, char) VALUES (4, 11)

statement ok
INSERT INTO kv4 (int, char) VALUES (4, 1)

statement ok
INSERT INTO kv4 (int, char) VALUES (4, 'a')
INSERT INTO kv4 (int, char) VALUES (5, 'a')

statement error value type int doesn't match type float of column "float"
INSERT INTO kv4 (int, float) VALUES (5, 1::INT)
statement ok
INSERT INTO kv4 (int, float) VALUES (6, 1::INT)

statement ok
INSERT INTO kv4 (int, float) VALUES (5, 2.3)
INSERT INTO kv4 (int, float) VALUES (7, 2.3)

query ITBTR rowsort
SELECT * from kv4
----
1 NULL NULL NULL NULL
2 1 NULL NULL NULL
3 NULL true NULL NULL
4 NULL NULL a NULL
5 NULL NULL NULL 2.3
4 NULL NULL 1 NULL
5 NULL NULL a NULL
6 NULL NULL NULL 1
7 NULL NULL NULL 2.3

statement ok
CREATE TABLE kv5 (
Expand Down Expand Up @@ -446,7 +451,7 @@ INSERT INTO string_t VALUES ('str')
query error value type string doesn't match type bytes of column "b"
INSERT INTO bytes_t SELECT * FROM string_t

query error value type bytes doesn't match type string of column "s"
statement ok
INSERT INTO string_t SELECT * FROM bytes_t

subtest string_width_check
Expand Down
Loading