github.com/dolthub/go-mysql-server@v0.18.0/sql/rowexec/other.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  	"fmt"
    19  	"io"
    20  
    21  	"github.com/dolthub/go-mysql-server/sql"
    22  	"github.com/dolthub/go-mysql-server/sql/expression"
    23  	"github.com/dolthub/go-mysql-server/sql/plan"
    24  	"github.com/dolthub/go-mysql-server/sql/transform"
    25  	"github.com/dolthub/go-mysql-server/sql/types"
    26  )
    27  
    28  func (b *BaseBuilder) buildStripRowNode(ctx *sql.Context, n *plan.StripRowNode, row sql.Row) (sql.RowIter, error) {
    29  	childIter, err := b.buildNodeExec(ctx, n.Child, row)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  
    34  	return &stripRowIter{
    35  		childIter,
    36  		n.NumCols,
    37  	}, nil
    38  }
    39  
    40  func (b *BaseBuilder) buildConcat(ctx *sql.Context, n *plan.Concat, row sql.Row) (sql.RowIter, error) {
    41  	span, ctx := ctx.Span("plan.Concat")
    42  	li, err := b.buildNodeExec(ctx, n.Left(), row)
    43  	if err != nil {
    44  		span.End()
    45  		return nil, err
    46  	}
    47  	i := newConcatIter(
    48  		ctx,
    49  		li,
    50  		func() (sql.RowIter, error) {
    51  			return b.buildNodeExec(ctx, n.Right(), row)
    52  		},
    53  	)
    54  	return sql.NewSpanIter(span, i), nil
    55  }
    56  
    57  func (b *BaseBuilder) buildReleaser(ctx *sql.Context, n *plan.Releaser, row sql.Row) (sql.RowIter, error) {
    58  	iter, err := b.buildNodeExec(ctx, n.Child, row)
    59  	if err != nil {
    60  		n.Release()
    61  		return nil, err
    62  	}
    63  
    64  	return &releaseIter{child: iter, release: n.Release}, nil
    65  }
    66  
    67  func (b *BaseBuilder) buildDeallocateQuery(ctx *sql.Context, n *plan.DeallocateQuery, row sql.Row) (sql.RowIter, error) {
    68  	return rowIterWithOkResultWithZeroRowsAffected(), nil
    69  }
    70  
    71  func (b *BaseBuilder) buildFetch(ctx *sql.Context, n *plan.Fetch, row sql.Row) (sql.RowIter, error) {
    72  	row, sch, err := n.Pref.FetchCursor(ctx, n.Name)
    73  	if err == io.EOF {
    74  		return sql.RowsToRowIter(), expression.FetchEOF
    75  	} else if err != nil {
    76  		return nil, err
    77  	}
    78  	if len(row) != len(n.ToSet) {
    79  		return nil, sql.ErrFetchIncorrectCount.New()
    80  	}
    81  	if len(n.ToSet) == 0 {
    82  		return sql.RowsToRowIter(), io.EOF
    83  	}
    84  
    85  	if n.Sch == nil {
    86  		n.Sch = sch
    87  	}
    88  	setExprs := make([]sql.Expression, len(n.ToSet))
    89  	for i, expr := range n.ToSet {
    90  		col := sch[i]
    91  		setExprs[i] = expression.NewSetField(expr, expression.NewGetField(i, col.Type, col.Name, col.Nullable))
    92  	}
    93  	set := plan.NewSet(setExprs)
    94  	return b.buildSet(ctx, set, row)
    95  }
    96  
    97  func (b *BaseBuilder) buildSignalName(ctx *sql.Context, n *plan.SignalName, row sql.Row) (sql.RowIter, error) {
    98  	return nil, fmt.Errorf("%T has no exchange iterator", n)
    99  }
   100  
   101  func (b *BaseBuilder) buildRepeat(ctx *sql.Context, n *plan.Repeat, row sql.Row) (sql.RowIter, error) {
   102  	return b.buildLoop(ctx, n.Loop, row)
   103  }
   104  
   105  func (b *BaseBuilder) buildDeferredFilteredTable(ctx *sql.Context, n *plan.DeferredFilteredTable, row sql.Row) (sql.RowIter, error) {
   106  	return nil, fmt.Errorf("%T has no execution iterator", n)
   107  }
   108  
   109  func (b *BaseBuilder) buildNamedWindows(ctx *sql.Context, n *plan.NamedWindows, row sql.Row) (sql.RowIter, error) {
   110  	return nil, fmt.Errorf("%T has no execution iterator", n)
   111  }
   112  
   113  func (b *BaseBuilder) buildExchange(ctx *sql.Context, n *plan.Exchange, row sql.Row) (sql.RowIter, error) {
   114  	var t sql.Table
   115  	transform.Inspect(n.Child, func(n sql.Node) bool {
   116  		if table, ok := n.(sql.Table); ok {
   117  			t = table
   118  			return false
   119  		}
   120  		return true
   121  	})
   122  	if t == nil {
   123  		return nil, plan.ErrNoPartitionable.New()
   124  	}
   125  
   126  	partitions, err := t.Partitions(ctx)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  
   131  	// How this is structured is a little subtle. A top-level
   132  	// errgroup run |iterPartitions| and listens on the shutdown
   133  	// hook.  A different, dependent, errgroup runs
   134  	// |e.Parallelism| instances of |iterPartitionRows|. A
   135  	// goroutine within the top-level errgroup |Wait|s on the
   136  	// dependent errgroup and closes |rowsCh| once all its
   137  	// goroutines are completed.
   138  
   139  	partitionsCh := make(chan sql.Partition)
   140  	rowsCh := make(chan sql.Row, n.Parallelism*16)
   141  
   142  	eg, egCtx := ctx.NewErrgroup()
   143  	eg.Go(func() error {
   144  		defer close(partitionsCh)
   145  		return iterPartitions(egCtx, partitions, partitionsCh)
   146  	})
   147  
   148  	// Spawn |iterPartitionRows| goroutines in the dependent
   149  	// errgroup.
   150  	getRowIter := b.exchangeIterGen(n, row)
   151  	seg, segCtx := egCtx.NewErrgroup()
   152  	for i := 0; i < n.Parallelism; i++ {
   153  		seg.Go(func() error {
   154  			return iterPartitionRows(segCtx, getRowIter, partitionsCh, rowsCh)
   155  		})
   156  	}
   157  
   158  	eg.Go(func() error {
   159  		defer close(rowsCh)
   160  		err := seg.Wait()
   161  		if err != nil {
   162  			return err
   163  		}
   164  		// If everything in |seg| returned |nil|,
   165  		// |iterPartitions| is done, |partitionsCh| is closed,
   166  		// and every partition RowIter returned |EOF|. That
   167  		// means we're EOF here.
   168  		return io.EOF
   169  	})
   170  
   171  	waiter := func() error { return eg.Wait() }
   172  	shutdownHook := newShutdownHook(eg, egCtx)
   173  	return &exchangeRowIter{shutdownHook: shutdownHook, waiter: waiter, rows: rowsCh}, nil
   174  }
   175  
   176  func (b *BaseBuilder) buildExchangePartition(ctx *sql.Context, n *plan.ExchangePartition, row sql.Row) (sql.RowIter, error) {
   177  	return n.Table.PartitionRows(ctx, n.Partition)
   178  }
   179  
   180  func (b *BaseBuilder) buildEmptyTable(ctx *sql.Context, n *plan.EmptyTable, row sql.Row) (sql.RowIter, error) {
   181  	return sql.RowsToRowIter(), nil
   182  }
   183  
   184  func (b *BaseBuilder) buildDeclareCursor(ctx *sql.Context, n *plan.DeclareCursor, row sql.Row) (sql.RowIter, error) {
   185  	return &declareCursorIter{n}, nil
   186  }
   187  
   188  func (b *BaseBuilder) buildTransformedNamedNode(ctx *sql.Context, n *plan.TransformedNamedNode, row sql.Row) (sql.RowIter, error) {
   189  	return b.buildNodeExec(ctx, n.Child, row)
   190  }
   191  
   192  func (b *BaseBuilder) buildCachedResults(ctx *sql.Context, n *plan.CachedResults, row sql.Row) (sql.RowIter, error) {
   193  	n.Mutex.Lock()
   194  	defer n.Mutex.Unlock()
   195  
   196  	if n.Disposed {
   197  		return nil, fmt.Errorf("%w: %T", plan.ErrRowIterDisposed, n)
   198  	}
   199  
   200  	if rows := n.GetCachedResults(); rows != nil {
   201  		return sql.RowsToRowIter(rows...), nil
   202  	} else if n.NoCache {
   203  		return b.buildNodeExec(ctx, n.Child, row)
   204  	} else if n.Finalized {
   205  		return plan.EmptyIter, nil
   206  	}
   207  
   208  	ci, err := b.buildNodeExec(ctx, n.Child, row)
   209  	if err != nil {
   210  		return nil, err
   211  	}
   212  	cache, dispose := ctx.Memory.NewRowsCache()
   213  	return &cachedResultsIter{n, ci, cache, dispose}, nil
   214  }
   215  
   216  func (b *BaseBuilder) buildBlock(ctx *sql.Context, n *plan.Block, row sql.Row) (sql.RowIter, error) {
   217  	var returnRows []sql.Row
   218  	var returnNode sql.Node
   219  	var returnSch sql.Schema
   220  
   221  	selectSeen := false
   222  	for _, s := range n.Children() {
   223  		// TODO: this should happen at iteration time, but this call is where the actual iteration happens
   224  		err := startTransaction(ctx)
   225  		if err != nil {
   226  			return nil, err
   227  		}
   228  
   229  		err = func() error {
   230  			rowCache, disposeFunc := ctx.Memory.NewRowsCache()
   231  			defer disposeFunc()
   232  
   233  			var isSelect bool
   234  			subIter, err := b.buildNodeExec(ctx, s, row)
   235  			if err != nil {
   236  				return err
   237  			}
   238  			subIterNode := s
   239  			subIterSch := s.Schema()
   240  			if blockSubIter, ok := subIter.(plan.BlockRowIter); ok {
   241  				subIterNode = blockSubIter.RepresentingNode()
   242  				subIterSch = blockSubIter.Schema()
   243  			}
   244  			if isSelect = plan.NodeRepresentsSelect(subIterNode); isSelect {
   245  				selectSeen = true
   246  				returnNode = subIterNode
   247  				returnSch = subIterSch
   248  			} else if !selectSeen {
   249  				returnNode = subIterNode
   250  				returnSch = subIterSch
   251  			}
   252  
   253  			for {
   254  				newRow, err := subIter.Next(ctx)
   255  				if err == io.EOF {
   256  					err := subIter.Close(ctx)
   257  					if err != nil {
   258  						return err
   259  					}
   260  					if isSelect || !selectSeen {
   261  						returnRows = rowCache.Get()
   262  					}
   263  					break
   264  				} else if err != nil {
   265  					return err
   266  				} else if isSelect || !selectSeen {
   267  					err = rowCache.Add(newRow)
   268  					if err != nil {
   269  						return err
   270  					}
   271  				}
   272  			}
   273  			return nil
   274  		}()
   275  		if err != nil {
   276  			return nil, err
   277  		}
   278  	}
   279  
   280  	n.SetSchema(returnSch)
   281  	return &blockIter{
   282  		internalIter: sql.RowsToRowIter(returnRows...),
   283  		repNode:      returnNode,
   284  		sch:          returnSch,
   285  	}, nil
   286  }
   287  
   288  func (b *BaseBuilder) buildDeferredAsOfTable(ctx *sql.Context, n *plan.DeferredAsOfTable, row sql.Row) (sql.RowIter, error) {
   289  	return nil, fmt.Errorf("%T has no execution iterator", n)
   290  }
   291  
   292  func (b *BaseBuilder) buildNothing(ctx *sql.Context, n plan.Nothing, row sql.Row) (sql.RowIter, error) {
   293  	return sql.RowsToRowIter(), nil
   294  }
   295  
   296  func (b *BaseBuilder) buildTableCopier(ctx *sql.Context, n *plan.TableCopier, row sql.Row) (sql.RowIter, error) {
   297  	if _, ok := n.Destination.(*plan.CreateTable); ok {
   298  		return n.ProcessCreateTable(ctx, b, row)
   299  	}
   300  
   301  	drt, ok := n.Destination.(*plan.ResolvedTable)
   302  	if !ok {
   303  		return nil, fmt.Errorf("TableCopier only accepts CreateTable or TableNode as the destination")
   304  	}
   305  
   306  	return n.CopyTableOver(ctx, n.Source.Schema()[0].Source, drt.Name())
   307  }
   308  
   309  func (b *BaseBuilder) buildUnresolvedTable(ctx *sql.Context, n *plan.UnresolvedTable, row sql.Row) (sql.RowIter, error) {
   310  	return nil, plan.ErrUnresolvedTable.New()
   311  }
   312  
   313  func (b *BaseBuilder) buildPrependNode(ctx *sql.Context, n *plan.PrependNode, row sql.Row) (sql.RowIter, error) {
   314  	childIter, err := b.buildNodeExec(ctx, n.Child, row)
   315  	if err != nil {
   316  		return nil, err
   317  	}
   318  
   319  	return &prependRowIter{
   320  		row:       n.Row,
   321  		childIter: childIter,
   322  	}, nil
   323  }
   324  
   325  func (b *BaseBuilder) buildQueryProcess(ctx *sql.Context, n *plan.QueryProcess, row sql.Row) (sql.RowIter, error) {
   326  	iter, err := b.Build(ctx, n.Child(), row)
   327  	if err != nil {
   328  		return nil, err
   329  	}
   330  
   331  	qType := plan.GetQueryType(n.Child())
   332  
   333  	trackedIter := plan.NewTrackedRowIter(n.Child(), iter, nil, n.Notify)
   334  	trackedIter.QueryType = qType
   335  	trackedIter.ShouldSetFoundRows = qType == plan.QueryTypeSelect && n.ShouldSetFoundRows()
   336  
   337  	return trackedIter, nil
   338  }
   339  
   340  func (b *BaseBuilder) buildAnalyzeTable(ctx *sql.Context, n *plan.AnalyzeTable, row sql.Row) (sql.RowIter, error) {
   341  	// Assume table is in current database
   342  	database := ctx.GetCurrentDatabase()
   343  	if database == "" {
   344  		return nil, sql.ErrNoDatabaseSelected.New()
   345  	}
   346  
   347  	return &analyzeTableIter{
   348  		idx:    0,
   349  		db:     n.Db,
   350  		tables: n.Tables,
   351  		stats:  n.Stats,
   352  	}, nil
   353  }
   354  
   355  func (b *BaseBuilder) buildDropHistogram(ctx *sql.Context, n *plan.DropHistogram, row sql.Row) (sql.RowIter, error) {
   356  	// Assume table is in current database
   357  	database := ctx.GetCurrentDatabase()
   358  	if database == "" {
   359  		return nil, sql.ErrNoDatabaseSelected.New()
   360  	}
   361  
   362  	return &dropHistogramIter{
   363  		db:      n.Db(),
   364  		table:   n.Table(),
   365  		columns: n.Cols(),
   366  		prov:    n.StatsProvider(),
   367  	}, nil
   368  }
   369  
   370  func (b *BaseBuilder) buildUpdateHistogram(ctx *sql.Context, n *plan.UpdateHistogram, row sql.Row) (sql.RowIter, error) {
   371  	// Assume table is in current database
   372  	database := ctx.GetCurrentDatabase()
   373  	if database == "" {
   374  		return nil, sql.ErrNoDatabaseSelected.New()
   375  	}
   376  
   377  	return &updateHistogramIter{
   378  		db:      n.Db(),
   379  		table:   n.Table(),
   380  		columns: n.Cols(),
   381  		stats:   n.Stats(),
   382  		prov:    n.StatsProvider(),
   383  	}, nil
   384  }
   385  
   386  func (b *BaseBuilder) buildCreateSpatialRefSys(ctx *sql.Context, n *plan.CreateSpatialRefSys, row sql.Row) (sql.RowIter, error) {
   387  	if _, ok := types.SupportedSRIDs[n.SRID]; ok {
   388  		if n.IfNotExists {
   389  			return rowIterWithOkResultWithZeroRowsAffected(), nil
   390  		}
   391  		if !n.OrReplace {
   392  			return nil, sql.ErrSpatialRefSysAlreadyExists.New(n.SRID)
   393  		}
   394  	}
   395  
   396  	types.SupportedSRIDs[n.SRID] = types.SpatialRef{
   397  		Name:          n.SrsAttr.Name,
   398  		ID:            n.SRID,
   399  		Organization:  n.SrsAttr.Organization,
   400  		OrgCoordsysId: n.SrsAttr.OrgID,
   401  		Definition:    n.SrsAttr.Definition,
   402  		Description:   n.SrsAttr.Description,
   403  	}
   404  
   405  	return rowIterWithOkResultWithZeroRowsAffected(), nil
   406  }