@@ -48,6 +48,7 @@ func run(out io.Writer, cfg Config) error {
4848 }
4949 ql := & queryList {
5050 queries : make (map [string ]* QueryAnalysisResult ),
51+ failed : make (map [string ]* QueryFailedResult ),
5152 }
5253 queries , err := cfg .Loader .Load (cfg .FileName )
5354 if err != nil {
@@ -78,11 +79,7 @@ func run(out io.Writer, cfg Config) error {
7879func process (q data.Query , si * schemaInfo , ql * queryList ) {
7980 ast , bv , err := sqlparser .NewTestParser ().Parse2 (q .Query )
8081 if err != nil {
81- ql .failed = append (ql .failed , QueryFailedResult {
82- Query : q .Query ,
83- LineNumber : q .Line ,
84- Error : err .Error (),
85- })
82+ ql .addFailedQuery (q , err )
8683 return
8784 }
8885
@@ -102,40 +99,28 @@ type Output struct {
10299
103100type queryList struct {
104101 queries map [string ]* QueryAnalysisResult
105- failed [] QueryFailedResult
102+ failed map [ string ] * QueryFailedResult
106103}
107104
108105func (ql * queryList ) processQuery (si * schemaInfo , ast sqlparser.Statement , q data.Query , bv sqlparser.BindVars ) {
109106 // handle panics
110107 defer func () {
111108 if r := recover (); r != nil {
112- ql .failed = append (ql .failed , QueryFailedResult {
113- Query : q .Query ,
114- LineNumber : q .Line ,
115- Error : fmt .Sprintf ("panic: %v" , r ),
116- })
109+ ql .addFailedQuery (q , fmt .Errorf ("panic: %v" , r ))
117110 }
118111 }()
119112
120113 mapBv := make (map [string ]* querypb.BindVariable )
121114 reservedVars := sqlparser .NewReservedVars ("" , bv )
122115 err := sqlparser .Normalize (ast , reservedVars , mapBv )
123116 if err != nil {
124- ql .failed = append (ql .failed , QueryFailedResult {
125- Query : q .Query ,
126- LineNumber : q .Line ,
127- Error : err .Error (),
128- })
117+ ql .addFailedQuery (q , err )
129118 return
130119 }
131120
132121 st , err := semantics .Analyze (ast , "ks" , si )
133122 if err != nil {
134- ql .failed = append (ql .failed , QueryFailedResult {
135- Query : q .Query ,
136- LineNumber : q .Line ,
137- Error : err .Error (),
138- })
123+ ql .addFailedQuery (q , err )
139124 return
140125 }
141126 ctx := & plancontext.PlanningContext {
@@ -173,20 +158,40 @@ func (ql *queryList) processQuery(si *schemaInfo, ast sqlparser.Statement, q dat
173158 }
174159}
175160
161+ func (ql * queryList ) addFailedQuery (q data.Query , err error ) {
162+ key := q .Query + err .Error ()
163+ if v , exists := ql .failed [key ]; exists {
164+ v .LineNumbers = append (v .LineNumbers , q .Line )
165+ } else {
166+ ql .failed [key ] = & QueryFailedResult {
167+ Query : q .Query ,
168+ LineNumbers : []int {q .Line },
169+ Error : err .Error (),
170+ }
171+ }
172+ }
173+
176174// writeJsonTo writes the query list, sorted by the first line number of the query, to the given writer.
177175func (ql * queryList ) writeJSONTo (w io.Writer ) error {
178176 values := make ([]QueryAnalysisResult , 0 , len (ql .queries ))
179177 for _ , result := range ql .queries {
180178 values = append (values , * result )
181179 }
182-
183180 sort .Slice (values , func (i , j int ) bool {
184181 return values [i ].LineNumbers [0 ] < values [j ].LineNumbers [0 ]
185182 })
186183
184+ failedQueries := make ([]QueryFailedResult , 0 , len (ql .failed ))
185+ for _ , result := range ql .failed {
186+ failedQueries = append (failedQueries , * result )
187+ }
188+ sort .Slice (failedQueries , func (i , j int ) bool {
189+ return failedQueries [i ].LineNumbers [0 ] < failedQueries [j ].LineNumbers [0 ]
190+ })
191+
187192 res := Output {
188193 Queries : values ,
189- Failed : ql . failed ,
194+ Failed : failedQueries ,
190195 }
191196
192197 jsonData , err := json .MarshalIndent (res , " " , " " )
@@ -216,7 +221,7 @@ type QueryAnalysisResult struct {
216221}
217222
218223type QueryFailedResult struct {
219- Query string `json:"query"`
220- LineNumber int `json:"lineNumber "`
221- Error string `json:"error"`
224+ Query string `json:"query"`
225+ LineNumbers [] int `json:"lineNumbers "`
226+ Error string `json:"error"`
222227}
0 commit comments