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 }