2022-11-04 14:30:22 -07:00
|
|
|
package sqlstash
|
|
|
|
|
|
2023-11-03 10:30:52 -04:00
|
|
|
import (
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
|
|
|
|
)
|
2022-11-04 14:30:22 -07:00
|
|
|
|
2024-02-07 15:05:10 -05:00
|
|
|
type Direction int
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
Ascending Direction = iota
|
|
|
|
|
Descending
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func (d Direction) String() string {
|
|
|
|
|
if d == Descending {
|
|
|
|
|
return "DESC"
|
|
|
|
|
}
|
|
|
|
|
return "ASC"
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-04 14:30:22 -07:00
|
|
|
type selectQuery struct {
|
2023-11-03 10:30:52 -04:00
|
|
|
dialect migrator.Dialect
|
2022-11-04 14:30:22 -07:00
|
|
|
fields []string // SELECT xyz
|
|
|
|
|
from string // FROM object
|
2024-02-07 15:05:10 -05:00
|
|
|
offset int64
|
2023-03-07 07:54:25 -08:00
|
|
|
limit int64
|
2022-11-04 14:30:22 -07:00
|
|
|
oneExtra bool
|
|
|
|
|
|
|
|
|
|
where []string
|
2023-08-30 08:46:47 -07:00
|
|
|
args []any
|
2024-02-07 15:05:10 -05:00
|
|
|
|
|
|
|
|
orderBy []string
|
|
|
|
|
direction []Direction
|
2022-11-04 14:30:22 -07:00
|
|
|
}
|
|
|
|
|
|
2023-11-03 10:30:52 -04:00
|
|
|
func (q *selectQuery) addWhere(f string, val ...any) {
|
|
|
|
|
q.args = append(q.args, val...)
|
|
|
|
|
// if the field contains a question mark, we assume it's a raw where clause
|
|
|
|
|
if strings.Contains(f, "?") {
|
|
|
|
|
q.where = append(q.where, f)
|
|
|
|
|
// otherwise we assume it's a field name
|
|
|
|
|
} else {
|
|
|
|
|
q.where = append(q.where, q.dialect.Quote(f)+"=?")
|
|
|
|
|
}
|
2022-11-04 14:30:22 -07:00
|
|
|
}
|
|
|
|
|
|
2023-08-30 08:46:47 -07:00
|
|
|
func (q *selectQuery) addWhereInSubquery(f string, subquery string, subqueryArgs []any) {
|
2022-12-06 23:21:12 +04:00
|
|
|
q.args = append(q.args, subqueryArgs...)
|
2023-11-03 10:30:52 -04:00
|
|
|
q.where = append(q.where, q.dialect.Quote(f)+" IN ("+subquery+")")
|
2022-12-06 23:21:12 +04:00
|
|
|
}
|
|
|
|
|
|
2022-11-04 14:30:22 -07:00
|
|
|
func (q *selectQuery) addWhereIn(f string, vals []string) {
|
|
|
|
|
count := len(vals)
|
|
|
|
|
if count > 1 {
|
|
|
|
|
sb := strings.Builder{}
|
2023-11-03 10:30:52 -04:00
|
|
|
sb.WriteString(q.dialect.Quote(f))
|
2022-11-04 14:30:22 -07:00
|
|
|
sb.WriteString(" IN (")
|
|
|
|
|
for i := 0; i < count; i++ {
|
|
|
|
|
if i > 0 {
|
|
|
|
|
sb.WriteString(",")
|
|
|
|
|
}
|
|
|
|
|
sb.WriteString("?")
|
|
|
|
|
q.args = append(q.args, vals[i])
|
|
|
|
|
}
|
|
|
|
|
sb.WriteString(") ")
|
|
|
|
|
q.where = append(q.where, sb.String())
|
|
|
|
|
} else if count == 1 {
|
|
|
|
|
q.addWhere(f, vals[0])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-07 15:05:10 -05:00
|
|
|
func (q *selectQuery) addOrderBy(field string, direction Direction) {
|
|
|
|
|
q.orderBy = append(q.orderBy, field)
|
|
|
|
|
q.direction = append(q.direction, direction)
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-30 08:46:47 -07:00
|
|
|
func (q *selectQuery) toQuery() (string, []any) {
|
2022-11-04 14:30:22 -07:00
|
|
|
args := q.args
|
|
|
|
|
sb := strings.Builder{}
|
|
|
|
|
sb.WriteString("SELECT ")
|
2023-11-03 10:30:52 -04:00
|
|
|
quotedFields := make([]string, len(q.fields))
|
|
|
|
|
for i, f := range q.fields {
|
|
|
|
|
quotedFields[i] = q.dialect.Quote(f)
|
|
|
|
|
}
|
|
|
|
|
sb.WriteString(strings.Join(quotedFields, ","))
|
2022-11-04 14:30:22 -07:00
|
|
|
sb.WriteString(" FROM ")
|
|
|
|
|
sb.WriteString(q.from)
|
|
|
|
|
|
|
|
|
|
// Templated where string
|
|
|
|
|
where := len(q.where)
|
|
|
|
|
if where > 0 {
|
|
|
|
|
sb.WriteString(" WHERE ")
|
|
|
|
|
for i := 0; i < where; i++ {
|
|
|
|
|
if i > 0 {
|
|
|
|
|
sb.WriteString(" AND ")
|
|
|
|
|
}
|
|
|
|
|
sb.WriteString(q.where[i])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-07 15:05:10 -05:00
|
|
|
if len(q.orderBy) > 0 && len(q.direction) == len(q.orderBy) {
|
|
|
|
|
sb.WriteString(" ORDER BY ")
|
|
|
|
|
for i, f := range q.orderBy {
|
|
|
|
|
if i > 0 {
|
|
|
|
|
sb.WriteString(",")
|
|
|
|
|
}
|
|
|
|
|
sb.WriteString(q.dialect.Quote(f))
|
|
|
|
|
sb.WriteString(" ")
|
|
|
|
|
sb.WriteString(q.direction[i].String())
|
2022-11-04 14:30:22 -07:00
|
|
|
}
|
|
|
|
|
}
|
2024-02-07 15:05:10 -05:00
|
|
|
|
|
|
|
|
limit := q.limit
|
|
|
|
|
if limit < 1 {
|
|
|
|
|
limit = 20
|
|
|
|
|
q.limit = limit
|
|
|
|
|
}
|
|
|
|
|
if q.oneExtra {
|
|
|
|
|
limit = limit + 1
|
|
|
|
|
}
|
|
|
|
|
sb.WriteString(q.dialect.LimitOffset(limit, q.offset))
|
|
|
|
|
|
2022-11-04 14:30:22 -07:00
|
|
|
return sb.String(), args
|
|
|
|
|
}
|