github.com/dolthub/go-mysql-server@v0.18.0/sql/rowexec/rel.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  	"encoding/json"
    19  	"errors"
    20  	"fmt"
    21  	"io"
    22  	"os"
    23  	"path/filepath"
    24  	"reflect"
    25  	"strings"
    26  
    27  	"github.com/dolthub/jsonpath"
    28  	"github.com/shopspring/decimal"
    29  	"go.opentelemetry.io/otel/attribute"
    30  	"go.opentelemetry.io/otel/trace"
    31  
    32  	"github.com/dolthub/go-mysql-server/sql"
    33  	"github.com/dolthub/go-mysql-server/sql/expression"
    34  	"github.com/dolthub/go-mysql-server/sql/expression/function/aggregation"
    35  	"github.com/dolthub/go-mysql-server/sql/plan"
    36  	"github.com/dolthub/go-mysql-server/sql/types"
    37  )
    38  
    39  func (b *BaseBuilder) buildTopN(ctx *sql.Context, n *plan.TopN, row sql.Row) (sql.RowIter, error) {
    40  	span, ctx := ctx.Span("plan.TopN")
    41  	i, err := b.buildNodeExec(ctx, n.Child, row)
    42  	if err != nil {
    43  		span.End()
    44  		return nil, err
    45  	}
    46  
    47  	limit, err := getInt64Value(ctx, n.Limit)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	return sql.NewSpanIter(span, newTopRowsIter(n.Fields, limit, n.CalcFoundRows, i, len(n.Child.Schema()))), nil
    52  }
    53  
    54  func (b *BaseBuilder) buildValueDerivedTable(ctx *sql.Context, n *plan.ValueDerivedTable, row sql.Row) (sql.RowIter, error) {
    55  	rows := make([]sql.Row, len(n.ExpressionTuples))
    56  	for i, et := range n.ExpressionTuples {
    57  		vals := make([]interface{}, len(et))
    58  		for j, e := range et {
    59  			var err error
    60  			p, err := e.Eval(ctx, row)
    61  			if err != nil {
    62  				return nil, err
    63  			}
    64  			// cast all row values to the most permissive type
    65  			vals[j], _, err = n.Schema()[j].Type.Convert(p)
    66  			if err != nil {
    67  				return nil, err
    68  			}
    69  			// decimalType.Convert() does not use the given type precision and scale information
    70  			if t, ok := n.Schema()[j].Type.(sql.DecimalType); ok {
    71  				vals[j] = vals[j].(decimal.Decimal).Round(int32(t.Scale()))
    72  			}
    73  		}
    74  
    75  		rows[i] = sql.NewRow(vals...)
    76  	}
    77  
    78  	return sql.RowsToRowIter(rows...), nil
    79  }
    80  
    81  func (b *BaseBuilder) buildValues(ctx *sql.Context, n *plan.Values, row sql.Row) (sql.RowIter, error) {
    82  	rows := make([]sql.Row, len(n.ExpressionTuples))
    83  	for i, et := range n.ExpressionTuples {
    84  		vals := make(sql.Row, len(et))
    85  
    86  		// A non-zero row means that we're executing in a trigger context, so we evaluate against the row provided
    87  		// TODO: this probably won't work with triggers that define explicit DEFAULT values
    88  		if len(row) > 0 {
    89  			for j, e := range et {
    90  				var err error
    91  				vals[j], err = e.Eval(ctx, row)
    92  				if err != nil {
    93  					return nil, err
    94  				}
    95  			}
    96  		} else {
    97  			// For the values node, the relevant values to evaluate are the tuple itself. We may need to project
    98  			// DEFAULT values onto them, which ProjectRow handles correctly (could require multiple passes)
    99  			var err error
   100  			vals, err = ProjectRow(ctx, et, vals)
   101  			if err != nil {
   102  				return nil, err
   103  			}
   104  		}
   105  
   106  		rows[i] = sql.NewRow(vals...)
   107  	}
   108  
   109  	return sql.RowsToRowIter(rows...), nil
   110  }
   111  
   112  func (b *BaseBuilder) buildWindow(ctx *sql.Context, n *plan.Window, row sql.Row) (sql.RowIter, error) {
   113  	childIter, err := b.buildNodeExec(ctx, n.Child, row)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	blockIters, outputOrdinals, err := windowToIter(n)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	return aggregation.NewWindowIter(blockIters, outputOrdinals, childIter), nil
   122  }
   123  
   124  func (b *BaseBuilder) buildOffset(ctx *sql.Context, n *plan.Offset, row sql.Row) (sql.RowIter, error) {
   125  	span, ctx := ctx.Span("plan.Offset", trace.WithAttributes(attribute.Stringer("offset", n.Offset)))
   126  
   127  	offset, err := getInt64Value(ctx, n.Offset)
   128  	if err != nil {
   129  		span.End()
   130  		return nil, err
   131  	}
   132  
   133  	it, err := b.buildNodeExec(ctx, n.Child, row)
   134  	if err != nil {
   135  		span.End()
   136  		return nil, err
   137  	}
   138  	return sql.NewSpanIter(span, &offsetIter{offset, it}), nil
   139  }
   140  
   141  func (b *BaseBuilder) buildJSONTableCols(ctx *sql.Context, jtCols []plan.JSONTableCol, row sql.Row) ([]*jsonTableCol, error) {
   142  	var cols []*jsonTableCol
   143  	for _, col := range jtCols {
   144  		if col.Opts == nil {
   145  			innerCols, err := b.buildJSONTableCols(ctx, col.NestedCols, row)
   146  			if err != nil {
   147  				return nil, err
   148  			}
   149  			cols = append(cols, &jsonTableCol{
   150  				path: col.Path,
   151  				cols: innerCols,
   152  			})
   153  			continue
   154  		}
   155  
   156  		defErrVal, err := col.Opts.DefErrorVal.Eval(ctx, row)
   157  		if err != nil {
   158  			return nil, err
   159  		}
   160  		defEmpVal, err := col.Opts.DefEmptyVal.Eval(ctx, row)
   161  		if err != nil {
   162  			return nil, err
   163  		}
   164  		cols = append(cols, &jsonTableCol{
   165  			path: col.Path,
   166  			opts: &jsonTableColOpts{
   167  				name:      col.Opts.Name,
   168  				typ:       col.Opts.Type,
   169  				forOrd:    col.Opts.ForOrd,
   170  				exists:    col.Opts.Exists,
   171  				defErrVal: defErrVal,
   172  				defEmpVal: defEmpVal,
   173  				errOnErr:  col.Opts.ErrorOnError,
   174  				errOnEmp:  col.Opts.ErrorOnEmpty,
   175  			},
   176  		})
   177  	}
   178  	return cols, nil
   179  }
   180  
   181  func (b *BaseBuilder) buildJSONTable(ctx *sql.Context, n *plan.JSONTable, row sql.Row) (sql.RowIter, error) {
   182  	// data must evaluate to JSON string
   183  	data, err := n.DataExpr.Eval(ctx, row)
   184  	if err != nil {
   185  		return nil, err
   186  	}
   187  
   188  	if jd, ok := data.(types.JSONDocument); ok {
   189  		data, err = jd.JSONString()
   190  		if err != nil {
   191  			return nil, err
   192  		}
   193  	}
   194  
   195  	strData, _, err := types.LongBlob.Convert(data)
   196  	if err != nil {
   197  		return nil, fmt.Errorf("invalid data type for JSON data in argument 1 to function json_table; a JSON string or JSON type is required")
   198  	}
   199  	if strData == nil {
   200  		return &jsonTableRowIter{}, nil
   201  	}
   202  
   203  	var jsonData interface{}
   204  	if err = json.Unmarshal(strData.([]byte), &jsonData); err != nil {
   205  		return nil, err
   206  	}
   207  	jsonPathData, err := jsonpath.JsonPathLookup(jsonData, n.RootPath)
   208  	if err != nil {
   209  		jsonPathData = []interface{}{}
   210  	}
   211  	if _, ok := jsonPathData.([]interface{}); !ok {
   212  		jsonPathData = []interface{}{jsonPathData}
   213  	}
   214  
   215  	cols, err := b.buildJSONTableCols(ctx, n.Cols, row)
   216  
   217  	rowIter := &jsonTableRowIter{
   218  		data: jsonPathData.([]interface{}),
   219  		cols: cols,
   220  	}
   221  	rowIter.NextSibling() // set to first sibling
   222  
   223  	return rowIter, nil
   224  }
   225  
   226  func (b *BaseBuilder) buildHashLookup(ctx *sql.Context, n *plan.HashLookup, row sql.Row) (sql.RowIter, error) {
   227  	n.Mutex.Lock()
   228  	defer n.Mutex.Unlock()
   229  	if n.Lookup == nil {
   230  		childIter, err := b.buildNodeExec(ctx, n.Child, row)
   231  		if err != nil {
   232  			return nil, err
   233  		}
   234  		return newHashLookupGeneratingIter(n, childIter), nil
   235  	}
   236  	key, err := n.GetHashKey(ctx, n.LeftProbeKey, row)
   237  	if err != nil {
   238  		return nil, err
   239  	}
   240  	if n.JoinType.IsExcludeNulls() {
   241  		// Some joins care if any of their filter comparisons have a NULL result.
   242  		// For these joins, we need to distinguish between an empty and non-empty secondary table.
   243  		// Thus, if there are any rows in the lookup, we must return at least one.
   244  		if len((*n.Lookup)[key]) > 0 {
   245  			return sql.RowsToRowIter((*n.Lookup)[key]...), nil
   246  		}
   247  		for k := range *n.Lookup {
   248  			if len((*n.Lookup)[k]) > 0 {
   249  				return sql.RowsToRowIter((*n.Lookup)[k]...), nil
   250  			}
   251  		}
   252  	}
   253  	return sql.RowsToRowIter((*n.Lookup)[key]...), nil
   254  }
   255  
   256  func (b *BaseBuilder) buildTableAlias(ctx *sql.Context, n *plan.TableAlias, row sql.Row) (sql.RowIter, error) {
   257  	var table string
   258  	if tbl, ok := n.Child.(sql.Nameable); ok {
   259  		table = tbl.Name()
   260  	} else {
   261  		table = reflect.TypeOf(n.Child).String()
   262  	}
   263  
   264  	span, ctx := ctx.Span("sql.TableAlias", trace.WithAttributes(attribute.String("table", table)))
   265  
   266  	iter, err := b.Build(ctx, n.Child, row)
   267  	if err != nil {
   268  		span.End()
   269  		return nil, err
   270  	}
   271  
   272  	return sql.NewSpanIter(span, iter), nil
   273  }
   274  
   275  func (b *BaseBuilder) buildJoinNode(ctx *sql.Context, n *plan.JoinNode, row sql.Row) (sql.RowIter, error) {
   276  	switch {
   277  	case n.Op.IsFullOuter():
   278  		return newFullJoinIter(ctx, b, n, row)
   279  	case n.Op.IsPartial():
   280  		return newExistsIter(ctx, b, n, row)
   281  	case n.Op.IsCross():
   282  		return newCrossJoinIter(ctx, b, n, row)
   283  	case n.Op.IsPlaceholder():
   284  		panic(fmt.Sprintf("%s is a placeholder, RowIter called", n.Op))
   285  	case n.Op.IsMerge():
   286  		return newMergeJoinIter(ctx, b, n, row)
   287  	case n.Op.IsLateral():
   288  		return newLateralJoinIter(ctx, b, n, row)
   289  	case n.Op.IsRange():
   290  		return newRangeHeapJoinIter(ctx, b, n, row)
   291  	default:
   292  		return newJoinIter(ctx, b, n, row)
   293  	}
   294  }
   295  
   296  func (b *BaseBuilder) buildOrderedDistinct(ctx *sql.Context, n *plan.OrderedDistinct, row sql.Row) (sql.RowIter, error) {
   297  	span, ctx := ctx.Span("plan.OrderedDistinct")
   298  
   299  	it, err := b.buildNodeExec(ctx, n.Child, row)
   300  	if err != nil {
   301  		span.End()
   302  		return nil, err
   303  	}
   304  
   305  	return sql.NewSpanIter(span, newOrderedDistinctIter(it, n.Child.Schema())), nil
   306  }
   307  
   308  func (b *BaseBuilder) buildWith(ctx *sql.Context, n *plan.With, row sql.Row) (sql.RowIter, error) {
   309  	return nil, fmt.Errorf("*plan.With has no execution iterator")
   310  }
   311  
   312  func (b *BaseBuilder) buildProject(ctx *sql.Context, n *plan.Project, row sql.Row) (sql.RowIter, error) {
   313  	span, ctx := ctx.Span("plan.Project", trace.WithAttributes(
   314  		attribute.Int("projections", len(n.Projections)),
   315  	))
   316  
   317  	i, err := b.buildNodeExec(ctx, n.Child, row)
   318  	if err != nil {
   319  		span.End()
   320  		return nil, err
   321  	}
   322  
   323  	return sql.NewSpanIter(span, &projectIter{
   324  		p:         n.Projections,
   325  		childIter: i,
   326  	}), nil
   327  }
   328  
   329  func (b *BaseBuilder) buildVirtualColumnTable(ctx *sql.Context, n *plan.VirtualColumnTable, tableIter sql.RowIter, row sql.Row) (sql.RowIter, error) {
   330  	span, ctx := ctx.Span("plan.VirtualColumnTable", trace.WithAttributes(
   331  		attribute.Int("projections", len(n.Projections)),
   332  	))
   333  
   334  	return sql.NewSpanIter(span, &projectIter{
   335  		p:         n.Projections,
   336  		childIter: tableIter,
   337  	}), nil
   338  }
   339  
   340  func (b *BaseBuilder) buildProcedure(ctx *sql.Context, n *plan.Procedure, row sql.Row) (sql.RowIter, error) {
   341  	return b.buildNodeExec(ctx, n.Body, row)
   342  }
   343  
   344  func (b *BaseBuilder) buildRecursiveTable(ctx *sql.Context, n *plan.RecursiveTable, row sql.Row) (sql.RowIter, error) {
   345  	return &recursiveTableIter{buf: n.Buf}, nil
   346  }
   347  
   348  func (b *BaseBuilder) buildSet(ctx *sql.Context, n *plan.Set, row sql.Row) (sql.RowIter, error) {
   349  	span, ctx := ctx.Span("plan.Set")
   350  	defer span.End()
   351  
   352  	var updateExprs []sql.Expression
   353  	for _, v := range n.Exprs {
   354  		setField, ok := v.(*expression.SetField)
   355  		if !ok {
   356  			return nil, fmt.Errorf("unsupported type for set: %T", v)
   357  		}
   358  
   359  		switch left := setField.LeftChild.(type) {
   360  		case *expression.SystemVar:
   361  			err := setSystemVar(ctx, left, setField.RightChild, row)
   362  			if err != nil {
   363  				return nil, err
   364  			}
   365  		case *expression.UserVar:
   366  			err := setUserVar(ctx, left, setField.RightChild, row)
   367  			if err != nil {
   368  				return nil, err
   369  			}
   370  		case *expression.ProcedureParam:
   371  			value, err := setField.RightChild.Eval(ctx, row)
   372  			if err != nil {
   373  				return nil, err
   374  			}
   375  			err = left.Set(value, setField.RightChild.Type())
   376  			if err != nil {
   377  				return nil, err
   378  			}
   379  		case *expression.GetField:
   380  			updateExprs = append(updateExprs, setField)
   381  		default:
   382  			return nil, fmt.Errorf("unsupported type for set: %T", left)
   383  		}
   384  	}
   385  
   386  	var resultRow sql.Row
   387  	if len(updateExprs) > 0 {
   388  		newRow, err := applyUpdateExpressions(ctx, updateExprs, row)
   389  		if err != nil {
   390  			return nil, err
   391  		}
   392  		copy(resultRow, row)
   393  		resultRow = row.Append(newRow)
   394  	}
   395  
   396  	return sql.RowsToRowIter(resultRow), nil
   397  }
   398  
   399  func (b *BaseBuilder) buildGroupBy(ctx *sql.Context, n *plan.GroupBy, row sql.Row) (sql.RowIter, error) {
   400  	span, ctx := ctx.Span("plan.GroupBy", trace.WithAttributes(
   401  		attribute.Int("groupings", len(n.GroupByExprs)),
   402  		attribute.Int("aggregates", len(n.SelectedExprs)),
   403  	))
   404  
   405  	i, err := b.buildNodeExec(ctx, n.Child, row)
   406  	if err != nil {
   407  		span.End()
   408  		return nil, err
   409  	}
   410  
   411  	var iter sql.RowIter
   412  	if len(n.GroupByExprs) == 0 {
   413  		iter = newGroupByIter(n.SelectedExprs, i)
   414  	} else {
   415  		iter = newGroupByGroupingIter(ctx, n.SelectedExprs, n.GroupByExprs, i)
   416  	}
   417  
   418  	return sql.NewSpanIter(span, iter), nil
   419  }
   420  
   421  func (b *BaseBuilder) buildFilter(ctx *sql.Context, n *plan.Filter, row sql.Row) (sql.RowIter, error) {
   422  	span, ctx := ctx.Span("plan.Filter")
   423  
   424  	i, err := b.buildNodeExec(ctx, n.Child, row)
   425  	if err != nil {
   426  		span.End()
   427  		return nil, err
   428  	}
   429  
   430  	return sql.NewSpanIter(span, plan.NewFilterIter(n.Expression, i)), nil
   431  }
   432  
   433  func (b *BaseBuilder) buildDeclareVariables(ctx *sql.Context, n *plan.DeclareVariables, row sql.Row) (sql.RowIter, error) {
   434  	return &declareVariablesIter{n, row}, nil
   435  }
   436  
   437  func (b *BaseBuilder) buildDeclareHandler(ctx *sql.Context, n *plan.DeclareHandler, row sql.Row) (sql.RowIter, error) {
   438  	return &declareHandlerIter{n}, nil
   439  }
   440  
   441  func (b *BaseBuilder) buildRecursiveCte(ctx *sql.Context, n *plan.RecursiveCte, row sql.Row) (sql.RowIter, error) {
   442  	var iter sql.RowIter = &recursiveCteIter{
   443  		init:        n.Left(),
   444  		rec:         n.Right(),
   445  		row:         row,
   446  		working:     n.Working,
   447  		temp:        make([]sql.Row, 0),
   448  		deduplicate: n.Union().Distinct,
   449  		b:           b,
   450  	}
   451  	if n.Union().Limit != nil && len(n.Union().SortFields) > 0 {
   452  		limit, err := getInt64Value(ctx, n.Union().Limit)
   453  		if err != nil {
   454  			return nil, err
   455  		}
   456  		iter = newTopRowsIter(n.Union().SortFields, limit, false, iter, len(n.Union().Schema()))
   457  	} else if n.Union().Limit != nil {
   458  		limit, err := getInt64Value(ctx, n.Union().Limit)
   459  		if err != nil {
   460  			return nil, err
   461  		}
   462  		iter = &limitIter{limit: limit, childIter: iter}
   463  	} else if len(n.Union().SortFields) > 0 {
   464  		iter = newSortIter(n.Union().SortFields, iter)
   465  	}
   466  	return iter, nil
   467  }
   468  
   469  func (b *BaseBuilder) buildLimit(ctx *sql.Context, n *plan.Limit, row sql.Row) (sql.RowIter, error) {
   470  	span, ctx := ctx.Span("plan.Limit", trace.WithAttributes(attribute.Stringer("limit", n.Limit)))
   471  
   472  	limit, err := getInt64Value(ctx, n.Limit)
   473  	if err != nil {
   474  		span.End()
   475  		return nil, err
   476  	}
   477  
   478  	childIter, err := b.buildNodeExec(ctx, n.Child, row)
   479  	if err != nil {
   480  		span.End()
   481  		return nil, err
   482  	}
   483  	return sql.NewSpanIter(span, &limitIter{
   484  		calcFoundRows: n.CalcFoundRows,
   485  		limit:         limit,
   486  		childIter:     childIter,
   487  	}), nil
   488  }
   489  
   490  func (b *BaseBuilder) buildMax1Row(ctx *sql.Context, n *plan.Max1Row, row sql.Row) (sql.RowIter, error) {
   491  	n.Mu.Lock()
   492  	defer n.Mu.Unlock()
   493  
   494  	if !n.HasResults() {
   495  		err := b.populateMax1Results(ctx, n, row)
   496  		if err != nil {
   497  			return nil, err
   498  		}
   499  	}
   500  
   501  	switch {
   502  	case n.EmptyResult:
   503  		return plan.EmptyIter, nil
   504  	case n.Result != nil:
   505  		return sql.RowsToRowIter(n.Result), nil
   506  	default:
   507  		return nil, fmt.Errorf("Max1Row failed to load results")
   508  	}
   509  }
   510  
   511  // PopulateResults loads and stores the state of its child iter:
   512  // 1) no rows returned, 2) 1 row returned, or 3) more than 1 row
   513  // returned
   514  func (b *BaseBuilder) populateMax1Results(ctx *sql.Context, n *plan.Max1Row, row sql.Row) error {
   515  	i, err := b.buildNodeExec(ctx, n.Child, row)
   516  	if err != nil {
   517  		return err
   518  	}
   519  	defer i.Close(ctx)
   520  	r1, err := i.Next(ctx)
   521  	if errors.Is(err, io.EOF) {
   522  		n.EmptyResult = true
   523  		return nil
   524  	} else if err != nil {
   525  		return err
   526  	}
   527  
   528  	_, err = i.Next(ctx)
   529  	if err == nil {
   530  		return sql.ErrExpectedSingleRow.New()
   531  	} else if !errors.Is(err, io.EOF) {
   532  		return err
   533  	}
   534  	n.Result = r1
   535  	return nil
   536  }
   537  
   538  // isUnderSecureFileDir ensures that fileStr is under secureFileDir or a subdirectory of secureFileDir, errors otherwise
   539  func isUnderSecureFileDir(secureFileDir interface{}, fileStr string) error {
   540  	if secureFileDir == nil || secureFileDir == "" {
   541  		return nil
   542  	}
   543  	sStat, err := os.Stat(secureFileDir.(string))
   544  	if err != nil {
   545  		return err
   546  	}
   547  	fStat, err := os.Stat(filepath.Dir(fileStr))
   548  	if err != nil {
   549  		return err
   550  	}
   551  	if os.SameFile(sStat, fStat) {
   552  		return nil
   553  	}
   554  
   555  	fileAbsPath, filePathErr := filepath.Abs(fileStr)
   556  	if filePathErr != nil {
   557  		return filePathErr
   558  	}
   559  	secureFileDirAbsPath, _ := filepath.Abs(secureFileDir.(string))
   560  	if strings.HasPrefix(fileAbsPath, secureFileDirAbsPath) {
   561  		return nil
   562  	}
   563  	return sql.ErrSecureFilePriv.New()
   564  }
   565  
   566  // createIfNotExists creates a file if it does not exist, errors otherwise
   567  func createIfNotExists(fileStr string) (*os.File, error) {
   568  	if _, fErr := os.Stat(fileStr); fErr == nil {
   569  		return nil, sql.ErrFileExists.New(fileStr)
   570  	}
   571  	file, fileErr := os.OpenFile(fileStr, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0640)
   572  	if fileErr != nil {
   573  		return nil, fileErr
   574  	}
   575  	return file, nil
   576  }
   577  
   578  func (b *BaseBuilder) buildInto(ctx *sql.Context, n *plan.Into, row sql.Row) (sql.RowIter, error) {
   579  	span, ctx := ctx.Span("plan.Into")
   580  	defer span.End()
   581  
   582  	rowIter, err := b.buildNodeExec(ctx, n.Child, row)
   583  	if err != nil {
   584  		return nil, err
   585  	}
   586  	rows, err := sql.RowIterToRows(ctx, rowIter)
   587  	if err != nil {
   588  		return nil, err
   589  	}
   590  
   591  	var secureFileDir interface{}
   592  	if n.Outfile != "" || n.Dumpfile != "" {
   593  		var ok bool
   594  		_, secureFileDir, ok = sql.SystemVariables.GetGlobal("secure_file_priv")
   595  		if !ok {
   596  			return nil, fmt.Errorf("error: secure_file_priv variable was not found")
   597  		}
   598  	}
   599  
   600  	if n.Outfile != "" {
   601  		// TODO: MySQL has relative paths from the "data dir"
   602  		if err = isUnderSecureFileDir(secureFileDir, n.Outfile); err != nil {
   603  			return nil, err
   604  		}
   605  		file, fileErr := createIfNotExists(n.Outfile)
   606  		if fileErr != nil {
   607  			return nil, fileErr
   608  		}
   609  		defer file.Close()
   610  
   611  		sch := n.Child.Schema()
   612  		for _, r := range rows {
   613  			file.WriteString(n.LinesStartingBy)
   614  			for i, val := range r {
   615  				if i != 0 {
   616  					file.WriteString(n.FieldsTerminatedBy)
   617  				}
   618  				if val == nil {
   619  					if len(n.FieldsEscapedBy) == 0 {
   620  						file.WriteString("NULL")
   621  					} else {
   622  						file.WriteString(fmt.Sprintf("%sN", n.FieldsEscapedBy))
   623  					}
   624  					continue
   625  				}
   626  				if !n.FieldsEnclosedByOpt || types.IsText(sch[i].Type) {
   627  					if strVal, ok := val.(string); ok {
   628  						if len(n.LinesTerminatedBy) != 0 {
   629  							strVal = strings.Replace(strVal, n.LinesTerminatedBy, n.FieldsEscapedBy+n.LinesTerminatedBy, -1)
   630  						}
   631  						file.WriteString(fmt.Sprintf("%s%v%s", n.FieldsEnclosedBy, strVal, n.FieldsEnclosedBy))
   632  					} else {
   633  						file.WriteString(fmt.Sprintf("%s%v%s", n.FieldsEnclosedBy, val, n.FieldsEnclosedBy))
   634  					}
   635  				} else {
   636  					file.WriteString(fmt.Sprintf("%v", val))
   637  				}
   638  			}
   639  			file.WriteString(n.LinesTerminatedBy)
   640  		}
   641  		return sql.RowsToRowIter(sql.Row{}), nil
   642  	}
   643  
   644  	rowNum := len(rows)
   645  	if rowNum > 1 {
   646  		return nil, sql.ErrMoreThanOneRow.New()
   647  	}
   648  
   649  	if n.Dumpfile != "" {
   650  		if err = isUnderSecureFileDir(secureFileDir, n.Dumpfile); err != nil {
   651  			return nil, err
   652  		}
   653  		file, fileErr := createIfNotExists(n.Dumpfile)
   654  		if fileErr != nil {
   655  			return nil, fileErr
   656  		}
   657  		defer file.Close()
   658  		if rowNum == 1 {
   659  			for _, val := range rows[0] {
   660  				file.WriteString(fmt.Sprintf("%v", val))
   661  			}
   662  		}
   663  		return sql.RowsToRowIter(sql.Row{}), nil
   664  	}
   665  
   666  	if rowNum == 0 {
   667  		// a warning with error code 1329 occurs (No data), and make no change to variables
   668  		return sql.RowsToRowIter(sql.Row{}), nil
   669  	}
   670  	if len(rows[0]) != len(n.IntoVars) {
   671  		return nil, sql.ErrColumnNumberDoesNotMatch.New()
   672  	}
   673  
   674  	var rowValues = make([]interface{}, len(rows[0]))
   675  	copy(rowValues, rows[0])
   676  
   677  	for j, v := range n.IntoVars {
   678  		switch variable := v.(type) {
   679  		case *expression.UserVar:
   680  			varType := types.ApproximateTypeFromValue(rowValues[j])
   681  			err = ctx.SetUserVariable(ctx, variable.Name, rowValues[j], varType)
   682  			if err != nil {
   683  				return nil, err
   684  			}
   685  		case *expression.ProcedureParam:
   686  			err = variable.Set(rowValues[j], types.ApproximateTypeFromValue(rowValues[j]))
   687  			if err != nil {
   688  				return nil, err
   689  			}
   690  		default:
   691  			return nil, fmt.Errorf("unsupported type for into: %T", variable)
   692  		}
   693  	}
   694  
   695  	return sql.RowsToRowIter(sql.Row{}), nil
   696  }
   697  
   698  func (b *BaseBuilder) buildExternalProcedure(ctx *sql.Context, n *plan.ExternalProcedure, row sql.Row) (sql.RowIter, error) {
   699  	// The function's structure has been verified by the analyzer, so no need to double-check any of it here
   700  	funcVal := reflect.ValueOf(n.Function)
   701  	funcType := funcVal.Type()
   702  	// The first parameter is always the context, but it doesn't exist as far as the stored procedures are concerned, so
   703  	// we prepend it here
   704  	funcParams := make([]reflect.Value, len(n.Params)+1)
   705  	funcParams[0] = reflect.ValueOf(ctx)
   706  
   707  	for i := range n.Params {
   708  		paramDefinition := n.ParamDefinitions[i]
   709  		var funcParamType reflect.Type
   710  		if paramDefinition.Variadic {
   711  			funcParamType = funcType.In(funcType.NumIn() - 1).Elem()
   712  		} else {
   713  			funcParamType = funcType.In(i + 1)
   714  		}
   715  		// Grab the passed-in variable and convert it to the type we expect
   716  		exprParamVal, err := n.Params[i].Eval(ctx, nil)
   717  		if err != nil {
   718  			return nil, err
   719  		}
   720  		exprParamVal, _, err = paramDefinition.Type.Convert(exprParamVal)
   721  		if err != nil {
   722  			return nil, err
   723  		}
   724  
   725  		funcParams[i+1], err = n.ProcessParam(ctx, funcParamType, exprParamVal)
   726  		if err != nil {
   727  			return nil, err
   728  		}
   729  	}
   730  	out := funcVal.Call(funcParams)
   731  
   732  	// Again, these types are enforced in the analyzer, so it's safe to assume their types here
   733  	if err, ok := out[1].Interface().(error); ok { // Only evaluates to true when error is not nil
   734  		return nil, err
   735  	}
   736  	for i, paramDefinition := range n.ParamDefinitions {
   737  		if paramDefinition.Direction == plan.ProcedureParamDirection_Inout || paramDefinition.Direction == plan.ProcedureParamDirection_Out {
   738  			exprParam := n.Params[i]
   739  			funcParamVal := funcParams[i+1].Elem().Interface()
   740  			err := exprParam.Set(funcParamVal, exprParam.Type())
   741  			if err != nil {
   742  				return nil, err
   743  			}
   744  		}
   745  	}
   746  	// It's not invalid to return a nil RowIter, as having no rows to return is expected of many stored procedures.
   747  	if rowIter, ok := out[0].Interface().(sql.RowIter); ok {
   748  		return rowIter, nil
   749  	}
   750  	return sql.RowsToRowIter(), nil
   751  }
   752  
   753  func (b *BaseBuilder) buildHaving(ctx *sql.Context, n *plan.Having, row sql.Row) (sql.RowIter, error) {
   754  	span, ctx := ctx.Span("plan.Having")
   755  	iter, err := b.buildNodeExec(ctx, n.Child, row)
   756  	if err != nil {
   757  		span.End()
   758  		return nil, err
   759  	}
   760  
   761  	return sql.NewSpanIter(span, plan.NewFilterIter(n.Cond, iter)), nil
   762  }
   763  
   764  func (b *BaseBuilder) buildDistinct(ctx *sql.Context, n *plan.Distinct, row sql.Row) (sql.RowIter, error) {
   765  	span, ctx := ctx.Span("plan.Distinct")
   766  
   767  	it, err := b.buildNodeExec(ctx, n.Child, row)
   768  	if err != nil {
   769  		span.End()
   770  		return nil, err
   771  	}
   772  
   773  	return sql.NewSpanIter(span, newDistinctIter(ctx, it)), nil
   774  }
   775  
   776  func (b *BaseBuilder) buildIndexedTableAccess(ctx *sql.Context, n *plan.IndexedTableAccess, row sql.Row) (sql.RowIter, error) {
   777  	span, ctx := ctx.Span("plan.IndexedTableAccess")
   778  
   779  	lookup, err := n.GetLookup(ctx, row)
   780  	if err != nil {
   781  		return nil, err
   782  	}
   783  
   784  	partIter, err := n.Table.LookupPartitions(ctx, lookup)
   785  	if err != nil {
   786  		return nil, err
   787  	}
   788  
   789  	var tableIter sql.RowIter
   790  	tableIter = sql.NewTableRowIter(ctx, n.Table, partIter)
   791  
   792  	if vct, ok := plan.FindVirtualColumnTable(n.Table); ok {
   793  		tableIter, err = b.buildVirtualColumnTable(ctx, vct, tableIter, row)
   794  		if err != nil {
   795  			return nil, err
   796  		}
   797  	}
   798  
   799  	return sql.NewSpanIter(span, tableIter), nil
   800  }
   801  
   802  func (b *BaseBuilder) buildSetOp(ctx *sql.Context, s *plan.SetOp, row sql.Row) (sql.RowIter, error) {
   803  	span, ctx := ctx.Span("plan.SetOp")
   804  	var iter sql.RowIter
   805  	var err error
   806  	iter, err = b.buildNodeExec(ctx, s.Left(), row)
   807  	if err != nil {
   808  		span.End()
   809  		return nil, err
   810  	}
   811  	switch s.SetOpType {
   812  	case plan.UnionType:
   813  		iter = &unionIter{
   814  			cur: iter,
   815  			nextIter: func(ctx *sql.Context) (sql.RowIter, error) {
   816  				return b.buildNodeExec(ctx, s.Right(), row)
   817  			},
   818  		}
   819  	case plan.IntersectType:
   820  		var iter2 sql.RowIter
   821  		iter2, err = b.buildNodeExec(ctx, s.Right(), row)
   822  		if err != nil {
   823  			span.End()
   824  			return nil, err
   825  		}
   826  		iter = &intersectIter{
   827  			lIter: iter,
   828  			rIter: iter2,
   829  		}
   830  	case plan.ExceptType:
   831  		var iter2 sql.RowIter
   832  		iter2, err = b.buildNodeExec(ctx, s.Right(), row)
   833  		if err != nil {
   834  			span.End()
   835  			return nil, err
   836  		}
   837  		if s.Distinct {
   838  			dIter := newDistinctIter(ctx, iter)
   839  			s.AddDispose(dIter.dispose)
   840  			iter = dIter
   841  
   842  			dIter2 := newDistinctIter(ctx, iter2)
   843  			s.AddDispose(dIter2.dispose)
   844  			iter2 = dIter2
   845  		}
   846  		iter = &exceptIter{
   847  			lIter: iter,
   848  			rIter: iter2,
   849  		}
   850  	}
   851  
   852  	if s.Distinct && s.SetOpType != plan.ExceptType {
   853  		dIter := newDistinctIter(ctx, iter)
   854  		s.AddDispose(dIter.dispose)
   855  		iter = dIter
   856  	}
   857  	// Limit must wrap offset, and not vice-versa, so that
   858  	// skipped rows don't count toward the returned row count.
   859  	if s.Offset != nil {
   860  		offset, err := getInt64Value(ctx, s.Offset)
   861  		if err != nil {
   862  			return nil, err
   863  		}
   864  		iter = &offsetIter{skip: offset, childIter: iter}
   865  	}
   866  	if s.Limit != nil && len(s.SortFields) > 0 {
   867  		limit, err := getInt64Value(ctx, s.Limit)
   868  		if err != nil {
   869  			return nil, err
   870  		}
   871  		iter = newTopRowsIter(s.SortFields, limit, false, iter, len(s.Schema()))
   872  	} else if s.Limit != nil {
   873  		limit, err := getInt64Value(ctx, s.Limit)
   874  		if err != nil {
   875  			return nil, err
   876  		}
   877  		iter = &limitIter{limit: limit, childIter: iter}
   878  	} else if len(s.SortFields) > 0 {
   879  		iter = newSortIter(s.SortFields, iter)
   880  	}
   881  	return sql.NewSpanIter(span, iter), nil
   882  }
   883  
   884  func (b *BaseBuilder) buildSubqueryAlias(ctx *sql.Context, n *plan.SubqueryAlias, row sql.Row) (sql.RowIter, error) {
   885  	span, ctx := ctx.Span("plan.SubqueryAlias")
   886  
   887  	if !n.OuterScopeVisibility && !n.IsLateral {
   888  		row = nil
   889  	}
   890  	iter, err := b.buildNodeExec(ctx, n.Child, row)
   891  	if err != nil {
   892  		span.End()
   893  		return nil, err
   894  	}
   895  
   896  	return sql.NewSpanIter(span, iter), nil
   897  }
   898  
   899  func (b *BaseBuilder) buildSort(ctx *sql.Context, n *plan.Sort, row sql.Row) (sql.RowIter, error) {
   900  	span, ctx := ctx.Span("plan.Sort")
   901  	i, err := b.buildNodeExec(ctx, n.Child, row)
   902  	if err != nil {
   903  		span.End()
   904  		return nil, err
   905  	}
   906  	return sql.NewSpanIter(span, newSortIter(n.SortFields, i)), nil
   907  }
   908  
   909  func (b *BaseBuilder) buildPrepareQuery(ctx *sql.Context, n *plan.PrepareQuery, row sql.Row) (sql.RowIter, error) {
   910  	return sql.RowsToRowIter(sql.NewRow(types.OkResult{RowsAffected: 0, Info: plan.PrepareInfo{}})), nil
   911  }
   912  
   913  func (b *BaseBuilder) buildResolvedTable(ctx *sql.Context, n *plan.ResolvedTable, row sql.Row) (sql.RowIter, error) {
   914  	span, ctx := ctx.Span("plan.TableNode")
   915  
   916  	partitions, err := n.Table.Partitions(ctx)
   917  	if err != nil {
   918  		span.End()
   919  		return nil, err
   920  	}
   921  
   922  	var iter sql.RowIter
   923  	iter = sql.NewTableRowIter(ctx, n.Table, partitions)
   924  
   925  	if vct, ok := plan.FindVirtualColumnTable(n.Table); ok {
   926  		iter, err = b.buildVirtualColumnTable(ctx, vct, iter, row)
   927  		if err != nil {
   928  			return nil, err
   929  		}
   930  	}
   931  
   932  	return sql.NewSpanIter(span, iter), nil
   933  }
   934  
   935  func (b *BaseBuilder) buildTableCount(_ *sql.Context, n *plan.TableCountLookup, _ sql.Row) (sql.RowIter, error) {
   936  	return sql.RowsToRowIter(sql.Row{int64(n.Count())}), nil
   937  }