github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/internal/sqlsmith/relational.go (about) 1 // Copyright 2019 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 sqlsmith 12 13 import ( 14 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 15 "github.com/cockroachdb/cockroach/pkg/sql/types" 16 ) 17 18 func (s *Smither) makeStmt() (stmt tree.Statement, ok bool) { 19 return s.stmtSampler.Next()(s) 20 } 21 22 func (s *Smither) makeSelectStmt( 23 desiredTypes []*types.T, refs colRefs, withTables tableRefs, 24 ) (stmt tree.SelectStatement, stmtRefs colRefs, ok bool) { 25 if s.canRecurse() { 26 for { 27 expr, exprRefs, ok := s.selectStmtSampler.Next()(s, desiredTypes, refs, withTables) 28 if ok { 29 return expr, exprRefs, ok 30 } 31 } 32 } 33 return makeValuesSelect(s, desiredTypes, refs, withTables) 34 } 35 36 func makeSchemaTable(s *Smither, refs colRefs, forJoin bool) (tree.TableExpr, colRefs, bool) { 37 // If there's no tables, don't keep failing in this function, just make 38 // a values table. 39 if len(s.tables) == 0 { 40 return makeValuesTable(s, refs, forJoin) 41 } 42 expr, _, _, exprRefs, ok := s.getSchemaTableWithIndexHint() 43 return expr, exprRefs, ok 44 } 45 46 // getSchemaTable returns a table expression without the index hint. 47 func (s *Smither) getSchemaTable() (tree.TableExpr, *tree.TableName, *tableRef, colRefs, bool) { 48 ate, name, tableRef, refs, ok := s.getSchemaTableWithIndexHint() 49 if ate != nil { 50 ate.IndexFlags = nil 51 } 52 return ate, name, tableRef, refs, ok 53 } 54 55 // getSchemaTableWithIndexHint returns a table expression that might contain an 56 // index hint. 57 func (s *Smither) getSchemaTableWithIndexHint() ( 58 *tree.AliasedTableExpr, 59 *tree.TableName, 60 *tableRef, 61 colRefs, 62 bool, 63 ) { 64 table, ok := s.getRandTable() 65 if !ok { 66 return nil, nil, nil, nil, false 67 } 68 alias := s.name("tab") 69 name := tree.NewUnqualifiedTableName(alias) 70 expr, refs := s.tableExpr(table.tableRef, name) 71 return &tree.AliasedTableExpr{ 72 Expr: expr, 73 IndexFlags: table.indexFlags, 74 As: tree.AliasClause{Alias: alias}, 75 }, name, table.tableRef, refs, true 76 } 77 78 func (s *Smither) tableExpr(table *tableRef, name *tree.TableName) (tree.TableExpr, colRefs) { 79 refs := make(colRefs, len(table.Columns)) 80 for i, c := range table.Columns { 81 refs[i] = &colRef{ 82 typ: tree.MustBeStaticallyKnownType(c.Type), 83 item: tree.NewColumnItem( 84 name, 85 c.Name, 86 ), 87 } 88 } 89 return table.TableName, refs 90 } 91 92 var ( 93 mutatingStatements = []statementWeight{ 94 {10, makeInsert}, 95 {10, makeDelete}, 96 {10, makeUpdate}, 97 {1, makeAlter}, 98 {1, makeBegin}, 99 {2, makeRollback}, 100 {6, makeCommit}, 101 {1, makeBackup}, 102 {1, makeRestore}, 103 {1, makeExport}, 104 {1, makeImport}, 105 } 106 nonMutatingStatements = []statementWeight{ 107 {10, makeSelect}, 108 } 109 allStatements = append(mutatingStatements, nonMutatingStatements...) 110 111 mutatingTableExprs = []tableExprWeight{ 112 {1, makeInsertReturning}, 113 {1, makeDeleteReturning}, 114 {1, makeUpdateReturning}, 115 } 116 nonMutatingTableExprs = []tableExprWeight{ 117 {40, makeMergeJoinExpr}, 118 {40, makeEquiJoinExpr}, 119 {20, makeSchemaTable}, 120 {10, makeJoinExpr}, 121 {1, makeValuesTable}, 122 {2, makeSelectTable}, 123 } 124 vectorizableTableExprs = []tableExprWeight{ 125 {20, makeEquiJoinExpr}, 126 {20, makeMergeJoinExpr}, 127 {20, makeSchemaTable}, 128 } 129 allTableExprs = append(mutatingTableExprs, nonMutatingTableExprs...) 130 131 selectStmts = []selectStatementWeight{ 132 {1, makeValuesSelect}, 133 {1, makeSetOp}, 134 {1, makeSelectClause}, 135 } 136 ) 137 138 // makeTableExpr returns a tableExpr. If forJoin is true the tableExpr is 139 // valid to be used as a join reference. 140 func makeTableExpr(s *Smither, refs colRefs, forJoin bool) (tree.TableExpr, colRefs, bool) { 141 if s.canRecurse() { 142 for i := 0; i < retryCount; i++ { 143 expr, exprRefs, ok := s.tableExprSampler.Next()(s, refs, forJoin) 144 if ok { 145 return expr, exprRefs, ok 146 } 147 } 148 } 149 return makeSchemaTable(s, refs, forJoin) 150 } 151 152 type typedExpr struct { 153 tree.TypedExpr 154 typ *types.T 155 } 156 157 func makeTypedExpr(expr tree.TypedExpr, typ *types.T) tree.TypedExpr { 158 return typedExpr{ 159 TypedExpr: expr, 160 typ: typ, 161 } 162 } 163 164 func (t typedExpr) ResolvedType() *types.T { 165 return t.typ 166 } 167 168 var joinTypes = []string{ 169 "", 170 tree.AstFull, 171 tree.AstLeft, 172 tree.AstRight, 173 tree.AstCross, 174 tree.AstInner, 175 } 176 177 func makeJoinExpr(s *Smither, refs colRefs, forJoin bool) (tree.TableExpr, colRefs, bool) { 178 left, leftRefs, ok := makeTableExpr(s, refs, true) 179 if !ok { 180 return nil, nil, false 181 } 182 right, rightRefs, ok := makeTableExpr(s, refs, true) 183 if !ok { 184 return nil, nil, false 185 } 186 187 joinExpr := &tree.JoinTableExpr{ 188 JoinType: joinTypes[s.rnd.Intn(len(joinTypes))], 189 Left: left, 190 Right: right, 191 } 192 193 if joinExpr.JoinType != tree.AstCross { 194 on := makeBoolExpr(s, refs) 195 joinExpr.Cond = &tree.OnJoinCond{Expr: on} 196 } 197 joinRefs := leftRefs.extend(rightRefs...) 198 199 return joinExpr, joinRefs, true 200 } 201 202 func makeEquiJoinExpr(s *Smither, refs colRefs, forJoin bool) (tree.TableExpr, colRefs, bool) { 203 left, leftRefs, ok := makeTableExpr(s, refs, true) 204 if !ok { 205 return nil, nil, false 206 } 207 right, rightRefs, ok := makeTableExpr(s, refs, true) 208 if !ok { 209 return nil, nil, false 210 } 211 212 // Determine overlapping types. 213 var available [][2]tree.TypedExpr 214 for _, leftCol := range leftRefs { 215 for _, rightCol := range rightRefs { 216 if leftCol.typ.Equivalent(rightCol.typ) { 217 available = append(available, [2]tree.TypedExpr{ 218 typedParen(leftCol.item, leftCol.typ), 219 typedParen(rightCol.item, rightCol.typ), 220 }) 221 } 222 } 223 } 224 if len(available) == 0 { 225 // left and right didn't have any columns with the same type. 226 return nil, nil, false 227 } 228 229 s.rnd.Shuffle(len(available), func(i, j int) { 230 available[i], available[j] = available[j], available[i] 231 }) 232 233 var cond tree.TypedExpr 234 for (cond == nil || s.coin()) && len(available) > 0 { 235 v := available[0] 236 available = available[1:] 237 expr := tree.NewTypedComparisonExpr(tree.EQ, v[0], v[1]) 238 if cond == nil { 239 cond = expr 240 } else { 241 cond = tree.NewTypedAndExpr(cond, expr) 242 } 243 } 244 245 joinExpr := &tree.JoinTableExpr{ 246 Left: left, 247 Right: right, 248 Cond: &tree.OnJoinCond{Expr: cond}, 249 } 250 joinRefs := leftRefs.extend(rightRefs...) 251 return joinExpr, joinRefs, true 252 } 253 254 func makeMergeJoinExpr(s *Smither, _ colRefs, forJoin bool) (tree.TableExpr, colRefs, bool) { 255 // A merge join is an equijoin where both sides are sorted in the same 256 // direction. Do this by looking for two indexes that have column 257 // prefixes that are the same type and direction. Identical indexes 258 // are fine. 259 260 // Start with some random index. 261 leftTableName, leftIdx, _, ok := s.getRandIndex() 262 if !ok { 263 return nil, nil, false 264 } 265 266 leftAlias := s.name("tab") 267 rightAlias := s.name("tab") 268 leftAliasName := tree.NewUnqualifiedTableName(leftAlias) 269 rightAliasName := tree.NewUnqualifiedTableName(rightAlias) 270 271 // Now look for one that satisfies our constraints (some shared prefix 272 // of type + direction), might end up being the same one. We rely on 273 // Go's non-deterministic map iteration ordering for randomness. 274 rightTableName, cols := func() (*tree.TableIndexName, [][2]colRef) { 275 s.lock.RLock() 276 defer s.lock.RUnlock() 277 for tbl, idxs := range s.indexes { 278 for idxName, idx := range idxs { 279 rightTableName := &tree.TableIndexName{ 280 Table: tbl, 281 Index: tree.UnrestrictedName(idxName), 282 } 283 // cols keeps track of matching column pairs. 284 var cols [][2]colRef 285 for _, rightColElem := range idx.Columns { 286 rightCol := s.columns[tbl][rightColElem.Column] 287 leftColElem := leftIdx.Columns[len(cols)] 288 leftCol := s.columns[leftTableName.Table][leftColElem.Column] 289 if rightColElem.Direction != leftColElem.Direction { 290 break 291 } 292 if !tree.MustBeStaticallyKnownType(rightCol.Type).Equivalent(tree.MustBeStaticallyKnownType(leftCol.Type)) { 293 break 294 } 295 cols = append(cols, [2]colRef{ 296 { 297 typ: tree.MustBeStaticallyKnownType(leftCol.Type), 298 item: tree.NewColumnItem(leftAliasName, leftColElem.Column), 299 }, 300 { 301 typ: tree.MustBeStaticallyKnownType(rightCol.Type), 302 item: tree.NewColumnItem(rightAliasName, rightColElem.Column), 303 }, 304 }) 305 if len(cols) >= len(leftIdx.Columns) { 306 break 307 } 308 } 309 if len(cols) > 0 { 310 return rightTableName, cols 311 } 312 } 313 } 314 // Since we can always match leftIdx we should never get here. 315 panic("unreachable") 316 }() 317 318 // joinRefs are limited to columns in the indexes (even if they don't 319 // appear in the join condition) because non-stored columns will cause 320 // a hash join. 321 var joinRefs colRefs 322 for _, pair := range cols { 323 joinRefs = append(joinRefs, &pair[0], &pair[1]) 324 } 325 326 var cond tree.TypedExpr 327 // Pick some prefix of the available columns. Not randomized because it 328 // needs to match the index column order. 329 for (cond == nil || s.coin()) && len(cols) > 0 { 330 v := cols[0] 331 cols = cols[1:] 332 expr := tree.NewTypedComparisonExpr( 333 tree.EQ, 334 typedParen(v[0].item, v[0].typ), 335 typedParen(v[1].item, v[1].typ), 336 ) 337 if cond == nil { 338 cond = expr 339 } else { 340 cond = tree.NewTypedAndExpr(cond, expr) 341 } 342 } 343 344 joinExpr := &tree.JoinTableExpr{ 345 Left: &tree.AliasedTableExpr{ 346 Expr: &leftTableName.Table, 347 As: tree.AliasClause{Alias: leftAlias}, 348 }, 349 Right: &tree.AliasedTableExpr{ 350 Expr: &rightTableName.Table, 351 As: tree.AliasClause{Alias: rightAlias}, 352 }, 353 Cond: &tree.OnJoinCond{Expr: cond}, 354 } 355 return joinExpr, joinRefs, true 356 } 357 358 // STATEMENTS 359 360 func (s *Smither) makeWith() (*tree.With, tableRefs) { 361 if s.disableWith { 362 return nil, nil 363 } 364 365 // WITHs are pretty rare, so just ignore them a lot. 366 if s.coin() { 367 return nil, nil 368 } 369 ctes := make([]*tree.CTE, 0, s.d6()/2) 370 if cap(ctes) == 0 { 371 return nil, nil 372 } 373 var tables tableRefs 374 for i := 0; i < cap(ctes); i++ { 375 var ok bool 376 var stmt tree.SelectStatement 377 var stmtRefs colRefs 378 stmt, stmtRefs, ok = s.makeSelectStmt(s.makeDesiredTypes(), nil /* refs */, tables) 379 if !ok { 380 continue 381 } 382 alias := s.name("with") 383 tblName := tree.NewUnqualifiedTableName(alias) 384 cols := make(tree.NameList, len(stmtRefs)) 385 defs := make([]*tree.ColumnTableDef, len(stmtRefs)) 386 for i, r := range stmtRefs { 387 var err error 388 cols[i] = r.item.ColumnName 389 defs[i], err = tree.NewColumnTableDef(r.item.ColumnName, r.typ, false /* isSerial */, nil) 390 if err != nil { 391 panic(err) 392 } 393 } 394 tables = append(tables, &tableRef{ 395 TableName: tblName, 396 Columns: defs, 397 }) 398 ctes = append(ctes, &tree.CTE{ 399 Name: tree.AliasClause{ 400 Alias: alias, 401 Cols: cols, 402 }, 403 Stmt: stmt, 404 }) 405 } 406 return &tree.With{ 407 CTEList: ctes, 408 }, tables 409 } 410 411 var orderDirections = []tree.Direction{ 412 tree.DefaultDirection, 413 tree.Ascending, 414 tree.Descending, 415 } 416 417 func (s *Smither) randDirection() tree.Direction { 418 return orderDirections[s.rnd.Intn(len(orderDirections))] 419 } 420 421 var nullabilities = []tree.Nullability{ 422 tree.NotNull, 423 tree.Null, 424 tree.SilentNull, 425 } 426 427 func (s *Smither) randNullability() tree.Nullability { 428 return nullabilities[s.rnd.Intn(len(nullabilities))] 429 } 430 431 var dropBehaviors = []tree.DropBehavior{ 432 tree.DropDefault, 433 tree.DropRestrict, 434 tree.DropCascade, 435 } 436 437 func (s *Smither) randDropBehavior() tree.DropBehavior { 438 return dropBehaviors[s.rnd.Intn(len(dropBehaviors))] 439 } 440 441 var stringComparisons = []tree.ComparisonOperator{ 442 tree.Like, 443 tree.NotLike, 444 tree.ILike, 445 tree.NotILike, 446 tree.SimilarTo, 447 tree.NotSimilarTo, 448 tree.RegMatch, 449 tree.NotRegMatch, 450 tree.RegIMatch, 451 tree.NotRegIMatch, 452 } 453 454 func (s *Smither) randStringComparison() tree.ComparisonOperator { 455 return stringComparisons[s.rnd.Intn(len(stringComparisons))] 456 } 457 458 // makeSelectTable returns a TableExpr of the form `(SELECT ...)`, which 459 // would end up looking like `SELECT ... FROM (SELECT ...)`. 460 func makeSelectTable(s *Smither, refs colRefs, forJoin bool) (tree.TableExpr, colRefs, bool) { 461 stmt, stmtRefs, ok := s.makeSelect(nil /* desiredTypes */, refs) 462 if !ok { 463 return nil, nil, false 464 } 465 466 table := s.name("tab") 467 names := make(tree.NameList, len(stmtRefs)) 468 clauseRefs := make(colRefs, len(stmtRefs)) 469 for i, ref := range stmtRefs { 470 names[i] = s.name("col") 471 clauseRefs[i] = &colRef{ 472 typ: ref.typ, 473 item: tree.NewColumnItem( 474 tree.NewUnqualifiedTableName(table), 475 names[i], 476 ), 477 } 478 } 479 480 return &tree.AliasedTableExpr{ 481 Expr: &tree.Subquery{ 482 Select: &tree.ParenSelect{Select: stmt}, 483 }, 484 As: tree.AliasClause{ 485 Alias: table, 486 Cols: names, 487 }, 488 }, clauseRefs, true 489 } 490 491 func makeSelectClause( 492 s *Smither, desiredTypes []*types.T, refs colRefs, withTables tableRefs, 493 ) (tree.SelectStatement, colRefs, bool) { 494 stmt, selectRefs, _, ok := s.makeSelectClause(desiredTypes, refs, withTables) 495 return stmt, selectRefs, ok 496 } 497 498 func (s *Smither) makeSelectClause( 499 desiredTypes []*types.T, refs colRefs, withTables tableRefs, 500 ) (clause *tree.SelectClause, selectRefs, orderByRefs colRefs, ok bool) { 501 if desiredTypes == nil && s.d9() == 1 { 502 return s.makeOrderedAggregate() 503 } 504 505 clause = &tree.SelectClause{} 506 507 var fromRefs colRefs 508 // Sometimes generate a SELECT with no FROM clause. 509 requireFrom := s.vectorizable || s.d6() != 1 510 for (requireFrom && len(clause.From.Tables) < 1) || s.canRecurse() { 511 var from tree.TableExpr 512 if len(withTables) == 0 || s.coin() { 513 // Add a normal data source. 514 source, sourceRefs, sourceOk := makeTableExpr(s, refs, false) 515 if !sourceOk { 516 return nil, nil, nil, false 517 } 518 from = source 519 fromRefs = append(fromRefs, sourceRefs...) 520 } else { 521 // Add a CTE reference. 522 table := withTables[s.rnd.Intn(len(withTables))] 523 524 alias := s.name("cte_ref") 525 name := tree.NewUnqualifiedTableName(alias) 526 expr, exprRefs := s.tableExpr(table, name) 527 528 from = &tree.AliasedTableExpr{ 529 Expr: expr, 530 As: tree.AliasClause{Alias: alias}, 531 } 532 fromRefs = append(fromRefs, exprRefs...) 533 } 534 clause.From.Tables = append(clause.From.Tables, from) 535 // Restrict so that we don't have a crazy amount of rows due to many joins. 536 if len(clause.From.Tables) >= 4 { 537 break 538 } 539 } 540 541 selectListRefs := refs 542 ctx := emptyCtx 543 544 if len(clause.From.Tables) > 0 { 545 clause.Where = s.makeWhere(fromRefs) 546 orderByRefs = fromRefs 547 selectListRefs = selectListRefs.extend(fromRefs...) 548 549 // TODO(mjibson): vec only supports GROUP BYs on fully-ordered 550 // columns, which we could support here. Also see #39240 which 551 // will support this more generally. 552 if !s.vectorizable && s.d6() <= 2 && s.canRecurse() { 553 // Enable GROUP BY. Choose some random subset of the 554 // fromRefs. 555 // TODO(mjibson): Refence handling and aggregation functions 556 // aren't quite handled correctly here. This currently 557 // does well enough to at least find some bugs but should 558 // be improved to do the correct thing wrt aggregate 559 // functions. That is, the select and having exprs can 560 // either reference a group by column or a non-group by 561 // column in an aggregate function. It's also possible 562 // the where and order by exprs are not correct. 563 groupByRefs := fromRefs.extend() 564 s.rnd.Shuffle(len(groupByRefs), func(i, j int) { 565 groupByRefs[i], groupByRefs[j] = groupByRefs[j], groupByRefs[i] 566 }) 567 var groupBy tree.GroupBy 568 for (len(groupBy) < 1 || s.coin()) && len(groupBy) < len(groupByRefs) { 569 groupBy = append(groupBy, groupByRefs[len(groupBy)].item) 570 } 571 groupByRefs = groupByRefs[:len(groupBy)] 572 clause.GroupBy = groupBy 573 clause.Having = s.makeHaving(fromRefs) 574 selectListRefs = groupByRefs 575 orderByRefs = groupByRefs 576 // TODO(mjibson): also use this context sometimes in 577 // non-aggregate mode (select sum(x) from a). 578 ctx = groupByCtx 579 } else if s.d6() <= 1 && s.canRecurse() { 580 // Enable window functions. This will enable them for all 581 // exprs, but makeFunc will only let a few through. 582 ctx = windowCtx 583 } 584 } 585 586 selectList, selectRefs, ok := s.makeSelectList(ctx, desiredTypes, selectListRefs) 587 if !ok { 588 return nil, nil, nil, false 589 } 590 clause.Exprs = selectList 591 592 // TODO(mjibson): Vectorized only supports ordered distinct, and so 593 // this often produces queries that won't vec. However since it will 594 // also sometimes produce vec queries with the distinctChainOps node, 595 // we allow this here. Teach this how to correctly limit itself to 596 // distinct only on ordered columns. 597 if s.d100() == 1 { 598 clause.Distinct = true 599 // For SELECT DISTINCT, ORDER BY expressions must appear in select list. 600 orderByRefs = selectRefs 601 } 602 603 return clause, selectRefs, orderByRefs, true 604 } 605 606 func (s *Smither) makeOrderedAggregate() ( 607 clause *tree.SelectClause, 608 selectRefs, orderByRefs colRefs, 609 ok bool, 610 ) { 611 // We need a SELECT with a GROUP BY on ordered columns. Choose a random 612 // table and index from that table and pick a random prefix from it. 613 tableExpr, tableAlias, table, tableColRefs, ok := s.getSchemaTableWithIndexHint() 614 if !ok { 615 return nil, nil, nil, false 616 } 617 _, _, idxRefs, ok := s.getRandTableIndex(*table.TableName, *tableAlias) 618 if !ok { 619 return nil, nil, nil, false 620 } 621 622 var groupBy tree.GroupBy 623 for (len(groupBy) < 1 || s.coin()) && len(groupBy) < len(idxRefs) { 624 groupBy = append(groupBy, idxRefs[len(groupBy)].item) 625 } 626 idxRefs = idxRefs[:len(groupBy)] 627 alias := s.name("col") 628 selectRefs = colRefs{ 629 { 630 typ: types.Int, 631 item: &tree.ColumnItem{ColumnName: alias}, 632 }, 633 } 634 return &tree.SelectClause{ 635 Exprs: tree.SelectExprs{ 636 { 637 Expr: countStar, 638 As: tree.UnrestrictedName(alias), 639 }, 640 }, 641 From: tree.From{ 642 Tables: tree.TableExprs{tableExpr}, 643 }, 644 Where: s.makeWhere(tableColRefs), 645 GroupBy: groupBy, 646 Having: s.makeHaving(idxRefs), 647 }, selectRefs, idxRefs, true 648 } 649 650 var countStar = func() tree.TypedExpr { 651 fn := tree.FunDefs["count"] 652 typ := types.Int 653 return tree.NewTypedFuncExpr( 654 tree.ResolvableFunctionReference{FunctionReference: fn}, 655 0, /* aggQualifier */ 656 tree.TypedExprs{tree.UnqualifiedStar{}}, 657 nil, /* filter */ 658 nil, /* window */ 659 typ, 660 &fn.FunctionProperties, 661 fn.Definition[0].(*tree.Overload), 662 ) 663 }() 664 665 func makeSelect(s *Smither) (tree.Statement, bool) { 666 stmt, refs, ok := s.makeSelect(nil, nil) 667 if !ok { 668 return stmt, ok 669 } 670 if s.outputSort { 671 order := make(tree.OrderBy, len(refs)) 672 for i, r := range refs { 673 order[i] = &tree.Order{ 674 Expr: r.item, 675 NullsOrder: tree.NullsFirst, 676 } 677 } 678 stmt = &tree.Select{ 679 Select: &tree.SelectClause{ 680 Exprs: tree.SelectExprs{ 681 tree.SelectExpr{ 682 Expr: tree.UnqualifiedStar{}, 683 }, 684 }, 685 From: tree.From{ 686 Tables: tree.TableExprs{ 687 &tree.AliasedTableExpr{ 688 Expr: &tree.Subquery{ 689 Select: &tree.ParenSelect{Select: stmt}, 690 }, 691 As: tree.AliasClause{ 692 Alias: s.name("tab"), 693 }, 694 }, 695 }, 696 }, 697 }, 698 OrderBy: order, 699 } 700 } 701 return stmt, ok 702 } 703 704 func (s *Smither) makeSelect(desiredTypes []*types.T, refs colRefs) (*tree.Select, colRefs, bool) { 705 withStmt, withTables := s.makeWith() 706 707 clause, selectRefs, orderByRefs, ok := s.makeSelectClause(desiredTypes, refs, withTables) 708 if !ok { 709 return nil, nil, ok 710 } 711 712 stmt := tree.Select{ 713 Select: clause, 714 With: withStmt, 715 OrderBy: s.makeOrderBy(orderByRefs), 716 Limit: makeLimit(s), 717 } 718 719 return &stmt, selectRefs, true 720 } 721 722 // makeSelectList generates SelectExprs corresponding to 723 // desiredTypes. desiredTypes can be nil which causes types to be randomly 724 // selected from refs, improving the chance they are chosen during 725 // makeScalar. Especially useful with the AvoidConsts option. 726 func (s *Smither) makeSelectList( 727 ctx Context, desiredTypes []*types.T, refs colRefs, 728 ) (tree.SelectExprs, colRefs, bool) { 729 // If we don't have any desired types, generate some from the given refs. 730 if len(desiredTypes) == 0 { 731 s.sample(len(refs), 6, func(i int) { 732 desiredTypes = append(desiredTypes, refs[i].typ) 733 }) 734 } 735 // If we still don't have any then there weren't any refs. 736 if len(desiredTypes) == 0 { 737 desiredTypes = s.makeDesiredTypes() 738 } 739 result := make(tree.SelectExprs, len(desiredTypes)) 740 selectRefs := make(colRefs, len(desiredTypes)) 741 for i, t := range desiredTypes { 742 result[i].Expr = makeScalarContext(s, ctx, t, refs) 743 alias := s.name("col") 744 result[i].As = tree.UnrestrictedName(alias) 745 selectRefs[i] = &colRef{ 746 typ: t, 747 item: &tree.ColumnItem{ColumnName: alias}, 748 } 749 } 750 return result, selectRefs, true 751 } 752 753 func makeDelete(s *Smither) (tree.Statement, bool) { 754 stmt, _, ok := s.makeDelete(nil) 755 return stmt, ok 756 } 757 758 func (s *Smither) makeDelete(refs colRefs) (*tree.Delete, *tableRef, bool) { 759 table, _, tableRef, tableRefs, ok := s.getSchemaTable() 760 if !ok { 761 return nil, nil, false 762 } 763 764 del := &tree.Delete{ 765 Table: table, 766 Where: s.makeWhere(tableRefs), 767 OrderBy: s.makeOrderBy(tableRefs), 768 Limit: makeLimit(s), 769 Returning: &tree.NoReturningClause{}, 770 } 771 if del.Limit == nil { 772 del.OrderBy = nil 773 } 774 775 return del, tableRef, true 776 } 777 778 func makeDeleteReturning(s *Smither, refs colRefs, forJoin bool) (tree.TableExpr, colRefs, bool) { 779 if forJoin { 780 return nil, nil, false 781 } 782 return s.makeDeleteReturning(refs) 783 } 784 785 func (s *Smither) makeDeleteReturning(refs colRefs) (tree.TableExpr, colRefs, bool) { 786 del, delRef, ok := s.makeDelete(refs) 787 if !ok { 788 return nil, nil, false 789 } 790 var returningRefs colRefs 791 del.Returning, returningRefs = s.makeReturning(delRef) 792 return &tree.StatementSource{ 793 Statement: del, 794 }, returningRefs, true 795 } 796 797 func makeUpdate(s *Smither) (tree.Statement, bool) { 798 stmt, _, ok := s.makeUpdate(nil) 799 return stmt, ok 800 } 801 802 func (s *Smither) makeUpdate(refs colRefs) (*tree.Update, *tableRef, bool) { 803 table, _, tableRef, tableRefs, ok := s.getSchemaTable() 804 if !ok { 805 return nil, nil, false 806 } 807 cols := make(map[tree.Name]*tree.ColumnTableDef) 808 for _, c := range tableRef.Columns { 809 cols[c.Name] = c 810 } 811 812 update := &tree.Update{ 813 Table: table, 814 Where: s.makeWhere(tableRefs), 815 OrderBy: s.makeOrderBy(tableRefs), 816 Limit: makeLimit(s), 817 Returning: &tree.NoReturningClause{}, 818 } 819 // Each row can be set at most once. Copy tableRefs to upRefs and remove 820 // elements from it as we use them. 821 upRefs := tableRefs.extend() 822 for (len(update.Exprs) < 1 || s.coin()) && len(upRefs) > 0 { 823 n := s.rnd.Intn(len(upRefs)) 824 ref := upRefs[n] 825 upRefs = append(upRefs[:n], upRefs[n+1:]...) 826 col := cols[ref.item.ColumnName] 827 // Ignore computed columns. 828 if col == nil || col.Computed.Computed { 829 continue 830 } 831 var expr tree.TypedExpr 832 for { 833 expr = makeScalar(s, ref.typ, tableRefs) 834 // Make sure expr isn't null if that's not allowed. 835 if col.Nullable.Nullability != tree.NotNull || expr != tree.DNull { 836 break 837 } 838 } 839 update.Exprs = append(update.Exprs, &tree.UpdateExpr{ 840 Names: tree.NameList{ref.item.ColumnName}, 841 Expr: expr, 842 }) 843 } 844 if len(update.Exprs) == 0 { 845 panic("empty") 846 } 847 if update.Limit == nil { 848 update.OrderBy = nil 849 } 850 851 return update, tableRef, true 852 } 853 854 func makeUpdateReturning(s *Smither, refs colRefs, forJoin bool) (tree.TableExpr, colRefs, bool) { 855 if forJoin { 856 return nil, nil, false 857 } 858 return s.makeUpdateReturning(refs) 859 } 860 861 func (s *Smither) makeUpdateReturning(refs colRefs) (tree.TableExpr, colRefs, bool) { 862 update, updateRef, ok := s.makeUpdate(refs) 863 if !ok { 864 return nil, nil, false 865 } 866 var returningRefs colRefs 867 update.Returning, returningRefs = s.makeReturning(updateRef) 868 return &tree.StatementSource{ 869 Statement: update, 870 }, returningRefs, true 871 } 872 873 func makeInsert(s *Smither) (tree.Statement, bool) { 874 stmt, _, ok := s.makeInsert(nil) 875 return stmt, ok 876 } 877 878 func makeBegin(s *Smither) (tree.Statement, bool) { 879 return &tree.BeginTransaction{}, true 880 } 881 882 func makeSavepoint(s *Smither) (tree.Statement, bool) { 883 savepointName := s.randString(s.d9(), letters) 884 s.activeSavepoints = append(s.activeSavepoints, savepointName) 885 return &tree.Savepoint{Name: tree.Name(savepointName)}, true 886 } 887 888 func makeReleaseSavepoint(s *Smither) (tree.Statement, bool) { 889 if len(s.activeSavepoints) == 0 { 890 return nil, false 891 } 892 idx := s.rnd.Intn(len(s.activeSavepoints)) 893 savepoint := s.activeSavepoints[idx] 894 // Remove the released savepoint from our set of active savepoints. 895 s.activeSavepoints = append(s.activeSavepoints[:idx], s.activeSavepoints[idx+1:]...) 896 return &tree.ReleaseSavepoint{Savepoint: tree.Name(savepoint)}, true 897 } 898 899 func makeRollbackToSavepoint(s *Smither) (tree.Statement, bool) { 900 if len(s.activeSavepoints) == 0 { 901 return nil, false 902 } 903 idx := s.rnd.Intn(len(s.activeSavepoints)) 904 savepoint := s.activeSavepoints[idx] 905 // Destroy all savepoints that come after the savepoint we rollback to. 906 s.activeSavepoints = s.activeSavepoints[:idx+1] 907 return &tree.RollbackToSavepoint{Savepoint: tree.Name(savepoint)}, true 908 } 909 910 func makeCommit(s *Smither) (tree.Statement, bool) { 911 return &tree.CommitTransaction{}, true 912 } 913 914 func makeRollback(s *Smither) (tree.Statement, bool) { 915 return &tree.RollbackTransaction{}, true 916 } 917 918 // makeInsert has only one valid reference: its table source, which can be 919 // used only in the optional returning section. Hence the irregular return 920 // signature. 921 func (s *Smither) makeInsert(refs colRefs) (*tree.Insert, *tableRef, bool) { 922 table, _, tableRef, _, ok := s.getSchemaTable() 923 if !ok { 924 return nil, nil, false 925 } 926 927 insert := &tree.Insert{ 928 Table: table, 929 Rows: &tree.Select{}, 930 Returning: &tree.NoReturningClause{}, 931 } 932 933 // Use DEFAULT VALUES only sometimes. A nil insert.Rows.Select indicates 934 // DEFAULT VALUES. 935 if s.d9() != 1 { 936 var desiredTypes []*types.T 937 var names tree.NameList 938 939 unnamed := s.coin() 940 941 // Grab some subset of the columns of the table to attempt to insert into. 942 for _, c := range tableRef.Columns { 943 // We *must* write a column if it's writable and non-nullable. 944 // We *can* write a column if it's writable and nullable. 945 if c.Computed.Computed { 946 continue 947 } 948 if unnamed || c.Nullable.Nullability == tree.NotNull || s.coin() { 949 desiredTypes = append(desiredTypes, tree.MustBeStaticallyKnownType(c.Type)) 950 names = append(names, c.Name) 951 } 952 } 953 if len(desiredTypes) == 0 { 954 return nil, nil, false 955 } 956 if !unnamed { 957 insert.Columns = names 958 } 959 960 insert.Rows, _, ok = s.makeSelect(desiredTypes, refs) 961 if !ok { 962 return nil, nil, false 963 } 964 } 965 966 return insert, tableRef, true 967 } 968 969 func makeInsertReturning(s *Smither, refs colRefs, forJoin bool) (tree.TableExpr, colRefs, bool) { 970 if forJoin { 971 return nil, nil, false 972 } 973 return s.makeInsertReturning(refs) 974 } 975 976 func (s *Smither) makeInsertReturning(refs colRefs) (tree.TableExpr, colRefs, bool) { 977 insert, insertRef, ok := s.makeInsert(refs) 978 if !ok { 979 return nil, nil, false 980 } 981 var returningRefs colRefs 982 insert.Returning, returningRefs = s.makeReturning(insertRef) 983 return &tree.StatementSource{ 984 Statement: insert, 985 }, returningRefs, true 986 } 987 988 func makeValuesTable(s *Smither, refs colRefs, forJoin bool) (tree.TableExpr, colRefs, bool) { 989 types := s.makeDesiredTypes() 990 values, valuesRefs := makeValues(s, types, refs) 991 return values, valuesRefs, true 992 } 993 994 func makeValues(s *Smither, desiredTypes []*types.T, refs colRefs) (tree.TableExpr, colRefs) { 995 numRowsToInsert := s.d6() 996 values := tree.ValuesClause{ 997 Rows: make([]tree.Exprs, numRowsToInsert), 998 } 999 1000 for i := 0; i < numRowsToInsert; i++ { 1001 tuple := make([]tree.Expr, len(desiredTypes)) 1002 for j, t := range desiredTypes { 1003 tuple[j] = makeScalar(s, t, refs) 1004 } 1005 values.Rows[i] = tuple 1006 } 1007 table := s.name("tab") 1008 names := make(tree.NameList, len(desiredTypes)) 1009 valuesRefs := make(colRefs, len(desiredTypes)) 1010 for i, typ := range desiredTypes { 1011 names[i] = s.name("col") 1012 valuesRefs[i] = &colRef{ 1013 typ: typ, 1014 item: tree.NewColumnItem( 1015 tree.NewUnqualifiedTableName(table), 1016 names[i], 1017 ), 1018 } 1019 } 1020 1021 return &tree.AliasedTableExpr{ 1022 Expr: &tree.Subquery{ 1023 Select: &tree.ParenSelect{ 1024 Select: &tree.Select{ 1025 Select: &values, 1026 }, 1027 }, 1028 }, 1029 As: tree.AliasClause{ 1030 Alias: table, 1031 Cols: names, 1032 }, 1033 }, valuesRefs 1034 } 1035 1036 func makeValuesSelect( 1037 s *Smither, desiredTypes []*types.T, refs colRefs, withTables tableRefs, 1038 ) (tree.SelectStatement, colRefs, bool) { 1039 values, valuesRefs := makeValues(s, desiredTypes, refs) 1040 1041 // Returning just &values here would result in a query like `VALUES (...)` where 1042 // the columns are arbitrarily named by index (column1, column2, etc.). Since 1043 // we want to be able to reference the columns in other places we need to 1044 // name them deterministically. We can use `SELECT * FROM (VALUES (...)) AS 1045 // tbl (c1, c2, etc.)` to achieve this. There's quite a lot of indirection 1046 // for how to achieve exactly that syntax as tree nodes, but it works. 1047 return &tree.SelectClause{ 1048 Exprs: tree.SelectExprs{tree.StarSelectExpr()}, 1049 From: tree.From{ 1050 Tables: tree.TableExprs{values}, 1051 }, 1052 }, valuesRefs, true 1053 } 1054 1055 var setOps = []tree.UnionType{ 1056 tree.UnionOp, 1057 tree.IntersectOp, 1058 tree.ExceptOp, 1059 } 1060 1061 func makeSetOp( 1062 s *Smither, desiredTypes []*types.T, refs colRefs, withTables tableRefs, 1063 ) (tree.SelectStatement, colRefs, bool) { 1064 left, leftRefs, ok := s.makeSelectStmt(desiredTypes, refs, withTables) 1065 if !ok { 1066 return nil, nil, false 1067 } 1068 1069 right, _, ok := s.makeSelectStmt(desiredTypes, refs, withTables) 1070 if !ok { 1071 return nil, nil, false 1072 } 1073 1074 return &tree.UnionClause{ 1075 Type: setOps[s.rnd.Intn(len(setOps))], 1076 Left: &tree.Select{Select: left}, 1077 Right: &tree.Select{Select: right}, 1078 All: s.coin(), 1079 }, leftRefs, true 1080 } 1081 1082 func (s *Smither) makeWhere(refs colRefs) *tree.Where { 1083 if s.coin() { 1084 where := makeBoolExpr(s, refs) 1085 return tree.NewWhere("WHERE", where) 1086 } 1087 return nil 1088 } 1089 1090 func (s *Smither) makeHaving(refs colRefs) *tree.Where { 1091 if s.coin() { 1092 where := makeBoolExprContext(s, havingCtx, refs) 1093 return tree.NewWhere("HAVING", where) 1094 } 1095 return nil 1096 } 1097 1098 func (s *Smither) makeOrderBy(refs colRefs) tree.OrderBy { 1099 if len(refs) == 0 { 1100 return nil 1101 } 1102 var ob tree.OrderBy 1103 for s.coin() { 1104 ref := refs[s.rnd.Intn(len(refs))] 1105 // We don't support order by jsonb columns. 1106 if ref.typ.Family() == types.JsonFamily { 1107 continue 1108 } 1109 ob = append(ob, &tree.Order{ 1110 Expr: ref.item, 1111 Direction: s.randDirection(), 1112 }) 1113 } 1114 return ob 1115 } 1116 1117 func makeLimit(s *Smither) *tree.Limit { 1118 if s.disableLimits { 1119 return nil 1120 } 1121 if s.d6() > 2 { 1122 return &tree.Limit{Count: tree.NewDInt(tree.DInt(s.d100()))} 1123 } 1124 return nil 1125 } 1126 1127 func (s *Smither) makeReturning(table *tableRef) (*tree.ReturningExprs, colRefs) { 1128 desiredTypes := s.makeDesiredTypes() 1129 1130 refs := make(colRefs, len(table.Columns)) 1131 for i, c := range table.Columns { 1132 refs[i] = &colRef{ 1133 typ: tree.MustBeStaticallyKnownType(c.Type), 1134 item: &tree.ColumnItem{ColumnName: c.Name}, 1135 } 1136 } 1137 1138 returning := make(tree.ReturningExprs, len(desiredTypes)) 1139 returningRefs := make(colRefs, len(desiredTypes)) 1140 for i, t := range desiredTypes { 1141 returning[i].Expr = makeScalar(s, t, refs) 1142 alias := s.name("ret") 1143 returning[i].As = tree.UnrestrictedName(alias) 1144 returningRefs[i] = &colRef{ 1145 typ: t, 1146 item: &tree.ColumnItem{ 1147 ColumnName: alias, 1148 }, 1149 } 1150 } 1151 return &returning, returningRefs 1152 }