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  }