github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/repeat.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 plan 16 17 import ( 18 "github.com/dolthub/go-mysql-server/sql" 19 "github.com/dolthub/go-mysql-server/sql/expression" 20 ) 21 22 // Repeat represents the REPEAT statement, which loops over a set of statements until the condition is true. 23 type Repeat struct { 24 *Loop 25 } 26 27 var _ sql.Node = (*Repeat)(nil) 28 var _ sql.DebugStringer = (*Repeat)(nil) 29 var _ sql.Expressioner = (*Repeat)(nil) 30 var _ sql.CollationCoercible = (*Repeat)(nil) 31 var _ RepresentsLabeledBlock = (*Repeat)(nil) 32 33 // NewRepeat returns a new *Repeat node. 34 func NewRepeat(label string, condition sql.Expression, block *Block) *Repeat { 35 return &Repeat{ 36 &Loop{ 37 Label: label, 38 Condition: expression.NewNot(condition), // Repeat stops when the condition is true, so we apply NOT to match loop's failure case 39 OnceBeforeEval: true, 40 Block: block, 41 }, 42 } 43 } 44 45 // String implements the interface sql.Node. 46 func (r *Repeat) String() string { 47 label := "" 48 if len(r.Label) > 0 { 49 label = r.Label + ": " 50 } 51 p := sql.NewTreePrinter() 52 _ = p.WriteNode("%s: REPEAT(%s)", label, r.Condition.String()) 53 var children []string 54 for _, s := range r.statements { 55 children = append(children, s.String()) 56 } 57 _ = p.WriteChildren(children...) 58 return p.String() 59 } 60 61 // DebugString implements the interface sql.DebugStringer. 62 func (r *Repeat) DebugString() string { 63 label := "" 64 if len(r.Label) > 0 { 65 label = r.Label + ": " 66 } 67 p := sql.NewTreePrinter() 68 _ = p.WriteNode("%s: REPEAT(%s)", label, sql.DebugString(r.Condition)) 69 var children []string 70 for _, s := range r.statements { 71 children = append(children, sql.DebugString(s)) 72 } 73 _ = p.WriteChildren(children...) 74 return p.String() 75 } 76 77 // WithChildren implements the interface sql.Node. 78 func (r *Repeat) WithChildren(children ...sql.Node) (sql.Node, error) { 79 return &Repeat{ 80 &Loop{ 81 Label: r.Loop.Label, 82 Condition: r.Loop.Condition, 83 OnceBeforeEval: true, 84 Block: NewBlock(children), 85 }, 86 }, nil 87 } 88 89 // WithExpressions implements the interface sql.Node. 90 func (r *Repeat) WithExpressions(exprs ...sql.Expression) (sql.Node, error) { 91 if len(exprs) != 1 { 92 return nil, sql.ErrInvalidChildrenNumber.New(r, len(exprs), 1) 93 } 94 95 return &Repeat{ 96 &Loop{ 97 Label: r.Loop.Label, 98 Condition: exprs[0], 99 OnceBeforeEval: true, 100 Block: r.Loop.Block, 101 }, 102 }, nil 103 }