nginx-proxy-manager/backend/internal/entity/lists_query.go

81 lines
2.2 KiB
Go

package entity
import (
"fmt"
"reflect"
"strings"
"npm/internal/database"
"npm/internal/model"
)
// ListQueryBuilder should be able to return the query and params to get items agnostically based
// on given params.
func ListQueryBuilder(modelExample interface{}, tableName string, pageInfo *model.PageInfo, defaultSort model.Sort, filters []model.Filter, filterMapFunctions map[string]FilterMapFunction, returnCount bool) (string, []interface{}) {
var queryStrings []string
var whereStrings []string
var params []interface{}
if returnCount {
queryStrings = append(queryStrings, "SELECT COUNT(*)")
} else {
queryStrings = append(queryStrings, "SELECT *")
}
// nolint: gosec
queryStrings = append(queryStrings, fmt.Sprintf("FROM `%s`", tableName))
// Append filters to where clause:
if filters != nil {
filterMap := GetFilterMap(modelExample)
filterQuery, filterParams := GenerateSQLFromFilters(filters, filterMap, filterMapFunctions)
whereStrings = []string{filterQuery}
params = append(params, filterParams...)
}
// Add is deletee check if model has the field
if hasDeletedField(modelExample) {
params = append(params, 0)
whereStrings = append(whereStrings, "`is_deleted` = ?")
}
// Append where clauses to query
if len(whereStrings) > 0 {
// nolint: gosec
queryStrings = append(queryStrings, fmt.Sprintf("WHERE %s", strings.Join(whereStrings, " AND ")))
}
if !returnCount {
var orderBy string
columns := GetDBColumns(modelExample)
orderBy, pageInfo.Sort = database.BuildOrderBySQL(columns, &pageInfo.Sort)
if orderBy != "" {
queryStrings = append(queryStrings, orderBy)
} else {
pageInfo.Sort = append(pageInfo.Sort, defaultSort)
queryStrings = append(queryStrings, fmt.Sprintf("ORDER BY `%v` COLLATE NOCASE %v", defaultSort.Field, defaultSort.Direction))
}
params = append(params, pageInfo.Offset)
params = append(params, pageInfo.Limit)
queryStrings = append(queryStrings, "LIMIT ?, ?")
}
return strings.Join(queryStrings, " "), params
}
func hasDeletedField(modelExample interface{}) bool {
t := reflect.TypeOf(modelExample)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
dbTag := field.Tag.Get(DBTagName)
if dbTag == "is_deleted" {
return true
}
}
return false
}