• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stephenafamo / bob / 17002678275

16 Aug 2025 01:28AM UTC coverage: 41.658% (+0.06%) from 41.598%
17002678275

push

github

stephenafamo
Properly detect end of function in postgres query parser

0 of 1 new or added line in 1 file covered. (0.0%)

110 existing lines in 2 files now uncovered.

9556 of 22939 relevant lines covered (41.66%)

567.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.74
/gen/bobgen-helpers/parser/args.go
1
package parser
2

3
import (
4
        "fmt"
5
        "slices"
6

7
        "github.com/stephenafamo/bob/gen/drivers"
8
)
9

10
func GetArgs(bindArgs, groupArgs []drivers.QueryArg) []drivers.QueryArg {
32✔
11
        argIsInGroup := make([]bool, len(bindArgs))
32✔
12
        groupIsInGroup := make([]bool, len(groupArgs))
32✔
13

32✔
14
        // Sort the groups by the size of the group
32✔
15
        slices.SortStableFunc(groupArgs, func(a, b drivers.QueryArg) int {
36✔
16
                return (a.Positions[0][1] - a.Positions[0][0]) -
4✔
17
                        (b.Positions[0][1] - b.Positions[0][0])
4✔
18
        })
4✔
19

20
        for groupIndex, group := range groupArgs {
60✔
21
                var groupChildren []drivers.QueryArg
28✔
22
                for argIndex, arg := range bindArgs {
84✔
23
                        // Do not add args with multiple positions into groups
56✔
24
                        if len(arg.Positions) > 1 {
56✔
25
                                continue
×
26
                        }
27

28
                        // So we don't add the same arg to multiple groups
29
                        if argIsInGroup[argIndex] {
64✔
30
                                continue
8✔
31
                        }
32

33
                        if group.Positions[0][0] <= arg.Positions[0][0] &&
48✔
34
                                arg.Positions[0][1] <= group.Positions[0][1] {
88✔
35
                                argIsInGroup[argIndex] = true
40✔
36
                                groupChildren = append(groupChildren, bindArgs[argIndex])
40✔
37
                        }
40✔
38
                }
39

40
                // If there is a smaller group that is a subset of this group
41
                // we add the smaller group to this group's children
42
                for smallGroupIndex, smallerGroup := range groupArgs[:groupIndex] {
32✔
43
                        // Do not add empty groups
4✔
44
                        if len(groupArgs[smallGroupIndex].Children) == 0 {
4✔
45
                                continue
×
46
                        }
47

48
                        // So we don't add the same group to multiple groups
49
                        if groupIsInGroup[smallGroupIndex] {
4✔
50
                                continue
×
51
                        }
52

53
                        if group.Positions[0][0] <= smallerGroup.Positions[0][0] &&
4✔
54
                                smallerGroup.Positions[0][1] <= group.Positions[0][1] {
4✔
55
                                groupChildren = append(groupChildren, groupArgs[smallGroupIndex])
×
56
                                groupIsInGroup[smallGroupIndex] = true
×
57
                                continue
×
58
                        }
59
                }
60

61
                // If there are no children, we can skip this group
62
                if len(groupChildren) == 0 {
28✔
63
                        continue
×
64
                }
65

66
                sortAndFixNames(groupChildren)
28✔
67
                groupArgs[groupIndex].Children = groupChildren
28✔
68
        }
69

70
        allArgs := make([]drivers.QueryArg, 0, len(bindArgs)+len(groupArgs))
32✔
71
        for i, arg := range bindArgs {
84✔
72
                if argIsInGroup[i] {
92✔
73
                        continue
40✔
74
                }
75
                allArgs = append(allArgs, arg)
12✔
76
        }
77

78
        for i, group := range groupArgs {
60✔
79
                if groupIsInGroup[i] {
28✔
80
                        continue
×
81
                }
82

83
                switch len(group.Children) {
28✔
84
                case 0:
×
85
                        // Do nothing
×
86
                        continue
×
87
                case 1:
16✔
88
                        if !group.CanBeMultiple {
32✔
89
                                allArgs = append(allArgs, group.Children[0])
16✔
90
                                continue
16✔
UNCOV
91
                        } else if !group.Children[0].CanBeMultiple {
×
92
                                group.Children = group.Children[0].Children
×
UNCOV
93
                        }
×
UNCOV
94
                        fallthrough
×
95
                default:
12✔
96
                        allArgs = append(allArgs, group)
12✔
97
                }
98
        }
99

100
        sortAndFixNames(allArgs)
32✔
101
        return allArgs
32✔
102
}
103

104
func sortAndFixNames(args []drivers.QueryArg) {
60✔
105
        // Sort the args by their original position
60✔
106
        sortArgsByPosition(args)
60✔
107

60✔
108
        // Fix duplicate arg names
60✔
109
        fixDuplicateArgNames(args)
60✔
110
}
60✔
111

112
func sortArgsByPosition(args []drivers.QueryArg) {
60✔
113
        slices.SortStableFunc(args, func(a, b drivers.QueryArg) int {
80✔
114
                beginningDiff := int(a.Positions[0][0] - b.Positions[0][0])
20✔
115
                if beginningDiff == 0 {
20✔
UNCOV
116
                        return int(a.Positions[0][1] - b.Positions[0][1])
×
UNCOV
117
                }
×
118
                return beginningDiff
20✔
119
        })
120
}
121

122
func fixDuplicateArgNames(args []drivers.QueryArg) {
60✔
123
        names := make(map[string]int, len(args))
60✔
124
        for i := range args {
140✔
125
                if args[i].Col.Name == "" {
80✔
UNCOV
126
                        continue
×
127
                }
128
                name := args[i].Col.Name
80✔
129
                index := names[name]
80✔
130
                names[name] = index + 1
80✔
131
                if index > 0 {
80✔
UNCOV
132
                        args[i].Col.Name = fmt.Sprintf("%s_%d", name, index+1)
×
UNCOV
133
                }
×
134
        }
135
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc