gotosocial/vendor/github.com/uptrace/bun/query_values.go
tobi 07727753b9
[feature] Clean up/uncache remote media (#407)
* Add whereNotEmptyAndNotNull

* Add GetRemoteOlderThanDays

* Add GetRemoteOlderThanDays

* Add PruneRemote to Manager interface

* Start implementing PruneRemote

* add new attachment + status to tests

* fix up and test GetRemoteOlderThan

* fix bad import

* PruneRemote: return number pruned

* add Cached column to mediaattachment

* update + test pruneRemote

* update mediaTest

* use Cached column

* upstep bun to latest version

* embed structs in mediaAttachment

* migrate mediaAttachment to new format

* don't default cached to true

* select only remote media

* update db dependencies

* step bun back to last working version

* update pruneRemote to use Cached field

* fix storage path of test attachments

* add recache logic to manager

* fix trimmed aspect ratio

* test prune and recache

* return errwithcode

* tidy up different paths for emoji vs attachment

* fix incorrect thumbnail type being stored

* expose TransportController to media processor

* implement tee-ing recached content

* add thoughts of dog to test fedi attachments

* test get remote files

* add comment on PruneRemote

* add postData cleanup to recache

* test thumbnail fetching

* add incredible diagram

* go mod tidy

* buffer pipes for recache streaming

* test for client stops reading after 1kb

* add media-remote-cache-days to config

* add cron package

* wrap logrus so it's available to cron

* start and stop cron jobs gracefully
2022-03-07 11:08:26 +01:00

216 lines
4 KiB
Go

package bun
import (
"fmt"
"reflect"
"strconv"
"github.com/uptrace/bun/dialect/feature"
"github.com/uptrace/bun/schema"
)
type ValuesQuery struct {
baseQuery
customValueQuery
withOrder bool
}
var (
_ Query = (*ValuesQuery)(nil)
_ schema.NamedArgAppender = (*ValuesQuery)(nil)
)
func NewValuesQuery(db *DB, model interface{}) *ValuesQuery {
q := &ValuesQuery{
baseQuery: baseQuery{
db: db,
conn: db.DB,
},
}
q.setTableModel(model)
return q
}
func (q *ValuesQuery) Conn(db IConn) *ValuesQuery {
q.setConn(db)
return q
}
// Value overwrites model value for the column.
func (q *ValuesQuery) Value(column string, expr string, args ...interface{}) *ValuesQuery {
if q.table == nil {
q.err = errNilModel
return q
}
q.addValue(q.table, column, expr, args)
return q
}
func (q *ValuesQuery) WithOrder() *ValuesQuery {
q.withOrder = true
return q
}
func (q *ValuesQuery) AppendNamedArg(fmter schema.Formatter, b []byte, name string) ([]byte, bool) {
switch name {
case "Columns":
bb, err := q.AppendColumns(fmter, b)
if err != nil {
q.setErr(err)
return b, true
}
return bb, true
}
return b, false
}
// AppendColumns appends the table columns. It is used by CTE.
func (q *ValuesQuery) AppendColumns(fmter schema.Formatter, b []byte) (_ []byte, err error) {
if q.err != nil {
return nil, q.err
}
if q.model == nil {
return nil, errNilModel
}
if q.tableModel != nil {
fields, err := q.getFields()
if err != nil {
return nil, err
}
b = appendColumns(b, "", fields)
if q.withOrder {
b = append(b, ", _order"...)
}
return b, nil
}
switch model := q.model.(type) {
case *mapSliceModel:
return model.appendColumns(fmter, b)
}
return nil, fmt.Errorf("bun: Values does not support %T", q.model)
}
func (q *ValuesQuery) Operation() string {
return "SELECT"
}
func (q *ValuesQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte, err error) {
if q.err != nil {
return nil, q.err
}
if q.model == nil {
return nil, errNilModel
}
fmter = formatterWithModel(fmter, q)
if q.tableModel != nil {
fields, err := q.getFields()
if err != nil {
return nil, err
}
return q.appendQuery(fmter, b, fields)
}
switch model := q.model.(type) {
case *mapSliceModel:
return model.appendValues(fmter, b)
}
return nil, fmt.Errorf("bun: Values does not support %T", q.model)
}
func (q *ValuesQuery) appendQuery(
fmter schema.Formatter,
b []byte,
fields []*schema.Field,
) (_ []byte, err error) {
b = append(b, "VALUES "...)
if q.db.features.Has(feature.ValuesRow) {
b = append(b, "ROW("...)
} else {
b = append(b, '(')
}
switch model := q.tableModel.(type) {
case *structTableModel:
b, err = q.appendValues(fmter, b, fields, model.strct)
if err != nil {
return nil, err
}
if q.withOrder {
b = append(b, ", "...)
b = strconv.AppendInt(b, 0, 10)
}
case *sliceTableModel:
slice := model.slice
sliceLen := slice.Len()
for i := 0; i < sliceLen; i++ {
if i > 0 {
b = append(b, "), "...)
if q.db.features.Has(feature.ValuesRow) {
b = append(b, "ROW("...)
} else {
b = append(b, '(')
}
}
b, err = q.appendValues(fmter, b, fields, slice.Index(i))
if err != nil {
return nil, err
}
if q.withOrder {
b = append(b, ", "...)
b = strconv.AppendInt(b, int64(i), 10)
}
}
default:
return nil, fmt.Errorf("bun: Values does not support %T", q.model)
}
b = append(b, ')')
return b, nil
}
func (q *ValuesQuery) appendValues(
fmter schema.Formatter, b []byte, fields []*schema.Field, strct reflect.Value,
) (_ []byte, err error) {
isTemplate := fmter.IsNop()
for i, f := range fields {
if i > 0 {
b = append(b, ", "...)
}
app, ok := q.modelValues[f.Name]
if ok {
b, err = app.AppendQuery(fmter, b)
if err != nil {
return nil, err
}
continue
}
if isTemplate {
b = append(b, '?')
} else {
b = f.AppendValue(fmter, b, indirect(strct))
}
if fmter.HasFeature(feature.DoubleColonCast) {
b = append(b, "::"...)
b = append(b, f.UserSQLType...)
}
}
return b, nil
}