mirror of https://github.com/stashapp/stash.git
246 lines
7.9 KiB
Go
246 lines
7.9 KiB
Go
![]() |
package goqu
|
||
|
|
||
|
import (
|
||
|
"github.com/doug-martin/goqu/v9/exec"
|
||
|
"github.com/doug-martin/goqu/v9/exp"
|
||
|
"github.com/doug-martin/goqu/v9/internal/errors"
|
||
|
"github.com/doug-martin/goqu/v9/internal/sb"
|
||
|
)
|
||
|
|
||
|
type UpdateDataset struct {
|
||
|
dialect SQLDialect
|
||
|
clauses exp.UpdateClauses
|
||
|
isPrepared prepared
|
||
|
queryFactory exec.QueryFactory
|
||
|
err error
|
||
|
}
|
||
|
|
||
|
var ErrUnsupportedUpdateTableType = errors.New("unsupported table type, a string or identifier expression is required")
|
||
|
|
||
|
// used internally by database to create a database with a specific adapter
|
||
|
func newUpdateDataset(d string, queryFactory exec.QueryFactory) *UpdateDataset {
|
||
|
return &UpdateDataset{
|
||
|
clauses: exp.NewUpdateClauses(),
|
||
|
dialect: GetDialect(d),
|
||
|
queryFactory: queryFactory,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Update(table interface{}) *UpdateDataset {
|
||
|
return newUpdateDataset("default", nil).Table(table)
|
||
|
}
|
||
|
|
||
|
// Set the parameter interpolation behavior. See examples
|
||
|
//
|
||
|
// prepared: If true the dataset WILL NOT interpolate the parameters.
|
||
|
func (ud *UpdateDataset) Prepared(prepared bool) *UpdateDataset {
|
||
|
ret := ud.copy(ud.clauses)
|
||
|
ret.isPrepared = preparedFromBool(prepared)
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
func (ud *UpdateDataset) IsPrepared() bool {
|
||
|
return ud.isPrepared.Bool()
|
||
|
}
|
||
|
|
||
|
// Sets the adapter used to serialize values and create the SQL statement
|
||
|
func (ud *UpdateDataset) WithDialect(dl string) *UpdateDataset {
|
||
|
ds := ud.copy(ud.GetClauses())
|
||
|
ds.dialect = GetDialect(dl)
|
||
|
return ds
|
||
|
}
|
||
|
|
||
|
// Returns the current adapter on the dataset
|
||
|
func (ud *UpdateDataset) Dialect() SQLDialect {
|
||
|
return ud.dialect
|
||
|
}
|
||
|
|
||
|
// Returns the current adapter on the dataset
|
||
|
func (ud *UpdateDataset) SetDialect(dialect SQLDialect) *UpdateDataset {
|
||
|
cd := ud.copy(ud.GetClauses())
|
||
|
cd.dialect = dialect
|
||
|
return cd
|
||
|
}
|
||
|
|
||
|
func (ud *UpdateDataset) Expression() exp.Expression {
|
||
|
return ud
|
||
|
}
|
||
|
|
||
|
// Clones the dataset
|
||
|
func (ud *UpdateDataset) Clone() exp.Expression {
|
||
|
return ud.copy(ud.clauses)
|
||
|
}
|
||
|
|
||
|
// Returns the current clauses on the dataset.
|
||
|
func (ud *UpdateDataset) GetClauses() exp.UpdateClauses {
|
||
|
return ud.clauses
|
||
|
}
|
||
|
|
||
|
// used internally to copy the dataset
|
||
|
func (ud *UpdateDataset) copy(clauses exp.UpdateClauses) *UpdateDataset {
|
||
|
return &UpdateDataset{
|
||
|
dialect: ud.dialect,
|
||
|
clauses: clauses,
|
||
|
isPrepared: ud.isPrepared,
|
||
|
queryFactory: ud.queryFactory,
|
||
|
err: ud.err,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Creates a WITH clause for a common table expression (CTE).
|
||
|
//
|
||
|
// The name will be available to use in the UPDATE from in the associated query; and can optionally
|
||
|
// contain a list of column names "name(col1, col2, col3)".
|
||
|
//
|
||
|
// The name will refer to the results of the specified subquery.
|
||
|
func (ud *UpdateDataset) With(name string, subquery exp.Expression) *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.CommonTablesAppend(exp.NewCommonTableExpression(false, name, subquery)))
|
||
|
}
|
||
|
|
||
|
// Creates a WITH RECURSIVE clause for a common table expression (CTE)
|
||
|
//
|
||
|
// The name will be available to use in the UPDATE from in the associated query; and must
|
||
|
// contain a list of column names "name(col1, col2, col3)" for a recursive clause.
|
||
|
//
|
||
|
// The name will refer to the results of the specified subquery. The subquery for
|
||
|
// a recursive query will always end with a UNION or UNION ALL with a clause that
|
||
|
// refers to the CTE by name.
|
||
|
func (ud *UpdateDataset) WithRecursive(name string, subquery exp.Expression) *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.CommonTablesAppend(exp.NewCommonTableExpression(true, name, subquery)))
|
||
|
}
|
||
|
|
||
|
// Sets the table to update.
|
||
|
func (ud *UpdateDataset) Table(table interface{}) *UpdateDataset {
|
||
|
switch t := table.(type) {
|
||
|
case exp.Expression:
|
||
|
return ud.copy(ud.clauses.SetTable(t))
|
||
|
case string:
|
||
|
return ud.copy(ud.clauses.SetTable(exp.ParseIdentifier(t)))
|
||
|
default:
|
||
|
panic(ErrUnsupportedUpdateTableType)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Sets the values to use in the SET clause. See examples.
|
||
|
func (ud *UpdateDataset) Set(values interface{}) *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.SetSetValues(values))
|
||
|
}
|
||
|
|
||
|
// Allows specifying other tables to reference in your update (If your dialect supports it). See examples.
|
||
|
func (ud *UpdateDataset) From(tables ...interface{}) *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.SetFrom(exp.NewColumnListExpression(tables...)))
|
||
|
}
|
||
|
|
||
|
// Adds a WHERE clause. See examples.
|
||
|
func (ud *UpdateDataset) Where(expressions ...exp.Expression) *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.WhereAppend(expressions...))
|
||
|
}
|
||
|
|
||
|
// Removes the WHERE clause. See examples.
|
||
|
func (ud *UpdateDataset) ClearWhere() *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.ClearWhere())
|
||
|
}
|
||
|
|
||
|
// Adds a ORDER clause. If the ORDER is currently set it replaces it. See examples.
|
||
|
func (ud *UpdateDataset) Order(order ...exp.OrderedExpression) *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.SetOrder(order...))
|
||
|
}
|
||
|
|
||
|
// Adds a more columns to the current ORDER BY clause. If no order has be previously specified it is the same as
|
||
|
// calling Order. See examples.
|
||
|
func (ud *UpdateDataset) OrderAppend(order ...exp.OrderedExpression) *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.OrderAppend(order...))
|
||
|
}
|
||
|
|
||
|
// Adds a more columns to the beginning of the current ORDER BY clause. If no order has be previously specified it is the same as
|
||
|
// calling Order. See examples.
|
||
|
func (ud *UpdateDataset) OrderPrepend(order ...exp.OrderedExpression) *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.OrderPrepend(order...))
|
||
|
}
|
||
|
|
||
|
// Removes the ORDER BY clause. See examples.
|
||
|
func (ud *UpdateDataset) ClearOrder() *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.ClearOrder())
|
||
|
}
|
||
|
|
||
|
// Adds a LIMIT clause. If the LIMIT is currently set it replaces it. See examples.
|
||
|
func (ud *UpdateDataset) Limit(limit uint) *UpdateDataset {
|
||
|
if limit > 0 {
|
||
|
return ud.copy(ud.clauses.SetLimit(limit))
|
||
|
}
|
||
|
return ud.copy(ud.clauses.ClearLimit())
|
||
|
}
|
||
|
|
||
|
// Adds a LIMIT ALL clause. If the LIMIT is currently set it replaces it. See examples.
|
||
|
func (ud *UpdateDataset) LimitAll() *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.SetLimit(L("ALL")))
|
||
|
}
|
||
|
|
||
|
// Removes the LIMIT clause.
|
||
|
func (ud *UpdateDataset) ClearLimit() *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.ClearLimit())
|
||
|
}
|
||
|
|
||
|
// Adds a RETURNING clause to the dataset if the adapter supports it. See examples.
|
||
|
func (ud *UpdateDataset) Returning(returning ...interface{}) *UpdateDataset {
|
||
|
return ud.copy(ud.clauses.SetReturning(exp.NewColumnListExpression(returning...)))
|
||
|
}
|
||
|
|
||
|
// Get any error that has been set or nil if no error has been set.
|
||
|
func (ud *UpdateDataset) Error() error {
|
||
|
return ud.err
|
||
|
}
|
||
|
|
||
|
// Set an error on the dataset if one has not already been set. This error will be returned by a future call to Error
|
||
|
// or as part of ToSQL. This can be used by end users to record errors while building up queries without having to
|
||
|
// track those separately.
|
||
|
func (ud *UpdateDataset) SetError(err error) *UpdateDataset {
|
||
|
if ud.err == nil {
|
||
|
ud.err = err
|
||
|
}
|
||
|
|
||
|
return ud
|
||
|
}
|
||
|
|
||
|
// Generates an UPDATE sql statement, if Prepared has been called with true then the parameters will not be interpolated.
|
||
|
// See examples.
|
||
|
//
|
||
|
// Errors:
|
||
|
// * There is an error generating the SQL
|
||
|
func (ud *UpdateDataset) ToSQL() (sql string, params []interface{}, err error) {
|
||
|
return ud.updateSQLBuilder().ToSQL()
|
||
|
}
|
||
|
|
||
|
// Appends this Dataset's UPDATE statement to the SQLBuilder
|
||
|
// This is used internally when using updates in CTEs
|
||
|
func (ud *UpdateDataset) AppendSQL(b sb.SQLBuilder) {
|
||
|
if ud.err != nil {
|
||
|
b.SetError(ud.err)
|
||
|
return
|
||
|
}
|
||
|
ud.dialect.ToUpdateSQL(b, ud.GetClauses())
|
||
|
}
|
||
|
|
||
|
func (ud *UpdateDataset) GetAs() exp.IdentifierExpression {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (ud *UpdateDataset) ReturnsColumns() bool {
|
||
|
return ud.clauses.HasReturning()
|
||
|
}
|
||
|
|
||
|
// Generates the UPDATE sql, and returns an exec.QueryExecutor with the sql set to the UPDATE statement
|
||
|
// db.Update("test").Set(Record{"name":"Bob", update: time.Now()}).Executor()
|
||
|
func (ud *UpdateDataset) Executor() exec.QueryExecutor {
|
||
|
return ud.queryFactory.FromSQLBuilder(ud.updateSQLBuilder())
|
||
|
}
|
||
|
|
||
|
func (ud *UpdateDataset) updateSQLBuilder() sb.SQLBuilder {
|
||
|
buf := sb.NewSQLBuilder(ud.isPrepared.Bool())
|
||
|
if ud.err != nil {
|
||
|
return buf.SetError(ud.err)
|
||
|
}
|
||
|
ud.dialect.ToUpdateSQL(buf, ud.clauses)
|
||
|
return buf
|
||
|
}
|