github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/optbuilder/select.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 optbuilder 12 13 import ( 14 "github.com/cockroachdb/cockroach/pkg/server/telemetry" 15 "github.com/cockroachdb/cockroach/pkg/sql/opt" 16 "github.com/cockroachdb/cockroach/pkg/sql/opt/cat" 17 "github.com/cockroachdb/cockroach/pkg/sql/opt/memo" 18 "github.com/cockroachdb/cockroach/pkg/sql/parser" 19 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" 20 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" 21 "github.com/cockroachdb/cockroach/pkg/sql/privilege" 22 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 23 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 24 "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" 25 "github.com/cockroachdb/cockroach/pkg/sql/types" 26 "github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented" 27 "github.com/cockroachdb/errors" 28 ) 29 30 const ( 31 excludeMutations = false 32 includeMutations = true 33 ) 34 35 // buildDataSource builds a set of memo groups that represent the given table 36 // expression. For example, if the tree.TableExpr consists of a single table, 37 // the resulting set of memo groups will consist of a single group with a 38 // scanOp operator. Joins will result in the construction of several groups, 39 // including two for the left and right table scans, at least one for the join 40 // condition, and one for the join itself. 41 // 42 // See Builder.buildStmt for a description of the remaining input and 43 // return values. 44 func (b *Builder) buildDataSource( 45 texpr tree.TableExpr, indexFlags *tree.IndexFlags, locking lockingSpec, inScope *scope, 46 ) (outScope *scope) { 47 defer func(prevAtRoot bool) { 48 inScope.atRoot = prevAtRoot 49 }(inScope.atRoot) 50 inScope.atRoot = false 51 // NB: The case statements are sorted lexicographically. 52 switch source := texpr.(type) { 53 case *tree.AliasedTableExpr: 54 if source.IndexFlags != nil { 55 telemetry.Inc(sqltelemetry.IndexHintUseCounter) 56 telemetry.Inc(sqltelemetry.IndexHintSelectUseCounter) 57 indexFlags = source.IndexFlags 58 } 59 if source.As.Alias != "" { 60 locking = locking.filter(source.As.Alias) 61 } 62 63 outScope = b.buildDataSource(source.Expr, indexFlags, locking, inScope) 64 65 if source.Ordinality { 66 outScope = b.buildWithOrdinality("ordinality", outScope) 67 } 68 69 // Overwrite output properties with any alias information. 70 b.renameSource(source.As, outScope) 71 72 return outScope 73 74 case *tree.JoinTableExpr: 75 return b.buildJoin(source, locking, inScope) 76 77 case *tree.TableName: 78 tn := source 79 80 // CTEs take precedence over other data sources. 81 if cte := inScope.resolveCTE(tn); cte != nil { 82 locking.ignoreLockingForCTE() 83 outScope = inScope.push() 84 inCols := make(opt.ColList, len(cte.cols)) 85 outCols := make(opt.ColList, len(cte.cols)) 86 outScope.cols = nil 87 for i, col := range cte.cols { 88 id := col.ID 89 c := b.factory.Metadata().ColumnMeta(id) 90 newCol := b.synthesizeColumn(outScope, col.Alias, c.Type, nil, nil) 91 newCol.table = *tn 92 inCols[i] = id 93 outCols[i] = newCol.id 94 } 95 96 outScope.expr = b.factory.ConstructWithScan(&memo.WithScanPrivate{ 97 With: cte.id, 98 Name: string(cte.name.Alias), 99 InCols: inCols, 100 OutCols: outCols, 101 BindingProps: cte.bindingProps, 102 ID: b.factory.Metadata().NextUniqueID(), 103 }) 104 105 return outScope 106 } 107 108 priv := privilege.SELECT 109 locking = locking.filter(tn.ObjectName) 110 if locking.isSet() { 111 // SELECT ... FOR [KEY] UPDATE/SHARE requires UPDATE privileges. 112 priv = privilege.UPDATE 113 } 114 115 ds, resName := b.resolveDataSource(tn, priv) 116 switch t := ds.(type) { 117 case cat.Table: 118 tabMeta := b.addTable(t, &resName) 119 return b.buildScan(tabMeta, nil /* ordinals */, indexFlags, locking, excludeMutations, inScope) 120 121 case cat.Sequence: 122 return b.buildSequenceSelect(t, &resName, inScope) 123 124 case cat.View: 125 return b.buildView(t, &resName, locking, inScope) 126 127 default: 128 panic(errors.AssertionFailedf("unknown DataSource type %T", ds)) 129 } 130 131 case *tree.ParenTableExpr: 132 return b.buildDataSource(source.Expr, indexFlags, locking, inScope) 133 134 case *tree.RowsFromExpr: 135 return b.buildZip(source.Items, inScope) 136 137 case *tree.Subquery: 138 // Remove any target relations from the current scope's locking spec, as 139 // those only apply to relations in this statement. Interestingly, this 140 // would not be necessary if we required all subqueries to have aliases 141 // like Postgres does. 142 locking = locking.withoutTargets() 143 144 outScope = b.buildSelectStmt(source.Select, locking, nil /* desiredTypes */, inScope) 145 146 // Treat the subquery result as an anonymous data source (i.e. column names 147 // are not qualified). Remove hidden columns, as they are not accessible 148 // outside the subquery. 149 outScope.setTableAlias("") 150 outScope.removeHiddenCols() 151 152 return outScope 153 154 case *tree.StatementSource: 155 // This is the special '[ ... ]' syntax. We treat this as syntactic sugar 156 // for a top-level CTE, so it cannot refer to anything in the input scope. 157 // See #41078. 158 emptyScope := b.allocScope() 159 innerScope := b.buildStmt(source.Statement, nil /* desiredTypes */, emptyScope) 160 if len(innerScope.cols) == 0 { 161 panic(pgerror.Newf(pgcode.UndefinedColumn, 162 "statement source \"%v\" does not return any columns", source.Statement)) 163 } 164 165 id := b.factory.Memo().NextWithID() 166 cte := cteSource{ 167 name: tree.AliasClause{}, 168 cols: innerScope.makePresentationWithHiddenCols(), 169 originalExpr: source.Statement, 170 expr: innerScope.expr, 171 id: id, 172 bindingProps: innerScope.expr.Relational(), 173 } 174 b.cteStack[len(b.cteStack)-1] = append(b.cteStack[len(b.cteStack)-1], cte) 175 176 inCols := make(opt.ColList, len(cte.cols)) 177 outCols := make(opt.ColList, len(cte.cols)) 178 for i, col := range cte.cols { 179 id := col.ID 180 c := b.factory.Metadata().ColumnMeta(id) 181 inCols[i] = id 182 outCols[i] = b.factory.Metadata().AddColumn(col.Alias, c.Type) 183 } 184 185 locking.ignoreLockingForCTE() 186 outScope = inScope.push() 187 // Similar to appendColumnsFromScope, but with re-numbering the column IDs. 188 for i, col := range innerScope.cols { 189 col.scalar = nil 190 col.id = outCols[i] 191 outScope.cols = append(outScope.cols, col) 192 } 193 194 outScope.expr = b.factory.ConstructWithScan(&memo.WithScanPrivate{ 195 With: cte.id, 196 Name: string(cte.name.Alias), 197 InCols: inCols, 198 OutCols: outCols, 199 BindingProps: cte.bindingProps, 200 ID: b.factory.Metadata().NextUniqueID(), 201 }) 202 203 return outScope 204 205 case *tree.TableRef: 206 priv := privilege.SELECT 207 locking = locking.filter(source.As.Alias) 208 if locking.isSet() { 209 // SELECT ... FOR [KEY] UPDATE/SHARE requires UPDATE privileges. 210 priv = privilege.UPDATE 211 } 212 213 ds := b.resolveDataSourceRef(source, priv) 214 switch t := ds.(type) { 215 case cat.Table: 216 outScope = b.buildScanFromTableRef(t, source, indexFlags, locking, inScope) 217 case cat.View: 218 if source.Columns != nil { 219 panic(pgerror.Newf(pgcode.FeatureNotSupported, 220 "cannot specify an explicit column list when accessing a view by reference")) 221 } 222 tn := tree.MakeUnqualifiedTableName(t.Name()) 223 224 outScope = b.buildView(t, &tn, locking, inScope) 225 case cat.Sequence: 226 tn := tree.MakeUnqualifiedTableName(t.Name()) 227 // Any explicitly listed columns are ignored. 228 outScope = b.buildSequenceSelect(t, &tn, inScope) 229 default: 230 panic(errors.AssertionFailedf("unsupported catalog object")) 231 } 232 b.renameSource(source.As, outScope) 233 return outScope 234 235 default: 236 panic(errors.AssertionFailedf("unknown table expr: %T", texpr)) 237 } 238 } 239 240 // buildView parses the view query text and builds it as a Select expression. 241 func (b *Builder) buildView( 242 view cat.View, viewName *tree.TableName, locking lockingSpec, inScope *scope, 243 ) (outScope *scope) { 244 // Cache the AST so that multiple references won't need to reparse. 245 if b.views == nil { 246 b.views = make(map[cat.View]*tree.Select) 247 } 248 249 // Check whether view has already been parsed, and if not, parse now. 250 sel, ok := b.views[view] 251 if !ok { 252 stmt, err := parser.ParseOne(view.Query()) 253 if err != nil { 254 wrapped := pgerror.Wrapf(err, pgcode.Syntax, 255 "failed to parse underlying query from view %q", view.Name()) 256 panic(wrapped) 257 } 258 259 sel, ok = stmt.AST.(*tree.Select) 260 if !ok { 261 panic(errors.AssertionFailedf("expected SELECT statement")) 262 } 263 264 b.views[view] = sel 265 266 // Keep track of referenced views for EXPLAIN (opt, env). 267 b.factory.Metadata().AddView(view) 268 } 269 270 // When building the view, we don't want to check for the SELECT privilege 271 // on the underlying tables, just on the view itself. Checking on the 272 // underlying tables as well would defeat the purpose of having separate 273 // SELECT privileges on the view, which is intended to allow for exposing 274 // some subset of a restricted table's data to less privileged users. 275 if !b.skipSelectPrivilegeChecks { 276 b.skipSelectPrivilegeChecks = true 277 defer func() { b.skipSelectPrivilegeChecks = false }() 278 } 279 trackDeps := b.trackViewDeps 280 if trackDeps { 281 // We are only interested in the direct dependency on this view descriptor. 282 // Any further dependency by the view's query should not be tracked. 283 b.trackViewDeps = false 284 defer func() { b.trackViewDeps = true }() 285 } 286 287 // We don't want the view to be able to refer to any outer scopes in the 288 // query. This shouldn't happen if the view is valid but there may be 289 // cornercases (e.g. renaming tables referenced by the view). To be safe, we 290 // build the view with an empty scope. But after that, we reattach the scope 291 // to the existing scope chain because we want the rest of the query to be 292 // able to refer to the higher scopes (see #46180). 293 emptyScope := b.allocScope() 294 outScope = b.buildSelect(sel, locking, nil /* desiredTypes */, emptyScope) 295 emptyScope.parent = inScope 296 297 // Update data source name to be the name of the view. And if view columns 298 // are specified, then update names of output columns. 299 hasCols := view.ColumnNameCount() > 0 300 for i := range outScope.cols { 301 outScope.cols[i].table = *viewName 302 if hasCols { 303 outScope.cols[i].name = view.ColumnName(i) 304 } 305 } 306 307 if trackDeps && !view.IsSystemView() { 308 dep := opt.ViewDep{DataSource: view} 309 for i := range outScope.cols { 310 dep.ColumnOrdinals.Add(i) 311 } 312 b.viewDeps = append(b.viewDeps, dep) 313 } 314 315 return outScope 316 } 317 318 // renameSource applies an AS clause to the columns in scope. 319 func (b *Builder) renameSource(as tree.AliasClause, scope *scope) { 320 if as.Alias != "" { 321 colAlias := as.Cols 322 323 // Special case for Postgres compatibility: if a data source does not 324 // currently have a name, and it is a set-generating function or a scalar 325 // function with just one column, and the AS clause doesn't specify column 326 // names, then use the specified table name both as the column name and 327 // table name. 328 noColNameSpecified := len(colAlias) == 0 329 if scope.isAnonymousTable() && noColNameSpecified && scope.singleSRFColumn { 330 colAlias = tree.NameList{as.Alias} 331 } 332 333 // If an alias was specified, use that to qualify the column names. 334 tableAlias := tree.MakeUnqualifiedTableName(as.Alias) 335 scope.setTableAlias(as.Alias) 336 337 // If input expression is a ScanExpr, then override metadata aliases for 338 // pretty-printing. 339 scan, isScan := scope.expr.(*memo.ScanExpr) 340 if isScan { 341 tabMeta := b.factory.Metadata().TableMeta(scan.ScanPrivate.Table) 342 tabMeta.Alias = tree.MakeUnqualifiedTableName(as.Alias) 343 } 344 345 if len(colAlias) > 0 { 346 // The column aliases can only refer to explicit columns. 347 for colIdx, aliasIdx := 0, 0; aliasIdx < len(colAlias); colIdx++ { 348 if colIdx >= len(scope.cols) { 349 srcName := tree.ErrString(&tableAlias) 350 panic(pgerror.Newf( 351 pgcode.InvalidColumnReference, 352 "source %q has %d columns available but %d columns specified", 353 srcName, aliasIdx, len(colAlias), 354 )) 355 } 356 col := &scope.cols[colIdx] 357 if col.hidden { 358 continue 359 } 360 col.name = colAlias[aliasIdx] 361 if isScan { 362 // Override column metadata alias. 363 colMeta := b.factory.Metadata().ColumnMeta(col.id) 364 colMeta.Alias = string(colAlias[aliasIdx]) 365 } 366 aliasIdx++ 367 } 368 } 369 } 370 } 371 372 // buildScanFromTableRef adds support for numeric references in queries. 373 // For example: 374 // SELECT * FROM [53 as t]; (table reference) 375 // SELECT * FROM [53(1) as t]; (+columnar reference) 376 // SELECT * FROM [53(1) as t]@1; (+index reference) 377 // Note, the query SELECT * FROM [53() as t] is unsupported. Column lists must 378 // be non-empty 379 func (b *Builder) buildScanFromTableRef( 380 tab cat.Table, 381 ref *tree.TableRef, 382 indexFlags *tree.IndexFlags, 383 locking lockingSpec, 384 inScope *scope, 385 ) (outScope *scope) { 386 var ordinals []int 387 if ref.Columns != nil { 388 // See tree.TableRef: "Note that a nil [Columns] array means 'unspecified' 389 // (all columns). whereas an array of length 0 means 'zero columns'. 390 // Lists of zero columns are not supported and will throw an error." 391 if len(ref.Columns) == 0 { 392 panic(pgerror.Newf(pgcode.Syntax, 393 "an explicit list of column IDs must include at least one column")) 394 } 395 ordinals = cat.ConvertColumnIDsToOrdinals(tab, ref.Columns) 396 } 397 398 tn := tree.MakeUnqualifiedTableName(tab.Name()) 399 tabMeta := b.addTable(tab, &tn) 400 return b.buildScan(tabMeta, ordinals, indexFlags, locking, excludeMutations, inScope) 401 } 402 403 // addTable adds a table to the metadata and returns the TableMeta. The table 404 // name is passed separately in order to preserve knowledge of whether the 405 // catalog and schema names were explicitly specified. 406 func (b *Builder) addTable(tab cat.Table, alias *tree.TableName) *opt.TableMeta { 407 md := b.factory.Metadata() 408 tabID := md.AddTable(tab, alias) 409 return md.TableMeta(tabID) 410 } 411 412 // buildScan builds a memo group for a ScanOp expression on the given table. 413 // 414 // If the ordinals slice is not nil, then only columns with ordinals in that 415 // list are projected by the scan. Otherwise, all columns from the table are 416 // projected. 417 // 418 // If scanMutationCols is true, then include columns being added or dropped from 419 // the table. These are currently required by the execution engine as "fetch 420 // columns", when performing mutation DML statements (INSERT, UPDATE, UPSERT, 421 // DELETE). 422 // 423 // NOTE: Callers must take care that these mutation columns are never used in 424 // any other way, since they may not have been initialized yet by the 425 // backfiller! 426 // 427 // See Builder.buildStmt for a description of the remaining input and return 428 // values. 429 func (b *Builder) buildScan( 430 tabMeta *opt.TableMeta, 431 ordinals []int, 432 indexFlags *tree.IndexFlags, 433 locking lockingSpec, 434 scanMutationCols bool, 435 inScope *scope, 436 ) (outScope *scope) { 437 tab := tabMeta.Table 438 tabID := tabMeta.MetaID 439 440 if indexFlags != nil && indexFlags.IgnoreForeignKeys { 441 tabMeta.IgnoreForeignKeys = true 442 } 443 444 colCount := len(ordinals) 445 if colCount == 0 { 446 // If scanning mutation columns, then include writable and deletable 447 // columns in the output, in addition to public columns. 448 if scanMutationCols { 449 colCount = tab.DeletableColumnCount() 450 } else { 451 colCount = tab.ColumnCount() 452 } 453 } 454 455 getOrdinal := func(i int) int { 456 if ordinals == nil { 457 return i 458 } 459 return ordinals[i] 460 } 461 462 var tabColIDs opt.ColSet 463 outScope = inScope.push() 464 outScope.cols = make([]scopeColumn, 0, colCount) 465 for i := 0; i < colCount; i++ { 466 ord := getOrdinal(i) 467 col := tab.Column(ord) 468 colID := tabID.ColumnID(ord) 469 tabColIDs.Add(colID) 470 name := col.ColName() 471 isMutation := cat.IsMutationColumn(tab, ord) 472 outScope.cols = append(outScope.cols, scopeColumn{ 473 id: colID, 474 name: name, 475 table: tabMeta.Alias, 476 typ: col.DatumType(), 477 hidden: col.IsHidden() || isMutation, 478 mutation: isMutation, 479 }) 480 } 481 482 if tab.IsVirtualTable() { 483 if indexFlags != nil { 484 panic(pgerror.Newf(pgcode.Syntax, 485 "index flags not allowed with virtual tables")) 486 } 487 if locking.isSet() { 488 panic(pgerror.Newf(pgcode.Syntax, 489 "%s not allowed with virtual tables", locking.get().Strength)) 490 } 491 private := memo.ScanPrivate{Table: tabID, Cols: tabColIDs} 492 outScope.expr = b.factory.ConstructScan(&private) 493 494 // Virtual tables should not be collected as view dependencies. 495 } else { 496 private := memo.ScanPrivate{Table: tabID, Cols: tabColIDs} 497 if indexFlags != nil { 498 private.Flags.NoIndexJoin = indexFlags.NoIndexJoin 499 if indexFlags.Index != "" || indexFlags.IndexID != 0 { 500 idx := -1 501 for i := 0; i < tab.IndexCount(); i++ { 502 if tab.Index(i).Name() == tree.Name(indexFlags.Index) || 503 tab.Index(i).ID() == cat.StableID(indexFlags.IndexID) { 504 idx = i 505 break 506 } 507 } 508 if idx == -1 { 509 var err error 510 if indexFlags.Index != "" { 511 err = errors.Errorf("index %q not found", tree.ErrString(&indexFlags.Index)) 512 } else { 513 err = errors.Errorf("index [%d] not found", indexFlags.IndexID) 514 } 515 panic(err) 516 } 517 private.Flags.ForceIndex = true 518 private.Flags.Index = idx 519 private.Flags.Direction = indexFlags.Direction 520 } 521 } 522 if locking.isSet() { 523 private.Locking = locking.get() 524 } 525 526 b.addCheckConstraintsForTable(tabMeta) 527 b.addComputedColsForTable(tabMeta) 528 529 outScope.expr = b.factory.ConstructScan(&private) 530 531 if b.trackViewDeps { 532 dep := opt.ViewDep{DataSource: tab} 533 for i := 0; i < colCount; i++ { 534 dep.ColumnOrdinals.Add(getOrdinal(i)) 535 } 536 if private.Flags.ForceIndex { 537 dep.SpecificIndex = true 538 dep.Index = private.Flags.Index 539 } 540 b.viewDeps = append(b.viewDeps, dep) 541 } 542 } 543 return outScope 544 } 545 546 // addCheckConstraintsForTable extracts filters from the check constraints that 547 // apply to the table and adds them to the table metadata (see 548 // TableMeta.Constraints). To do this, the scalar expressions of the check 549 // constraints are built here. 550 func (b *Builder) addCheckConstraintsForTable(tabMeta *opt.TableMeta) { 551 tab := tabMeta.Table 552 553 // Check if we have any validated check constraints. Only validated 554 // constraints are known to hold on existing table data. 555 numChecks := tab.CheckCount() 556 chkIdx := 0 557 for ; chkIdx < numChecks; chkIdx++ { 558 if tab.Check(chkIdx).Validated { 559 break 560 } 561 } 562 if chkIdx == numChecks { 563 return 564 } 565 566 // Create a scope that can be used for building the scalar expressions. 567 tableScope := b.allocScope() 568 tableScope.appendColumnsFromTable(tabMeta, &tabMeta.Alias) 569 570 // Find the non-nullable table columns. 571 var notNullCols opt.ColSet 572 for i := 0; i < tab.ColumnCount(); i++ { 573 if !tab.Column(i).IsNullable() { 574 notNullCols.Add(tabMeta.MetaID.ColumnID(i)) 575 } 576 } 577 578 var filters memo.FiltersExpr 579 // Skip to the first validated constraint we found above. 580 for ; chkIdx < numChecks; chkIdx++ { 581 checkConstraint := tab.Check(chkIdx) 582 583 // Only add validated check constraints to the table's metadata. 584 if !checkConstraint.Validated { 585 continue 586 } 587 expr, err := parser.ParseExpr(checkConstraint.Constraint) 588 if err != nil { 589 panic(err) 590 } 591 592 texpr := tableScope.resolveAndRequireType(expr, types.Bool) 593 condition := b.buildScalar(texpr, tableScope, nil, nil, nil) 594 // Check constraints that are guaranteed to not evaluate to NULL 595 // are the only ones converted into filters. This is because a NULL 596 // constraint is interpreted as passing, whereas a NULL filter is not. 597 if memo.ExprIsNeverNull(condition, notNullCols) { 598 filters = append(filters, b.factory.ConstructFiltersItem(condition)) 599 } 600 } 601 if len(filters) > 0 { 602 tabMeta.SetConstraints(&filters) 603 } 604 } 605 606 // addComputedColsForTable finds all computed columns in the given table and 607 // caches them in the table metadata as scalar expressions. 608 func (b *Builder) addComputedColsForTable(tabMeta *opt.TableMeta) { 609 var tableScope *scope 610 tab := tabMeta.Table 611 for i, n := 0, tab.ColumnCount(); i < n; i++ { 612 tabCol := tab.Column(i) 613 if !tabCol.IsComputed() { 614 continue 615 } 616 expr, err := parser.ParseExpr(tabCol.ComputedExprStr()) 617 if err != nil { 618 continue 619 } 620 621 if tableScope == nil { 622 tableScope = b.allocScope() 623 tableScope.appendColumnsFromTable(tabMeta, &tabMeta.Alias) 624 } 625 626 if texpr := tableScope.resolveAndRequireType(expr, types.Any); texpr != nil { 627 colID := tabMeta.MetaID.ColumnID(i) 628 scalar := b.buildScalar(texpr, tableScope, nil, nil, nil) 629 tabMeta.AddComputedCol(colID, scalar) 630 } 631 } 632 } 633 634 func (b *Builder) buildSequenceSelect( 635 seq cat.Sequence, seqName *tree.TableName, inScope *scope, 636 ) (outScope *scope) { 637 md := b.factory.Metadata() 638 outScope = inScope.push() 639 640 cols := make(opt.ColList, len(sqlbase.SequenceSelectColumns)) 641 642 for i, c := range sqlbase.SequenceSelectColumns { 643 cols[i] = md.AddColumn(c.Name, c.Typ) 644 } 645 646 outScope.cols = make([]scopeColumn, 3) 647 for i, c := range cols { 648 col := md.ColumnMeta(c) 649 outScope.cols[i] = scopeColumn{ 650 id: c, 651 name: tree.Name(col.Alias), 652 table: *seqName, 653 typ: col.Type, 654 } 655 } 656 657 private := memo.SequenceSelectPrivate{ 658 Sequence: md.AddSequence(seq), 659 Cols: cols, 660 } 661 outScope.expr = b.factory.ConstructSequenceSelect(&private) 662 663 if b.trackViewDeps { 664 b.viewDeps = append(b.viewDeps, opt.ViewDep{DataSource: seq}) 665 } 666 return outScope 667 } 668 669 // buildWithOrdinality builds a group which appends an increasing integer column to 670 // the output. colName optionally denotes the name this column is given, or can 671 // be blank for none. 672 // 673 // See Builder.buildStmt for a description of the remaining input and 674 // return values. 675 func (b *Builder) buildWithOrdinality(colName string, inScope *scope) (outScope *scope) { 676 col := b.synthesizeColumn(inScope, colName, types.Int, nil, nil /* scalar */) 677 678 // See https://www.cockroachlabs.com/docs/stable/query-order.html#order-preservation 679 // for the semantics around WITH ORDINALITY and ordering. 680 681 input := inScope.expr.(memo.RelExpr) 682 inScope.expr = b.factory.ConstructOrdinality(input, &memo.OrdinalityPrivate{ 683 Ordering: inScope.makeOrderingChoice(), 684 ColID: col.id, 685 }) 686 687 return inScope 688 } 689 690 func (b *Builder) buildCTEs(with *tree.With, inScope *scope) (outScope *scope) { 691 if with == nil { 692 return inScope 693 } 694 695 outScope = inScope.push() 696 addedCTEs := make([]cteSource, len(with.CTEList)) 697 hasRecursive := false 698 699 // Make a fake subquery to ensure that no CTEs are correlated. 700 // TODO(justin): relax this restriction. 701 outer := b.subquery 702 defer func() { b.subquery = outer }() 703 b.subquery = &subquery{} 704 705 outScope.ctes = make(map[string]*cteSource) 706 for i, cte := range with.CTEList { 707 hasRecursive = hasRecursive || with.Recursive 708 cteExpr, cteCols := b.buildCTE(cte, outScope, with.Recursive) 709 710 // TODO(justin): lift this restriction when possible. WITH should be hoistable. 711 if b.subquery != nil && !b.subquery.outerCols.Empty() { 712 panic(pgerror.Newf(pgcode.FeatureNotSupported, "CTEs may not be correlated")) 713 } 714 715 aliasStr := cte.Name.Alias.String() 716 if _, ok := outScope.ctes[aliasStr]; ok { 717 panic(pgerror.Newf( 718 pgcode.DuplicateAlias, "WITH query name %s specified more than once", aliasStr, 719 )) 720 } 721 722 id := b.factory.Memo().NextWithID() 723 724 addedCTEs[i] = cteSource{ 725 name: cte.Name, 726 cols: cteCols, 727 originalExpr: cte.Stmt, 728 expr: cteExpr, 729 bindingProps: cteExpr.Relational(), 730 id: id, 731 mtr: cte.Mtr, 732 } 733 cte := &addedCTEs[i] 734 outScope.ctes[cte.name.Alias.String()] = cte 735 b.cteStack[len(b.cteStack)-1] = append(b.cteStack[len(b.cteStack)-1], *cte) 736 737 if cteExpr.Relational().CanMutate && !inScope.atRoot { 738 panic( 739 pgerror.Newf( 740 pgcode.FeatureNotSupported, 741 "WITH clause containing a data-modifying statement must be at the top level", 742 ), 743 ) 744 } 745 746 } 747 748 telemetry.Inc(sqltelemetry.CteUseCounter) 749 if hasRecursive { 750 telemetry.Inc(sqltelemetry.RecursiveCteUseCounter) 751 } 752 753 return outScope 754 } 755 756 // A WITH constructed within an EXPLAIN should not be hoisted above it, and so 757 // we need to denote a boundary which blocks them. 758 func (b *Builder) pushWithFrame() { 759 b.cteStack = append(b.cteStack, []cteSource{}) 760 } 761 762 // popWithFrame wraps the given scope's expression in the CTEs that have been 763 // queued up at this level. 764 func (b *Builder) popWithFrame(s *scope) { 765 s.expr = b.flushCTEs(s.expr) 766 } 767 768 // flushCTEs adds With expressions on top of an expression. 769 func (b *Builder) flushCTEs(expr memo.RelExpr) memo.RelExpr { 770 ctes := b.cteStack[len(b.cteStack)-1] 771 b.cteStack = b.cteStack[:len(b.cteStack)-1] 772 773 if len(ctes) == 0 { 774 return expr 775 } 776 777 // Since later CTEs can refer to earlier ones, we want to add these in 778 // reverse order. 779 for i := len(ctes) - 1; i >= 0; i-- { 780 expr = b.factory.ConstructWith( 781 ctes[i].expr, 782 expr, 783 &memo.WithPrivate{ 784 ID: ctes[i].id, 785 Name: string(ctes[i].name.Alias), 786 Mtr: ctes[i].mtr, 787 OriginalExpr: ctes[i].originalExpr, 788 }, 789 ) 790 } 791 return expr 792 } 793 794 // buildSelectStmt builds a set of memo groups that represent the given select 795 // statement. 796 // 797 // See Builder.buildStmt for a description of the remaining input and 798 // return values. 799 func (b *Builder) buildSelectStmt( 800 stmt tree.SelectStatement, locking lockingSpec, desiredTypes []*types.T, inScope *scope, 801 ) (outScope *scope) { 802 // NB: The case statements are sorted lexicographically. 803 switch stmt := stmt.(type) { 804 case *tree.ParenSelect: 805 return b.buildSelect(stmt.Select, locking, desiredTypes, inScope) 806 807 case *tree.SelectClause: 808 return b.buildSelectClause(stmt, nil /* orderBy */, locking, desiredTypes, inScope) 809 810 case *tree.UnionClause: 811 return b.buildUnionClause(stmt, desiredTypes, inScope) 812 813 case *tree.ValuesClause: 814 return b.buildValuesClause(stmt, desiredTypes, inScope) 815 816 default: 817 panic(errors.AssertionFailedf("unknown select statement type: %T", stmt)) 818 } 819 } 820 821 // buildSelect builds a set of memo groups that represent the given select 822 // expression. 823 // 824 // See Builder.buildStmt for a description of the remaining input and 825 // return values. 826 func (b *Builder) buildSelect( 827 stmt *tree.Select, locking lockingSpec, desiredTypes []*types.T, inScope *scope, 828 ) (outScope *scope) { 829 wrapped := stmt.Select 830 with := stmt.With 831 orderBy := stmt.OrderBy 832 limit := stmt.Limit 833 locking.apply(stmt.Locking) 834 835 for s, ok := wrapped.(*tree.ParenSelect); ok; s, ok = wrapped.(*tree.ParenSelect) { 836 stmt = s.Select 837 wrapped = stmt.Select 838 if stmt.With != nil { 839 if with != nil { 840 // (WITH ... (WITH ...)) 841 // Currently we are unable to nest the scopes inside ParenSelect so we 842 // must refuse the syntax so that the query does not get invalid results. 843 panic(unimplemented.NewWithIssue( 844 24303, "multiple WITH clauses in parentheses", 845 )) 846 } 847 with = s.Select.With 848 } 849 if stmt.OrderBy != nil { 850 if orderBy != nil { 851 panic(pgerror.Newf( 852 pgcode.Syntax, "multiple ORDER BY clauses not allowed", 853 )) 854 } 855 orderBy = stmt.OrderBy 856 } 857 if stmt.Limit != nil { 858 if limit != nil { 859 panic(pgerror.Newf( 860 pgcode.Syntax, "multiple LIMIT clauses not allowed", 861 )) 862 } 863 limit = stmt.Limit 864 } 865 if stmt.Locking != nil { 866 locking.apply(stmt.Locking) 867 } 868 } 869 870 return b.processWiths(with, inScope, func(inScope *scope) *scope { 871 return b.buildSelectStmtWithoutParens( 872 wrapped, orderBy, limit, locking, desiredTypes, inScope, 873 ) 874 }) 875 } 876 877 // buildSelectStmtWithoutParens builds a set of memo groups that represent 878 // the given select statement components. The wrapped select statement can 879 // be any variant except ParenSelect, which should be unwrapped by callers. 880 // 881 // See Builder.buildStmt for a description of the remaining input and 882 // return values. 883 func (b *Builder) buildSelectStmtWithoutParens( 884 wrapped tree.SelectStatement, 885 orderBy tree.OrderBy, 886 limit *tree.Limit, 887 locking lockingSpec, 888 desiredTypes []*types.T, 889 inScope *scope, 890 ) (outScope *scope) { 891 // NB: The case statements are sorted lexicographically. 892 switch t := wrapped.(type) { 893 case *tree.ParenSelect: 894 panic(errors.AssertionFailedf( 895 "%T in buildSelectStmtWithoutParens", wrapped)) 896 897 case *tree.SelectClause: 898 outScope = b.buildSelectClause(t, orderBy, locking, desiredTypes, inScope) 899 900 case *tree.UnionClause: 901 b.rejectIfLocking(locking, "UNION/INTERSECT/EXCEPT") 902 outScope = b.buildUnionClause(t, desiredTypes, inScope) 903 904 case *tree.ValuesClause: 905 b.rejectIfLocking(locking, "VALUES") 906 outScope = b.buildValuesClause(t, desiredTypes, inScope) 907 908 default: 909 panic(pgerror.Newf(pgcode.FeatureNotSupported, 910 "unknown select statement: %T", wrapped)) 911 } 912 913 if outScope.ordering.Empty() && orderBy != nil { 914 projectionsScope := outScope.replace() 915 projectionsScope.cols = make([]scopeColumn, 0, len(outScope.cols)) 916 for i := range outScope.cols { 917 expr := &outScope.cols[i] 918 col := b.addColumn(projectionsScope, "" /* alias */, expr) 919 b.buildScalar(expr, outScope, projectionsScope, col, nil) 920 } 921 orderByScope := b.analyzeOrderBy(orderBy, outScope, projectionsScope) 922 b.buildOrderBy(outScope, projectionsScope, orderByScope) 923 b.constructProjectForScope(outScope, projectionsScope) 924 outScope = projectionsScope 925 } 926 927 if limit != nil { 928 b.buildLimit(limit, inScope, outScope) 929 } 930 931 // TODO(rytaft): Support FILTER expression. 932 return outScope 933 } 934 935 // buildSelectClause builds a set of memo groups that represent the given 936 // select clause. We pass the entire select statement rather than just the 937 // select clause in order to handle ORDER BY scoping rules. ORDER BY can sort 938 // results using columns from the FROM/GROUP BY clause and/or from the 939 // projection list. 940 // 941 // See Builder.buildStmt for a description of the remaining input and 942 // return values. 943 func (b *Builder) buildSelectClause( 944 sel *tree.SelectClause, 945 orderBy tree.OrderBy, 946 locking lockingSpec, 947 desiredTypes []*types.T, 948 inScope *scope, 949 ) (outScope *scope) { 950 fromScope := b.buildFrom(sel.From, locking, inScope) 951 b.processWindowDefs(sel, fromScope) 952 b.buildWhere(sel.Where, fromScope) 953 954 projectionsScope := fromScope.replace() 955 956 // This is where the magic happens. When this call reaches an aggregate 957 // function that refers to variables in fromScope or an ancestor scope, 958 // buildAggregateFunction is called which adds columns to the appropriate 959 // aggInScope and aggOutScope. 960 b.analyzeProjectionList(sel.Exprs, desiredTypes, fromScope, projectionsScope) 961 962 // Any aggregates in the HAVING, ORDER BY and DISTINCT ON clauses (if they 963 // exist) will be added here. 964 havingExpr := b.analyzeHaving(sel.Having, fromScope) 965 orderByScope := b.analyzeOrderBy(orderBy, fromScope, projectionsScope) 966 distinctOnScope := b.analyzeDistinctOnArgs(sel.DistinctOn, fromScope, projectionsScope) 967 968 var having opt.ScalarExpr 969 needsAgg := b.needsAggregation(sel, fromScope) 970 if needsAgg { 971 // Grouping columns must be built before building the projection list so 972 // we can check that any column references that appear in the SELECT list 973 // outside of aggregate functions are present in the grouping list. 974 b.buildGroupingColumns(sel, projectionsScope, fromScope) 975 having = b.buildHaving(havingExpr, fromScope) 976 } 977 978 b.buildProjectionList(fromScope, projectionsScope) 979 b.buildOrderBy(fromScope, projectionsScope, orderByScope) 980 b.buildDistinctOnArgs(fromScope, projectionsScope, distinctOnScope) 981 b.buildProjectSet(fromScope) 982 983 if needsAgg { 984 // We must wait to build the aggregation until after the above block since 985 // any SRFs found in the SELECT list will change the FROM scope (they 986 // create an implicit lateral join). 987 outScope = b.buildAggregation(having, fromScope) 988 } else { 989 outScope = fromScope 990 } 991 992 b.buildWindow(outScope, fromScope) 993 b.validateLockingInFrom(sel, locking, fromScope) 994 995 // Construct the projection. 996 b.constructProjectForScope(outScope, projectionsScope) 997 outScope = projectionsScope 998 999 if sel.Distinct { 1000 if projectionsScope.distinctOnCols.Empty() { 1001 outScope.expr = b.constructDistinct(outScope) 1002 } else { 1003 outScope = b.buildDistinctOn( 1004 projectionsScope.distinctOnCols, 1005 outScope, 1006 false, /* nullsAreDistinct */ 1007 "", /* errorOnDup */ 1008 ) 1009 } 1010 } 1011 return outScope 1012 } 1013 1014 // buildFrom builds a set of memo groups that represent the given FROM clause. 1015 // 1016 // See Builder.buildStmt for a description of the remaining input and return 1017 // values. 1018 func (b *Builder) buildFrom(from tree.From, locking lockingSpec, inScope *scope) (outScope *scope) { 1019 // The root AS OF clause is recognized and handled by the executor. The only 1020 // thing that must be done at this point is to ensure that if any timestamps 1021 // are specified, the root SELECT was an AS OF SYSTEM TIME and that the time 1022 // specified matches the one found at the root. 1023 if from.AsOf.Expr != nil { 1024 b.validateAsOf(from.AsOf) 1025 } 1026 1027 if len(from.Tables) > 0 { 1028 outScope = b.buildFromTables(from.Tables, locking, inScope) 1029 } else { 1030 outScope = inScope.push() 1031 outScope.expr = b.factory.ConstructValues(memo.ScalarListWithEmptyTuple, &memo.ValuesPrivate{ 1032 Cols: opt.ColList{}, 1033 ID: b.factory.Metadata().NextUniqueID(), 1034 }) 1035 } 1036 1037 return outScope 1038 } 1039 1040 // processWindowDefs validates that any window defs have unique names and adds 1041 // them to the given scope. 1042 func (b *Builder) processWindowDefs(sel *tree.SelectClause, fromScope *scope) { 1043 // Just do an O(n^2) loop since the number of window defs is likely small. 1044 for i := range sel.Window { 1045 for j := i + 1; j < len(sel.Window); j++ { 1046 if sel.Window[i].Name == sel.Window[j].Name { 1047 panic(pgerror.Newf( 1048 pgcode.Windowing, 1049 "window %q is already defined", 1050 sel.Window[i].Name, 1051 )) 1052 } 1053 } 1054 } 1055 1056 // Pass down the set of window definitions so that they can be referenced 1057 // elsewhere in the SELECT. 1058 fromScope.windowDefs = sel.Window 1059 } 1060 1061 // buildWhere builds a set of memo groups that represent the given WHERE clause. 1062 // 1063 // See Builder.buildStmt for a description of the remaining input and return 1064 // values. 1065 func (b *Builder) buildWhere(where *tree.Where, inScope *scope) { 1066 if where == nil { 1067 return 1068 } 1069 1070 filter := b.resolveAndBuildScalar( 1071 where.Expr, 1072 types.Bool, 1073 exprKindWhere, 1074 tree.RejectGenerators|tree.RejectWindowApplications, 1075 inScope, 1076 ) 1077 1078 // Wrap the filter in a FiltersOp. 1079 inScope.expr = b.factory.ConstructSelect( 1080 inScope.expr.(memo.RelExpr), 1081 memo.FiltersExpr{b.factory.ConstructFiltersItem(filter)}, 1082 ) 1083 } 1084 1085 // buildFromTables builds a series of InnerJoin expressions that together 1086 // represent the given FROM tables. 1087 // 1088 // See Builder.buildStmt for a description of the remaining input and 1089 // return values. 1090 func (b *Builder) buildFromTables( 1091 tables tree.TableExprs, locking lockingSpec, inScope *scope, 1092 ) (outScope *scope) { 1093 // If there are any lateral data sources, we need to build the join tree 1094 // left-deep instead of right-deep. 1095 for i := range tables { 1096 if b.exprIsLateral(tables[i]) { 1097 telemetry.Inc(sqltelemetry.LateralJoinUseCounter) 1098 return b.buildFromWithLateral(tables, locking, inScope) 1099 } 1100 } 1101 return b.buildFromTablesRightDeep(tables, locking, inScope) 1102 } 1103 1104 // buildFromTablesRightDeep recursively builds a series of InnerJoin 1105 // expressions that join together the given FROM tables. The tables are joined 1106 // in the reverse order that they appear in the list, with the innermost join 1107 // involving the tables at the end of the list. For example: 1108 // 1109 // SELECT * FROM a,b,c 1110 // 1111 // is joined like: 1112 // 1113 // SELECT * FROM a JOIN (b JOIN c ON true) ON true 1114 // 1115 // This ordering is guaranteed for queries not involving lateral joins for the 1116 // time being, to ensure we don't break any queries which have been 1117 // hand-optimized. 1118 // 1119 // See Builder.buildStmt for a description of the remaining input and 1120 // return values. 1121 func (b *Builder) buildFromTablesRightDeep( 1122 tables tree.TableExprs, locking lockingSpec, inScope *scope, 1123 ) (outScope *scope) { 1124 outScope = b.buildDataSource(tables[0], nil /* indexFlags */, locking, inScope) 1125 1126 // Recursively build table join. 1127 tables = tables[1:] 1128 if len(tables) == 0 { 1129 return outScope 1130 } 1131 tableScope := b.buildFromTablesRightDeep(tables, locking, inScope) 1132 1133 // Check that the same table name is not used multiple times. 1134 b.validateJoinTableNames(outScope, tableScope) 1135 1136 outScope.appendColumnsFromScope(tableScope) 1137 1138 left := outScope.expr.(memo.RelExpr) 1139 right := tableScope.expr.(memo.RelExpr) 1140 outScope.expr = b.factory.ConstructInnerJoin(left, right, memo.TrueFilter, memo.EmptyJoinPrivate) 1141 return outScope 1142 } 1143 1144 // exprIsLateral returns whether the table expression should have access to the 1145 // scope of the tables to the left of it. 1146 func (b *Builder) exprIsLateral(t tree.TableExpr) bool { 1147 ate, ok := t.(*tree.AliasedTableExpr) 1148 if !ok { 1149 return false 1150 } 1151 // Expressions which explicitly use the LATERAL keyword are lateral. 1152 if ate.Lateral { 1153 return true 1154 } 1155 // SRFs are always lateral. 1156 _, ok = ate.Expr.(*tree.RowsFromExpr) 1157 return ok 1158 } 1159 1160 // buildFromWithLateral builds a FROM clause in the case where it contains a 1161 // LATERAL table. This differs from buildFromTablesRightDeep because the 1162 // semantics of LATERAL require that the join tree is built left-deep (from 1163 // left-to-right) rather than right-deep (from right-to-left) which we do 1164 // typically for perf backwards-compatibility. 1165 // 1166 // SELECT * FROM a, b, c 1167 // 1168 // buildFromTablesRightDeep: a JOIN (b JOIN c) 1169 // buildFromWithLateral: (a JOIN b) JOIN c 1170 func (b *Builder) buildFromWithLateral( 1171 tables tree.TableExprs, locking lockingSpec, inScope *scope, 1172 ) (outScope *scope) { 1173 outScope = b.buildDataSource(tables[0], nil /* indexFlags */, locking, inScope) 1174 for i := 1; i < len(tables); i++ { 1175 scope := inScope 1176 // Lateral expressions need to be able to refer to the expressions that 1177 // have been built already. 1178 if b.exprIsLateral(tables[i]) { 1179 scope = outScope 1180 scope.context = exprKindLateralJoin 1181 } 1182 tableScope := b.buildDataSource(tables[i], nil /* indexFlags */, locking, scope) 1183 1184 // Check that the same table name is not used multiple times. 1185 b.validateJoinTableNames(outScope, tableScope) 1186 1187 outScope.appendColumnsFromScope(tableScope) 1188 1189 left := outScope.expr.(memo.RelExpr) 1190 right := tableScope.expr.(memo.RelExpr) 1191 outScope.expr = b.factory.ConstructInnerJoinApply(left, right, memo.TrueFilter, memo.EmptyJoinPrivate) 1192 } 1193 1194 return outScope 1195 } 1196 1197 // validateAsOf ensures that any AS OF SYSTEM TIME timestamp is consistent with 1198 // that of the root statement. 1199 func (b *Builder) validateAsOf(asOf tree.AsOfClause) { 1200 ts, err := tree.EvalAsOfTimestamp(b.ctx, asOf, b.semaCtx, b.evalCtx) 1201 if err != nil { 1202 panic(err) 1203 } 1204 1205 if b.semaCtx.AsOfTimestamp == nil { 1206 panic(pgerror.Newf(pgcode.Syntax, 1207 "AS OF SYSTEM TIME must be provided on a top-level statement")) 1208 } 1209 1210 if *b.semaCtx.AsOfTimestamp != ts { 1211 panic(unimplementedWithIssueDetailf(35712, "", 1212 "cannot specify AS OF SYSTEM TIME with different timestamps")) 1213 } 1214 } 1215 1216 // validateLockingInFrom checks for operations that are not supported with FOR 1217 // [KEY] UPDATE/SHARE. If a locking clause was specified with the select and an 1218 // incompatible operation is in use, a locking error is raised. 1219 func (b *Builder) validateLockingInFrom( 1220 sel *tree.SelectClause, locking lockingSpec, fromScope *scope, 1221 ) { 1222 if !locking.isSet() { 1223 // No FOR [KEY] UPDATE/SHARE locking modes in scope. 1224 return 1225 } 1226 1227 switch { 1228 case sel.Distinct: 1229 b.raiseLockingContextError(locking, "DISTINCT clause") 1230 1231 case sel.GroupBy != nil: 1232 b.raiseLockingContextError(locking, "GROUP BY clause") 1233 1234 case sel.Having != nil: 1235 b.raiseLockingContextError(locking, "HAVING clause") 1236 1237 case fromScope.groupby != nil && fromScope.groupby.hasAggregates(): 1238 b.raiseLockingContextError(locking, "aggregate functions") 1239 1240 case len(fromScope.windows) != 0: 1241 b.raiseLockingContextError(locking, "window functions") 1242 1243 case len(fromScope.srfs) != 0: 1244 b.raiseLockingContextError(locking, "set-returning functions in the target list") 1245 } 1246 1247 for _, li := range locking { 1248 // Validate locking strength. 1249 switch li.Strength { 1250 case tree.ForNone: 1251 // AST nodes should not be created with this locking strength. 1252 panic(errors.AssertionFailedf("locking item without strength")) 1253 case tree.ForUpdate, tree.ForNoKeyUpdate, tree.ForShare, tree.ForKeyShare: 1254 // CockroachDB treats all of the FOR LOCKED modes as no-ops. Since all 1255 // transactions are serializable in CockroachDB, clients can't observe 1256 // whether or not FOR UPDATE (or any of the other weaker modes) actually 1257 // created a lock. This behavior may improve as the transaction model gains 1258 // more capabilities. 1259 default: 1260 panic(errors.AssertionFailedf("unknown locking strength: %s", li.Strength)) 1261 } 1262 1263 // Validating locking wait policy. 1264 switch li.WaitPolicy { 1265 case tree.LockWaitBlock: 1266 // Default. 1267 case tree.LockWaitSkip: 1268 panic(unimplementedWithIssueDetailf(40476, "", 1269 "SKIP LOCKED lock wait policy is not supported")) 1270 case tree.LockWaitError: 1271 panic(unimplementedWithIssueDetailf(40476, "", 1272 "NOWAIT lock wait policy is not supported")) 1273 default: 1274 panic(errors.AssertionFailedf("unknown locking wait policy: %s", li.WaitPolicy)) 1275 } 1276 1277 // Validate locking targets by checking that all targets are well-formed 1278 // and all point to real relations present in the FROM clause. 1279 for _, target := range li.Targets { 1280 // Insist on unqualified alias names here. We could probably do 1281 // something smarter, but it's better to just mirror Postgres 1282 // exactly. See transformLockingClause in Postgres' source. 1283 if target.CatalogName != "" || target.SchemaName != "" { 1284 panic(pgerror.Newf(pgcode.Syntax, 1285 "%s must specify unqualified relation names", li.Strength)) 1286 } 1287 1288 // Search for the target in fromScope. If a target is missing from 1289 // the scope then raise an error. This will end up looping over all 1290 // columns in scope for each of the locking targets. We could use a 1291 // more efficient data structure (e.g. a hash map of relation names) 1292 // to improve the time complexity here, but we expect the number of 1293 // columns to be small enough that doing so is likely not worth it. 1294 found := false 1295 for _, col := range fromScope.cols { 1296 if target.ObjectName == col.table.ObjectName { 1297 found = true 1298 break 1299 } 1300 } 1301 if !found { 1302 panic(pgerror.Newf( 1303 pgcode.UndefinedTable, 1304 "relation %q in %s clause not found in FROM clause", 1305 target.ObjectName, li.Strength, 1306 )) 1307 } 1308 } 1309 } 1310 } 1311 1312 // rejectIfLocking raises a locking error if a locking clause was specified. 1313 func (b *Builder) rejectIfLocking(locking lockingSpec, context string) { 1314 if !locking.isSet() { 1315 // No FOR [KEY] UPDATE/SHARE locking modes in scope. 1316 return 1317 } 1318 b.raiseLockingContextError(locking, context) 1319 } 1320 1321 // raiseLockingContextError raises an error indicating that a row-level locking 1322 // clause is not permitted in the specified context. locking.isSet() must be true. 1323 func (b *Builder) raiseLockingContextError(locking lockingSpec, context string) { 1324 panic(pgerror.Newf(pgcode.FeatureNotSupported, 1325 "%s is not allowed with %s", locking.get().Strength, context)) 1326 }