Files
stash/vendor/github.com/doug-martin/goqu/v9/select_dataset.go
WithoutPants 5495d72849 File storage rewrite (#2676)
* 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
2022-09-06 07:03:42 +00:00

696 lines
25 KiB
Go

package goqu
import (
"context"
"fmt"
"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"
)
// Dataset for creating and/or executing SELECT SQL statements.
type SelectDataset struct {
dialect SQLDialect
clauses exp.SelectClauses
isPrepared prepared
queryFactory exec.QueryFactory
err error
}
var ErrQueryFactoryNotFoundError = errors.New(
"unable to execute query did you use goqu.Database#From to create the dataset",
)
// used internally by database to create a database with a specific adapter
func newDataset(d string, queryFactory exec.QueryFactory) *SelectDataset {
return &SelectDataset{
clauses: exp.NewSelectClauses(),
dialect: GetDialect(d),
queryFactory: queryFactory,
}
}
func From(table ...interface{}) *SelectDataset {
return newDataset("default", nil).From(table...)
}
func Select(cols ...interface{}) *SelectDataset {
return newDataset("default", nil).Select(cols...)
}
// Sets the adapter used to serialize values and create the SQL statement
func (sd *SelectDataset) WithDialect(dl string) *SelectDataset {
ds := sd.copy(sd.GetClauses())
ds.dialect = GetDialect(dl)
return ds
}
// Set the parameter interpolation behavior. See examples
//
// prepared: If true the dataset WILL NOT interpolate the parameters.
func (sd *SelectDataset) Prepared(prepared bool) *SelectDataset {
ret := sd.copy(sd.clauses)
ret.isPrepared = preparedFromBool(prepared)
return ret
}
func (sd *SelectDataset) IsPrepared() bool {
return sd.isPrepared.Bool()
}
// Returns the current adapter on the dataset
func (sd *SelectDataset) Dialect() SQLDialect {
return sd.dialect
}
// Returns the current adapter on the dataset
func (sd *SelectDataset) SetDialect(dialect SQLDialect) *SelectDataset {
cd := sd.copy(sd.GetClauses())
cd.dialect = dialect
return cd
}
func (sd *SelectDataset) Expression() exp.Expression {
return sd
}
// Clones the dataset
func (sd *SelectDataset) Clone() exp.Expression {
return sd.copy(sd.clauses)
}
// Returns the current clauses on the dataset.
func (sd *SelectDataset) GetClauses() exp.SelectClauses {
return sd.clauses
}
// used interally to copy the dataset
func (sd *SelectDataset) copy(clauses exp.SelectClauses) *SelectDataset {
return &SelectDataset{
dialect: sd.dialect,
clauses: clauses,
isPrepared: sd.isPrepared,
queryFactory: sd.queryFactory,
err: sd.err,
}
}
// Creates a new UpdateDataset using the FROM of this dataset. This method will also copy over the `WITH`, `WHERE`,
// `ORDER , and `LIMIT`
func (sd *SelectDataset) Update() *UpdateDataset {
u := newUpdateDataset(sd.dialect.Dialect(), sd.queryFactory).
Prepared(sd.isPrepared.Bool())
if sd.clauses.HasSources() {
u = u.Table(sd.GetClauses().From().Columns()[0])
}
c := u.clauses
for _, ce := range sd.clauses.CommonTables() {
c = c.CommonTablesAppend(ce)
}
if sd.clauses.Where() != nil {
c = c.WhereAppend(sd.clauses.Where())
}
if sd.clauses.HasLimit() {
c = c.SetLimit(sd.clauses.Limit())
}
if sd.clauses.HasOrder() {
for _, oe := range sd.clauses.Order().Columns() {
c = c.OrderAppend(oe.(exp.OrderedExpression))
}
}
u.clauses = c
return u
}
// Creates a new InsertDataset using the FROM of this dataset. This method will also copy over the `WITH` clause to the
// insert.
func (sd *SelectDataset) Insert() *InsertDataset {
i := newInsertDataset(sd.dialect.Dialect(), sd.queryFactory).
Prepared(sd.isPrepared.Bool())
if sd.clauses.HasSources() {
i = i.Into(sd.GetClauses().From().Columns()[0])
}
c := i.clauses
for _, ce := range sd.clauses.CommonTables() {
c = c.CommonTablesAppend(ce)
}
i.clauses = c
return i
}
// Creates a new DeleteDataset using the FROM of this dataset. This method will also copy over the `WITH`, `WHERE`,
// `ORDER , and `LIMIT`
func (sd *SelectDataset) Delete() *DeleteDataset {
d := newDeleteDataset(sd.dialect.Dialect(), sd.queryFactory).
Prepared(sd.isPrepared.Bool())
if sd.clauses.HasSources() {
d = d.From(sd.clauses.From().Columns()[0])
}
c := d.clauses
for _, ce := range sd.clauses.CommonTables() {
c = c.CommonTablesAppend(ce)
}
if sd.clauses.Where() != nil {
c = c.WhereAppend(sd.clauses.Where())
}
if sd.clauses.HasLimit() {
c = c.SetLimit(sd.clauses.Limit())
}
if sd.clauses.HasOrder() {
for _, oe := range sd.clauses.Order().Columns() {
c = c.OrderAppend(oe.(exp.OrderedExpression))
}
}
d.clauses = c
return d
}
// Creates a new TruncateDataset using the FROM of this dataset.
func (sd *SelectDataset) Truncate() *TruncateDataset {
td := newTruncateDataset(sd.dialect.Dialect(), sd.queryFactory)
if sd.clauses.HasSources() {
td = td.Table(sd.clauses.From())
}
return td
}
// 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 (sd *SelectDataset) With(name string, subquery exp.Expression) *SelectDataset {
return sd.copy(sd.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 (sd *SelectDataset) WithRecursive(name string, subquery exp.Expression) *SelectDataset {
return sd.copy(sd.clauses.CommonTablesAppend(exp.NewCommonTableExpression(true, name, subquery)))
}
// Adds columns to the SELECT clause. See examples
// You can pass in the following.
// string: Will automatically be turned into an identifier
// Dataset: Will use the SQL generated from that Dataset. If the dataset is aliased it will use that alias as the
// column name.
// LiteralExpression: (See Literal) Will use the literal SQL
// SQLFunction: (See Func, MIN, MAX, COUNT....)
// Struct: If passing in an instance of a struct, we will parse the struct for the column names to select.
// See examples
func (sd *SelectDataset) Select(selects ...interface{}) *SelectDataset {
if len(selects) == 0 {
return sd.ClearSelect()
}
return sd.copy(sd.clauses.SetSelect(exp.NewColumnListExpression(selects...)))
}
// Adds columns to the SELECT DISTINCT clause. See examples
// You can pass in the following.
// string: Will automatically be turned into an identifier
// Dataset: Will use the SQL generated from that Dataset. If the dataset is aliased it will use that alias as the
// column name.
// LiteralExpression: (See Literal) Will use the literal SQL
// SQLFunction: (See Func, MIN, MAX, COUNT....)
// Struct: If passing in an instance of a struct, we will parse the struct for the column names to select.
// See examples
// Deprecated: Use Distinct() instead.
func (sd *SelectDataset) SelectDistinct(selects ...interface{}) *SelectDataset {
if len(selects) == 0 {
cleared := sd.ClearSelect()
return cleared.copy(cleared.clauses.SetDistinct(nil))
}
return sd.copy(sd.clauses.SetSelect(exp.NewColumnListExpression(selects...)).SetDistinct(exp.NewColumnListExpression()))
}
// Resets to SELECT *. If the SelectDistinct or Distinct was used the returned Dataset will have the the dataset set to SELECT *.
// See examples.
func (sd *SelectDataset) ClearSelect() *SelectDataset {
return sd.copy(sd.clauses.SetSelect(exp.NewColumnListExpression(exp.Star())).SetDistinct(nil))
}
// Adds columns to the SELECT clause. See examples
// You can pass in the following.
// string: Will automatically be turned into an identifier
// Dataset: Will use the SQL generated from that Dataset. If the dataset is aliased it will use that alias as the
// column name.
// LiteralExpression: (See Literal) Will use the literal SQL
// SQLFunction: (See Func, MIN, MAX, COUNT....)
func (sd *SelectDataset) SelectAppend(selects ...interface{}) *SelectDataset {
return sd.copy(sd.clauses.SelectAppend(exp.NewColumnListExpression(selects...)))
}
func (sd *SelectDataset) Distinct(on ...interface{}) *SelectDataset {
return sd.copy(sd.clauses.SetDistinct(exp.NewColumnListExpression(on...)))
}
// 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 (sd *SelectDataset) From(from ...interface{}) *SelectDataset {
var sources []interface{}
numSources := 0
for _, source := range from {
if ds, ok := source.(*SelectDataset); ok && !ds.clauses.HasAlias() {
numSources++
sources = append(sources, ds.As(fmt.Sprintf("t%d", numSources)))
} else {
sources = append(sources, source)
}
}
return sd.copy(sd.clauses.SetFrom(exp.NewColumnListExpression(sources...)))
}
// Returns a new Dataset with the current one as an source. If the current Dataset is not aliased (See Dataset#As) then
// it will automatically be aliased. See examples.
func (sd *SelectDataset) FromSelf() *SelectDataset {
return sd.copy(exp.NewSelectClauses()).From(sd)
}
// Alias to InnerJoin. See examples.
func (sd *SelectDataset) Join(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
return sd.InnerJoin(table, condition)
}
// Adds an INNER JOIN clause. See examples.
func (sd *SelectDataset) InnerJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
return sd.joinTable(exp.NewConditionedJoinExpression(exp.InnerJoinType, table, condition))
}
// Adds a FULL OUTER JOIN clause. See examples.
func (sd *SelectDataset) FullOuterJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
return sd.joinTable(exp.NewConditionedJoinExpression(exp.FullOuterJoinType, table, condition))
}
// Adds a RIGHT OUTER JOIN clause. See examples.
func (sd *SelectDataset) RightOuterJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
return sd.joinTable(exp.NewConditionedJoinExpression(exp.RightOuterJoinType, table, condition))
}
// Adds a LEFT OUTER JOIN clause. See examples.
func (sd *SelectDataset) LeftOuterJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
return sd.joinTable(exp.NewConditionedJoinExpression(exp.LeftOuterJoinType, table, condition))
}
// Adds a FULL JOIN clause. See examples.
func (sd *SelectDataset) FullJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
return sd.joinTable(exp.NewConditionedJoinExpression(exp.FullJoinType, table, condition))
}
// Adds a RIGHT JOIN clause. See examples.
func (sd *SelectDataset) RightJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
return sd.joinTable(exp.NewConditionedJoinExpression(exp.RightJoinType, table, condition))
}
// Adds a LEFT JOIN clause. See examples.
func (sd *SelectDataset) LeftJoin(table exp.Expression, condition exp.JoinCondition) *SelectDataset {
return sd.joinTable(exp.NewConditionedJoinExpression(exp.LeftJoinType, table, condition))
}
// Adds a NATURAL JOIN clause. See examples.
func (sd *SelectDataset) NaturalJoin(table exp.Expression) *SelectDataset {
return sd.joinTable(exp.NewUnConditionedJoinExpression(exp.NaturalJoinType, table))
}
// Adds a NATURAL LEFT JOIN clause. See examples.
func (sd *SelectDataset) NaturalLeftJoin(table exp.Expression) *SelectDataset {
return sd.joinTable(exp.NewUnConditionedJoinExpression(exp.NaturalLeftJoinType, table))
}
// Adds a NATURAL RIGHT JOIN clause. See examples.
func (sd *SelectDataset) NaturalRightJoin(table exp.Expression) *SelectDataset {
return sd.joinTable(exp.NewUnConditionedJoinExpression(exp.NaturalRightJoinType, table))
}
// Adds a NATURAL FULL JOIN clause. See examples.
func (sd *SelectDataset) NaturalFullJoin(table exp.Expression) *SelectDataset {
return sd.joinTable(exp.NewUnConditionedJoinExpression(exp.NaturalFullJoinType, table))
}
// Adds a CROSS JOIN clause. See examples.
func (sd *SelectDataset) CrossJoin(table exp.Expression) *SelectDataset {
return sd.joinTable(exp.NewUnConditionedJoinExpression(exp.CrossJoinType, table))
}
// Joins this Datasets table with another
func (sd *SelectDataset) joinTable(join exp.JoinExpression) *SelectDataset {
return sd.copy(sd.clauses.JoinsAppend(join))
}
// Adds a WHERE clause. See examples.
func (sd *SelectDataset) Where(expressions ...exp.Expression) *SelectDataset {
return sd.copy(sd.clauses.WhereAppend(expressions...))
}
// Removes the WHERE clause. See examples.
func (sd *SelectDataset) ClearWhere() *SelectDataset {
return sd.copy(sd.clauses.ClearWhere())
}
// Adds a FOR UPDATE clause. See examples.
func (sd *SelectDataset) ForUpdate(waitOption exp.WaitOption, of ...exp.IdentifierExpression) *SelectDataset {
return sd.withLock(exp.ForUpdate, waitOption, of...)
}
// Adds a FOR NO KEY UPDATE clause. See examples.
func (sd *SelectDataset) ForNoKeyUpdate(waitOption exp.WaitOption, of ...exp.IdentifierExpression) *SelectDataset {
return sd.withLock(exp.ForNoKeyUpdate, waitOption, of...)
}
// Adds a FOR KEY SHARE clause. See examples.
func (sd *SelectDataset) ForKeyShare(waitOption exp.WaitOption, of ...exp.IdentifierExpression) *SelectDataset {
return sd.withLock(exp.ForKeyShare, waitOption, of...)
}
// Adds a FOR SHARE clause. See examples.
func (sd *SelectDataset) ForShare(waitOption exp.WaitOption, of ...exp.IdentifierExpression) *SelectDataset {
return sd.withLock(exp.ForShare, waitOption, of...)
}
func (sd *SelectDataset) withLock(strength exp.LockStrength, option exp.WaitOption, of ...exp.IdentifierExpression) *SelectDataset {
return sd.copy(sd.clauses.SetLock(exp.NewLock(strength, option, of...)))
}
// Adds a GROUP BY clause. See examples.
func (sd *SelectDataset) GroupBy(groupBy ...interface{}) *SelectDataset {
return sd.copy(sd.clauses.SetGroupBy(exp.NewColumnListExpression(groupBy...)))
}
// Adds more columns to the current GROUP BY clause. See examples.
func (sd *SelectDataset) GroupByAppend(groupBy ...interface{}) *SelectDataset {
return sd.copy(sd.clauses.GroupByAppend(exp.NewColumnListExpression(groupBy...)))
}
// Adds a HAVING clause. See examples.
func (sd *SelectDataset) Having(expressions ...exp.Expression) *SelectDataset {
return sd.copy(sd.clauses.HavingAppend(expressions...))
}
// Adds a ORDER clause. If the ORDER is currently set it replaces it. See examples.
func (sd *SelectDataset) Order(order ...exp.OrderedExpression) *SelectDataset {
return sd.copy(sd.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 (sd *SelectDataset) OrderAppend(order ...exp.OrderedExpression) *SelectDataset {
return sd.copy(sd.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 (sd *SelectDataset) OrderPrepend(order ...exp.OrderedExpression) *SelectDataset {
return sd.copy(sd.clauses.OrderPrepend(order...))
}
// Removes the ORDER BY clause. See examples.
func (sd *SelectDataset) ClearOrder() *SelectDataset {
return sd.copy(sd.clauses.ClearOrder())
}
// Adds a LIMIT clause. If the LIMIT is currently set it replaces it. See examples.
func (sd *SelectDataset) Limit(limit uint) *SelectDataset {
if limit > 0 {
return sd.copy(sd.clauses.SetLimit(limit))
}
return sd.copy(sd.clauses.ClearLimit())
}
// Adds a LIMIT ALL clause. If the LIMIT is currently set it replaces it. See examples.
func (sd *SelectDataset) LimitAll() *SelectDataset {
return sd.copy(sd.clauses.SetLimit(L("ALL")))
}
// Removes the LIMIT clause.
func (sd *SelectDataset) ClearLimit() *SelectDataset {
return sd.copy(sd.clauses.ClearLimit())
}
// Adds an OFFSET clause. If the OFFSET is currently set it replaces it. See examples.
func (sd *SelectDataset) Offset(offset uint) *SelectDataset {
return sd.copy(sd.clauses.SetOffset(offset))
}
// Removes the OFFSET clause from the Dataset
func (sd *SelectDataset) ClearOffset() *SelectDataset {
return sd.copy(sd.clauses.ClearOffset())
}
// Creates an UNION statement with another dataset.
// If this or the other dataset has a limit or offset it will use that dataset as a subselect in the FROM clause.
// See examples.
func (sd *SelectDataset) Union(other *SelectDataset) *SelectDataset {
return sd.withCompound(exp.UnionCompoundType, other.CompoundFromSelf())
}
// Creates an UNION ALL statement with another dataset.
// If this or the other dataset has a limit or offset it will use that dataset as a subselect in the FROM clause.
// See examples.
func (sd *SelectDataset) UnionAll(other *SelectDataset) *SelectDataset {
return sd.withCompound(exp.UnionAllCompoundType, other.CompoundFromSelf())
}
// Creates an INTERSECT statement with another dataset.
// If this or the other dataset has a limit or offset it will use that dataset as a subselect in the FROM clause.
// See examples.
func (sd *SelectDataset) Intersect(other *SelectDataset) *SelectDataset {
return sd.withCompound(exp.IntersectCompoundType, other.CompoundFromSelf())
}
// Creates an INTERSECT ALL statement with another dataset.
// If this or the other dataset has a limit or offset it will use that dataset as a subselect in the FROM clause.
// See examples.
func (sd *SelectDataset) IntersectAll(other *SelectDataset) *SelectDataset {
return sd.withCompound(exp.IntersectAllCompoundType, other.CompoundFromSelf())
}
func (sd *SelectDataset) withCompound(ct exp.CompoundType, other exp.AppendableExpression) *SelectDataset {
ce := exp.NewCompoundExpression(ct, other)
ret := sd.CompoundFromSelf()
ret.clauses = ret.clauses.CompoundsAppend(ce)
return ret
}
// Used internally to determine if the dataset needs to use iteself as a source.
// If the dataset has an order or limit it will select from itself
func (sd *SelectDataset) CompoundFromSelf() *SelectDataset {
if sd.clauses.HasOrder() || sd.clauses.HasLimit() {
return sd.FromSelf()
}
return sd.copy(sd.clauses)
}
// Sets the alias for this dataset. This is typically used when using a Dataset as a subselect. See examples.
func (sd *SelectDataset) As(alias string) *SelectDataset {
return sd.copy(sd.clauses.SetAlias(T(alias)))
}
// Returns the alias value as an identiier expression
func (sd *SelectDataset) GetAs() exp.IdentifierExpression {
return sd.clauses.Alias()
}
// Sets the WINDOW clauses
func (sd *SelectDataset) Window(ws ...exp.WindowExpression) *SelectDataset {
return sd.copy(sd.clauses.SetWindows(ws))
}
// Sets the WINDOW clauses
func (sd *SelectDataset) WindowAppend(ws ...exp.WindowExpression) *SelectDataset {
return sd.copy(sd.clauses.WindowsAppend(ws...))
}
// Sets the WINDOW clauses
func (sd *SelectDataset) ClearWindow() *SelectDataset {
return sd.copy(sd.clauses.ClearWindows())
}
// Get any error that has been set or nil if no error has been set.
func (sd *SelectDataset) Error() error {
return sd.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 (sd *SelectDataset) SetError(err error) *SelectDataset {
if sd.err == nil {
sd.err = err
}
return sd
}
// Generates a SELECT 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 (sd *SelectDataset) ToSQL() (sql string, params []interface{}, err error) {
return sd.selectSQLBuilder().ToSQL()
}
// Generates the SELECT sql, and returns an Exec struct with the sql set to the SELECT statement
// db.From("test").Select("col").Executor()
//
// See Dataset#ToUpdateSQL for arguments
func (sd *SelectDataset) Executor() exec.QueryExecutor {
return sd.queryFactory.FromSQLBuilder(sd.selectSQLBuilder())
}
// Appends this Dataset's SELECT statement to the SQLBuilder
// This is used internally for sub-selects by the dialect
func (sd *SelectDataset) AppendSQL(b sb.SQLBuilder) {
if sd.err != nil {
b.SetError(sd.err)
return
}
sd.dialect.ToSelectSQL(b, sd.GetClauses())
}
func (sd *SelectDataset) ReturnsColumns() bool {
return true
}
// Generates the SELECT sql for this dataset and uses Exec#ScanStructs to scan the results into a slice of structs.
//
// ScanStructs will only select the columns that can be scanned in to the struct unless you have explicitly selected
// certain columns. See examples.
//
// i: A pointer to a slice of structs
func (sd *SelectDataset) ScanStructs(i interface{}) error {
return sd.ScanStructsContext(context.Background(), i)
}
// Generates the SELECT sql for this dataset and uses Exec#ScanStructsContext to scan the results into a slice of
// structs.
//
// ScanStructsContext will only select the columns that can be scanned in to the struct unless you have explicitly
// selected certain columns. See examples.
//
// i: A pointer to a slice of structs
func (sd *SelectDataset) ScanStructsContext(ctx context.Context, i interface{}) error {
if sd.queryFactory == nil {
return ErrQueryFactoryNotFoundError
}
ds := sd
if sd.GetClauses().IsDefaultSelect() {
ds = sd.Select(i)
}
return ds.Executor().ScanStructsContext(ctx, i)
}
// Generates the SELECT sql for this dataset and uses Exec#ScanStruct to scan the result into a slice of structs
//
// ScanStruct will only select the columns that can be scanned in to the struct unless you have explicitly selected
// certain columns. See examples.
//
// i: A pointer to a structs
func (sd *SelectDataset) ScanStruct(i interface{}) (bool, error) {
return sd.ScanStructContext(context.Background(), i)
}
// Generates the SELECT sql for this dataset and uses Exec#ScanStructContext to scan the result into a slice of structs
//
// ScanStructContext will only select the columns that can be scanned in to the struct unless you have explicitly
// selected certain columns. See examples.
//
// i: A pointer to a structs
func (sd *SelectDataset) ScanStructContext(ctx context.Context, i interface{}) (bool, error) {
if sd.queryFactory == nil {
return false, ErrQueryFactoryNotFoundError
}
ds := sd
if sd.GetClauses().IsDefaultSelect() {
ds = sd.Select(i)
}
return ds.Limit(1).Executor().ScanStructContext(ctx, i)
}
// Generates the SELECT sql for this dataset and uses Exec#ScanVals to scan the results into a slice of primitive values
//
// i: A pointer to a slice of primitive values
func (sd *SelectDataset) ScanVals(i interface{}) error {
return sd.ScanValsContext(context.Background(), i)
}
// Generates the SELECT sql for this dataset and uses Exec#ScanValsContext to scan the results into a slice of primitive
// values
//
// i: A pointer to a slice of primitive values
func (sd *SelectDataset) ScanValsContext(ctx context.Context, i interface{}) error {
if sd.queryFactory == nil {
return ErrQueryFactoryNotFoundError
}
return sd.Executor().ScanValsContext(ctx, i)
}
// Generates the SELECT sql for this dataset and uses Exec#ScanVal to scan the result into a primitive value
//
// i: A pointer to a primitive value
func (sd *SelectDataset) ScanVal(i interface{}) (bool, error) {
return sd.ScanValContext(context.Background(), i)
}
// Generates the SELECT sql for this dataset and uses Exec#ScanValContext to scan the result into a primitive value
//
// i: A pointer to a primitive value
func (sd *SelectDataset) ScanValContext(ctx context.Context, i interface{}) (bool, error) {
if sd.queryFactory == nil {
return false, ErrQueryFactoryNotFoundError
}
return sd.Limit(1).Executor().ScanValContext(ctx, i)
}
// Generates the SELECT COUNT(*) sql for this dataset and uses Exec#ScanVal to scan the result into an int64.
func (sd *SelectDataset) Count() (int64, error) {
return sd.CountContext(context.Background())
}
// Generates the SELECT COUNT(*) sql for this dataset and uses Exec#ScanValContext to scan the result into an int64.
func (sd *SelectDataset) CountContext(ctx context.Context) (int64, error) {
var count int64
_, err := sd.Select(COUNT(Star()).As("count")).ScanValContext(ctx, &count)
return count, err
}
// Generates the SELECT sql only selecting the passed in column and uses Exec#ScanVals to scan the result into a slice
// of primitive values.
//
// i: A slice of primitive values
//
// col: The column to select when generative the SQL
func (sd *SelectDataset) Pluck(i interface{}, col string) error {
return sd.PluckContext(context.Background(), i, col)
}
// Generates the SELECT sql only selecting the passed in column and uses Exec#ScanValsContext to scan the result into a
// slice of primitive values.
//
// i: A slice of primitive values
//
// col: The column to select when generative the SQL
func (sd *SelectDataset) PluckContext(ctx context.Context, i interface{}, col string) error {
return sd.Select(col).ScanValsContext(ctx, i)
}
func (sd *SelectDataset) selectSQLBuilder() sb.SQLBuilder {
buf := sb.NewSQLBuilder(sd.isPrepared.Bool())
if sd.err != nil {
return buf.SetError(sd.err)
}
sd.dialect.ToSelectSQL(buf, sd.GetClauses())
return buf
}