github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/split_test.go (about) 1 // Copyright 2016 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 "strings" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/roachpb" 20 "github.com/cockroachdb/cockroach/pkg/server" 21 "github.com/cockroachdb/cockroach/pkg/sql/tests" 22 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 23 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" 24 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 25 ) 26 27 func TestSplitAt(t *testing.T) { 28 defer leaktest.AfterTest(t)() 29 30 params, _ := tests.CreateTestServerParams() 31 s, db, _ := serverutils.StartServer(t, params) 32 defer s.Stopper().Stop(context.Background()) 33 34 r := sqlutils.MakeSQLRunner(db) 35 36 r.Exec(t, "CREATE DATABASE d") 37 r.Exec(t, `CREATE TABLE d.t ( 38 i INT, 39 s STRING, 40 PRIMARY KEY (i, s), 41 INDEX s_idx (s) 42 )`) 43 r.Exec(t, `CREATE TABLE d.i (k INT PRIMARY KEY)`) 44 45 tests := []struct { 46 in string 47 error string 48 args []interface{} 49 }{ 50 { 51 in: "ALTER TABLE d.t SPLIT AT VALUES (2, 'b')", 52 }, 53 { 54 // Splitting at an existing split is a silent no-op. 55 in: "ALTER TABLE d.t SPLIT AT VALUES (2, 'b')", 56 }, 57 { 58 in: "ALTER TABLE d.t SPLIT AT VALUES (3, 'c'), (4, 'd')", 59 }, 60 { 61 in: "ALTER TABLE d.t SPLIT AT SELECT 5, 'd'", 62 }, 63 { 64 in: "ALTER TABLE d.t SPLIT AT SELECT * FROM (VALUES (6, 'e'), (7, 'f')) AS a", 65 }, 66 { 67 in: "ALTER TABLE d.t SPLIT AT VALUES (10)", 68 }, 69 { 70 in: "ALTER TABLE d.t SPLIT AT VALUES ('c', 3)", 71 error: "could not parse \"c\" as type int", 72 }, 73 { 74 in: "ALTER TABLE d.t SPLIT AT VALUES (i, s)", 75 error: `column "i" does not exist`, 76 }, 77 { 78 in: "ALTER INDEX d.t@s_idx SPLIT AT VALUES ('f')", 79 }, 80 { 81 in: "ALTER INDEX d.t@not_present SPLIT AT VALUES ('g')", 82 error: `index "not_present" does not exist`, 83 }, 84 { 85 in: "ALTER TABLE d.i SPLIT AT VALUES (avg(1::float))", 86 error: "aggregate functions are not allowed in VALUES", 87 }, 88 { 89 in: "ALTER TABLE d.i SPLIT AT VALUES ($1)", 90 args: []interface{}{8}, 91 }, 92 { 93 in: "ALTER TABLE d.i SPLIT AT VALUES ($1)", 94 error: "no value provided for placeholder: $1", 95 }, 96 { 97 in: "ALTER TABLE d.i SPLIT AT VALUES ($1)", 98 args: []interface{}{"blah"}, 99 error: "error in argument for $1: strconv.ParseInt", 100 }, 101 { 102 in: "ALTER TABLE d.i SPLIT AT VALUES ($1::string)", 103 args: []interface{}{"1"}, 104 error: "SPLIT AT data column 1 (k) must be of type int, not type string", 105 }, 106 { 107 in: "ALTER TABLE d.i SPLIT AT VALUES ((SELECT 1))", 108 }, 109 { 110 in: "ALTER TABLE d.i SPLIT AT VALUES (10) WITH EXPIRATION '1 day'", 111 }, 112 { 113 in: "ALTER TABLE d.i SPLIT AT VALUES (11) WITH EXPIRATION '1 day'::interval", 114 }, 115 { 116 in: "ALTER TABLE d.i SPLIT AT VALUES (12) WITH EXPIRATION '7258118400000000000.0'", 117 }, 118 { 119 in: "ALTER TABLE d.i SPLIT AT VALUES (13) WITH EXPIRATION '2200-01-01 00:00:00.0'", 120 }, 121 { 122 in: "ALTER TABLE d.i SPLIT AT VALUES (14) WITH EXPIRATION TIMESTAMP '2200-01-01 00:00:00.0'", 123 }, 124 { 125 in: "ALTER TABLE d.i SPLIT AT VALUES (15) WITH EXPIRATION '2200-01-01 00:00:00.0':::timestamp", 126 }, 127 { 128 in: "ALTER TABLE d.i SPLIT AT VALUES (16) WITH EXPIRATION TIMESTAMPTZ '2200-01-01 00:00:00.0'", 129 }, 130 { 131 in: "ALTER TABLE d.i SPLIT AT VALUES (17) WITH EXPIRATION 'a'", 132 error: "SPLIT AT: value is neither timestamp, decimal, nor interval", 133 }, 134 { 135 in: "ALTER TABLE d.i SPLIT AT VALUES (17) WITH EXPIRATION true", 136 error: "SPLIT AT: expected timestamp, decimal, or interval, got bool (*tree.DBool)", 137 }, 138 { 139 in: "ALTER TABLE d.i SPLIT AT VALUES (17) WITH EXPIRATION '1969-01-01 00:00:00.0'", 140 error: "SPLIT AT: timestamp before 1970-01-01T00:00:00Z is invalid", 141 }, 142 { 143 in: "ALTER TABLE d.i SPLIT AT VALUES (17) WITH EXPIRATION '1970-01-01 00:00:00.0'", 144 error: "SPLIT AT: zero timestamp is invalid", 145 }, 146 { 147 in: "ALTER TABLE d.i SPLIT AT VALUES (17) WITH EXPIRATION '-1 day'::interval", 148 error: "SPLIT AT: expiration time should be greater than or equal to current time", 149 }, 150 { 151 in: "ALTER TABLE d.i SPLIT AT VALUES (17) WITH EXPIRATION '0.1us'", 152 error: "SPLIT AT: interval value '0.1us' too small, absolute value must be >= 1µs", 153 }, 154 } 155 156 for _, tt := range tests { 157 var key roachpb.Key 158 var pretty string 159 var expirationTimestamp gosql.NullString 160 err := db.QueryRow(tt.in, tt.args...).Scan(&key, &pretty, &expirationTimestamp) 161 if err != nil && tt.error == "" { 162 t.Fatalf("%s: unexpected error: %s", tt.in, err) 163 } else if tt.error != "" && err == nil { 164 t.Fatalf("%s: expected error: %s", tt.in, tt.error) 165 } else if err != nil && tt.error != "" { 166 if !strings.Contains(err.Error(), tt.error) { 167 t.Fatalf("%s: unexpected error: %s", tt.in, err) 168 } 169 } else { 170 // Successful split, verify it happened. 171 rng, err := s.(*server.TestServer).LookupRange(key) 172 if err != nil { 173 t.Fatal(err) 174 } 175 expect := roachpb.Key(rng.StartKey) 176 if !expect.Equal(key) { 177 t.Fatalf("%s: expected range start %s, got %s", tt.in, expect, pretty) 178 } 179 } 180 } 181 }