mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
* Restructure data layer part 2 (#2599) * Refactor and separate image model * Refactor image query builder * Handle relationships in image query builder * Remove relationship management methods * Refactor gallery model/query builder * Add scenes to gallery model * Convert scene model * Refactor scene models * Remove unused methods * Add unit tests for gallery * Add image tests * Add scene tests * Convert unnecessary scene value pointers to values * Convert unnecessary pointer values to values * Refactor scene partial * Add scene partial tests * Refactor ImagePartial * Add image partial tests * Refactor gallery partial update * Add partial gallery update tests * Use zero/null package for null values * Add files and scan system * Add sqlite implementation for files/folders * Add unit tests for files/folders * Image refactors * Update image data layer * Refactor gallery model and creation * Refactor scene model * Refactor scenes * Don't set title from filename * Allow galleries to freely add/remove images * Add multiple scene file support to graphql and UI * Add multiple file support for images in graphql/UI * Add multiple file for galleries in graphql/UI * Remove use of some deprecated fields * Remove scene path usage * Remove gallery path usage * Remove path from image * Move funscript to video file * Refactor caption detection * Migrate existing data * Add post commit/rollback hook system * Lint. Comment out import/export tests * Add WithDatabase read only wrapper * Prepend tasks to list * Add 32 pre-migration * Add warnings in release and migration notes
245 lines
7.8 KiB
Go
245 lines
7.8 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"
|
|
)
|
|
|
|
var ErrBadFromArgument = errors.New("unsupported DeleteDataset#From argument, a string or identifier expression is required")
|
|
|
|
type DeleteDataset struct {
|
|
dialect SQLDialect
|
|
clauses exp.DeleteClauses
|
|
isPrepared prepared
|
|
queryFactory exec.QueryFactory
|
|
err error
|
|
}
|
|
|
|
// used internally by database to create a database with a specific adapter
|
|
func newDeleteDataset(d string, queryFactory exec.QueryFactory) *DeleteDataset {
|
|
return &DeleteDataset{
|
|
clauses: exp.NewDeleteClauses(),
|
|
dialect: GetDialect(d),
|
|
queryFactory: queryFactory,
|
|
isPrepared: preparedNoPreference,
|
|
err: nil,
|
|
}
|
|
}
|
|
|
|
func Delete(table interface{}) *DeleteDataset {
|
|
return newDeleteDataset("default", nil).From(table)
|
|
}
|
|
|
|
func (dd *DeleteDataset) Expression() exp.Expression {
|
|
return dd
|
|
}
|
|
|
|
// Clones the dataset
|
|
func (dd *DeleteDataset) Clone() exp.Expression {
|
|
return dd.copy(dd.clauses)
|
|
}
|
|
|
|
// Set the parameter interpolation behavior. See examples
|
|
//
|
|
// prepared: If true the dataset WILL NOT interpolate the parameters.
|
|
func (dd *DeleteDataset) Prepared(prepared bool) *DeleteDataset {
|
|
ret := dd.copy(dd.clauses)
|
|
ret.isPrepared = preparedFromBool(prepared)
|
|
return ret
|
|
}
|
|
|
|
// Returns true if Prepared(true) has been called on this dataset
|
|
func (dd *DeleteDataset) IsPrepared() bool {
|
|
return dd.isPrepared.Bool()
|
|
}
|
|
|
|
// Sets the adapter used to serialize values and create the SQL statement
|
|
func (dd *DeleteDataset) WithDialect(dl string) *DeleteDataset {
|
|
ds := dd.copy(dd.GetClauses())
|
|
ds.dialect = GetDialect(dl)
|
|
return ds
|
|
}
|
|
|
|
// Returns the current SQLDialect on the dataset
|
|
func (dd *DeleteDataset) Dialect() SQLDialect {
|
|
return dd.dialect
|
|
}
|
|
|
|
// Set the dialect for this dataset.
|
|
func (dd *DeleteDataset) SetDialect(dialect SQLDialect) *DeleteDataset {
|
|
cd := dd.copy(dd.GetClauses())
|
|
cd.dialect = dialect
|
|
return cd
|
|
}
|
|
|
|
// Returns the current clauses on the dataset.
|
|
func (dd *DeleteDataset) GetClauses() exp.DeleteClauses {
|
|
return dd.clauses
|
|
}
|
|
|
|
// used interally to copy the dataset
|
|
func (dd *DeleteDataset) copy(clauses exp.DeleteClauses) *DeleteDataset {
|
|
return &DeleteDataset{
|
|
dialect: dd.dialect,
|
|
clauses: clauses,
|
|
isPrepared: dd.isPrepared,
|
|
queryFactory: dd.queryFactory,
|
|
err: dd.err,
|
|
}
|
|
}
|
|
|
|
// Creates a WITH clause for a common table expression (CTE).
|
|
//
|
|
// The name will be available to SELECT 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 (dd *DeleteDataset) With(name string, subquery exp.Expression) *DeleteDataset {
|
|
return dd.copy(dd.clauses.CommonTablesAppend(exp.NewCommonTableExpression(false, name, subquery)))
|
|
}
|
|
|
|
// Creates a WITH RECURSIVE clause for a common table expression (CTE)
|
|
//
|
|
// The name will be available to SELECT 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 (dd *DeleteDataset) WithRecursive(name string, subquery exp.Expression) *DeleteDataset {
|
|
return dd.copy(dd.clauses.CommonTablesAppend(exp.NewCommonTableExpression(true, name, subquery)))
|
|
}
|
|
|
|
// Adds a FROM clause. This return a new dataset with the original sources replaced. See examples.
|
|
// You can pass in the following.
|
|
// string: Will automatically be turned into an identifier
|
|
// Dataset: Will be added as a sub select. If the Dataset is not aliased it will automatically be aliased
|
|
// LiteralExpression: (See Literal) Will use the literal SQL
|
|
func (dd *DeleteDataset) From(table interface{}) *DeleteDataset {
|
|
switch t := table.(type) {
|
|
case exp.IdentifierExpression:
|
|
return dd.copy(dd.clauses.SetFrom(t))
|
|
case string:
|
|
return dd.copy(dd.clauses.SetFrom(exp.ParseIdentifier(t)))
|
|
default:
|
|
panic(ErrBadFromArgument)
|
|
}
|
|
}
|
|
|
|
// Adds a WHERE clause. See examples.
|
|
func (dd *DeleteDataset) Where(expressions ...exp.Expression) *DeleteDataset {
|
|
return dd.copy(dd.clauses.WhereAppend(expressions...))
|
|
}
|
|
|
|
// Removes the WHERE clause. See examples.
|
|
func (dd *DeleteDataset) ClearWhere() *DeleteDataset {
|
|
return dd.copy(dd.clauses.ClearWhere())
|
|
}
|
|
|
|
// Adds a ORDER clause. If the ORDER is currently set it replaces it. See examples.
|
|
func (dd *DeleteDataset) Order(order ...exp.OrderedExpression) *DeleteDataset {
|
|
return dd.copy(dd.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 (dd *DeleteDataset) OrderAppend(order ...exp.OrderedExpression) *DeleteDataset {
|
|
return dd.copy(dd.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 (dd *DeleteDataset) OrderPrepend(order ...exp.OrderedExpression) *DeleteDataset {
|
|
return dd.copy(dd.clauses.OrderPrepend(order...))
|
|
}
|
|
|
|
// Removes the ORDER BY clause. See examples.
|
|
func (dd *DeleteDataset) ClearOrder() *DeleteDataset {
|
|
return dd.copy(dd.clauses.ClearOrder())
|
|
}
|
|
|
|
// Adds a LIMIT clause. If the LIMIT is currently set it replaces it. See examples.
|
|
func (dd *DeleteDataset) Limit(limit uint) *DeleteDataset {
|
|
if limit > 0 {
|
|
return dd.copy(dd.clauses.SetLimit(limit))
|
|
}
|
|
return dd.copy(dd.clauses.ClearLimit())
|
|
}
|
|
|
|
// Adds a LIMIT ALL clause. If the LIMIT is currently set it replaces it. See examples.
|
|
func (dd *DeleteDataset) LimitAll() *DeleteDataset {
|
|
return dd.copy(dd.clauses.SetLimit(L("ALL")))
|
|
}
|
|
|
|
// Removes the LIMIT clause.
|
|
func (dd *DeleteDataset) ClearLimit() *DeleteDataset {
|
|
return dd.copy(dd.clauses.ClearLimit())
|
|
}
|
|
|
|
// Adds a RETURNING clause to the dataset if the adapter supports it.
|
|
func (dd *DeleteDataset) Returning(returning ...interface{}) *DeleteDataset {
|
|
return dd.copy(dd.clauses.SetReturning(exp.NewColumnListExpression(returning...)))
|
|
}
|
|
|
|
// Get any error that has been set or nil if no error has been set.
|
|
func (dd *DeleteDataset) Error() error {
|
|
return dd.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 (dd *DeleteDataset) SetError(err error) *DeleteDataset {
|
|
if dd.err == nil {
|
|
dd.err = err
|
|
}
|
|
|
|
return dd
|
|
}
|
|
|
|
// Generates a DELETE 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 (dd *DeleteDataset) ToSQL() (sql string, params []interface{}, err error) {
|
|
return dd.deleteSQLBuilder().ToSQL()
|
|
}
|
|
|
|
// Appends this Dataset's DELETE statement to the SQLBuilder
|
|
// This is used internally when using deletes in CTEs
|
|
func (dd *DeleteDataset) AppendSQL(b sb.SQLBuilder) {
|
|
if dd.err != nil {
|
|
b.SetError(dd.err)
|
|
return
|
|
}
|
|
dd.dialect.ToDeleteSQL(b, dd.GetClauses())
|
|
}
|
|
|
|
func (dd *DeleteDataset) GetAs() exp.IdentifierExpression {
|
|
return nil
|
|
}
|
|
|
|
func (dd *DeleteDataset) ReturnsColumns() bool {
|
|
return dd.clauses.HasReturning()
|
|
}
|
|
|
|
// Creates an QueryExecutor to execute the query.
|
|
// db.Delete("test").Exec()
|
|
//
|
|
// See Dataset#ToUpdateSQL for arguments
|
|
func (dd *DeleteDataset) Executor() exec.QueryExecutor {
|
|
return dd.queryFactory.FromSQLBuilder(dd.deleteSQLBuilder())
|
|
}
|
|
|
|
func (dd *DeleteDataset) deleteSQLBuilder() sb.SQLBuilder {
|
|
buf := sb.NewSQLBuilder(dd.isPrepared.Bool())
|
|
if dd.err != nil {
|
|
return buf.SetError(dd.err)
|
|
}
|
|
dd.dialect.ToDeleteSQL(buf, dd.clauses)
|
|
return buf
|
|
}
|