github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sqlbase/structured_test.go (about) 1 // Copyright 2015 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 sqlbase 12 13 import ( 14 "context" 15 "encoding/json" 16 "fmt" 17 "reflect" 18 "testing" 19 20 "github.com/cockroachdb/cockroach/pkg/base" 21 "github.com/cockroachdb/cockroach/pkg/keys" 22 "github.com/cockroachdb/cockroach/pkg/kv" 23 "github.com/cockroachdb/cockroach/pkg/roachpb" 24 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 25 "github.com/cockroachdb/cockroach/pkg/sql/types" 26 "github.com/cockroachdb/cockroach/pkg/testutils" 27 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 28 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" 29 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 30 "github.com/cockroachdb/cockroach/pkg/util/protoutil" 31 ) 32 33 // Makes an IndexDescriptor with all columns being ascending. 34 func makeIndexDescriptor(name string, columnNames []string) IndexDescriptor { 35 dirs := make([]IndexDescriptor_Direction, 0, len(columnNames)) 36 for range columnNames { 37 dirs = append(dirs, IndexDescriptor_ASC) 38 } 39 idx := IndexDescriptor{ 40 ID: IndexID(0), 41 Name: name, 42 ColumnNames: columnNames, 43 ColumnDirections: dirs, 44 } 45 return idx 46 } 47 48 func TestAllocateIDs(t *testing.T) { 49 defer leaktest.AfterTest(t)() 50 51 desc := NewMutableCreatedTableDescriptor(TableDescriptor{ 52 ParentID: keys.MinUserDescID, 53 ID: keys.MinUserDescID + 1, 54 Name: "foo", 55 Columns: []ColumnDescriptor{ 56 {Name: "a", Type: types.Int}, 57 {Name: "b", Type: types.Int}, 58 {Name: "c", Type: types.Int}, 59 }, 60 PrimaryIndex: makeIndexDescriptor("c", []string{"a", "b"}), 61 Indexes: []IndexDescriptor{ 62 makeIndexDescriptor("d", []string{"b", "a"}), 63 makeIndexDescriptor("e", []string{"b"}), 64 func() IndexDescriptor { 65 idx := makeIndexDescriptor("f", []string{"c"}) 66 idx.EncodingType = PrimaryIndexEncoding 67 return idx 68 }(), 69 }, 70 Privileges: NewDefaultPrivilegeDescriptor(), 71 FormatVersion: FamilyFormatVersion, 72 }) 73 if err := desc.AllocateIDs(); err != nil { 74 t.Fatal(err) 75 } 76 77 expected := NewMutableCreatedTableDescriptor(TableDescriptor{ 78 ParentID: keys.MinUserDescID, 79 ID: keys.MinUserDescID + 1, 80 Version: 1, 81 Name: "foo", 82 Columns: []ColumnDescriptor{ 83 {ID: 1, Name: "a", Type: types.Int}, 84 {ID: 2, Name: "b", Type: types.Int}, 85 {ID: 3, Name: "c", Type: types.Int}, 86 }, 87 Families: []ColumnFamilyDescriptor{ 88 { 89 ID: 0, Name: "primary", 90 ColumnNames: []string{"a", "b", "c"}, 91 ColumnIDs: []ColumnID{1, 2, 3}, 92 DefaultColumnID: 3, 93 }, 94 }, 95 PrimaryIndex: IndexDescriptor{ 96 ID: 1, Name: "c", ColumnIDs: []ColumnID{1, 2}, 97 ColumnNames: []string{"a", "b"}, 98 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, 99 IndexDescriptor_ASC}}, 100 Indexes: []IndexDescriptor{ 101 {ID: 2, Name: "d", ColumnIDs: []ColumnID{2, 1}, ColumnNames: []string{"b", "a"}, 102 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, 103 IndexDescriptor_ASC}}, 104 {ID: 3, Name: "e", ColumnIDs: []ColumnID{2}, ColumnNames: []string{"b"}, 105 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 106 ExtraColumnIDs: []ColumnID{1}}, 107 {ID: 4, Name: "f", ColumnIDs: []ColumnID{3}, ColumnNames: []string{"c"}, 108 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 109 EncodingType: PrimaryIndexEncoding}, 110 }, 111 Privileges: NewDefaultPrivilegeDescriptor(), 112 NextColumnID: 4, 113 NextFamilyID: 1, 114 NextIndexID: 5, 115 NextMutationID: 1, 116 FormatVersion: FamilyFormatVersion, 117 }) 118 if !reflect.DeepEqual(expected, desc) { 119 a, _ := json.MarshalIndent(expected, "", " ") 120 b, _ := json.MarshalIndent(desc, "", " ") 121 t.Fatalf("expected %s, but found %s", a, b) 122 } 123 124 if err := desc.AllocateIDs(); err != nil { 125 t.Fatal(err) 126 } 127 if !reflect.DeepEqual(expected, desc) { 128 a, _ := json.MarshalIndent(expected, "", " ") 129 b, _ := json.MarshalIndent(desc, "", " ") 130 t.Fatalf("expected %s, but found %s", a, b) 131 } 132 } 133 134 func TestValidateTableDesc(t *testing.T) { 135 defer leaktest.AfterTest(t)() 136 137 testData := []struct { 138 err string 139 desc TableDescriptor 140 }{ 141 {`empty table name`, 142 TableDescriptor{}}, 143 {`invalid table ID 0`, 144 TableDescriptor{ID: 0, Name: "foo"}}, 145 {`invalid parent ID 0`, 146 TableDescriptor{ID: 2, Name: "foo"}}, 147 {`table "foo" is encoded using using version 0, but this client only supports version 2 and 3`, 148 TableDescriptor{ID: 2, ParentID: 1, Name: "foo"}}, 149 {`table must contain at least 1 column`, 150 TableDescriptor{ 151 ID: 2, 152 ParentID: 1, 153 Name: "foo", 154 FormatVersion: FamilyFormatVersion, 155 }}, 156 {`empty column name`, 157 TableDescriptor{ 158 ID: 2, 159 ParentID: 1, 160 Name: "foo", 161 FormatVersion: FamilyFormatVersion, 162 Columns: []ColumnDescriptor{ 163 {ID: 0}, 164 }, 165 NextColumnID: 2, 166 }}, 167 {`invalid column ID 0`, 168 TableDescriptor{ 169 ID: 2, 170 ParentID: 1, 171 Name: "foo", 172 FormatVersion: FamilyFormatVersion, 173 Columns: []ColumnDescriptor{ 174 {ID: 0, Name: "bar"}, 175 }, 176 NextColumnID: 2, 177 }}, 178 {`table must contain a primary key`, 179 TableDescriptor{ 180 ID: 2, 181 ParentID: 1, 182 Name: "foo", 183 FormatVersion: FamilyFormatVersion, 184 Columns: []ColumnDescriptor{ 185 {ID: 1, Name: "bar"}, 186 }, 187 Families: []ColumnFamilyDescriptor{ 188 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 189 }, 190 NextColumnID: 2, 191 NextFamilyID: 1, 192 }}, 193 {`duplicate column name: "bar"`, 194 TableDescriptor{ 195 ID: 2, 196 ParentID: 1, 197 Name: "foo", 198 FormatVersion: FamilyFormatVersion, 199 Columns: []ColumnDescriptor{ 200 {ID: 1, Name: "bar"}, 201 {ID: 1, Name: "bar"}, 202 }, 203 NextColumnID: 2, 204 }}, 205 {`column "blah" duplicate ID of column "bar": 1`, 206 TableDescriptor{ 207 ID: 2, 208 ParentID: 1, 209 Name: "foo", 210 FormatVersion: FamilyFormatVersion, 211 Columns: []ColumnDescriptor{ 212 {ID: 1, Name: "bar"}, 213 {ID: 1, Name: "blah"}, 214 }, 215 NextColumnID: 2, 216 }}, 217 {`at least 1 column family must be specified`, 218 TableDescriptor{ 219 ID: 2, 220 ParentID: 1, 221 Name: "foo", 222 FormatVersion: FamilyFormatVersion, 223 Columns: []ColumnDescriptor{ 224 {ID: 1, Name: "bar"}, 225 }, 226 NextColumnID: 2, 227 }}, 228 {`the 0th family must have ID 0`, 229 TableDescriptor{ 230 ID: 2, 231 ParentID: 1, 232 Name: "foo", 233 FormatVersion: FamilyFormatVersion, 234 Columns: []ColumnDescriptor{ 235 {ID: 1, Name: "bar"}, 236 }, 237 Families: []ColumnFamilyDescriptor{ 238 {ID: 1}, 239 }, 240 NextColumnID: 2, 241 }}, 242 {`duplicate family name: "baz"`, 243 TableDescriptor{ 244 ID: 2, 245 ParentID: 1, 246 Name: "foo", 247 FormatVersion: FamilyFormatVersion, 248 Columns: []ColumnDescriptor{ 249 {ID: 1, Name: "bar"}, 250 }, 251 Families: []ColumnFamilyDescriptor{ 252 {ID: 0, Name: "baz"}, 253 {ID: 1, Name: "baz"}, 254 }, 255 NextColumnID: 2, 256 NextFamilyID: 2, 257 }}, 258 {`family "qux" duplicate ID of family "baz": 0`, 259 TableDescriptor{ 260 ID: 2, 261 ParentID: 1, 262 Name: "foo", 263 FormatVersion: FamilyFormatVersion, 264 Columns: []ColumnDescriptor{ 265 {ID: 1, Name: "bar"}, 266 }, 267 Families: []ColumnFamilyDescriptor{ 268 {ID: 0, Name: "baz"}, 269 {ID: 0, Name: "qux"}, 270 }, 271 NextColumnID: 2, 272 NextFamilyID: 2, 273 }}, 274 {`duplicate family name: "baz"`, 275 TableDescriptor{ 276 ID: 2, 277 ParentID: 1, 278 Name: "foo", 279 FormatVersion: FamilyFormatVersion, 280 Columns: []ColumnDescriptor{ 281 {ID: 1, Name: "bar"}, 282 }, 283 Families: []ColumnFamilyDescriptor{ 284 {ID: 0, Name: "baz"}, 285 {ID: 3, Name: "baz"}, 286 }, 287 NextColumnID: 2, 288 NextFamilyID: 2, 289 }}, 290 {`mismatched column ID size (1) and name size (0)`, 291 TableDescriptor{ 292 ID: 2, 293 ParentID: 1, 294 Name: "foo", 295 FormatVersion: FamilyFormatVersion, 296 Columns: []ColumnDescriptor{ 297 {ID: 1, Name: "bar"}, 298 }, 299 Families: []ColumnFamilyDescriptor{ 300 {ID: 0, Name: "baz", ColumnIDs: []ColumnID{1}}, 301 }, 302 NextColumnID: 2, 303 NextFamilyID: 1, 304 }}, 305 {`family "baz" contains unknown column "2"`, 306 TableDescriptor{ 307 ID: 2, 308 ParentID: 1, 309 Name: "foo", 310 FormatVersion: FamilyFormatVersion, 311 Columns: []ColumnDescriptor{ 312 {ID: 1, Name: "bar"}, 313 }, 314 Families: []ColumnFamilyDescriptor{ 315 {ID: 0, Name: "baz", ColumnIDs: []ColumnID{2}, ColumnNames: []string{"bar"}}, 316 }, 317 NextColumnID: 2, 318 NextFamilyID: 1, 319 }}, 320 {`family "baz" column 1 should have name "bar", but found name "qux"`, 321 TableDescriptor{ 322 ID: 2, 323 ParentID: 1, 324 Name: "foo", 325 FormatVersion: FamilyFormatVersion, 326 Columns: []ColumnDescriptor{ 327 {ID: 1, Name: "bar"}, 328 }, 329 Families: []ColumnFamilyDescriptor{ 330 {ID: 0, Name: "baz", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"qux"}}, 331 }, 332 NextColumnID: 2, 333 NextFamilyID: 1, 334 }}, 335 {`column 1 is not in any column family`, 336 TableDescriptor{ 337 ID: 2, 338 ParentID: 1, 339 Name: "foo", 340 FormatVersion: FamilyFormatVersion, 341 Columns: []ColumnDescriptor{ 342 {ID: 1, Name: "bar"}, 343 }, 344 Families: []ColumnFamilyDescriptor{ 345 {ID: 0, Name: "baz"}, 346 }, 347 NextColumnID: 2, 348 NextFamilyID: 1, 349 }}, 350 {`column 1 is in both family 0 and 1`, 351 TableDescriptor{ 352 ID: 2, 353 ParentID: 1, 354 Name: "foo", 355 FormatVersion: FamilyFormatVersion, 356 Columns: []ColumnDescriptor{ 357 {ID: 1, Name: "bar"}, 358 }, 359 Families: []ColumnFamilyDescriptor{ 360 {ID: 0, Name: "baz", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 361 {ID: 1, Name: "qux", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 362 }, 363 NextColumnID: 2, 364 NextFamilyID: 2, 365 }}, 366 {`table must contain a primary key`, 367 TableDescriptor{ 368 ID: 2, 369 ParentID: 1, 370 Name: "foo", 371 FormatVersion: FamilyFormatVersion, 372 Columns: []ColumnDescriptor{ 373 {ID: 1, Name: "bar"}, 374 }, 375 Families: []ColumnFamilyDescriptor{ 376 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 377 }, 378 PrimaryIndex: IndexDescriptor{ 379 ID: 0, 380 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}}, 381 NextColumnID: 2, 382 NextFamilyID: 1, 383 }}, 384 {`invalid index ID 0`, 385 TableDescriptor{ 386 ID: 2, 387 ParentID: 1, 388 Name: "foo", 389 FormatVersion: FamilyFormatVersion, 390 Columns: []ColumnDescriptor{ 391 {ID: 1, Name: "bar"}, 392 }, 393 Families: []ColumnFamilyDescriptor{ 394 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 395 }, 396 PrimaryIndex: IndexDescriptor{ID: 0, Name: "bar", 397 ColumnIDs: []ColumnID{0}, 398 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}}, 399 NextColumnID: 2, 400 NextFamilyID: 1, 401 }}, 402 {`index "bar" must contain at least 1 column`, 403 TableDescriptor{ 404 ID: 2, 405 ParentID: 1, 406 Name: "foo", 407 FormatVersion: FamilyFormatVersion, 408 Columns: []ColumnDescriptor{ 409 {ID: 1, Name: "bar"}, 410 }, 411 Families: []ColumnFamilyDescriptor{ 412 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 413 }, 414 PrimaryIndex: IndexDescriptor{ 415 ID: 1, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}, 416 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 417 }, 418 Indexes: []IndexDescriptor{ 419 {ID: 2, Name: "bar"}, 420 }, 421 NextColumnID: 2, 422 NextFamilyID: 1, 423 NextIndexID: 3, 424 }}, 425 {`mismatched column IDs (1) and names (0)`, 426 TableDescriptor{ 427 ID: 2, 428 ParentID: 1, 429 Name: "foo", 430 FormatVersion: FamilyFormatVersion, 431 Columns: []ColumnDescriptor{ 432 {ID: 1, Name: "bar"}, 433 }, 434 Families: []ColumnFamilyDescriptor{ 435 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 436 }, 437 PrimaryIndex: IndexDescriptor{ID: 1, Name: "bar", ColumnIDs: []ColumnID{1}}, 438 NextColumnID: 2, 439 NextFamilyID: 1, 440 NextIndexID: 2, 441 }}, 442 {`mismatched column IDs (1) and names (2)`, 443 TableDescriptor{ 444 ID: 2, 445 ParentID: 1, 446 Name: "foo", 447 FormatVersion: FamilyFormatVersion, 448 Columns: []ColumnDescriptor{ 449 {ID: 1, Name: "bar"}, 450 {ID: 2, Name: "blah"}, 451 }, 452 Families: []ColumnFamilyDescriptor{ 453 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1, 2}, ColumnNames: []string{"bar", "blah"}}, 454 }, 455 PrimaryIndex: IndexDescriptor{ID: 1, Name: "bar", 456 ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar", "blah"}, 457 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 458 }, 459 NextColumnID: 3, 460 NextFamilyID: 1, 461 NextIndexID: 2, 462 }}, 463 {`duplicate index name: "bar"`, 464 TableDescriptor{ 465 ID: 2, 466 ParentID: 1, 467 Name: "foo", 468 FormatVersion: FamilyFormatVersion, 469 Columns: []ColumnDescriptor{ 470 {ID: 1, Name: "bar"}, 471 }, 472 Families: []ColumnFamilyDescriptor{ 473 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 474 }, 475 PrimaryIndex: IndexDescriptor{ID: 1, Name: "bar", 476 ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}, 477 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 478 }, 479 Indexes: []IndexDescriptor{ 480 {ID: 2, Name: "bar", ColumnIDs: []ColumnID{1}, 481 ColumnNames: []string{"bar"}, 482 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 483 }, 484 }, 485 NextColumnID: 2, 486 NextFamilyID: 1, 487 NextIndexID: 3, 488 }}, 489 {`index "blah" duplicate ID of index "bar": 1`, 490 TableDescriptor{ 491 ID: 2, 492 ParentID: 1, 493 Name: "foo", 494 FormatVersion: FamilyFormatVersion, 495 Columns: []ColumnDescriptor{ 496 {ID: 1, Name: "bar"}, 497 }, 498 Families: []ColumnFamilyDescriptor{ 499 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 500 }, 501 PrimaryIndex: IndexDescriptor{ID: 1, Name: "bar", ColumnIDs: []ColumnID{1}, 502 ColumnNames: []string{"bar"}, 503 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 504 }, 505 Indexes: []IndexDescriptor{ 506 {ID: 1, Name: "blah", ColumnIDs: []ColumnID{1}, 507 ColumnNames: []string{"bar"}, 508 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 509 }, 510 }, 511 NextColumnID: 2, 512 NextFamilyID: 1, 513 NextIndexID: 2, 514 }}, 515 {`index "bar" column "bar" should have ID 1, but found ID 2`, 516 TableDescriptor{ 517 ID: 2, 518 ParentID: 1, 519 Name: "foo", 520 FormatVersion: FamilyFormatVersion, 521 Columns: []ColumnDescriptor{ 522 {ID: 1, Name: "bar"}, 523 }, 524 Families: []ColumnFamilyDescriptor{ 525 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 526 }, 527 PrimaryIndex: IndexDescriptor{ID: 1, Name: "bar", ColumnIDs: []ColumnID{2}, 528 ColumnNames: []string{"bar"}, 529 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 530 }, 531 NextColumnID: 2, 532 NextFamilyID: 1, 533 NextIndexID: 2, 534 }}, 535 {`index "bar" contains unknown column "blah"`, 536 TableDescriptor{ 537 ID: 2, 538 ParentID: 1, 539 Name: "foo", 540 FormatVersion: FamilyFormatVersion, 541 Columns: []ColumnDescriptor{ 542 {ID: 1, Name: "bar"}, 543 }, 544 Families: []ColumnFamilyDescriptor{ 545 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 546 }, 547 PrimaryIndex: IndexDescriptor{ID: 1, Name: "bar", ColumnIDs: []ColumnID{1}, 548 ColumnNames: []string{"blah"}, 549 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 550 }, 551 NextColumnID: 2, 552 NextFamilyID: 1, 553 NextIndexID: 2, 554 }}, 555 {`mismatched column IDs (1) and directions (0)`, 556 TableDescriptor{ 557 ID: 2, 558 ParentID: 1, 559 Name: "foo", 560 FormatVersion: FamilyFormatVersion, 561 Columns: []ColumnDescriptor{ 562 {ID: 1, Name: "bar"}, 563 }, 564 Families: []ColumnFamilyDescriptor{ 565 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 566 }, 567 PrimaryIndex: IndexDescriptor{ID: 1, Name: "bar", ColumnIDs: []ColumnID{1}, 568 ColumnNames: []string{"blah"}, 569 }, 570 NextColumnID: 2, 571 NextFamilyID: 1, 572 NextIndexID: 2, 573 }}, 574 {`at least one of LIST or RANGE partitioning must be used`, 575 // Verify that validatePartitioning is hooked up. The rest of these 576 // tests are in TestValidatePartitionion. 577 TableDescriptor{ 578 ID: 2, 579 ParentID: 1, 580 Name: "foo", 581 FormatVersion: FamilyFormatVersion, 582 Columns: []ColumnDescriptor{ 583 {ID: 1, Name: "bar"}, 584 }, 585 Families: []ColumnFamilyDescriptor{ 586 {ID: 0, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}}, 587 }, 588 PrimaryIndex: IndexDescriptor{ 589 ID: 1, Name: "primary", ColumnIDs: []ColumnID{1}, ColumnNames: []string{"bar"}, 590 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 591 Partitioning: PartitioningDescriptor{ 592 NumColumns: 1, 593 }, 594 }, 595 NextColumnID: 2, 596 NextFamilyID: 1, 597 NextIndexID: 3, 598 }}, 599 {`index "foo_crdb_internal_bar_shard_5_bar_idx" refers to non-existent shard column "does not exist"`, 600 TableDescriptor{ 601 ID: 2, 602 ParentID: 1, 603 Name: "foo", 604 FormatVersion: FamilyFormatVersion, 605 Columns: []ColumnDescriptor{ 606 {ID: 1, Name: "bar"}, 607 {ID: 2, Name: "crdb_internal_bar_shard_5"}, 608 }, 609 Families: []ColumnFamilyDescriptor{ 610 {ID: 0, Name: "primary", 611 ColumnIDs: []ColumnID{1, 2}, 612 ColumnNames: []string{"bar", "crdb_internal_bar_shard_5"}, 613 }, 614 }, 615 PrimaryIndex: IndexDescriptor{ 616 ID: 1, Name: "primary", 617 Unique: true, 618 ColumnIDs: []ColumnID{1}, 619 ColumnNames: []string{"bar"}, 620 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 621 StoreColumnNames: []string{"crdb_internal_bar_shard_5"}, 622 StoreColumnIDs: []ColumnID{2}, 623 }, 624 Indexes: []IndexDescriptor{ 625 {ID: 2, Name: "foo_crdb_internal_bar_shard_5_bar_idx", 626 ColumnIDs: []ColumnID{2, 1}, 627 ColumnNames: []string{"crdb_internal_bar_shard_5", "bar"}, 628 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC}, 629 Sharded: ShardedDescriptor{ 630 IsSharded: true, 631 Name: "does not exist", 632 ShardBuckets: 5, 633 }, 634 }, 635 }, 636 NextColumnID: 3, 637 NextFamilyID: 1, 638 NextIndexID: 3, 639 }}, 640 } 641 for i, d := range testData { 642 if err := d.desc.ValidateTable(); err == nil { 643 t.Errorf("%d: expected \"%s\", but found success: %+v", i, d.err, d.desc) 644 } else if d.err != err.Error() && "internal error: "+d.err != err.Error() { 645 t.Errorf("%d: expected \"%s\", but found \"%+v\"", i, d.err, err) 646 } 647 } 648 } 649 650 func TestValidateCrossTableReferences(t *testing.T) { 651 defer leaktest.AfterTest(t)() 652 ctx := context.Background() 653 654 s, _, kvDB := serverutils.StartServer(t, base.TestServerArgs{}) 655 defer s.Stopper().Stop(ctx) 656 657 tests := []struct { 658 err string 659 desc TableDescriptor 660 otherDescs []TableDescriptor 661 }{ 662 // Foreign keys 663 { 664 err: `invalid foreign key: missing table=52: descriptor not found`, 665 desc: TableDescriptor{ 666 ID: 51, 667 OutboundFKs: []ForeignKeyConstraint{ 668 { 669 Name: "fk", 670 ReferencedTableID: 52, 671 ReferencedColumnIDs: []ColumnID{1}, 672 OriginTableID: 51, 673 OriginColumnIDs: []ColumnID{1}, 674 }, 675 }, 676 }, 677 otherDescs: nil, 678 }, 679 { 680 err: `missing fk back reference "fk" to "foo" from "baz"`, 681 desc: TableDescriptor{ 682 ID: 51, 683 Name: "foo", 684 OutboundFKs: []ForeignKeyConstraint{ 685 { 686 Name: "fk", 687 ReferencedTableID: 52, 688 ReferencedColumnIDs: []ColumnID{1}, 689 OriginTableID: 51, 690 OriginColumnIDs: []ColumnID{1}, 691 }, 692 }, 693 }, 694 otherDescs: []TableDescriptor{{ 695 ID: 52, 696 Name: "baz", 697 }}, 698 }, 699 { 700 err: `invalid foreign key backreference: missing table=52: descriptor not found`, 701 desc: TableDescriptor{ 702 ID: 51, 703 InboundFKs: []ForeignKeyConstraint{ 704 { 705 Name: "fk", 706 ReferencedTableID: 51, 707 ReferencedColumnIDs: []ColumnID{1}, 708 OriginTableID: 52, 709 OriginColumnIDs: []ColumnID{1}, 710 }, 711 }, 712 }, 713 }, 714 { 715 err: `missing fk forward reference "fk" to "foo" from "baz"`, 716 desc: TableDescriptor{ 717 ID: 51, 718 Name: "foo", 719 PrimaryIndex: IndexDescriptor{ 720 ID: 1, 721 Name: "bar", 722 }, 723 InboundFKs: []ForeignKeyConstraint{ 724 { 725 Name: "fk", 726 ReferencedTableID: 51, 727 ReferencedColumnIDs: []ColumnID{1}, 728 OriginTableID: 52, 729 OriginColumnIDs: []ColumnID{1}, 730 }, 731 }, 732 }, 733 otherDescs: []TableDescriptor{{ 734 ID: 52, 735 Name: "baz", 736 }}, 737 }, 738 739 // Interleaves 740 { 741 err: `invalid interleave: missing table=52 index=2: descriptor not found`, 742 desc: TableDescriptor{ 743 ID: 51, 744 PrimaryIndex: IndexDescriptor{ 745 ID: 1, 746 Interleave: InterleaveDescriptor{Ancestors: []InterleaveDescriptor_Ancestor{ 747 {TableID: 52, IndexID: 2}, 748 }}, 749 }, 750 }, 751 otherDescs: nil, 752 }, 753 { 754 err: `invalid interleave: missing table=baz index=2: index-id "2" does not exist`, 755 desc: TableDescriptor{ 756 ID: 51, 757 PrimaryIndex: IndexDescriptor{ 758 ID: 1, 759 Interleave: InterleaveDescriptor{Ancestors: []InterleaveDescriptor_Ancestor{ 760 {TableID: 52, IndexID: 2}, 761 }}, 762 }, 763 }, 764 otherDescs: []TableDescriptor{{ 765 ID: 52, 766 Name: "baz", 767 }}, 768 }, 769 { 770 err: `missing interleave back reference to "foo"@"bar" from "baz"@"qux"`, 771 desc: TableDescriptor{ 772 ID: 51, 773 Name: "foo", 774 PrimaryIndex: IndexDescriptor{ 775 ID: 1, 776 Name: "bar", 777 Interleave: InterleaveDescriptor{Ancestors: []InterleaveDescriptor_Ancestor{ 778 {TableID: 52, IndexID: 2}, 779 }}, 780 }, 781 }, 782 otherDescs: []TableDescriptor{{ 783 ID: 52, 784 Name: "baz", 785 PrimaryIndex: IndexDescriptor{ 786 ID: 2, 787 Name: "qux", 788 }, 789 }}, 790 }, 791 { 792 err: `invalid interleave backreference table=52 index=2: descriptor not found`, 793 desc: TableDescriptor{ 794 ID: 51, 795 PrimaryIndex: IndexDescriptor{ 796 ID: 1, 797 InterleavedBy: []ForeignKeyReference{{Table: 52, Index: 2}}, 798 }, 799 }, 800 }, 801 { 802 err: `invalid interleave backreference table=baz index=2: index-id "2" does not exist`, 803 desc: TableDescriptor{ 804 ID: 51, 805 PrimaryIndex: IndexDescriptor{ 806 ID: 1, 807 InterleavedBy: []ForeignKeyReference{{Table: 52, Index: 2}}, 808 }, 809 }, 810 otherDescs: []TableDescriptor{{ 811 ID: 52, 812 Name: "baz", 813 }}, 814 }, 815 { 816 err: `broken interleave backward reference from "foo"@"bar" to "baz"@"qux"`, 817 desc: TableDescriptor{ 818 ID: 51, 819 Name: "foo", 820 PrimaryIndex: IndexDescriptor{ 821 ID: 1, 822 Name: "bar", 823 InterleavedBy: []ForeignKeyReference{{Table: 52, Index: 2}}, 824 }, 825 }, 826 otherDescs: []TableDescriptor{{ 827 ID: 52, 828 Name: "baz", 829 PrimaryIndex: IndexDescriptor{ 830 ID: 2, 831 Name: "qux", 832 }, 833 }}, 834 }, 835 } 836 837 { 838 var v roachpb.Value 839 desc := &Descriptor{Union: &Descriptor_Database{}} 840 if err := v.SetProto(desc); err != nil { 841 t.Fatal(err) 842 } 843 if err := kvDB.Put(ctx, MakeDescMetadataKey(keys.SystemSQLCodec, 0), &v); err != nil { 844 t.Fatal(err) 845 } 846 } 847 848 for i, test := range tests { 849 for _, otherDesc := range test.otherDescs { 850 otherDesc.Privileges = NewDefaultPrivilegeDescriptor() 851 var v roachpb.Value 852 desc := &Descriptor{Union: &Descriptor_Table{Table: &otherDesc}} 853 if err := v.SetProto(desc); err != nil { 854 t.Fatal(err) 855 } 856 if err := kvDB.Put(ctx, MakeDescMetadataKey(keys.SystemSQLCodec, otherDesc.ID), &v); err != nil { 857 t.Fatal(err) 858 } 859 } 860 txn := kv.NewTxn(ctx, kvDB, s.NodeID()) 861 if err := test.desc.validateCrossReferences(ctx, txn, keys.SystemSQLCodec); err == nil { 862 t.Errorf("%d: expected \"%s\", but found success: %+v", i, test.err, test.desc) 863 } else if test.err != err.Error() && "internal error: "+test.err != err.Error() { 864 t.Errorf("%d: expected \"%s\", but found \"%s\"", i, test.err, err.Error()) 865 } 866 for _, otherDesc := range test.otherDescs { 867 if err := kvDB.Del(ctx, MakeDescMetadataKey(keys.SystemSQLCodec, otherDesc.ID)); err != nil { 868 t.Fatal(err) 869 } 870 } 871 } 872 } 873 874 func TestValidatePartitioning(t *testing.T) { 875 defer leaktest.AfterTest(t)() 876 877 tests := []struct { 878 err string 879 desc TableDescriptor 880 }{ 881 {"at least one of LIST or RANGE partitioning must be used", 882 TableDescriptor{ 883 PrimaryIndex: IndexDescriptor{ 884 Partitioning: PartitioningDescriptor{ 885 NumColumns: 1, 886 }, 887 }, 888 }, 889 }, 890 {"PARTITION p1: must contain values", 891 TableDescriptor{ 892 PrimaryIndex: IndexDescriptor{ 893 Partitioning: PartitioningDescriptor{ 894 NumColumns: 1, 895 List: []PartitioningDescriptor_List{{Name: "p1"}}, 896 }, 897 }, 898 }, 899 }, 900 {"not enough columns in index for this partitioning", 901 TableDescriptor{ 902 PrimaryIndex: IndexDescriptor{ 903 Partitioning: PartitioningDescriptor{ 904 NumColumns: 1, 905 List: []PartitioningDescriptor_List{{Name: "p1", Values: [][]byte{{}}}}, 906 }, 907 }, 908 }, 909 }, 910 {"only one LIST or RANGE partitioning may used", 911 TableDescriptor{ 912 PrimaryIndex: IndexDescriptor{ 913 ColumnIDs: []ColumnID{1}, 914 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 915 Partitioning: PartitioningDescriptor{ 916 NumColumns: 1, 917 List: []PartitioningDescriptor_List{{}}, 918 Range: []PartitioningDescriptor_Range{{}}, 919 }, 920 }, 921 }, 922 }, 923 {"PARTITION name must be non-empty", 924 TableDescriptor{ 925 Columns: []ColumnDescriptor{{ID: 1, Type: types.Int}}, 926 PrimaryIndex: IndexDescriptor{ 927 ColumnIDs: []ColumnID{1}, 928 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 929 Partitioning: PartitioningDescriptor{ 930 NumColumns: 1, 931 List: []PartitioningDescriptor_List{{}}, 932 }, 933 }, 934 }, 935 }, 936 {"PARTITION p1: must contain values", 937 TableDescriptor{ 938 Columns: []ColumnDescriptor{{ID: 1, Type: types.Int}}, 939 PrimaryIndex: IndexDescriptor{ 940 ColumnIDs: []ColumnID{1}, 941 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 942 Partitioning: PartitioningDescriptor{ 943 NumColumns: 1, 944 List: []PartitioningDescriptor_List{{Name: "p1"}}, 945 }, 946 }, 947 }, 948 }, 949 {"PARTITION p1: decoding: empty array", 950 TableDescriptor{ 951 Columns: []ColumnDescriptor{{ID: 1, Type: types.Int}}, 952 PrimaryIndex: IndexDescriptor{ 953 ColumnIDs: []ColumnID{1}, 954 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 955 Partitioning: PartitioningDescriptor{ 956 NumColumns: 1, 957 List: []PartitioningDescriptor_List{{ 958 Name: "p1", Values: [][]byte{{}}, 959 }}, 960 }, 961 }, 962 }, 963 }, 964 {"PARTITION p1: decoding: int64 varint decoding failed: 0", 965 TableDescriptor{ 966 Columns: []ColumnDescriptor{{ID: 1, Type: types.Int}}, 967 PrimaryIndex: IndexDescriptor{ 968 ColumnIDs: []ColumnID{1}, 969 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 970 Partitioning: PartitioningDescriptor{ 971 NumColumns: 1, 972 List: []PartitioningDescriptor_List{ 973 {Name: "p1", Values: [][]byte{{0x03}}}, 974 }, 975 }, 976 }, 977 }, 978 }, 979 {"PARTITION p1: superfluous data in encoded value", 980 TableDescriptor{ 981 Columns: []ColumnDescriptor{{ID: 1, Type: types.Int}}, 982 PrimaryIndex: IndexDescriptor{ 983 ColumnIDs: []ColumnID{1}, 984 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 985 Partitioning: PartitioningDescriptor{ 986 NumColumns: 1, 987 List: []PartitioningDescriptor_List{ 988 {Name: "p1", Values: [][]byte{{0x03, 0x02, 0x00}}}, 989 }, 990 }, 991 }, 992 }, 993 }, 994 {"partitions p1 and p2 overlap", 995 TableDescriptor{ 996 Columns: []ColumnDescriptor{{ID: 1, Type: types.Int}}, 997 PrimaryIndex: IndexDescriptor{ 998 ColumnIDs: []ColumnID{1, 1}, 999 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC}, 1000 Partitioning: PartitioningDescriptor{ 1001 NumColumns: 1, 1002 Range: []PartitioningDescriptor_Range{ 1003 {Name: "p1", FromInclusive: []byte{0x03, 0x02}, ToExclusive: []byte{0x03, 0x04}}, 1004 {Name: "p2", FromInclusive: []byte{0x03, 0x02}, ToExclusive: []byte{0x03, 0x04}}, 1005 }, 1006 }, 1007 }, 1008 }, 1009 }, 1010 {"PARTITION p1: name must be unique", 1011 TableDescriptor{ 1012 Columns: []ColumnDescriptor{{ID: 1, Type: types.Int}}, 1013 PrimaryIndex: IndexDescriptor{ 1014 ColumnIDs: []ColumnID{1}, 1015 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 1016 Partitioning: PartitioningDescriptor{ 1017 NumColumns: 1, 1018 List: []PartitioningDescriptor_List{ 1019 {Name: "p1", Values: [][]byte{{0x03, 0x02}}}, 1020 {Name: "p1", Values: [][]byte{{0x03, 0x04}}}, 1021 }, 1022 }, 1023 }, 1024 }, 1025 }, 1026 {"not enough columns in index for this partitioning", 1027 TableDescriptor{ 1028 Columns: []ColumnDescriptor{{ID: 1, Type: types.Int}}, 1029 PrimaryIndex: IndexDescriptor{ 1030 ColumnIDs: []ColumnID{1}, 1031 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, 1032 Partitioning: PartitioningDescriptor{ 1033 NumColumns: 1, 1034 List: []PartitioningDescriptor_List{{ 1035 Name: "p1", 1036 Values: [][]byte{{0x03, 0x02}}, 1037 Subpartitioning: PartitioningDescriptor{ 1038 NumColumns: 1, 1039 List: []PartitioningDescriptor_List{{Name: "p1_1", Values: [][]byte{{}}}}, 1040 }, 1041 }}, 1042 }, 1043 }, 1044 }, 1045 }, 1046 {"PARTITION p1: name must be unique", 1047 TableDescriptor{ 1048 Columns: []ColumnDescriptor{{ID: 1, Type: types.Int}}, 1049 PrimaryIndex: IndexDescriptor{ 1050 ColumnIDs: []ColumnID{1, 1}, 1051 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC}, 1052 Partitioning: PartitioningDescriptor{ 1053 NumColumns: 1, 1054 List: []PartitioningDescriptor_List{ 1055 {Name: "p1", Values: [][]byte{{0x03, 0x02}}}, 1056 { 1057 Name: "p2", 1058 Values: [][]byte{{0x03, 0x04}}, 1059 Subpartitioning: PartitioningDescriptor{ 1060 NumColumns: 1, 1061 List: []PartitioningDescriptor_List{ 1062 {Name: "p1", Values: [][]byte{{0x03, 0x02}}}, 1063 }, 1064 }, 1065 }, 1066 }, 1067 }, 1068 }, 1069 }, 1070 }, 1071 } 1072 for i, test := range tests { 1073 err := test.desc.validatePartitioning() 1074 if !testutils.IsError(err, test.err) { 1075 t.Errorf(`%d: got "%v" expected "%v"`, i, err, test.err) 1076 } 1077 } 1078 } 1079 1080 func TestColumnTypeSQLString(t *testing.T) { 1081 defer leaktest.AfterTest(t)() 1082 1083 testData := []struct { 1084 colType *types.T 1085 expectedSQL string 1086 }{ 1087 {types.MakeBit(2), "BIT(2)"}, 1088 {types.MakeVarBit(2), "VARBIT(2)"}, 1089 {types.Int, "INT8"}, 1090 {types.Float, "FLOAT8"}, 1091 {types.Float4, "FLOAT4"}, 1092 {types.Decimal, "DECIMAL"}, 1093 {types.MakeDecimal(6, 0), "DECIMAL(6)"}, 1094 {types.MakeDecimal(8, 7), "DECIMAL(8,7)"}, 1095 {types.Date, "DATE"}, 1096 {types.Timestamp, "TIMESTAMP"}, 1097 {types.Interval, "INTERVAL"}, 1098 {types.String, "STRING"}, 1099 {types.MakeString(10), "STRING(10)"}, 1100 {types.Bytes, "BYTES"}, 1101 } 1102 for i, d := range testData { 1103 t.Run(d.colType.DebugString(), func(t *testing.T) { 1104 sql := d.colType.SQLString() 1105 if d.expectedSQL != sql { 1106 t.Errorf("%d: expected %s, but got %s", i, d.expectedSQL, sql) 1107 } 1108 }) 1109 } 1110 } 1111 1112 func TestFitColumnToFamily(t *testing.T) { 1113 intEncodedSize := 10 // 1 byte tag + 9 bytes max varint encoded size 1114 1115 makeTestTableDescriptor := func(familyTypes [][]*types.T) *MutableTableDescriptor { 1116 nextColumnID := ColumnID(8) 1117 var desc TableDescriptor 1118 for _, fTypes := range familyTypes { 1119 var family ColumnFamilyDescriptor 1120 for _, t := range fTypes { 1121 desc.Columns = append(desc.Columns, ColumnDescriptor{ 1122 ID: nextColumnID, 1123 Type: t, 1124 }) 1125 family.ColumnIDs = append(family.ColumnIDs, nextColumnID) 1126 nextColumnID++ 1127 } 1128 desc.Families = append(desc.Families, family) 1129 } 1130 return NewMutableCreatedTableDescriptor(desc) 1131 } 1132 1133 emptyFamily := []*types.T{} 1134 partiallyFullFamily := []*types.T{ 1135 types.Int, 1136 types.Bytes, 1137 } 1138 fullFamily := []*types.T{ 1139 types.Bytes, 1140 } 1141 maxIntsInOneFamily := make([]*types.T, FamilyHeuristicTargetBytes/intEncodedSize) 1142 for i := range maxIntsInOneFamily { 1143 maxIntsInOneFamily[i] = types.Int 1144 } 1145 1146 tests := []struct { 1147 newCol *types.T 1148 existingFamilies [][]*types.T 1149 colFits bool 1150 idx int // not applicable if colFits is false 1151 }{ 1152 // Bounded size column. 1153 {colFits: true, idx: 0, newCol: types.Bool, 1154 existingFamilies: nil, 1155 }, 1156 {colFits: true, idx: 0, newCol: types.Bool, 1157 existingFamilies: [][]*types.T{emptyFamily}, 1158 }, 1159 {colFits: true, idx: 0, newCol: types.Bool, 1160 existingFamilies: [][]*types.T{partiallyFullFamily}, 1161 }, 1162 {colFits: true, idx: 0, newCol: types.Bool, 1163 existingFamilies: [][]*types.T{fullFamily}, 1164 }, 1165 {colFits: true, idx: 0, newCol: types.Bool, 1166 existingFamilies: [][]*types.T{fullFamily, emptyFamily}, 1167 }, 1168 1169 // Unbounded size column. 1170 {colFits: true, idx: 0, newCol: types.Decimal, 1171 existingFamilies: [][]*types.T{emptyFamily}, 1172 }, 1173 {colFits: true, idx: 0, newCol: types.Decimal, 1174 existingFamilies: [][]*types.T{partiallyFullFamily}, 1175 }, 1176 } 1177 for i, test := range tests { 1178 desc := makeTestTableDescriptor(test.existingFamilies) 1179 idx, colFits := fitColumnToFamily(desc, ColumnDescriptor{Type: test.newCol}) 1180 if colFits != test.colFits { 1181 if colFits { 1182 t.Errorf("%d: expected no fit for the column but got one", i) 1183 } else { 1184 t.Errorf("%d: expected fit for the column but didn't get one", i) 1185 } 1186 continue 1187 } 1188 if colFits && idx != test.idx { 1189 t.Errorf("%d: got a fit in family offset %d but expected offset %d", i, idx, test.idx) 1190 } 1191 } 1192 } 1193 1194 func TestMaybeUpgradeFormatVersion(t *testing.T) { 1195 tests := []struct { 1196 desc TableDescriptor 1197 expUpgrade bool 1198 verify func(int, TableDescriptor) // nil means no extra verification. 1199 }{ 1200 { 1201 desc: TableDescriptor{ 1202 FormatVersion: BaseFormatVersion, 1203 Columns: []ColumnDescriptor{ 1204 {ID: 1, Name: "foo"}, 1205 }, 1206 }, 1207 expUpgrade: true, 1208 verify: func(i int, desc TableDescriptor) { 1209 if len(desc.Families) == 0 { 1210 t.Errorf("%d: expected families to be set, but it was empty", i) 1211 } 1212 }, 1213 }, 1214 // Test that a version from the future is left alone. 1215 { 1216 desc: TableDescriptor{ 1217 FormatVersion: InterleavedFormatVersion, 1218 Columns: []ColumnDescriptor{ 1219 {ID: 1, Name: "foo"}, 1220 }, 1221 }, 1222 expUpgrade: false, 1223 verify: nil, 1224 }, 1225 } 1226 for i, test := range tests { 1227 desc := test.desc 1228 upgraded := desc.maybeUpgradeFormatVersion() 1229 if upgraded != test.expUpgrade { 1230 t.Fatalf("%d: expected upgraded=%t, but got upgraded=%t", i, test.expUpgrade, upgraded) 1231 } 1232 if test.verify != nil { 1233 test.verify(i, desc) 1234 } 1235 } 1236 } 1237 1238 func TestUnvalidateConstraints(t *testing.T) { 1239 desc := NewMutableCreatedTableDescriptor(TableDescriptor{ 1240 Name: "test", 1241 ParentID: ID(1), 1242 Columns: []ColumnDescriptor{ 1243 {Name: "a", Type: types.Int}, 1244 {Name: "b", Type: types.Int}, 1245 {Name: "c", Type: types.Int}}, 1246 FormatVersion: FamilyFormatVersion, 1247 Indexes: []IndexDescriptor{makeIndexDescriptor("d", []string{"b", "a"})}, 1248 Privileges: NewDefaultPrivilegeDescriptor(), 1249 OutboundFKs: []ForeignKeyConstraint{ 1250 { 1251 Name: "fk", 1252 ReferencedTableID: ID(1), 1253 Validity: ConstraintValidity_Validated, 1254 }, 1255 }, 1256 }) 1257 if err := desc.AllocateIDs(); err != nil { 1258 t.Fatal(err) 1259 } 1260 lookup := func(_ ID) (*TableDescriptor, error) { 1261 return desc.TableDesc(), nil 1262 } 1263 1264 before, err := desc.GetConstraintInfoWithLookup(lookup) 1265 if err != nil { 1266 t.Fatal(err) 1267 } 1268 if c, ok := before["fk"]; !ok || c.Unvalidated { 1269 t.Fatalf("expected to find a validated constraint fk before, found %v", c) 1270 } 1271 desc.InvalidateFKConstraints() 1272 1273 after, err := desc.GetConstraintInfoWithLookup(lookup) 1274 if err != nil { 1275 t.Fatal(err) 1276 } 1277 if c, ok := after["fk"]; !ok || !c.Unvalidated { 1278 t.Fatalf("expected to find an unvalidated constraint fk before, found %v", c) 1279 } 1280 } 1281 1282 func TestKeysPerRow(t *testing.T) { 1283 defer leaktest.AfterTest(t)() 1284 1285 // TODO(dan): This server is only used to turn a CREATE TABLE statement into 1286 // a TableDescriptor. It should be possible to move MakeTableDesc into 1287 // sqlbase. If/when that happens, use it here instead of this server. 1288 s, conn, _ := serverutils.StartServer(t, base.TestServerArgs{}) 1289 defer s.Stopper().Stop(context.Background()) 1290 if _, err := conn.Exec(`CREATE DATABASE d`); err != nil { 1291 t.Fatalf("%+v", err) 1292 } 1293 1294 tests := []struct { 1295 createTable string 1296 indexID IndexID 1297 expected int 1298 }{ 1299 {"(a INT PRIMARY KEY, b INT, INDEX (b))", 1, 1}, // Primary index 1300 {"(a INT PRIMARY KEY, b INT, INDEX (b))", 2, 1}, // 'b' index 1301 {"(a INT PRIMARY KEY, b INT, FAMILY (a), FAMILY (b), INDEX (b))", 1, 2}, // Primary index 1302 {"(a INT PRIMARY KEY, b INT, FAMILY (a), FAMILY (b), INDEX (b))", 2, 1}, // 'b' index 1303 {"(a INT PRIMARY KEY, b INT, FAMILY (a), FAMILY (b), INDEX (a) STORING (b))", 2, 2}, // 'a' index 1304 } 1305 1306 for i, test := range tests { 1307 t.Run(fmt.Sprintf("%s - %d", test.createTable, test.indexID), func(t *testing.T) { 1308 sqlDB := sqlutils.MakeSQLRunner(conn) 1309 tableName := fmt.Sprintf("t%d", i) 1310 sqlDB.Exec(t, fmt.Sprintf(`CREATE TABLE d.%s %s`, tableName, test.createTable)) 1311 1312 var descBytes []byte 1313 // Grab the most recently created descriptor. 1314 row := sqlDB.QueryRow(t, 1315 `SELECT descriptor FROM system.descriptor ORDER BY id DESC LIMIT 1`) 1316 row.Scan(&descBytes) 1317 var desc Descriptor 1318 if err := protoutil.Unmarshal(descBytes, &desc); err != nil { 1319 t.Fatalf("%+v", err) 1320 } 1321 1322 keys, err := desc.GetTable().KeysPerRow(test.indexID) 1323 if err != nil { 1324 t.Fatal(err) 1325 } 1326 if test.expected != keys { 1327 t.Errorf("expected %d keys got %d", test.expected, keys) 1328 } 1329 }) 1330 } 1331 } 1332 1333 func TestColumnNeedsBackfill(t *testing.T) { 1334 // Define variable strings here such that we can pass their address below. 1335 null := "NULL" 1336 four := "4:::INT8" 1337 // Create Column Descriptors that reflect the definition of a column with a 1338 // default value of NULL that was set implicitly, one that was set explicitly, 1339 // and one that has an INT default value, respectively. 1340 implicitNull := &ColumnDescriptor{Name: "im", ID: 2, Type: types.Int, DefaultExpr: nil, Nullable: true, ComputeExpr: nil} 1341 explicitNull := &ColumnDescriptor{Name: "ex", ID: 3, Type: types.Int, DefaultExpr: &null, Nullable: true, ComputeExpr: nil} 1342 defaultNotNull := &ColumnDescriptor{Name: "four", ID: 4, Type: types.Int, DefaultExpr: &four, Nullable: true, ComputeExpr: nil} 1343 // Verify that a backfill doesn't occur according to the ColumnNeedsBackfill 1344 // function for the default NULL values, and that it does occur for an INT 1345 // default value. 1346 if ColumnNeedsBackfill(implicitNull) != false { 1347 t.Fatal("Expected implicit SET DEFAULT NULL to not require a backfill," + 1348 " ColumnNeedsBackfill states that it does.") 1349 } 1350 if ColumnNeedsBackfill(explicitNull) != false { 1351 t.Fatal("Expected explicit SET DEFAULT NULL to not require a backfill," + 1352 " ColumnNeedsBackfill states that it does.") 1353 } 1354 if ColumnNeedsBackfill(defaultNotNull) != true { 1355 t.Fatal("Expected explicit SET DEFAULT NULL to require a backfill," + 1356 " ColumnNeedsBackfill states that it does not.") 1357 } 1358 } 1359 1360 func TestDefaultExprNil(t *testing.T) { 1361 s, conn, _ := serverutils.StartServer(t, base.TestServerArgs{}) 1362 defer s.Stopper().Stop(context.Background()) 1363 if _, err := conn.Exec(`CREATE DATABASE t`); err != nil { 1364 t.Fatalf("%+v", err) 1365 } 1366 t.Run(fmt.Sprintf("%s - %d", "(a INT PRIMARY KEY)", 1), func(t *testing.T) { 1367 sqlDB := sqlutils.MakeSQLRunner(conn) 1368 // Execute SQL commands with both implicit and explicit setting of the 1369 // default expression. 1370 sqlDB.Exec(t, `CREATE TABLE t (a INT PRIMARY KEY)`) 1371 sqlDB.Exec(t, `INSERT INTO t (a) VALUES (1), (2)`) 1372 sqlDB.Exec(t, `ALTER TABLE t ADD COLUMN b INT NULL`) 1373 sqlDB.Exec(t, `INSERT INTO t (a) VALUES (3)`) 1374 sqlDB.Exec(t, `ALTER TABLE t ADD COLUMN c INT DEFAULT NULL`) 1375 1376 var descBytes []byte 1377 // Grab the most recently created descriptor. 1378 row := sqlDB.QueryRow(t, 1379 `SELECT descriptor FROM system.descriptor ORDER BY id DESC LIMIT 1`) 1380 row.Scan(&descBytes) 1381 var desc Descriptor 1382 if err := protoutil.Unmarshal(descBytes, &desc); err != nil { 1383 t.Fatalf("%+v", err) 1384 } 1385 // Test and verify that the default expressions of the column descriptors 1386 // are all nil. 1387 for _, col := range desc.GetTable().Columns { 1388 if col.DefaultExpr != nil { 1389 t.Errorf("expected Column Default Expression to be 'nil', got %s instead.", *col.DefaultExpr) 1390 } 1391 } 1392 }) 1393 } 1394 1395 func TestSQLString(t *testing.T) { 1396 colNames := []string{"derp", "foo"} 1397 indexName := "idx" 1398 tableName := tree.MakeTableName("DB", "t1") 1399 tableName.ExplicitCatalog = false 1400 tableName.ExplicitSchema = false 1401 index := IndexDescriptor{Name: indexName, 1402 ID: 0x0, 1403 Unique: false, 1404 ColumnNames: colNames, 1405 ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC}, 1406 } 1407 expected := fmt.Sprintf("INDEX %s ON t1 (%s ASC, %s ASC)", indexName, colNames[0], colNames[1]) 1408 if got := index.SQLString(&tableName); got != expected { 1409 t.Errorf("Expected '%s', but got '%s'", expected, got) 1410 } 1411 expected = fmt.Sprintf("INDEX %s (%s ASC, %s ASC)", indexName, colNames[0], colNames[1]) 1412 if got := index.SQLString(&AnonymousTable); got != expected { 1413 t.Errorf("Expected '%s', but got '%s'", expected, got) 1414 } 1415 } 1416 1417 func TestLogicalColumnID(t *testing.T) { 1418 tests := []struct { 1419 desc TableDescriptor 1420 expected ColumnID 1421 }{ 1422 {TableDescriptor{Columns: []ColumnDescriptor{{ID: 1, LogicalColumnID: 1}}}, 1}, 1423 // If LogicalColumnID is not explicitly set, it should be lazy loaded as ID. 1424 {TableDescriptor{Columns: []ColumnDescriptor{{ID: 2}}}, 2}, 1425 } 1426 1427 for i := range tests { 1428 actual := tests[i].desc.Columns[0].GetLogicalColumnID() 1429 expected := tests[i].expected 1430 1431 if expected != actual { 1432 t.Fatalf("Expected LogicalColumnID to be %d, got %d.", expected, actual) 1433 } 1434 } 1435 1436 }