github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/mutation_test.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package sql_test 12 13 import ( 14 "context" 15 gosql "database/sql" 16 "testing" 17 18 "github.com/cockroachdb/cockroach/pkg/sql/tests" 19 "github.com/cockroachdb/cockroach/pkg/testutils" 20 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 21 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 22 ) 23 24 // Regression tests for #22304. 25 // Checks that a mutation with RETURNING checks low-level constraints 26 // before returning anything -- or that at least no constraint-violating 27 // values are visible to the client. 28 func TestConstraintValidationBeforeBuffering(t *testing.T) { 29 defer leaktest.AfterTest(t)() 30 31 params, _ := tests.CreateTestServerParams() 32 s, db, _ := serverutils.StartServer(t, params) 33 defer s.Stopper().Stop(context.Background()) 34 35 if _, err := db.Exec(` 36 CREATE DATABASE d; 37 CREATE TABLE d.a(a INT PRIMARY KEY); 38 INSERT INTO d.a(a) VALUES (1); 39 `); err != nil { 40 t.Fatal(err) 41 } 42 43 step1 := func() (*gosql.Rows, error) { 44 return db.Query("INSERT INTO d.a(a) TABLE generate_series(1,3000) RETURNING a") 45 } 46 step2 := func() (*gosql.Rows, error) { 47 if _, err := db.Exec(`INSERT INTO d.a(a) TABLE generate_series(2, 3000)`); err != nil { 48 return nil, err 49 } 50 return db.Query("UPDATE d.a SET a = a - 1 WHERE a > 1 RETURNING a") 51 } 52 for i, step := range []func() (*gosql.Rows, error){step1, step2} { 53 rows, err := step() 54 if err != nil { 55 if !testutils.IsError(err, `duplicate key value \(a\)=\(1\)`) { 56 t.Errorf("%d: %v", i, err) 57 } 58 } else { 59 defer rows.Close() 60 61 hasNext := rows.Next() 62 if !hasNext { 63 t.Errorf("%d: returning claims to return no error, yet returns no rows either", i) 64 } else { 65 var val int 66 err := rows.Scan(&val) 67 68 if err != nil { 69 if !testutils.IsError(err, `duplicate key value \(a\)=\(1\)`) { 70 t.Errorf("%d: %v", i, err) 71 } 72 } else { 73 // No error. Maybe it'll come later. 74 if val == 1 { 75 t.Errorf("%d: returning returns rows, including an invalid duplicate", i) 76 } 77 78 for rows.Next() { 79 err := rows.Scan(&val) 80 if err != nil { 81 if !testutils.IsError(err, `duplicate key value \(a\)=\(1\)`) { 82 t.Errorf("%d: %v", i, err) 83 } 84 } 85 if val == 1 { 86 t.Errorf("%d returning returns rows, including an invalid duplicate", i) 87 } 88 } 89 } 90 } 91 } 92 } 93 }