github.com/Ali-iotechsys/sqlboiler/v4@v4.0.0-20221208124957-6aec9a5f1f71/queries/query.go (about)

     1  package queries
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"fmt"
     7  	"regexp"
     8  
     9  	"github.com/volatiletech/sqlboiler/v4/boil"
    10  	"github.com/volatiletech/sqlboiler/v4/drivers"
    11  )
    12  
    13  // joinKind is the type of join
    14  type joinKind int
    15  
    16  // Join type constants
    17  const (
    18  	JoinInner joinKind = iota
    19  	JoinOuterLeft
    20  	JoinOuterRight
    21  	JoinNatural
    22  	JoinOuterFull
    23  )
    24  
    25  // Query holds the state for the built up query
    26  type Query struct {
    27  	dialect *drivers.Dialect
    28  	rawSQL  rawSQL
    29  
    30  	load     []string
    31  	loadMods map[string]Applicator
    32  
    33  	delete     bool
    34  	update     map[string]interface{}
    35  	withs      []argClause
    36  	selectCols []string
    37  	count      bool
    38  	from       []string
    39  	joins      []join
    40  	where      []where
    41  	groupBy    []string
    42  	orderBy    []argClause
    43  	having     []argClause
    44  	limit      *int
    45  	offset     int
    46  	forlock    string
    47  	distinct   string
    48  	comment    string
    49  
    50  	// This field is a hack to allow a query to strip out the reference
    51  	// to deleted at is null.
    52  	removeSoftDelete bool
    53  }
    54  
    55  // Applicator exists only to allow
    56  // query mods into the query struct around
    57  // eager loaded relationships.
    58  type Applicator interface {
    59  	Apply(*Query)
    60  }
    61  
    62  type whereKind int
    63  
    64  const (
    65  	whereKindNormal whereKind = iota
    66  	whereKindLeftParen
    67  	whereKindRightParen
    68  	whereKindIn
    69  	whereKindNotIn
    70  )
    71  
    72  type where struct {
    73  	kind whereKind
    74  
    75  	clause      string
    76  	orSeparator bool
    77  	args        []interface{}
    78  }
    79  
    80  type in struct {
    81  	clause      string
    82  	orSeparator bool
    83  	args        []interface{}
    84  }
    85  
    86  type argClause struct {
    87  	clause string
    88  	args   []interface{}
    89  }
    90  
    91  type rawSQL struct {
    92  	sql  string
    93  	args []interface{}
    94  }
    95  
    96  type join struct {
    97  	kind   joinKind
    98  	clause string
    99  	args   []interface{}
   100  }
   101  
   102  // Raw makes a raw query, usually for use with bind
   103  func Raw(query string, args ...interface{}) *Query {
   104  	return &Query{
   105  		rawSQL: rawSQL{
   106  			sql:  query,
   107  			args: args,
   108  		},
   109  	}
   110  }
   111  
   112  // RawG makes a raw query using the global boil.Executor, usually for use with bind
   113  func RawG(query string, args ...interface{}) *Query {
   114  	return Raw(query, args...)
   115  }
   116  
   117  // Exec executes a query that does not need a row returned
   118  func (q *Query) Exec(exec boil.Executor) (sql.Result, error) {
   119  	qs, args := BuildQuery(q)
   120  	if boil.DebugMode {
   121  		fmt.Fprintln(boil.DebugWriter, qs)
   122  		fmt.Fprintln(boil.DebugWriter, args)
   123  	}
   124  	return exec.Exec(qs, args...)
   125  }
   126  
   127  // QueryRow executes the query for the One finisher and returns a row
   128  func (q *Query) QueryRow(exec boil.Executor) *sql.Row {
   129  	qs, args := BuildQuery(q)
   130  	if boil.DebugMode {
   131  		fmt.Fprintln(boil.DebugWriter, qs)
   132  		fmt.Fprintln(boil.DebugWriter, args)
   133  	}
   134  	return exec.QueryRow(qs, args...)
   135  }
   136  
   137  // Query executes the query for the All finisher and returns multiple rows
   138  func (q *Query) Query(exec boil.Executor) (*sql.Rows, error) {
   139  	qs, args := BuildQuery(q)
   140  	if boil.DebugMode {
   141  		fmt.Fprintln(boil.DebugWriter, qs)
   142  		fmt.Fprintln(boil.DebugWriter, args)
   143  	}
   144  	return exec.Query(qs, args...)
   145  }
   146  
   147  // ExecContext executes a query that does not need a row returned
   148  func (q *Query) ExecContext(ctx context.Context, exec boil.ContextExecutor) (sql.Result, error) {
   149  	qs, args := BuildQuery(q)
   150  	if boil.IsDebug(ctx) {
   151  		writer := boil.DebugWriterFrom(ctx)
   152  		fmt.Fprintln(writer, qs)
   153  		fmt.Fprintln(writer, args)
   154  	}
   155  	return exec.ExecContext(ctx, qs, args...)
   156  }
   157  
   158  // QueryRowContext executes the query for the One finisher and returns a row
   159  func (q *Query) QueryRowContext(ctx context.Context, exec boil.ContextExecutor) *sql.Row {
   160  	qs, args := BuildQuery(q)
   161  	if boil.IsDebug(ctx) {
   162  		writer := boil.DebugWriterFrom(ctx)
   163  		fmt.Fprintln(writer, qs)
   164  		fmt.Fprintln(writer, args)
   165  	}
   166  	return exec.QueryRowContext(ctx, qs, args...)
   167  }
   168  
   169  // QueryContext executes the query for the All finisher and returns multiple rows
   170  func (q *Query) QueryContext(ctx context.Context, exec boil.ContextExecutor) (*sql.Rows, error) {
   171  	qs, args := BuildQuery(q)
   172  	if boil.IsDebug(ctx) {
   173  		writer := boil.DebugWriterFrom(ctx)
   174  		fmt.Fprintln(writer, qs)
   175  		fmt.Fprintln(writer, args)
   176  	}
   177  	return exec.QueryContext(ctx, qs, args...)
   178  }
   179  
   180  // ExecP executes a query that does not need a row returned
   181  // It will panic on error
   182  func (q *Query) ExecP(exec boil.Executor) sql.Result {
   183  	res, err := q.Exec(exec)
   184  	if err != nil {
   185  		panic(boil.WrapErr(err))
   186  	}
   187  
   188  	return res
   189  }
   190  
   191  // QueryP executes the query for the All finisher and returns multiple rows
   192  // It will panic on error
   193  func (q *Query) QueryP(exec boil.Executor) *sql.Rows {
   194  	rows, err := q.Query(exec)
   195  	if err != nil {
   196  		panic(boil.WrapErr(err))
   197  	}
   198  
   199  	return rows
   200  }
   201  
   202  // SetDialect on the query.
   203  func SetDialect(q *Query, dialect *drivers.Dialect) {
   204  	q.dialect = dialect
   205  }
   206  
   207  // SetSQL on the query.
   208  func SetSQL(q *Query, sql string, args ...interface{}) {
   209  	q.rawSQL = rawSQL{sql: sql, args: args}
   210  }
   211  
   212  // SetArgs is primarily for re-use of a query so that the
   213  // query text does not need to be re-generated, useful
   214  // if you're performing the same query with different arguments
   215  // over and over.
   216  func SetArgs(q *Query, args ...interface{}) {
   217  	q.rawSQL.args = args
   218  }
   219  
   220  // SetLoad on the query.
   221  func SetLoad(q *Query, relationships ...string) {
   222  	q.load = append([]string(nil), relationships...)
   223  }
   224  
   225  // AppendLoad on the query.
   226  func AppendLoad(q *Query, relationships string) {
   227  	q.load = append(q.load, relationships)
   228  }
   229  
   230  // SetLoadMods on the query.
   231  func SetLoadMods(q *Query, rel string, appl Applicator) {
   232  	if q.loadMods == nil {
   233  		q.loadMods = make(map[string]Applicator)
   234  	}
   235  
   236  	q.loadMods[rel] = appl
   237  }
   238  
   239  // SetSelect on the query.
   240  func SetSelect(q *Query, sel []string) {
   241  	q.selectCols = sel
   242  }
   243  
   244  // GetSelect from the query
   245  func GetSelect(q *Query) []string {
   246  	return q.selectCols
   247  }
   248  
   249  // SetDistinct on the query.
   250  func SetDistinct(q *Query, distinct string) {
   251  	q.distinct = distinct
   252  }
   253  
   254  // SetCount on the query.
   255  func SetCount(q *Query) {
   256  	q.count = true
   257  }
   258  
   259  // SetDelete on the query.
   260  func SetDelete(q *Query) {
   261  	q.delete = true
   262  }
   263  
   264  // SetLimit on the query.
   265  func SetLimit(q *Query, limit int) {
   266  	q.limit = &limit
   267  }
   268  
   269  // SetOffset on the query.
   270  func SetOffset(q *Query, offset int) {
   271  	q.offset = offset
   272  }
   273  
   274  // SetFor on the query.
   275  func SetFor(q *Query, clause string) {
   276  	q.forlock = clause
   277  }
   278  
   279  // SetComment on the query.
   280  func SetComment(q *Query, comment string) {
   281  	q.comment = comment
   282  }
   283  
   284  // SetUpdate on the query.
   285  func SetUpdate(q *Query, cols map[string]interface{}) {
   286  	q.update = cols
   287  }
   288  
   289  // AppendSelect on the query.
   290  func AppendSelect(q *Query, columns ...string) {
   291  	q.selectCols = append(q.selectCols, columns...)
   292  }
   293  
   294  // AppendFrom on the query.
   295  func AppendFrom(q *Query, from ...string) {
   296  	q.from = append(q.from, from...)
   297  }
   298  
   299  // SetFrom replaces the current from statements.
   300  func SetFrom(q *Query, from ...string) {
   301  	q.from = append([]string(nil), from...)
   302  }
   303  
   304  // AppendInnerJoin on the query.
   305  func AppendInnerJoin(q *Query, clause string, args ...interface{}) {
   306  	q.joins = append(q.joins, join{clause: clause, kind: JoinInner, args: args})
   307  }
   308  
   309  // AppendLeftOuterJoin on the query.
   310  func AppendLeftOuterJoin(q *Query, clause string, args ...interface{}) {
   311  	q.joins = append(q.joins, join{clause: clause, kind: JoinOuterLeft, args: args})
   312  }
   313  
   314  // AppendRightOuterJoin on the query.
   315  func AppendRightOuterJoin(q *Query, clause string, args ...interface{}) {
   316  	q.joins = append(q.joins, join{clause: clause, kind: JoinOuterRight, args: args})
   317  }
   318  
   319  // AppendFullOuterJoin on the query.
   320  func AppendFullOuterJoin(q *Query, clause string, args ...interface{}) {
   321  	q.joins = append(q.joins, join{clause: clause, kind: JoinOuterFull, args: args})
   322  }
   323  
   324  // AppendHaving on the query.
   325  func AppendHaving(q *Query, clause string, args ...interface{}) {
   326  	q.having = append(q.having, argClause{clause: clause, args: args})
   327  }
   328  
   329  // AppendWhere on the query.
   330  func AppendWhere(q *Query, clause string, args ...interface{}) {
   331  	q.where = append(q.where, where{clause: clause, args: args})
   332  }
   333  
   334  // AppendIn on the query.
   335  func AppendIn(q *Query, clause string, args ...interface{}) {
   336  	q.where = append(q.where, where{kind: whereKindIn, clause: clause, args: args})
   337  }
   338  
   339  // AppendNotIn on the query.
   340  func AppendNotIn(q *Query, clause string, args ...interface{}) {
   341  	q.where = append(q.where, where{kind: whereKindNotIn, clause: clause, args: args})
   342  }
   343  
   344  // SetLastWhereAsOr sets the or separator for the tail "WHERE" in the slice
   345  func SetLastWhereAsOr(q *Query) {
   346  	if len(q.where) == 0 {
   347  		return
   348  	}
   349  
   350  	pos := len(q.where) - 1
   351  	where := q.where[pos]
   352  	if where.kind != whereKindRightParen {
   353  		q.where[len(q.where)-1].orSeparator = true
   354  		return
   355  	}
   356  
   357  	stack := 0
   358  	pos--
   359  	for ; pos >= 0; pos-- {
   360  		switch q.where[pos].kind {
   361  		case whereKindLeftParen:
   362  			if stack == 0 {
   363  				q.where[pos].orSeparator = true
   364  				return
   365  			}
   366  			stack--
   367  		case whereKindRightParen:
   368  			stack++
   369  		}
   370  	}
   371  
   372  	panic("could not find matching ( in where query expr")
   373  }
   374  
   375  // SetLastInAsOr is an alias for SetLastWhereAsOr
   376  func SetLastInAsOr(q *Query) {
   377  	SetLastWhereAsOr(q)
   378  }
   379  
   380  // AppendWhereLeftParen creates a right left in the where expression
   381  func AppendWhereLeftParen(q *Query) {
   382  	q.where = append(q.where, where{kind: whereKindLeftParen})
   383  }
   384  
   385  // AppendWhereRightParen creates a right paren in the where expression
   386  func AppendWhereRightParen(q *Query) {
   387  	q.where = append(q.where, where{kind: whereKindRightParen})
   388  }
   389  
   390  // AppendGroupBy on the query.
   391  func AppendGroupBy(q *Query, clause string) {
   392  	q.groupBy = append(q.groupBy, clause)
   393  }
   394  
   395  // AppendOrderBy on the query.
   396  func AppendOrderBy(q *Query, clause string, args ...interface{}) {
   397  	q.orderBy = append(q.orderBy, argClause{clause: clause, args: args})
   398  }
   399  
   400  // AppendWith on the query.
   401  func AppendWith(q *Query, clause string, args ...interface{}) {
   402  	q.withs = append(q.withs, argClause{clause: clause, args: args})
   403  }
   404  
   405  // RemoveSoftDeleteWhere prevents the automatic soft delete where clause
   406  // from being included when building the query.
   407  func RemoveSoftDeleteWhere(q *Query) {
   408  	q.removeSoftDelete = true
   409  }
   410  
   411  var deletedAtRgx = regexp.MustCompile("deleted_at[\"'`]? is null")
   412  
   413  // removeSoftDeleteWhere attempts to remove the soft delete where clause
   414  // added automatically by sqlboiler.
   415  func (q *Query) removeSoftDeleteWhere() {
   416  	if !q.removeSoftDelete {
   417  		return
   418  	}
   419  
   420  	for i := len(q.where) - 1; i >= 0; i-- {
   421  		w := q.where[i]
   422  		if w.kind != whereKindNormal || !deletedAtRgx.MatchString(w.clause) {
   423  			continue
   424  		}
   425  
   426  		// It's of vital importance we preserve order here
   427  		if i != len(q.where)-1 {
   428  			// If this is not the last element we shift all elements
   429  			// left one.
   430  			copy(q.where[i:], q.where[i+1:])
   431  		}
   432  		q.where = q.where[:len(q.where)-1]
   433  		// Only delete one of these - the rest could be from the user.
   434  		break
   435  	}
   436  }