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 }