github.com/dolthub/go-mysql-server@v0.18.0/sql/rowexec/other_iters.go (about) 1 // Copyright 2023 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package rowexec 16 17 import ( 18 "context" 19 "fmt" 20 "io" 21 "sync" 22 23 "go.opentelemetry.io/otel/attribute" 24 "golang.org/x/sync/errgroup" 25 26 "github.com/dolthub/go-mysql-server/sql" 27 "github.com/dolthub/go-mysql-server/sql/plan" 28 "github.com/dolthub/go-mysql-server/sql/transform" 29 ) 30 31 type analyzeTableIter struct { 32 idx int 33 db string 34 tables []sql.Table 35 stats sql.StatsProvider 36 } 37 38 var _ sql.RowIter = &analyzeTableIter{} 39 40 func (itr *analyzeTableIter) Next(ctx *sql.Context) (sql.Row, error) { 41 if itr.idx >= len(itr.tables) { 42 return nil, io.EOF 43 } 44 45 t := itr.tables[itr.idx] 46 47 msgType := "status" 48 msgText := "OK" 49 err := itr.stats.RefreshTableStats(ctx, t, itr.db) 50 if err != nil { 51 msgType = "Error" 52 msgText = err.Error() 53 } 54 itr.idx++ 55 return sql.Row{t.Name(), "analyze", msgType, msgText}, nil 56 } 57 58 func (itr *analyzeTableIter) Close(ctx *sql.Context) error { 59 return nil 60 } 61 62 type updateHistogramIter struct { 63 db string 64 table string 65 columns []string 66 stats sql.Statistic 67 prov sql.StatsProvider 68 done bool 69 } 70 71 var _ sql.RowIter = &updateHistogramIter{} 72 73 func (itr *updateHistogramIter) Next(ctx *sql.Context) (sql.Row, error) { 74 if itr.done { 75 return nil, io.EOF 76 } 77 defer func() { 78 itr.done = true 79 }() 80 err := itr.prov.SetStats(ctx, itr.stats) 81 if err != nil { 82 return sql.Row{itr.table, "histogram", "error", err.Error()}, nil 83 } 84 return sql.Row{itr.table, "histogram", "status", "OK"}, nil 85 } 86 87 func (itr *updateHistogramIter) Close(_ *sql.Context) error { 88 return nil 89 } 90 91 type dropHistogramIter struct { 92 db string 93 table string 94 columns []string 95 prov sql.StatsProvider 96 done bool 97 } 98 99 var _ sql.RowIter = &dropHistogramIter{} 100 101 func (itr *dropHistogramIter) Next(ctx *sql.Context) (sql.Row, error) { 102 if itr.done { 103 return nil, io.EOF 104 } 105 defer func() { 106 itr.done = true 107 }() 108 qual := sql.NewStatQualifier(itr.db, itr.table, "") 109 err := itr.prov.DropStats(ctx, qual, itr.columns) 110 if err != nil { 111 return sql.Row{itr.table, "histogram", "error", err.Error()}, nil 112 } 113 return sql.Row{itr.table, "histogram", "status", "OK"}, nil 114 } 115 116 func (itr *dropHistogramIter) Close(_ *sql.Context) error { 117 return nil 118 } 119 120 // blockIter is a sql.RowIter that iterates over the given rows. 121 type blockIter struct { 122 internalIter sql.RowIter 123 repNode sql.Node 124 sch sql.Schema 125 } 126 127 var _ plan.BlockRowIter = (*blockIter)(nil) 128 129 // Next implements the sql.RowIter interface. 130 func (i *blockIter) Next(ctx *sql.Context) (sql.Row, error) { 131 return i.internalIter.Next(ctx) 132 } 133 134 // Close implements the sql.RowIter interface. 135 func (i *blockIter) Close(ctx *sql.Context) error { 136 return i.internalIter.Close(ctx) 137 } 138 139 // RepresentingNode implements the sql.BlockRowIter interface. 140 func (i *blockIter) RepresentingNode() sql.Node { 141 return i.repNode 142 } 143 144 // Schema implements the sql.BlockRowIter interface. 145 func (i *blockIter) Schema() sql.Schema { 146 return i.sch 147 } 148 149 type prependRowIter struct { 150 row sql.Row 151 childIter sql.RowIter 152 } 153 154 func (p *prependRowIter) Next(ctx *sql.Context) (sql.Row, error) { 155 next, err := p.childIter.Next(ctx) 156 if err != nil { 157 return next, err 158 } 159 return p.row.Append(next), nil 160 } 161 162 func (p *prependRowIter) Close(ctx *sql.Context) error { 163 return p.childIter.Close(ctx) 164 } 165 166 type cachedResultsIter struct { 167 parent *plan.CachedResults 168 iter sql.RowIter 169 cache sql.RowsCache 170 dispose sql.DisposeFunc 171 } 172 173 func (i *cachedResultsIter) Next(ctx *sql.Context) (sql.Row, error) { 174 r, err := i.iter.Next(ctx) 175 if i.cache != nil { 176 if err != nil { 177 if err == io.EOF { 178 i.saveResultsInGlobalCache() 179 i.parent.Finalized = true 180 } 181 i.cleanUp() 182 } else { 183 aerr := i.cache.Add(r) 184 if aerr != nil { 185 i.cleanUp() 186 i.parent.Mutex.Lock() 187 defer i.parent.Mutex.Unlock() 188 i.parent.NoCache = true 189 } 190 } 191 } 192 return r, err 193 } 194 195 func (i *cachedResultsIter) saveResultsInGlobalCache() { 196 if plan.CachedResultsGlobalCache.AddNewCache(i.parent.Id, i.cache, i.dispose) { 197 i.cache = nil 198 i.dispose = nil 199 } 200 } 201 202 func (i *cachedResultsIter) cleanUp() { 203 if i.dispose != nil { 204 i.dispose() 205 i.cache = nil 206 i.dispose = nil 207 } 208 } 209 210 func (i *cachedResultsIter) Close(ctx *sql.Context) error { 211 i.cleanUp() 212 return i.iter.Close(ctx) 213 } 214 215 type hashLookupGeneratingIter struct { 216 n *plan.HashLookup 217 childIter sql.RowIter 218 lookup *map[interface{}][]sql.Row 219 } 220 221 func newHashLookupGeneratingIter(n *plan.HashLookup, chlidIter sql.RowIter) *hashLookupGeneratingIter { 222 h := &hashLookupGeneratingIter{ 223 n: n, 224 childIter: chlidIter, 225 } 226 lookup := make(map[interface{}][]sql.Row) 227 h.lookup = &lookup 228 return h 229 } 230 231 func (h *hashLookupGeneratingIter) Next(ctx *sql.Context) (sql.Row, error) { 232 childRow, err := h.childIter.Next(ctx) 233 if err == io.EOF { 234 // We wait until we finish the child iter before caching the Lookup map. 235 // This is because some plans may not fully exhaust the iterator. 236 h.n.Lookup = h.lookup 237 return nil, io.EOF 238 } 239 if err != nil { 240 return nil, err 241 } 242 // TODO: Maybe do not put nil stuff in here. 243 key, err := h.n.GetHashKey(ctx, h.n.RightEntryKey, childRow) 244 if err != nil { 245 return nil, err 246 } 247 (*(h.lookup))[key] = append((*(h.lookup))[key], childRow) 248 return childRow, nil 249 } 250 251 func (h *hashLookupGeneratingIter) Close(c *sql.Context) error { 252 return nil 253 } 254 255 var _ sql.RowIter = (*hashLookupGeneratingIter)(nil) 256 257 // declareCursorIter is the sql.RowIter of *DeclareCursor. 258 type declareCursorIter struct { 259 *plan.DeclareCursor 260 } 261 262 var _ sql.RowIter = (*declareCursorIter)(nil) 263 264 // Next implements the interface sql.RowIter. 265 func (d *declareCursorIter) Next(ctx *sql.Context) (sql.Row, error) { 266 d.Pref.InitializeCursor(d.Name, d.Select) 267 return nil, io.EOF 268 } 269 270 // Close implements the interface sql.RowIter. 271 func (d *declareCursorIter) Close(ctx *sql.Context) error { 272 return nil 273 } 274 275 // iterPartitions will call Next() on |iter| and send every result it 276 // finds to |partitions|. Meant to be run as a goroutine in an 277 // errgroup, it returns a non-nil error if it gets an error and it 278 // return |ctx.Err()| if the context becomes Done(). 279 func iterPartitions(ctx *sql.Context, iter sql.PartitionIter, partitions chan<- sql.Partition) (rerr error) { 280 defer func() { 281 if r := recover(); r != nil { 282 rerr = fmt.Errorf("panic in iterPartitions: %v", r) 283 } 284 }() 285 defer func() { 286 cerr := iter.Close(ctx) 287 if rerr == nil { 288 rerr = cerr 289 } 290 }() 291 for { 292 p, err := iter.Next(ctx) 293 if err != nil { 294 if err == io.EOF { 295 return nil 296 } 297 return err 298 } 299 select { 300 case partitions <- p: 301 case <-ctx.Done(): 302 return ctx.Err() 303 } 304 } 305 } 306 307 type rowIterPartitionFunc func(ctx *sql.Context, partition sql.Partition) (sql.RowIter, error) 308 309 // iterPartitionRows is the parallel worker for an Exchange node. It 310 // is meant to be run as a goroutine in an errgroup.Group. It will 311 // values read off of |partitions|. For each value it reads, it will 312 // call |getRowIter| to get a row projectIter, and will then call |Next| on 313 // that row projectIter, passing every row it gets into |rows|. If it 314 // receives an error at any point, it returns it. |iterPartitionRows| 315 // stops iterating and returns |nil| when |partitions| is closed. 316 func iterPartitionRows(ctx *sql.Context, getRowIter rowIterPartitionFunc, partitions <-chan sql.Partition, rows chan<- sql.Row) (rerr error) { 317 defer func() { 318 if r := recover(); r != nil { 319 rerr = fmt.Errorf("panic in ExchangeIterPartitionRows: %v", r) 320 } 321 }() 322 for { 323 select { 324 case p, ok := <-partitions: 325 if !ok { 326 return nil 327 } 328 span, ctx := ctx.Span("exchange.IterPartition") 329 iter, err := getRowIter(ctx, p) 330 if err != nil { 331 return err 332 } 333 count, err := sendAllRows(ctx, iter, rows) 334 span.SetAttributes(attribute.Int("num_rows", count)) 335 span.End() 336 if err != nil { 337 return err 338 } 339 case <-ctx.Done(): 340 return ctx.Err() 341 } 342 } 343 } 344 345 func sendAllRows(ctx *sql.Context, iter sql.RowIter, rows chan<- sql.Row) (rowCount int, rerr error) { 346 defer func() { 347 cerr := iter.Close(ctx) 348 if rerr == nil { 349 rerr = cerr 350 } 351 }() 352 for { 353 r, err := iter.Next(ctx) 354 if err == io.EOF { 355 return rowCount, nil 356 } 357 if err != nil { 358 return rowCount, err 359 } 360 rowCount++ 361 select { 362 case rows <- r: 363 case <-ctx.Done(): 364 return rowCount, ctx.Err() 365 } 366 } 367 } 368 369 func (b *BaseBuilder) exchangeIterGen(e *plan.Exchange, row sql.Row) func(*sql.Context, sql.Partition) (sql.RowIter, error) { 370 return func(ctx *sql.Context, partition sql.Partition) (sql.RowIter, error) { 371 node, _, err := transform.Node(e.Child, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) { 372 if t, ok := n.(sql.Table); ok { 373 return &plan.ExchangePartition{partition, t}, transform.NewTree, nil 374 } 375 return n, transform.SameTree, nil 376 }) 377 if err != nil { 378 return nil, err 379 } 380 return b.buildNodeExec(ctx, node, row) 381 } 382 } 383 384 // exchangeRowIter implements sql.RowIter for an exchange 385 // node. Calling |Next| reads off of |rows|, while calling |Close| 386 // calls |shutdownHook| and waits for exchange node workers to 387 // shutdown. If |rows| is closed, |Next| returns the error returned by 388 // |waiter|. |Close| returns the error returned by |waiter|, except it 389 // returns |nil| if |waiter| returns |io.EOF| or |shutdownHookErr|. 390 type exchangeRowIter struct { 391 shutdownHook func() 392 waiter func() error 393 rows <-chan sql.Row 394 rows2 <-chan sql.Row2 395 } 396 397 var _ sql.RowIter = (*exchangeRowIter)(nil) 398 399 func (i *exchangeRowIter) Next(ctx *sql.Context) (sql.Row, error) { 400 if i.rows == nil { 401 panic("Next called for a Next2 iterator") 402 } 403 r, ok := <-i.rows 404 if !ok { 405 return nil, i.waiter() 406 } 407 return r, nil 408 } 409 410 func (i *exchangeRowIter) Close(ctx *sql.Context) error { 411 i.shutdownHook() 412 err := i.waiter() 413 if err == shutdownHookErr || err == io.EOF { 414 return nil 415 } 416 return err 417 } 418 419 var shutdownHookErr = fmt.Errorf("shutdown hook") 420 421 // newShutdownHook returns a |func()| that can be called to cancel the 422 // |ctx| associated with the supplied |eg|. It is safe to call the 423 // hook more than once. 424 // 425 // If an errgroup is shutdown with a shutdown hook, eg.Wait() will 426 // return |shutdownHookErr|. This can be used to consider requested 427 // shutdowns successful in some contexts, for example. 428 func newShutdownHook(eg *errgroup.Group, ctx context.Context) func() { 429 stop := make(chan struct{}) 430 eg.Go(func() error { 431 select { 432 case <-stop: 433 return shutdownHookErr 434 case <-ctx.Done(): 435 return nil 436 } 437 }) 438 shutdownOnce := &sync.Once{} 439 return func() { 440 shutdownOnce.Do(func() { 441 close(stop) 442 }) 443 } 444 } 445 446 type releaseIter struct { 447 child sql.RowIter 448 release func() 449 once sync.Once 450 } 451 452 func (i *releaseIter) Next(ctx *sql.Context) (sql.Row, error) { 453 row, err := i.child.Next(ctx) 454 if err != nil { 455 _ = i.Close(ctx) 456 return nil, err 457 } 458 return row, nil 459 } 460 461 func (i *releaseIter) Close(ctx *sql.Context) (err error) { 462 i.once.Do(i.release) 463 if i.child != nil { 464 err = i.child.Close(ctx) 465 } 466 return err 467 } 468 469 type concatIter struct { 470 cur sql.RowIter 471 inLeft sql.KeyValueCache 472 dispose sql.DisposeFunc 473 nextIter func() (sql.RowIter, error) 474 } 475 476 func newConcatIter(ctx *sql.Context, cur sql.RowIter, nextIter func() (sql.RowIter, error)) *concatIter { 477 seen, dispose := ctx.Memory.NewHistoryCache() 478 return &concatIter{ 479 cur, 480 seen, 481 dispose, 482 nextIter, 483 } 484 } 485 486 var _ sql.Disposable = (*concatIter)(nil) 487 var _ sql.RowIter = (*concatIter)(nil) 488 489 func (ci *concatIter) Next(ctx *sql.Context) (sql.Row, error) { 490 for { 491 res, err := ci.cur.Next(ctx) 492 if err == io.EOF { 493 if ci.nextIter == nil { 494 return nil, io.EOF 495 } 496 err = ci.cur.Close(ctx) 497 if err != nil { 498 return nil, err 499 } 500 ci.cur, err = ci.nextIter() 501 ci.nextIter = nil 502 if err != nil { 503 return nil, err 504 } 505 res, err = ci.cur.Next(ctx) 506 } 507 if err != nil { 508 return nil, err 509 } 510 hash, err := sql.HashOf(res) 511 if err != nil { 512 return nil, err 513 } 514 if ci.nextIter != nil { 515 // On Left 516 if err := ci.inLeft.Put(hash, struct{}{}); err != nil { 517 return nil, err 518 } 519 } else { 520 // On Right 521 if _, err := ci.inLeft.Get(hash); err == nil { 522 continue 523 } 524 } 525 return res, err 526 } 527 } 528 529 func (ci *concatIter) Dispose() { 530 ci.dispose() 531 } 532 533 func (ci *concatIter) Close(ctx *sql.Context) error { 534 ci.Dispose() 535 if ci.cur != nil { 536 return ci.cur.Close(ctx) 537 } else { 538 return nil 539 } 540 } 541 542 type stripRowIter struct { 543 sql.RowIter 544 numCols int 545 } 546 547 func (sri *stripRowIter) Next(ctx *sql.Context) (sql.Row, error) { 548 r, err := sri.RowIter.Next(ctx) 549 if err != nil { 550 return nil, err 551 } 552 return r[sri.numCols:], nil 553 } 554 555 func (sri *stripRowIter) Close(ctx *sql.Context) error { 556 return sri.RowIter.Close(ctx) 557 }