github.com/acoshift/pgsql@v0.15.3/pgstmt/select.go (about) 1 package pgstmt 2 3 // Select builds select statement 4 func Select(f func(b SelectStatement)) *Result { 5 var st selectStmt 6 f(&st) 7 return newResult(build(st.make())) 8 } 9 10 // SelectStatement is the select statement builder 11 type SelectStatement interface { 12 Distinct() Distinct 13 Columns(col ...any) 14 ColumnSelect(f func(b SelectStatement), as string) 15 ColumnExists(f func(b SelectStatement)) 16 From(table ...string) 17 FromSelect(f func(b SelectStatement), as string) 18 FromValues(f func(b Values), as string) 19 20 Join(table string) Join 21 InnerJoin(table string) Join 22 FullOuterJoin(table string) Join 23 LeftJoin(table string) Join 24 RightJoin(table string) Join 25 26 JoinSelect(f func(b SelectStatement), as string) Join 27 InnerJoinSelect(f func(b SelectStatement), as string) Join 28 FullOuterJoinSelect(f func(b SelectStatement), as string) Join 29 LeftJoinSelect(f func(b SelectStatement), as string) Join 30 RightJoinSelect(f func(b SelectStatement), as string) Join 31 32 JoinLateralSelect(f func(b SelectStatement), as string) Join 33 InnerJoinLateralSelect(f func(b SelectStatement), as string) Join 34 FullOuterJoinLateralSelect(f func(b SelectStatement), as string) Join 35 LeftJoinLateralSelect(f func(b SelectStatement), as string) Join 36 RightJoinLateralSelect(f func(b SelectStatement), as string) Join 37 38 JoinUnion(f func(b UnionStatement), as string) Join 39 InnerJoinUnion(f func(b UnionStatement), as string) Join 40 FullOuterJoinUnion(f func(b UnionStatement), as string) Join 41 LeftJoinUnion(f func(b UnionStatement), as string) Join 42 RightJoinUnion(f func(b UnionStatement), as string) Join 43 44 Where(f func(b Cond)) 45 GroupBy(col ...string) 46 Having(f func(b Cond)) 47 OrderBy(col string) OrderBy 48 Limit(n int64) 49 Offset(n int64) 50 } 51 52 type Distinct interface { 53 On(col ...string) 54 } 55 56 type Values interface { 57 Value(value ...any) 58 Values(values ...[]any) 59 } 60 61 type OrderBy interface { 62 Asc() OrderBy 63 Desc() OrderBy 64 NullsFirst() OrderBy 65 NullsLast() OrderBy 66 } 67 68 type Join interface { 69 On(f func(b Cond)) 70 Using(col ...string) 71 } 72 73 type selectStmt struct { 74 distinct *distinct 75 columns group 76 from group 77 joins buffer 78 where cond 79 groupBy group 80 having cond 81 orderBy group 82 limit *int64 83 offset *int64 84 } 85 86 func (st *selectStmt) Distinct() Distinct { 87 st.distinct = &distinct{} 88 return st.distinct 89 } 90 91 func (st *selectStmt) Columns(col ...any) { 92 st.columns.push(col...) 93 } 94 95 func (st *selectStmt) ColumnSelect(f func(b SelectStatement), as string) { 96 var x selectStmt 97 f(&x) 98 99 var b buffer 100 b.push(paren(x.make())) 101 if as != "" { 102 b.push(as) 103 } 104 st.columns.push(&b) 105 } 106 107 func (st *selectStmt) ColumnExists(f func(b SelectStatement)) { 108 var x selectStmt 109 f(&x) 110 111 var b buffer 112 b.push("exists", paren(x.make())) 113 st.columns.push(&b) 114 } 115 116 func (st *selectStmt) From(table ...string) { 117 st.from.pushString(table...) 118 } 119 120 func (st *selectStmt) FromSelect(f func(b SelectStatement), as string) { 121 var x selectStmt 122 f(&x) 123 124 var b buffer 125 b.push(paren(x.make())) 126 if as != "" { 127 b.push(as) 128 } 129 st.from.push(&b) 130 } 131 132 func (st *selectStmt) FromValues(f func(b Values), as string) { 133 var x values 134 f(&x) 135 136 if x.empty() { 137 return 138 } 139 140 st.from.push(withGroup(" ", 141 withGroup(" ", 142 withParen(" ", 143 "values", 144 withGroup(", ", x.q...), 145 ), 146 ), 147 as, 148 )) 149 } 150 151 func (st *selectStmt) join(typ, table string) Join { 152 var b buffer 153 b.push(table) 154 x := join{ 155 typ: typ, 156 table: &b, 157 } 158 st.joins.push(&x) 159 return &x 160 } 161 162 func (st *selectStmt) Join(table string) Join { 163 return st.join("join", table) 164 } 165 166 func (st *selectStmt) InnerJoin(table string) Join { 167 return st.join("inner join", table) 168 } 169 170 func (st *selectStmt) FullOuterJoin(table string) Join { 171 return st.join("full outer join", table) 172 } 173 174 func (st *selectStmt) LeftJoin(table string) Join { 175 return st.join("left join", table) 176 } 177 178 func (st *selectStmt) RightJoin(table string) Join { 179 return st.join("right join", table) 180 } 181 182 func (st *selectStmt) joinSelect(typ string, f func(b SelectStatement), as string) Join { 183 var x selectStmt 184 f(&x) 185 186 var b buffer 187 b.push(paren(x.make())) 188 if as != "" { 189 b.push(as) 190 } 191 192 j := join{ 193 typ: typ, 194 table: &b, 195 } 196 st.joins.push(&j) 197 return &j 198 } 199 200 func (st *selectStmt) JoinSelect(f func(b SelectStatement), as string) Join { 201 return st.joinSelect("join", f, as) 202 } 203 204 func (st *selectStmt) InnerJoinSelect(f func(b SelectStatement), as string) Join { 205 return st.joinSelect("inner join", f, as) 206 } 207 208 func (st *selectStmt) FullOuterJoinSelect(f func(b SelectStatement), as string) Join { 209 return st.joinSelect("full outer join", f, as) 210 } 211 212 func (st *selectStmt) LeftJoinSelect(f func(b SelectStatement), as string) Join { 213 return st.joinSelect("left join", f, as) 214 } 215 216 func (st *selectStmt) RightJoinSelect(f func(b SelectStatement), as string) Join { 217 return st.joinSelect("right join", f, as) 218 } 219 220 func (st *selectStmt) JoinLateralSelect(f func(b SelectStatement), as string) Join { 221 return st.joinSelect("join lateral", f, as) 222 } 223 224 func (st *selectStmt) InnerJoinLateralSelect(f func(b SelectStatement), as string) Join { 225 return st.joinSelect("inner join lateral", f, as) 226 } 227 228 func (st *selectStmt) FullOuterJoinLateralSelect(f func(b SelectStatement), as string) Join { 229 return st.joinSelect("full outer join lateral", f, as) 230 } 231 232 func (st *selectStmt) LeftJoinLateralSelect(f func(b SelectStatement), as string) Join { 233 return st.joinSelect("left join lateral", f, as) 234 } 235 236 func (st *selectStmt) RightJoinLateralSelect(f func(b SelectStatement), as string) Join { 237 return st.joinSelect("right join lateral", f, as) 238 } 239 240 func (st *selectStmt) joinUnion(typ string, f func(b UnionStatement), as string) Join { 241 var x unionStmt 242 f(&x) 243 244 var b buffer 245 b.push(paren(x.make())) 246 if as != "" { 247 b.push(as) 248 } 249 250 j := join{ 251 typ: typ, 252 table: &b, 253 } 254 st.joins.push(&j) 255 return &j 256 } 257 258 func (st *selectStmt) JoinUnion(f func(b UnionStatement), as string) Join { 259 return st.joinUnion("join", f, as) 260 } 261 262 func (st *selectStmt) InnerJoinUnion(f func(b UnionStatement), as string) Join { 263 return st.joinUnion("inner join", f, as) 264 } 265 266 func (st *selectStmt) FullOuterJoinUnion(f func(b UnionStatement), as string) Join { 267 return st.joinUnion("full outer join", f, as) 268 } 269 270 func (st *selectStmt) LeftJoinUnion(f func(b UnionStatement), as string) Join { 271 return st.joinUnion("left join", f, as) 272 } 273 274 func (st *selectStmt) RightJoinUnion(f func(b UnionStatement), as string) Join { 275 return st.joinUnion("right join", f, as) 276 } 277 278 func (st *selectStmt) Where(f func(b Cond)) { 279 f(&st.where) 280 } 281 282 func (st *selectStmt) GroupBy(col ...string) { 283 st.groupBy.pushString(col...) 284 } 285 286 func (st *selectStmt) Having(f func(b Cond)) { 287 f(&st.having) 288 } 289 290 func (st *selectStmt) OrderBy(col string) OrderBy { 291 p := orderBy{ 292 col: col, 293 } 294 st.orderBy.push(&p) 295 return &p 296 } 297 298 func (st *selectStmt) Limit(n int64) { 299 st.limit = &n 300 } 301 302 func (st *selectStmt) Offset(n int64) { 303 st.offset = &n 304 } 305 306 func (st *selectStmt) make() *buffer { 307 var b buffer 308 b.push("select") 309 if st.distinct != nil { 310 b.push("distinct") 311 312 if !st.distinct.columns.empty() { 313 b.push("on") 314 b.push(&st.distinct.columns) 315 } 316 } 317 if !st.columns.empty() { 318 b.push(&st.columns) 319 } 320 if !st.from.empty() { 321 st.from.sep = ", " 322 b.push("from", &st.from) 323 324 if !st.joins.empty() { 325 b.push(st.joins.q...) 326 } 327 } 328 if !st.where.empty() { 329 b.push("where", &st.where) 330 } 331 if !st.groupBy.empty() { 332 b.push("group by", paren(&st.groupBy)) 333 } 334 if !st.having.empty() { 335 b.push("having", &st.having) 336 } 337 if !st.orderBy.empty() { 338 b.push("order by", &st.orderBy) 339 } 340 if st.limit != nil { 341 b.push("limit", *st.limit) 342 } 343 if st.offset != nil { 344 b.push("offset", *st.offset) 345 } 346 347 return &b 348 } 349 350 type join struct { 351 typ string // join, inner join, full outer join, left join, right join 352 table builder 353 using group 354 on cond 355 } 356 357 func (st *join) On(f func(b Cond)) { 358 f(&st.on) 359 } 360 361 func (st *join) Using(col ...string) { 362 st.using.push(parenString(col...)) 363 } 364 365 func (st *join) build() []any { 366 var b buffer 367 b.push(st.typ, st.table) 368 if !st.using.empty() { 369 b.push("using") 370 b.push(&st.using) 371 } 372 if !st.on.empty() { 373 b.push("on", &st.on) 374 } 375 return b.q 376 } 377 378 type orderBy struct { 379 col string 380 direction string 381 nulls string 382 } 383 384 func (st *orderBy) Asc() OrderBy { 385 st.direction = "asc" 386 return st 387 } 388 389 func (st *orderBy) Desc() OrderBy { 390 st.direction = "desc" 391 return st 392 } 393 394 func (st *orderBy) NullsFirst() OrderBy { 395 st.nulls = "first" 396 return st 397 } 398 399 func (st *orderBy) NullsLast() OrderBy { 400 st.nulls = "last" 401 return st 402 } 403 404 func (st *orderBy) build() []any { 405 var b buffer 406 b.push(st.col) 407 if st.direction != "" { 408 b.push(st.direction) 409 } 410 if st.nulls != "" { 411 b.push("nulls", st.nulls) 412 } 413 return b.q 414 } 415 416 type values struct { 417 group 418 } 419 420 func (st *values) Value(value ...any) { 421 var x parenGroup 422 for _, v := range value { 423 x.push(Arg(v)) 424 } 425 st.push(&x) 426 } 427 428 func (st *values) Values(values ...[]any) { 429 for _, value := range values { 430 st.Value(value...) 431 } 432 } 433 434 type distinct struct { 435 columns parenGroup 436 } 437 438 func (st *distinct) On(col ...string) { 439 st.columns.pushString(col...) 440 }