github.com/dolthub/go-mysql-server@v0.18.0/sql/rowexec/expr_closer.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 "github.com/dolthub/go-mysql-server/sql" 19 "github.com/dolthub/go-mysql-server/sql/transform" 20 ) 21 22 // exprCloserIter ensures that all expressions that implement sql.Closer are closed. This is implemented as a capturing 23 // iterator, as our workflow only supports closing nodes, not expressions. 24 type exprCloserIter struct { 25 iter sql.RowIter 26 exprs []sql.Closer 27 } 28 29 var _ sql.RowIter = (*exprCloserIter)(nil) 30 31 // AddExpressionCloser returns a new iterator that ensures that any expressions that implement sql.Closer are closed. 32 // If there are no expressions that implement sql.Closer in the tree, then the original iterator is returned. 33 func AddExpressionCloser(node sql.Node, iter sql.RowIter) sql.RowIter { 34 var exprs []sql.Closer 35 transform.InspectExpressions(node, func(expr sql.Expression) bool { 36 if closer, ok := expr.(sql.Closer); ok { 37 exprs = append(exprs, closer) 38 // If we've hit an expression that closes, then we assume that the expression will also close its children. 39 return false 40 } 41 return true 42 }) 43 if len(exprs) == 0 { 44 return iter 45 } 46 return &exprCloserIter{ 47 iter: iter, 48 exprs: exprs, 49 } 50 } 51 52 // Next implements the interface sql.RowIter. 53 func (eci *exprCloserIter) Next(ctx *sql.Context) (sql.Row, error) { 54 return eci.iter.Next(ctx) 55 } 56 57 // Close implements the interface sql.RowIter. 58 func (eci *exprCloserIter) Close(ctx *sql.Context) error { 59 err := eci.iter.Close(ctx) 60 for _, expr := range eci.exprs { 61 if nErr := expr.Close(ctx); err == nil { 62 err = nErr 63 } 64 } 65 return err 66 }