Skip to content

Commit 61b3af6

Browse files
authored
refactor(node): remove NodeWriter interface and AcceptTo methods (#543)
1 parent b6428ea commit 61b3af6

File tree

5 files changed

+49
-142
lines changed

5 files changed

+49
-142
lines changed

node/condition.go

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package node
1818

1919
import (
2020
"errors"
21-
"strings"
2221

2322
"github.com/go-juicedev/juice/driver"
2423
"github.com/go-juicedev/juice/eval"
@@ -52,20 +51,6 @@ func (c *ConditionNode) Parse(test string) (err error) {
5251
return err
5352
}
5453

55-
func (c *ConditionNode) AcceptTo(translator driver.Translator, p eval.Parameter, builder *strings.Builder, args *[]any) error {
56-
p = c.BindNodes.ConvertParameter(p)
57-
58-
matched, err := c.Match(p)
59-
if err != nil {
60-
return err
61-
}
62-
if !matched {
63-
return nil
64-
}
65-
66-
return c.Nodes.AcceptTo(translator, p, builder, args)
67-
}
68-
6954
// Accept accepts parameters and returns query and arguments.
7055
// Accept implements Node interface.
7156
func (c *ConditionNode) Accept(translator driver.Translator, p eval.Parameter) (query string, args []any, err error) {
@@ -100,4 +85,4 @@ func (c *ConditionNode) Match(p eval.Parameter) (bool, error) {
10085
return !value.IsZero(), nil
10186
}
10287

103-
var _ NodeWriter = (*ConditionNode)(nil)
88+
var _ Node = (*ConditionNode)(nil)

node/foreach.go

Lines changed: 41 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package node
1919
import (
2020
"fmt"
2121
"reflect"
22-
"strings"
2322

2423
"github.com/go-juicedev/juice/driver"
2524
"github.com/go-juicedev/juice/eval"
@@ -79,65 +78,22 @@ type ForeachNode struct {
7978

8079
// Accept accepts parameters and returns query and arguments.
8180
func (f ForeachNode) Accept(translator driver.Translator, p eval.Parameter) (query string, args []any, err error) {
82-
builder := getStringBuilder()
83-
defer putStringBuilder(builder)
84-
85-
// Estimation logic for pre-allocation
86-
var totalPlaceholders int
87-
for _, node := range f.Nodes {
88-
if t, ok := node.(*TextNode); ok {
89-
for _, token := range t.tokens {
90-
if !token.isFormat {
91-
totalPlaceholders++
92-
}
93-
}
94-
} else {
95-
totalPlaceholders += 2
96-
}
97-
}
98-
99-
// We don't know the exact length yet, but we can guess from p
100-
coll, exists := p.Get(f.Collection)
101-
var length int
102-
if exists {
103-
c := coll
104-
for c.Kind() == reflect.Interface || c.Kind() == reflect.Ptr {
105-
if c.IsNil() {
106-
break
107-
}
108-
c = c.Elem()
109-
}
110-
if c.Kind() == reflect.Slice || c.Kind() == reflect.Array || c.Kind() == reflect.Map {
111-
length = c.Len()
112-
}
113-
}
114-
115-
argsList := make([]any, 0, length*totalPlaceholders)
116-
117-
if err = f.AcceptTo(translator, p, builder, &argsList); err != nil {
118-
return "", nil, err
119-
}
120-
121-
return builder.String(), argsList, nil
122-
}
123-
124-
func (f ForeachNode) AcceptTo(translator driver.Translator, p eval.Parameter, builder *strings.Builder, args *[]any) error {
12581
p = f.BindNodes.ConvertParameter(p)
12682

12783
// if item already exists
12884
if _, exists := p.Get(f.Item); exists {
129-
return fmt.Errorf("item %s already exists", f.Item)
85+
return "", nil, fmt.Errorf("item %s already exists", f.Item)
13086
}
13187

13288
// one collection from parameter
13389
value, exists := p.Get(f.Collection)
13490
if !exists {
135-
return fmt.Errorf("collection %s not found", f.Collection)
91+
return "", nil, fmt.Errorf("collection %s not found", f.Collection)
13692
}
13793

13894
// if valueItem can not be iterated
13995
if !value.CanInterface() {
140-
return fmt.Errorf("collection %s can not be iterated", f.Collection)
96+
return "", nil, fmt.Errorf("collection %s can not be iterated", f.Collection)
14197
}
14298

14399
// if valueItem is not a slice
@@ -147,28 +103,33 @@ func (f ForeachNode) AcceptTo(translator driver.Translator, p eval.Parameter, bu
147103

148104
switch value.Kind() {
149105
case reflect.Array, reflect.Slice:
150-
return f.acceptSliceTo(value, translator, p, builder, args)
106+
return f.acceptSlice(value, translator, p)
151107
case reflect.Map:
152-
return f.acceptMapTo(value, translator, p, builder, args)
108+
return f.acceptMap(value, translator, p)
153109
default:
154-
return fmt.Errorf("collection %s is not a slice or map", f.Collection)
110+
return "", nil, fmt.Errorf("collection %s is not a slice or map", f.Collection)
155111
}
156112
}
157113

158-
func (f ForeachNode) acceptSliceTo(value reflect.Value, translator driver.Translator, p eval.Parameter, builder *strings.Builder, args *[]any) error {
114+
func (f ForeachNode) acceptSlice(value reflect.Value, translator driver.Translator, p eval.Parameter) (string, []any, error) {
159115
sliceLength := value.Len()
160116

161117
if sliceLength == 0 {
162-
return nil
118+
return "", nil, nil
163119
}
164120

121+
builder := getStringBuilder()
122+
defer putStringBuilder(builder)
123+
165124
builder.WriteString(f.Open)
166125

167126
end := sliceLength - 1
168127

169128
// Create and reuse foreachParameter outside the loop to avoid allocations per iteration
170129
fp := eval.NewForeachParameter(p, f.Item, f.Index)
171130

131+
var args []any
132+
172133
for i := 0; i < sliceLength; i++ {
173134

174135
fp.ItemValue = value.Index(i)
@@ -177,21 +138,15 @@ func (f ForeachNode) acceptSliceTo(value reflect.Value, translator driver.Transl
177138
}
178139

179140
for _, node := range f.Nodes {
180-
if nw, ok := node.(NodeWriter); ok {
181-
if err := nw.AcceptTo(translator, fp, builder, args); err != nil {
182-
return err
183-
}
184-
} else {
185-
q, a, err := node.Accept(translator, fp)
186-
if err != nil {
187-
return err
188-
}
189-
if len(q) > 0 {
190-
builder.WriteString(q)
191-
}
192-
if len(a) > 0 {
193-
*args = append(*args, a...)
194-
}
141+
q, a, err := node.Accept(translator, fp)
142+
if err != nil {
143+
return "", nil, err
144+
}
145+
if len(q) > 0 {
146+
builder.WriteString(q)
147+
}
148+
if len(a) > 0 {
149+
args = append(args, a...)
195150
}
196151
}
197152

@@ -201,19 +156,21 @@ func (f ForeachNode) acceptSliceTo(value reflect.Value, translator driver.Transl
201156
fp.Clear()
202157
}
203158

204-
// if sliceLength is not zero, add close
205159
builder.WriteString(f.Close)
206160

207-
return nil
161+
return builder.String(), args, nil
208162
}
209163

210-
func (f ForeachNode) acceptMapTo(value reflect.Value, translator driver.Translator, p eval.Parameter, builder *strings.Builder, args *[]any) error {
164+
func (f ForeachNode) acceptMap(value reflect.Value, translator driver.Translator, p eval.Parameter) (string, []any, error) {
211165
mapLength := value.Len()
212166

213167
if mapLength == 0 {
214-
return nil
168+
return "", nil, nil
215169
}
216170

171+
builder := getStringBuilder()
172+
defer putStringBuilder(builder)
173+
217174
builder.WriteString(f.Open)
218175

219176
end := mapLength - 1
@@ -225,27 +182,23 @@ func (f ForeachNode) acceptMapTo(value reflect.Value, translator driver.Translat
225182

226183
iter := value.MapRange()
227184

185+
var args []any
186+
228187
for iter.Next() {
229188

230189
fp.ItemValue = iter.Value()
231190
fp.IndexValue = iter.Key()
232191

233192
for _, node := range f.Nodes {
234-
if nw, ok := node.(NodeWriter); ok {
235-
if err := nw.AcceptTo(translator, fp, builder, args); err != nil {
236-
return err
237-
}
238-
} else {
239-
q, a, err := node.Accept(translator, fp)
240-
if err != nil {
241-
return err
242-
}
243-
if len(q) > 0 {
244-
builder.WriteString(q)
245-
}
246-
if len(a) > 0 {
247-
*args = append(*args, a...)
248-
}
193+
q, a, err := node.Accept(translator, fp)
194+
if err != nil {
195+
return "", nil, err
196+
}
197+
if len(q) > 0 {
198+
builder.WriteString(q)
199+
}
200+
if len(a) > 0 {
201+
args = append(args, a...)
249202
}
250203
}
251204

@@ -260,7 +213,7 @@ func (f ForeachNode) acceptMapTo(value reflect.Value, translator driver.Translat
260213

261214
builder.WriteString(f.Close)
262215

263-
return nil
216+
return builder.String(), args, nil
264217
}
265218

266-
var _ NodeWriter = (*ForeachNode)(nil)
219+
var _ Node = (*ForeachNode)(nil)

node/sql.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ limitations under the License.
1717
package node
1818

1919
import (
20-
"strings"
21-
2220
"github.com/go-juicedev/juice/driver"
2321
"github.com/go-juicedev/juice/eval"
2422
)
@@ -72,9 +70,4 @@ func (s SQLNode) Accept(translator driver.Translator, p eval.Parameter) (query s
7270
return s.Nodes.Accept(translator, p)
7371
}
7472

75-
func (s SQLNode) AcceptTo(translator driver.Translator, p eval.Parameter, builder *strings.Builder, args *[]any) error {
76-
p = s.BindNodes.ConvertParameter(p)
77-
return s.Nodes.AcceptTo(translator, p, builder, args)
78-
}
79-
80-
var _ NodeWriter = (*SQLNode)(nil)
73+
var _ Node = (*SQLNode)(nil)

node/text.go

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package node
1919
import (
2020
"fmt"
2121
"sort"
22-
"strings"
2322

2423
"github.com/go-juicedev/juice/driver"
2524
"github.com/go-juicedev/juice/eval"
@@ -70,38 +69,25 @@ func (c *TextNode) Accept(translator driver.Translator, p eval.Parameter) (query
7069
}
7170
args = make([]any, 0, capacity)
7271

73-
if err = c.AcceptTo(translator, p, builder, &args); err != nil {
74-
return "", nil, err
75-
}
76-
77-
return builder.String(), args, nil
78-
}
79-
80-
func (c *TextNode) AcceptTo(translator driver.Translator, p eval.Parameter, builder *strings.Builder, args *[]any) error {
81-
if len(c.tokens) == 0 {
82-
builder.WriteString(c.value)
83-
return nil
84-
}
8572
lastIndex := 0
8673
for _, t := range c.tokens {
8774
builder.WriteString(c.value[lastIndex:t.index])
8875
value, exists := p.Get(t.name)
8976
if !exists {
90-
return fmt.Errorf("parameter %s not found", t.name)
77+
return "", nil, fmt.Errorf("parameter %s not found", t.name)
9178
}
9279

9380
if t.isFormat {
9481
builder.WriteString(reflectValueToString(value))
9582
} else {
9683
builder.WriteString(translator.Translate(t.name))
97-
if args != nil {
98-
*args = append(*args, value.Interface())
99-
}
84+
args = append(args, value.Interface())
10085
}
10186
lastIndex = t.index + len(t.match)
10287
}
10388
builder.WriteString(c.value[lastIndex:])
104-
return nil
89+
90+
return builder.String(), args, nil
10591
}
10692

10793
// NewTextNode creates a new text node based on the input string.
@@ -141,4 +127,4 @@ func NewTextNode(str string) Node {
141127
return &TextNode{value: str, tokens: tokens}
142128
}
143129

144-
var _ NodeWriter = (*TextNode)(nil)
130+
var _ Node = (*TextNode)(nil)

node/where.go

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,4 @@ func (w WhereNode) Accept(translator driver.Translator, p eval.Parameter) (query
6868
return
6969
}
7070

71-
func (w WhereNode) AcceptTo(translator driver.Translator, p eval.Parameter, builder *strings.Builder, args *[]any) error {
72-
query, a, err := w.Accept(translator, p)
73-
if err != nil {
74-
return err
75-
}
76-
builder.WriteString(query)
77-
*args = append(*args, a...)
78-
return nil
79-
}
80-
81-
var _ NodeWriter = (*WhereNode)(nil)
71+
var _ Node = (*WhereNode)(nil)

0 commit comments

Comments
 (0)