@@ -45,18 +45,18 @@ func NewAppListingRepositoryQueryBuilder(logger *zap.SugaredLogger) AppListingRe
4545}
4646
4747type AppListingFilter struct {
48- Environments []int `json:"environments"`
49- Statuses []string `json:"statutes"`
50- Teams []int `json:"teams"`
51- AppStatuses []string `json:"appStatuses"`
52- TagFilters []TagFilter `json:"tagFilters"`
53- AppNameSearch string `json:"appNameSearch"`
54- SortOrder SortOrder `json:"sortOrder"`
55- SortBy SortBy `json:"sortBy"`
56- Offset int `json:"offset"`
57- Size int `json:"size"`
58- DeploymentGroupId int `json:"deploymentGroupId"`
59- AppIds []int `json:"-"` // internal use only
48+ Environments []int `json:"environments"`
49+ Statuses []string `json:"statutes"`
50+ Teams []int `json:"teams"`
51+ AppStatuses []string `json:"appStatuses"`
52+ TagFilters * []TagFilter `json:"tagFilters"`
53+ AppNameSearch string `json:"appNameSearch"`
54+ SortOrder SortOrder `json:"sortOrder"`
55+ SortBy SortBy `json:"sortBy"`
56+ Offset int `json:"offset"`
57+ Size int `json:"size"`
58+ DeploymentGroupId int `json:"deploymentGroupId"`
59+ AppIds []int `json:"-"` // internal use only
6060}
6161
6262type SortBy string
@@ -170,14 +170,17 @@ func getAppListingCommonQueryString() string {
170170 " LEFT JOIN app_status aps on aps.app_id = a.id and p.environment_id = aps.env_id "
171171}
172172
173- func (impl AppListingRepositoryQueryBuilder ) GetQueryForAppEnvContainers (appListingFilter AppListingFilter ) (string , []interface {}) {
173+ func (impl AppListingRepositoryQueryBuilder ) GetQueryForAppEnvContainers (appListingFilter AppListingFilter ) (string , []interface {}, error ) {
174174 query := "SELECT p.environment_id , a.id AS app_id, a.app_name,p.id as pipeline_id, a.team_id ,aps.status as app_status "
175- queryTemp , queryParams := impl .TestForCommonAppFilter (appListingFilter )
175+ queryTemp , queryParams , err := impl .TestForCommonAppFilter (appListingFilter )
176+ if err != nil {
177+ return "" , nil , err
178+ }
176179 query += queryTemp
177- return query , queryParams
180+ return query , queryParams , nil
178181}
179182
180- func (impl AppListingRepositoryQueryBuilder ) CommonJoinSubQuery (appListingFilter AppListingFilter ) (string , []interface {}) {
183+ func (impl AppListingRepositoryQueryBuilder ) CommonJoinSubQuery (appListingFilter AppListingFilter ) (string , []interface {}, error ) {
181184 var queryParams []interface {}
182185 query := ` LEFT JOIN pipeline p ON a.id=p.app_id and p.deleted=?
183186 LEFT JOIN deployment_config dc ON ( p.app_id=dc.app_id and p.environment_id=dc.environment_id and dc.active=? )
@@ -186,16 +189,22 @@ func (impl AppListingRepositoryQueryBuilder) CommonJoinSubQuery(appListingFilter
186189 if appListingFilter .DeploymentGroupId != 0 {
187190 query = query + " INNER JOIN deployment_group_app dga ON a.id = dga.app_id "
188191 }
189- whereCondition , whereConditionParams := impl .buildAppListingWhereCondition (appListingFilter )
192+ whereCondition , whereConditionParams , err := impl .buildAppListingWhereCondition (appListingFilter )
193+ if err != nil {
194+ return "" , nil , err
195+ }
190196 query = query + whereCondition
191197 queryParams = append (queryParams , whereConditionParams ... )
192- return query , queryParams
198+ return query , queryParams , nil
193199}
194200
195- func (impl AppListingRepositoryQueryBuilder ) TestForCommonAppFilter (appListingFilter AppListingFilter ) (string , []interface {}) {
196- queryTemp , queryParams := impl .CommonJoinSubQuery (appListingFilter )
201+ func (impl AppListingRepositoryQueryBuilder ) TestForCommonAppFilter (appListingFilter AppListingFilter ) (string , []interface {}, error ) {
202+ queryTemp , queryParams , err := impl .CommonJoinSubQuery (appListingFilter )
203+ if err != nil {
204+ return "" , nil , err
205+ }
197206 query := " FROM app a " + queryTemp
198- return query , queryParams
207+ return query , queryParams , nil
199208}
200209
201210func (impl AppListingRepositoryQueryBuilder ) BuildAppListingQueryLastDeploymentTimeV2 (pipelineIDs []int ) (string , []interface {}) {
@@ -211,8 +220,11 @@ func (impl AppListingRepositoryQueryBuilder) BuildAppListingQueryLastDeploymentT
211220 return query , queryParams
212221}
213222
214- func (impl AppListingRepositoryQueryBuilder ) GetAppIdsQueryWithPaginationForLastDeployedSearch (appListingFilter AppListingFilter ) (string , []interface {}) {
215- join , queryParams := impl .CommonJoinSubQuery (appListingFilter )
223+ func (impl AppListingRepositoryQueryBuilder ) GetAppIdsQueryWithPaginationForLastDeployedSearch (appListingFilter AppListingFilter ) (string , []interface {}, error ) {
224+ join , queryParams , err := impl .CommonJoinSubQuery (appListingFilter )
225+ if err != nil {
226+ return "" , nil , err
227+ }
216228 countQuery := " (SELECT count(distinct(a.id)) as count FROM app a " + join + ") AS total_count "
217229 // appending query params for count query as well
218230 queryParams = append (queryParams , queryParams ... )
@@ -234,12 +246,15 @@ func (impl AppListingRepositoryQueryBuilder) GetAppIdsQueryWithPaginationForLast
234246 }
235247 query += " LIMIT ? OFFSET ? "
236248 queryParams = append (queryParams , appListingFilter .Size , appListingFilter .Offset )
237- return query , queryParams
249+ return query , queryParams , nil
238250}
239251
240- func (impl AppListingRepositoryQueryBuilder ) GetAppIdsQueryWithPaginationForAppNameSearch (appListingFilter AppListingFilter ) (string , []interface {}) {
252+ func (impl AppListingRepositoryQueryBuilder ) GetAppIdsQueryWithPaginationForAppNameSearch (appListingFilter AppListingFilter ) (string , []interface {}, error ) {
241253 orderByClause := impl .buildAppListingSortBy (appListingFilter )
242- join , queryParams := impl .CommonJoinSubQuery (appListingFilter )
254+ join , queryParams , err := impl .CommonJoinSubQuery (appListingFilter )
255+ if err != nil {
256+ return "" , nil , err
257+ }
243258 countQuery := "( SELECT count(distinct(a.id)) as count FROM app a" + join + " ) as total_count"
244259 query := "SELECT DISTINCT(a.id) as app_id, a.app_name, " + countQuery +
245260 " FROM app a " + join
@@ -250,7 +265,7 @@ func (impl AppListingRepositoryQueryBuilder) GetAppIdsQueryWithPaginationForAppN
250265 //adding queryParams two times because join query is used in countQuery and mainQuery two times
251266 queryParams = append (queryParams , queryParams ... )
252267 queryParams = append (queryParams , appListingFilter .Size , appListingFilter .Offset )
253- return query , queryParams
268+ return query , queryParams , nil
254269}
255270
256271func (impl AppListingRepositoryQueryBuilder ) buildAppListingSortBy (appListingFilter AppListingFilter ) string {
@@ -263,7 +278,7 @@ func (impl AppListingRepositoryQueryBuilder) buildAppListingSortBy(appListingFil
263278 return orderByCondition
264279}
265280
266- func (impl AppListingRepositoryQueryBuilder ) buildAppListingWhereCondition (appListingFilter AppListingFilter ) (string , []interface {}) {
281+ func (impl AppListingRepositoryQueryBuilder ) buildAppListingWhereCondition (appListingFilter AppListingFilter ) (string , []interface {}, error ) {
267282 var queryParams []interface {}
268283 whereCondition := " WHERE a.active = ? and a.app_type = ? "
269284 queryParams = append (queryParams , true , CustomApp )
@@ -313,30 +328,39 @@ func (impl AppListingRepositoryQueryBuilder) buildAppListingWhereCondition(appLi
313328 }
314329 // Tag filters are AND-combined for now as requested by product.
315330 // Each row translates to a correlated EXISTS/NOT EXISTS on app_label.
316- tagWhereCondition , tagQueryParams := impl .buildTagFiltersWhereConditionAND (appListingFilter .TagFilters )
331+ tagWhereCondition , tagQueryParams , err := impl .buildTagFiltersWhereConditionAND (appListingFilter .TagFilters )
332+ if err != nil {
333+ return "" , nil , err
334+ }
317335 whereCondition += tagWhereCondition
318- queryParams = append (queryParams , tagQueryParams ... )
336+ if len (tagQueryParams ) > 0 {
337+ queryParams = append (queryParams , tagQueryParams ... )
338+ }
319339
320340 if len (appListingFilter .AppIds ) > 0 {
321341 whereCondition += " and a.id IN (?) "
322342 queryParams = append (queryParams , pg .In (appListingFilter .AppIds ))
323343 }
324- return whereCondition , queryParams
344+
345+ return whereCondition , queryParams , nil
325346}
326347
327- func (impl AppListingRepositoryQueryBuilder ) buildTagFiltersWhereConditionAND (tagFilters []TagFilter ) (string , []interface {}) {
328- if len (tagFilters ) == 0 {
329- return "" , nil
348+ func (impl AppListingRepositoryQueryBuilder ) buildTagFiltersWhereConditionAND (tagFilters * []TagFilter ) (string , []interface {}, error ) {
349+ if tagFilters == nil || len (* tagFilters ) == 0 {
350+ return "" , make ([] interface {}, 0 ), nil
330351 }
331352 var queryBuilder strings.Builder
332- queryParams := make ([]interface {}, 0 , len (tagFilters )* 2 )
333- for _ , tagFilter := range tagFilters {
334- predicate , predicateParams := impl .buildTagFilterPredicate (tagFilter )
353+ queryParams := make ([]interface {}, 0 , len (* tagFilters )* 2 )
354+ for _ , tagFilter := range * tagFilters {
355+ predicate , predicateParams , err := impl .buildTagFilterPredicate (tagFilter )
356+ if err != nil {
357+ return "" , nil , err
358+ }
335359 queryBuilder .WriteString (" and " )
336360 queryBuilder .WriteString (predicate )
337361 queryParams = append (queryParams , predicateParams ... )
338362 }
339- return queryBuilder .String (), queryParams
363+ return queryBuilder .String (), queryParams , nil
340364}
341365
342366// buildTagFilterPredicate converts one UI tag filter row into a SQL predicate.
@@ -347,38 +371,36 @@ func (impl AppListingRepositoryQueryBuilder) buildTagFiltersWhereConditionAND(ta
347371// - DOES_NOT_CONTAIN: key exists with at least one value not containing target substring.
348372// - EXISTS: key exists.
349373// - DOES_NOT_EXIST: key does not exist.
350- func (impl AppListingRepositoryQueryBuilder ) buildTagFilterPredicate (tagFilter TagFilter ) (string , []interface {}) {
374+ func (impl AppListingRepositoryQueryBuilder ) buildTagFilterPredicate (tagFilter TagFilter ) (string , []interface {}, error ) {
351375 value := ""
352376 if tagFilter .Value != nil {
353377 value = * tagFilter .Value
354378 }
355379 switch tagFilter .Operator {
356380 case TagFilterOperatorEquals :
357381 return "EXISTS (SELECT 1 FROM app_label al WHERE al.app_id = a.id and al.key = ? and al.value = ?)" ,
358- []interface {}{tagFilter .Key , value }
382+ []interface {}{tagFilter .Key , value }, nil
359383 case TagFilterOperatorDoesNotEqual :
360384 // Best-practice semantics for multi-value keys:
361385 // include app when key exists and at least one value is different from target.
362386 return "EXISTS (SELECT 1 FROM app_label al WHERE al.app_id = a.id and al.key = ? and al.value <> ?)" ,
363- []interface {}{tagFilter .Key , value }
387+ []interface {}{tagFilter .Key , value }, nil
364388 case TagFilterOperatorContains :
365389 return "EXISTS (SELECT 1 FROM app_label al WHERE al.app_id = a.id and al.key = ? and al.value LIKE ? ESCAPE '\\ ')" ,
366- []interface {}{tagFilter .Key , buildContainsPattern (value )}
390+ []interface {}{tagFilter .Key , buildContainsPattern (value )}, nil
367391 case TagFilterOperatorDoesNotContain :
368392 // Best-practice semantics for multi-value keys:
369393 // include app when key exists and at least one value does not contain target.
370394 return "EXISTS (SELECT 1 FROM app_label al WHERE al.app_id = a.id and al.key = ? and al.value NOT LIKE ? ESCAPE '\\ ')" ,
371- []interface {}{tagFilter .Key , buildContainsPattern (value )}
395+ []interface {}{tagFilter .Key , buildContainsPattern (value )}, nil
372396 case TagFilterOperatorExists :
373397 return "EXISTS (SELECT 1 FROM app_label al WHERE al.app_id = a.id and al.key = ?)" ,
374- []interface {}{tagFilter .Key }
398+ []interface {}{tagFilter .Key }, nil
375399 case TagFilterOperatorDoesNotExist :
376400 return "NOT EXISTS (SELECT 1 FROM app_label al WHERE al.app_id = a.id and al.key = ?)" ,
377- []interface {}{tagFilter .Key }
401+ []interface {}{tagFilter .Key }, nil
378402 default :
379- // Invalid operator should never reach here due request validation.
380- // Returning false condition keeps query safe if validation is bypassed.
381- return "1 = 0" , nil
403+ return "" , nil , fmt .Errorf ("unsupported tag filter operator: %s" , tagFilter .Operator )
382404 }
383405}
384406
0 commit comments