github.com/mitranim/sqlb@v0.7.2/sqlb_expr.go (about) 1 package sqlb 2 3 import ( 4 "fmt" 5 r "reflect" 6 "strconv" 7 "strings" 8 ) 9 10 /* 11 Shortcut for interpolating strings into queries. Because this implements `Expr`, 12 when used as an argument in another expression, this will be directly 13 interpolated into the resulting query string. See the examples. 14 */ 15 type Str string 16 17 // Implement the `Expr` interface, making this a sub-expression. 18 func (self Str) AppendExpr(text []byte, args []any) ([]byte, []any) { 19 return self.AppendTo(text), args 20 } 21 22 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 23 // encoding. 24 func (self Str) AppendTo(text []byte) []byte { 25 return appendMaybeSpaced(text, string(self)) 26 } 27 28 // Implement the `fmt.Stringer` interface for debug purposes. 29 func (self Str) String() string { return string(self) } 30 31 // Represents an SQL identifier, always quoted. 32 type Ident string 33 34 // Implement the `Expr` interface, making this a sub-expression. 35 func (self Ident) AppendExpr(text []byte, args []any) ([]byte, []any) { 36 return self.AppendTo(text), args 37 } 38 39 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 40 // encoding. 41 func (self Ident) AppendTo(text []byte) []byte { 42 validateIdent(string(self)) 43 text = maybeAppendSpace(text) 44 text = append(text, quoteDouble) 45 text = append(text, self...) 46 text = append(text, quoteDouble) 47 return text 48 } 49 50 // Implement the `fmt.Stringer` interface for debug purposes. 51 func (self Ident) String() string { return AppenderString(&self) } 52 53 // Shortcut for internal use. 54 func (self Ident) BuiAppend(bui *Bui) { 55 bui.Text = self.AppendTo(bui.Text) 56 } 57 58 /* 59 Represents a nested SQL identifier where all elements are quoted but not 60 parenthesized. Useful for schema-qualified paths. For nested paths that don't 61 begin with a schema, use `Path` instead. 62 */ 63 type Identifier []string 64 65 // Implement the `Expr` interface, making this a sub-expression. 66 func (self Identifier) AppendExpr(text []byte, args []any) ([]byte, []any) { 67 return self.AppendTo(text), args 68 } 69 70 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 71 // encoding. 72 func (self Identifier) AppendTo(text []byte) []byte { 73 if len(self) == 0 { 74 return text 75 } 76 for ind, val := range self { 77 if ind > 0 { 78 text = append(text, `.`...) 79 } 80 text = Ident(val).AppendTo(text) 81 } 82 return text 83 } 84 85 // Implement the `fmt.Stringer` interface for debug purposes. 86 func (self Identifier) String() string { return AppenderString(&self) } 87 88 // Normalizes the expression, returning nil or a single `Ident` if the length 89 // allows this. Otherwise returns self as-is. 90 func (self Identifier) Norm() Expr { 91 switch len(self) { 92 case 0: 93 return Identifier(nil) 94 case 1: 95 return Ident(self[0]) 96 default: 97 return self 98 } 99 } 100 101 /* 102 Represents a nested SQL identifier where the first outer element is 103 parenthesized, and every element is quoted. Useful for nested paths that begin 104 with a table or view name. For schema-qualified paths, use `Identifier` 105 instead. 106 */ 107 type Path []string 108 109 // Implement the `Expr` interface, making this a sub-expression. 110 func (self Path) AppendExpr(text []byte, args []any) ([]byte, []any) { 111 return self.AppendTo(text), args 112 } 113 114 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 115 // encoding. 116 func (self Path) AppendTo(text []byte) []byte { 117 if len(self) == 0 { 118 return text 119 } 120 121 if len(self) == 1 { 122 return Ident(self[0]).AppendTo(text) 123 } 124 125 text = appendMaybeSpaced(text, `(`) 126 text = Ident(self[0]).AppendTo(text) 127 text = append(text, `)`...) 128 129 for _, val := range self[1:] { 130 text = append(text, `.`...) 131 text = Ident(val).AppendTo(text) 132 } 133 return text 134 } 135 136 // Implement the `fmt.Stringer` interface for debug purposes. 137 func (self Path) String() string { return AppenderString(&self) } 138 139 // Normalizes the expression, returning nil or a single `Ident` if the length 140 // allows this. Otherwise returns self as-is. 141 func (self Path) Norm() Expr { 142 switch len(self) { 143 case 0: 144 return Path(nil) 145 case 1: 146 return Ident(self[0]) 147 default: 148 return self 149 } 150 } 151 152 /* 153 Represents an arbitrarily-nested SQL path that gets encoded as a SINGLE quoted 154 identifier, where elements are dot-separated. This is a common convention for 155 nested structs, supported by SQL-scanning libraries such as 156 https://github.com/mitranim/gos. 157 */ 158 type PseudoPath []string 159 160 // Implement the `Expr` interface, making this a sub-expression. 161 func (self PseudoPath) AppendExpr(text []byte, args []any) ([]byte, []any) { 162 return self.AppendTo(text), args 163 } 164 165 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 166 // encoding. 167 func (self PseudoPath) AppendTo(text []byte) []byte { 168 if len(self) == 0 { 169 return text 170 } 171 172 text = maybeAppendSpace(text) 173 text = append(text, quoteDouble) 174 175 for ind, val := range self { 176 validateIdent(val) 177 if ind > 0 { 178 text = append(text, `.`...) 179 } 180 text = append(text, val...) 181 } 182 183 text = append(text, quoteDouble) 184 return text 185 } 186 187 // Implement the `fmt.Stringer` interface for debug purposes. 188 func (self PseudoPath) String() string { return AppenderString(&self) } 189 190 // Normalizes the expression, returning nil or a single `Ident` if the length 191 // allows this. Otherwise returns self as-is. 192 func (self PseudoPath) Norm() Expr { 193 switch len(self) { 194 case 0: 195 return PseudoPath(nil) 196 case 1: 197 return Ident(self[0]) 198 default: 199 return self 200 } 201 } 202 203 /* 204 Represents an arbitrarily-nested SQL path that gets encoded as `Path` followed 205 by `PseudoPath` alias. Useful for building "select" clauses. Used internally by 206 `ColsDeep`. 207 */ 208 type AliasedPath []string 209 210 // Implement the `Expr` interface, making this a sub-expression. 211 func (self AliasedPath) AppendExpr(text []byte, args []any) ([]byte, []any) { 212 return self.AppendTo(text), args 213 } 214 215 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 216 // encoding. 217 func (self AliasedPath) AppendTo(text []byte) []byte { 218 if len(self) == 0 { 219 return text 220 } 221 222 if len(self) == 1 { 223 return Ident(self[0]).AppendTo(text) 224 } 225 226 text = Path(self).AppendTo(text) 227 text = append(text, ` as `...) 228 text = PseudoPath(self).AppendTo(text) 229 return text 230 } 231 232 // Implement the `fmt.Stringer` interface for debug purposes. 233 func (self AliasedPath) String() string { return AppenderString(&self) } 234 235 // Normalizes the expression, returning nil or a single `Ident` if the length 236 // allows this. Otherwise returns self as-is. 237 func (self AliasedPath) Norm() Expr { 238 switch len(self) { 239 case 0: 240 return AliasedPath(nil) 241 case 1: 242 return Ident(self[0]) 243 default: 244 return self 245 } 246 } 247 248 /* 249 Same as `Identifier`, but preceded by the word "table". The SQL clause 250 "table some_name" is equivalent to "select * from some_name". 251 */ 252 type Table Identifier 253 254 // Implement the `Expr` interface, making this a sub-expression. 255 func (self Table) AppendExpr(text []byte, args []any) ([]byte, []any) { 256 return self.AppendTo(text), args 257 } 258 259 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 260 // encoding. 261 func (self Table) AppendTo(text []byte) []byte { 262 if len(self) == 0 { 263 return text 264 } 265 text = appendMaybeSpaced(text, `table`) 266 text = Identifier(self).AppendTo(text) 267 return text 268 } 269 270 // Implement the `fmt.Stringer` interface for debug purposes. 271 func (self Table) String() string { return AppenderString(&self) } 272 273 /* 274 Variable-sized sequence of expressions. When encoding, expressions will be 275 space-separated if necessary. 276 */ 277 type Exprs []Expr 278 279 // Implement the `Expr` interface, making this a sub-expression. 280 func (self Exprs) AppendExpr(text []byte, args []any) ([]byte, []any) { 281 bui := Bui{text, args} 282 for _, val := range self { 283 bui.Expr(val) 284 } 285 return bui.Get() 286 } 287 288 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 289 // encoding. 290 func (self Exprs) AppendTo(text []byte) []byte { return exprAppend(self, text) } 291 292 // Implement the `fmt.Stringer` interface for debug purposes. 293 func (self Exprs) String() string { return exprString(self) } 294 295 /* 296 Represents an SQL "any()" expression. The inner value may be an instance of 297 `Expr`, or an arbitrary argument. 298 */ 299 type Any [1]any 300 301 // Implement the `Expr` interface, making this a sub-expression. 302 func (self Any) AppendExpr(text []byte, args []any) ([]byte, []any) { 303 bui := Bui{text, args} 304 bui.Str(`any (`) 305 bui.Any(self[0]) 306 bui.Str(`)`) 307 return bui.Get() 308 } 309 310 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 311 // encoding. 312 func (self Any) AppendTo(text []byte) []byte { return exprAppend(self, text) } 313 314 // Implement the `fmt.Stringer` interface for debug purposes. 315 func (self Any) String() string { return exprString(self) } 316 317 /* 318 Represents an SQL assignment such as `"some_col" = arbitrary_expression`. The 319 LHS must be a column name, while the RHS can be an `Expr` instance or an 320 arbitrary argument. 321 */ 322 type Assign struct { 323 Lhs Ident 324 Rhs any 325 } 326 327 // Implement the `Expr` interface, making this a sub-expression. 328 func (self Assign) AppendExpr(text []byte, args []any) ([]byte, []any) { 329 bui := Bui{text, args} 330 bui.Any(self.Lhs) 331 bui.Str(`=`) 332 bui.SubAny(self.Rhs) 333 return bui.Get() 334 } 335 336 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 337 // encoding. 338 func (self Assign) AppendTo(text []byte) []byte { return exprAppend(self, text) } 339 340 // Implement the `fmt.Stringer` interface for debug purposes. 341 func (self Assign) String() string { return exprString(self) } 342 343 /* 344 Short for "equal". Represents SQL equality such as `A = B` or `A is null`. 345 Counterpart to `Neq`. 346 */ 347 type Eq [2]any 348 349 // Implement the `Expr` interface, making this a sub-expression. 350 func (self Eq) AppendExpr(text []byte, args []any) ([]byte, []any) { 351 text, args = self.AppendLhs(text, args) 352 text, args = self.AppendRhs(text, args) 353 return text, args 354 } 355 356 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 357 // encoding. 358 func (self Eq) AppendTo(text []byte) []byte { return exprAppend(self, text) } 359 360 // Implement the `fmt.Stringer` interface for debug purposes. 361 func (self Eq) String() string { return exprString(self) } 362 363 /* 364 Note: LHS and RHS are encoded differently because some SQL equality expressions 365 are asymmetric. For example, `any` allows an array only on the RHS, and there's 366 no way to invert it (AFAIK). 367 */ 368 func (self Eq) AppendLhs(text []byte, args []any) ([]byte, []any) { 369 bui := Bui{text, args} 370 bui.SubAny(self[0]) 371 return bui.Get() 372 } 373 374 func (self Eq) AppendRhs(text []byte, args []any) ([]byte, []any) { 375 bui := Bui{text, args} 376 val := norm(self[1]) 377 378 if val == nil { 379 bui.Str(`is null`) 380 return bui.Get() 381 } 382 383 bui.Str(`=`) 384 bui.SubAny(val) 385 return bui.Get() 386 } 387 388 /* 389 Short for "not equal". Represents SQL non-equality such as `A <> B` or 390 `A is not null`. Counterpart to `Eq`. 391 */ 392 type Neq [2]any 393 394 // Implement the `Expr` interface, making this a sub-expression. 395 func (self Neq) AppendExpr(text []byte, args []any) ([]byte, []any) { 396 text, args = self.AppendLhs(text, args) 397 text, args = self.AppendRhs(text, args) 398 return text, args 399 } 400 401 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 402 // encoding. 403 func (self Neq) AppendTo(text []byte) []byte { return exprAppend(self, text) } 404 405 // Implement the `fmt.Stringer` interface for debug purposes. 406 func (self Neq) String() string { return exprString(self) } 407 408 // See the comment on `Eq.AppendLhs`. 409 func (self Neq) AppendLhs(text []byte, args []any) ([]byte, []any) { 410 bui := Bui{text, args} 411 bui.SubAny(self[0]) 412 return bui.Get() 413 } 414 415 func (self Neq) AppendRhs(text []byte, args []any) ([]byte, []any) { 416 bui := Bui{text, args} 417 val := norm(self[1]) 418 419 if val == nil { 420 bui.Str(`is not null`) 421 return bui.Get() 422 } 423 424 bui.Str(`<>`) 425 bui.SubAny(val) 426 return bui.Get() 427 } 428 429 // Represents an SQL expression `A = any(B)`. Counterpart to `NeqAny`. 430 type EqAny [2]any 431 432 // Implement the `Expr` interface, making this a sub-expression. 433 func (self EqAny) AppendExpr(text []byte, args []any) ([]byte, []any) { 434 bui := Bui{text, args} 435 bui.SubAny(self[0]) 436 bui.Str(`=`) 437 bui.Set(Any{self[1]}.AppendExpr(bui.Get())) 438 return bui.Get() 439 } 440 441 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 442 // encoding. 443 func (self EqAny) AppendTo(text []byte) []byte { return exprAppend(self, text) } 444 445 // Implement the `fmt.Stringer` interface for debug purposes. 446 func (self EqAny) String() string { return exprString(self) } 447 448 // Represents an SQL expression `A <> any(B)`. Counterpart to `EqAny`. 449 type NeqAny [2]any 450 451 // Implement the `Expr` interface, making this a sub-expression. 452 func (self NeqAny) AppendExpr(text []byte, args []any) ([]byte, []any) { 453 bui := Bui{text, args} 454 bui.SubAny(self[0]) 455 bui.Str(`<>`) 456 bui.Set(Any{self[1]}.AppendExpr(bui.Get())) 457 return bui.Get() 458 } 459 460 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 461 // encoding. 462 func (self NeqAny) AppendTo(text []byte) []byte { return exprAppend(self, text) } 463 464 // Implement the `fmt.Stringer` interface for debug purposes. 465 func (self NeqAny) String() string { return exprString(self) } 466 467 // Represents SQL logical negation such as `not A`. The inner value can be an 468 // instance of `Expr` or an arbitrary argument. 469 type Not [1]any 470 471 // Implement the `Expr` interface, making this a sub-expression. 472 func (self Not) AppendExpr(text []byte, args []any) ([]byte, []any) { 473 bui := Bui{text, args} 474 bui.Str(`not`) 475 bui.SubAny(self[0]) 476 return bui.Get() 477 } 478 479 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 480 // encoding. 481 func (self Not) AppendTo(text []byte) []byte { return exprAppend(self, text) } 482 483 // Implement the `fmt.Stringer` interface for debug purposes. 484 func (self Not) String() string { return exprString(self) } 485 486 /* 487 Represents a sequence of arbitrary sub-expressions or arguments, joined with a 488 customizable delimiter, with a customizable fallback in case of empty list. 489 This is mostly an internal tool for building other sequences, such as `And` and 490 `Or`. The inner value may be nil or a single `Expr`, otherwise it must be a 491 slice. 492 */ 493 type Seq struct { 494 Empty string 495 Delim string 496 Val any 497 } 498 499 // Implement the `Expr` interface, making this a sub-expression. 500 func (self Seq) AppendExpr(text []byte, args []any) ([]byte, []any) { 501 bui := Bui{text, args} 502 val := self.Val 503 504 impl, _ := val.(Expr) 505 if impl != nil { 506 bui.Expr(impl) 507 } else { 508 self.any(&bui, val) 509 } 510 511 return bui.Get() 512 } 513 514 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 515 // encoding. 516 func (self Seq) AppendTo(text []byte) []byte { return exprAppend(self, text) } 517 518 // Implement the `fmt.Stringer` interface for debug purposes. 519 func (self Seq) String() string { return exprString(self) } 520 521 func (self *Seq) any(bui *Bui, val any) { 522 switch kindOf(val) { 523 case r.Invalid: 524 self.appendEmpty(bui) 525 case r.Slice: 526 self.appendSlice(bui, val) 527 default: 528 panic(errExpectedSlice(`building SQL expression`, val)) 529 } 530 } 531 532 func (self *Seq) appendEmpty(bui *Bui) { 533 bui.Str(self.Empty) 534 } 535 536 func (self Seq) appendSlice(bui *Bui, src any) { 537 val := valueOf(src) 538 539 if val.Len() == 0 { 540 self.appendEmpty(bui) 541 return 542 } 543 544 if val.Len() == 1 { 545 bui.Any(val.Index(0).Interface()) 546 return 547 } 548 549 for ind := range counter(val.Len()) { 550 if ind > 0 { 551 bui.Str(self.Delim) 552 } 553 bui.SubAny(val.Index(ind).Interface()) 554 } 555 } 556 557 /* 558 Represents a comma-separated list of arbitrary sub-expressions. The inner value 559 may be nil or a single `Expr`, otherwise it must be a slice. 560 */ 561 type Comma [1]any 562 563 // Implement the `Expr` interface, making this a sub-expression. 564 func (self Comma) AppendExpr(text []byte, args []any) ([]byte, []any) { 565 // May revise in the future. Some SQL expressions, such as composite literals 566 // expressed as strings, are sensitive to whitespace around commas. 567 return Seq{``, `, `, self[0]}.AppendExpr(text, args) 568 } 569 570 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 571 // encoding. 572 func (self Comma) AppendTo(text []byte) []byte { return exprAppend(self, text) } 573 574 // Implement the `fmt.Stringer` interface for debug purposes. 575 func (self Comma) String() string { return exprString(self) } 576 577 /* 578 Represents a sequence of arbitrary sub-expressions or arguments joined by the 579 SQL `and` operator. Rules for the inner value: 580 581 * nil or empty -> fallback to `true` 582 * single `Expr` -> render it as-is 583 * non-empty slice -> render its individual elements joined by `and` 584 * non-empty struct -> render column equality conditions joined by `and` 585 */ 586 type And [1]any 587 588 // Implement the `Expr` interface, making this a sub-expression. 589 func (self And) AppendExpr(text []byte, args []any) ([]byte, []any) { 590 return Cond{`true`, `and`, self[0]}.AppendExpr(text, args) 591 } 592 593 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 594 // encoding. 595 func (self And) AppendTo(text []byte) []byte { return exprAppend(self, text) } 596 597 // Implement the `fmt.Stringer` interface for debug purposes. 598 func (self And) String() string { return exprString(self) } 599 600 /* 601 Represents a sequence of arbitrary sub-expressions or arguments joined by the 602 SQL `or` operator. Rules for the inner value: 603 604 * nil or empty -> fallback to `false` 605 * single `Expr` -> render it as-is 606 * non-empty slice -> render its individual elements joined by `or` 607 * non-empty struct -> render column equality conditions joined by `or` 608 */ 609 type Or [1]any 610 611 // Implement the `Expr` interface, making this a sub-expression. 612 func (self Or) AppendExpr(text []byte, args []any) ([]byte, []any) { 613 return Cond{`false`, `or`, self[0]}.AppendExpr(text, args) 614 } 615 616 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 617 // encoding. 618 func (self Or) AppendTo(text []byte) []byte { return exprAppend(self, text) } 619 620 // Implement the `fmt.Stringer` interface for debug purposes. 621 func (self Or) String() string { return exprString(self) } 622 623 // Syntactic shortcut, same as `And` with a slice of sub-expressions or arguments. 624 type Ands []any 625 626 // Implement the `Expr` interface, making this a sub-expression. 627 func (self Ands) AppendExpr(text []byte, args []any) ([]byte, []any) { 628 if len(self) == 0 { 629 return And{}.AppendExpr(text, args) 630 } 631 return And{[]any(self)}.AppendExpr(text, args) 632 } 633 634 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 635 // encoding. 636 func (self Ands) AppendTo(text []byte) []byte { return exprAppend(self, text) } 637 638 // Implement the `fmt.Stringer` interface for debug purposes. 639 func (self Ands) String() string { return exprString(self) } 640 641 // Syntactic shortcut, same as `Or` with a slice of sub-expressions or arguments. 642 type Ors []any 643 644 // Implement the `Expr` interface, making this a sub-expression. 645 func (self Ors) AppendExpr(text []byte, args []any) ([]byte, []any) { 646 if len(self) == 0 { 647 return Or{}.AppendExpr(text, args) 648 } 649 return Or{[]any(self)}.AppendExpr(text, args) 650 } 651 652 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 653 // encoding. 654 func (self Ors) AppendTo(text []byte) []byte { return exprAppend(self, text) } 655 656 // Implement the `fmt.Stringer` interface for debug purposes. 657 func (self Ors) String() string { return exprString(self) } 658 659 /* 660 Superset of `Seq` with additional support for structs. When the inner value is 661 a struct, this generates a sequence of equality expressions, comparing the 662 struct's column names against the corresponding field values. Field values may 663 be arbitrary sub-expressions or arguments. 664 665 This is mostly an internal tool for building other expression types. Used 666 internally by `And` and `Or`. 667 */ 668 type Cond Seq 669 670 // Implement the `Expr` interface, making this a sub-expression. 671 func (self Cond) AppendExpr(text []byte, args []any) ([]byte, []any) { 672 bui := Bui{text, args} 673 val := self.Val 674 675 impl, _ := val.(Expr) 676 if impl != nil { 677 bui.Expr(impl) 678 } else { 679 self.any(&bui, val) 680 } 681 682 return bui.Get() 683 } 684 685 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 686 // encoding. 687 func (self Cond) AppendTo(text []byte) []byte { return exprAppend(self, text) } 688 689 // Implement the `fmt.Stringer` interface for debug purposes. 690 func (self Cond) String() string { return exprString(self) } 691 692 func (self *Cond) any(bui *Bui, val any) { 693 switch kindOf(val) { 694 case r.Invalid: 695 self.appendEmpty(bui) 696 case r.Struct: 697 self.appendStruct(bui, val) 698 case r.Slice: 699 self.appendSlice(bui, val) 700 default: 701 bui.Any(val) 702 } 703 } 704 705 func (self *Cond) appendEmpty(bui *Bui) { 706 (*Seq)(self).appendEmpty(bui) 707 } 708 709 // TODO consider if we should support nested non-embedded structs. 710 func (self *Cond) appendStruct(bui *Bui, src any) { 711 iter := makeIter(src) 712 713 for iter.next() { 714 if !iter.first() { 715 bui.Str(self.Delim) 716 } 717 718 lhs := Ident(FieldDbName(iter.field)) 719 rhs := Eq{nil, iter.value.Interface()} 720 721 // Equivalent to using `Eq` for the full expression, but avoids an 722 // allocation caused by converting `Ident` to `Expr`. As a bonus, this also 723 // avoids unnecessary parens around the ident. 724 bui.Set(lhs.AppendExpr(bui.Get())) 725 bui.Set(rhs.AppendRhs(bui.Get())) 726 } 727 728 if iter.empty() { 729 self.appendEmpty(bui) 730 } 731 } 732 733 func (self *Cond) appendSlice(bui *Bui, val any) { 734 (*Seq)(self).appendSlice(bui, val) 735 } 736 737 /* 738 Represents a column list for a "select" expression. The inner value may be of 739 any type, and is used as a type carrier; its actual value is ignored. If the 740 inner value is a struct or struct slice, the resulting expression is a list of 741 column names corresponding to its fields, using a "db" tag. Otherwise the 742 expression is `*`. 743 744 Unlike many other struct-scanning expressions, this doesn't support filtering 745 via `Sparse`. It operates at the level of a struct type, not an individual 746 struct value. 747 748 TODO actually support `Sparse` because it's used for insert. 749 */ 750 type Cols [1]any 751 752 // Implement the `Expr` interface, making this a sub-expression. 753 func (self Cols) AppendExpr(text []byte, args []any) ([]byte, []any) { 754 return self.AppendTo(text), args 755 } 756 757 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 758 // encoding. 759 func (self Cols) AppendTo(text []byte) []byte { 760 return appendMaybeSpaced(text, self.String()) 761 } 762 763 // Implement the `fmt.Stringer` interface for debug purposes. 764 func (self Cols) String() string { 765 return TypeCols(r.TypeOf(self[0])) 766 } 767 768 /* 769 Represents a column list for a "select" expression. The inner value may be of 770 any type, and is used as a type carrier; its actual value is ignored. If the 771 inner value is a struct or struct slice, the resulting expression is a list of 772 column names corresponding to its fields, using a "db" tag. Otherwise the 773 expression is `*`. 774 775 Unlike `Cols`, this has special support for nested structs and nested column 776 paths. See the examples. 777 778 Unlike many other struct-scanning expressions, this doesn't support filtering 779 via `Sparse`. It operates at the level of a struct type, not an individual 780 struct value. 781 */ 782 type ColsDeep [1]any 783 784 // Implement the `Expr` interface, making this a sub-expression. 785 func (self ColsDeep) AppendExpr(text []byte, args []any) ([]byte, []any) { 786 return self.AppendTo(text), args 787 } 788 789 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 790 // encoding. 791 func (self ColsDeep) AppendTo(text []byte) []byte { 792 return appendMaybeSpaced(text, self.String()) 793 } 794 795 // Implement the `fmt.Stringer` interface for debug purposes. 796 func (self ColsDeep) String() string { 797 return TypeColsDeep(r.TypeOf(self[0])) 798 } 799 800 /* 801 Represents comma-separated values from the "db"-tagged fields of an arbitrary 802 struct. Field/column names are ignored. Values may be arbitrary sub-expressions 803 or arguments. The value passed to `StructValues` may be nil, which is 804 equivalent to an empty struct. It may also be an arbitrarily-nested struct 805 pointer, which is automatically dereferenced. 806 807 Supports filtering. If the inner value implements `Sparse`, then not all fields 808 are considered to be "present", which is useful for PATCH semantics. See the 809 docs on `Sparse` and `Part`. 810 */ 811 type StructValues [1]any 812 813 // Implement the `Expr` interface, making this a sub-expression. 814 func (self StructValues) AppendExpr(text []byte, args []any) ([]byte, []any) { 815 bui := Bui{text, args} 816 iter := makeIter(self[0]) 817 // TODO consider panicking when empty. 818 iterAppendVals(&bui, iter, false) 819 return bui.Get() 820 } 821 822 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 823 // encoding. 824 func (self StructValues) AppendTo(text []byte) []byte { return exprAppend(self, text) } 825 826 // Implement the `fmt.Stringer` interface for debug purposes. 827 func (self StructValues) String() string { return exprString(self) } 828 829 /* 830 Represents a names-and-values clause suitable for insertion. The inner value 831 must be nil or a struct. Nil or empty struct generates a "default values" 832 clause. Otherwise the resulting expression has SQL column names and values 833 generated by scanning the input struct. See the examples. 834 835 Supports filtering. If the inner value implements `Sparse`, then not all fields 836 are considered to be "present", which is useful for PATCH semantics. See the 837 docs on `Sparse` and `Part`. 838 */ 839 type StructInsert [1]any 840 841 // Implement the `Expr` interface, making this a sub-expression. 842 func (self StructInsert) AppendExpr(text []byte, args []any) ([]byte, []any) { 843 bui := Bui{text, args} 844 iter := makeIter(self[0]) 845 846 /** 847 The condition is slightly suboptimal: if the source is `Sparse`, `iter.has` 848 may iterate the fields and invoke a filter for multiple fields which happen 849 to be "missing", until it finds one that is "present". Then we iterate to 850 append cols, and to append values, for a total of three loops. It would be 851 more optimal to iterate only for cols and values, not for the condition. 852 */ 853 if iter.has() { 854 bui.Str(`(`) 855 iterAppendCols(&bui, iter, false) 856 bui.Str(`)`) 857 bui.Str(`values (`) 858 iterAppendVals(&bui, iter, false) 859 bui.Str(`)`) 860 } else { 861 bui.Str(`default values`) 862 } 863 return bui.Get() 864 } 865 866 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 867 // encoding. 868 func (self StructInsert) AppendTo(text []byte) []byte { return exprAppend(self, text) } 869 870 // Implement the `fmt.Stringer` interface for debug purposes. 871 func (self StructInsert) String() string { return exprString(self) } 872 873 /* 874 Shortcut for creating `StructsInsert` from the given values. 875 Workaround for lack of type inference in type literals. 876 */ 877 func StructsInsertOf[A any](val ...A) StructsInsert[A] { return val } 878 879 /* 880 Variant of `StructInsert` that supports multiple structs. Generates a 881 names-and-values clause suitable for bulk insertion. The inner type must be a 882 struct. An empty slice generates an empty expression. See the examples. 883 */ 884 type StructsInsert[A any] []A 885 886 // Implement the `Expr` interface, making this a sub-expression. 887 func (self StructsInsert[A]) AppendExpr(text []byte, args []any) ([]byte, []any) { 888 if len(self) == 0 { 889 return text, args 890 } 891 892 bui := Bui{text, args} 893 894 bui.Str(`(`) 895 bui.Str(TypeCols(typeOf((*A)(nil)))) 896 bui.Str(`) values`) 897 898 for ind, val := range self { 899 if ind > 0 { 900 bui.Str(`, `) 901 } 902 bui.Str(`(`) 903 bui.Set(StructValues{val}.AppendExpr(bui.Get())) 904 bui.Str(`)`) 905 } 906 907 return bui.Get() 908 } 909 910 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 911 // encoding. 912 func (self StructsInsert[_]) AppendTo(text []byte) []byte { return exprAppend(self, text) } 913 914 // Implement the `fmt.Stringer` interface for debug purposes. 915 func (self StructsInsert[_]) String() string { return exprString(self) } 916 917 /* 918 Represents an SQL assignment clause suitable for "update set" operations. The 919 inner value must be a struct. The resulting expression consists of 920 comma-separated assignments with column names and values derived from the 921 provided struct. See the example. 922 923 Supports filtering. If the inner value implements `Sparse`, then not all fields 924 are considered to be "present", which is useful for PATCH semantics. See the 925 docs on `Sparse` and `Part`. If there are NO fields, panics with 926 `ErrEmptyAssign`, which can be detected by user code via `errors.Is`. 927 */ 928 type StructAssign [1]any 929 930 // Implement the `Expr` interface, making this a sub-expression. 931 func (self StructAssign) AppendExpr(text []byte, args []any) ([]byte, []any) { 932 bui := Bui{text, args} 933 iter := makeIter(self[0]) 934 935 for iter.next() { 936 if !iter.first() { 937 bui.Str(`,`) 938 } 939 bui.Set(Assign{ 940 Ident(FieldDbName(iter.field)), 941 iter.value.Interface(), 942 }.AppendExpr(bui.Get())) 943 } 944 945 if iter.empty() { 946 panic(ErrEmptyAssign) 947 } 948 949 return bui.Get() 950 } 951 952 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 953 // encoding. 954 func (self StructAssign) AppendTo(text []byte) []byte { return exprAppend(self, text) } 955 956 // Implement the `fmt.Stringer` interface for debug purposes. 957 func (self StructAssign) String() string { return exprString(self) } 958 959 /* 960 Wraps an arbitrary sub-expression, using `Cols{.Type}` to select specific 961 columns from it. If `.Type` doesn't specify a set of columns, for example 962 because it's not a struct type, then this uses the sub-expression as-is without 963 wrapping. Counterpart to `SelectColsDeep`. 964 */ 965 type SelectCols struct { 966 From Expr 967 Type any 968 } 969 970 // Implement the `Expr` interface, making this a sub-expression. 971 func (self SelectCols) AppendExpr(text []byte, args []any) ([]byte, []any) { 972 // Type-to-string is nearly free due to caching. 973 return SelectString{self.From, Cols{self.Type}.String()}.AppendExpr(text, args) 974 } 975 976 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 977 // encoding. 978 func (self SelectCols) AppendTo(text []byte) []byte { return exprAppend(self, text) } 979 980 // Implement the `fmt.Stringer` interface for debug purposes. 981 func (self SelectCols) String() string { return exprString(self) } 982 983 /* 984 Wraps an arbitrary sub-expression, using `ColsDeep{.Type}` to select specific 985 columns from it. If `.Type` doesn't specify a set of columns, for example 986 because it's not a struct type, then this uses the sub-expression as-is without 987 wrapping. Counterpart to `SelectCols`. 988 */ 989 type SelectColsDeep struct { 990 From Expr 991 Type any 992 } 993 994 // Implement the `Expr` interface, making this a sub-expression. 995 func (self SelectColsDeep) AppendExpr(text []byte, args []any) ([]byte, []any) { 996 // Type-to-string is nearly free due to caching. 997 return SelectString{self.From, ColsDeep{self.Type}.String()}.AppendExpr(text, args) 998 } 999 1000 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1001 // encoding. 1002 func (self SelectColsDeep) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1003 1004 // Implement the `fmt.Stringer` interface for debug purposes. 1005 func (self SelectColsDeep) String() string { return exprString(self) } 1006 1007 /* 1008 Represents an SQL expression "select .What from (.From) as _". Mostly an 1009 internal tool for building other expression types. Used internally by `Cols` 1010 and `ColsDeep`; see their docs and examples. 1011 */ 1012 type SelectString struct { 1013 From Expr 1014 What string 1015 } 1016 1017 // Implement the `Expr` interface, making this a sub-expression. 1018 func (self SelectString) AppendExpr(text []byte, args []any) ([]byte, []any) { 1019 bui := Bui{text, args} 1020 1021 if self.What == `*` { 1022 bui.Expr(self.From) 1023 return bui.Get() 1024 } 1025 1026 if self.From != nil { 1027 bui.Str(`with _ as (`) 1028 bui.Expr(self.From) 1029 bui.Str(`)`) 1030 } 1031 1032 bui.Str(`select`) 1033 bui.Str(self.What) 1034 1035 if self.From != nil { 1036 bui.Str(`from _`) 1037 } 1038 1039 return bui.Get() 1040 } 1041 1042 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1043 // encoding. 1044 func (self SelectString) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1045 1046 // Implement the `fmt.Stringer` interface for debug purposes. 1047 func (self SelectString) String() string { return exprString(self) } 1048 1049 /* 1050 Combines an expression with a string prefix. If the expr is nil, this is a nop, 1051 and the prefix is ignored. Mostly an internal tool for building other 1052 expression types. 1053 */ 1054 type Prefix struct { 1055 Prefix string 1056 Expr Expr 1057 } 1058 1059 // Implement the `Expr` interface, making this a sub-expression. 1060 func (self Prefix) AppendExpr(text []byte, args []any) ([]byte, []any) { 1061 return Wrap{self.Prefix, self.Expr, ``}.AppendExpr(text, args) 1062 } 1063 1064 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1065 // encoding. 1066 func (self Prefix) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1067 1068 // Implement the `fmt.Stringer` interface for debug purposes. 1069 func (self Prefix) String() string { return exprString(self) } 1070 1071 /* 1072 Combines an expression with a string prefix and suffix. If the expr is nil, this 1073 is a nop, and the prefix and suffix are ignored. Mostly an internal tool for 1074 building other expression types. 1075 */ 1076 type Wrap struct { 1077 Prefix string 1078 Expr Expr 1079 Suffix string 1080 } 1081 1082 // Difference from `Trio`: if the expr is nil, nothing is appended. 1083 // Implement the `Expr` interface, making this a sub-expression. 1084 func (self Wrap) AppendExpr(text []byte, args []any) ([]byte, []any) { 1085 bui := Bui{text, args} 1086 1087 if self.Expr != nil { 1088 bui.Str(self.Prefix) 1089 bui.Expr(self.Expr) 1090 bui.Str(self.Suffix) 1091 } 1092 1093 return bui.Get() 1094 } 1095 1096 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1097 // encoding. 1098 func (self Wrap) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1099 1100 // Implement the `fmt.Stringer` interface for debug purposes. 1101 func (self Wrap) String() string { return exprString(self) } 1102 1103 /* 1104 If the provided expression is not nil, prepends the keywords "order by" to it. 1105 If the provided expression is nil, this is a nop. 1106 */ 1107 type OrderBy [1]Expr 1108 1109 // Implement the `Expr` interface, making this a sub-expression. 1110 func (self OrderBy) AppendExpr(text []byte, args []any) ([]byte, []any) { 1111 return Prefix{`order by`, self[0]}.AppendExpr(text, args) 1112 } 1113 1114 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1115 // encoding. 1116 func (self OrderBy) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1117 1118 // Implement the `fmt.Stringer` interface for debug purposes. 1119 func (self OrderBy) String() string { return exprString(self) } 1120 1121 // Shortcut for simple "select * from A where B" expressions. See the examples. 1122 type Select struct { 1123 From Ident 1124 Where any 1125 } 1126 1127 // Implement the `Expr` interface, making this a sub-expression. 1128 func (self Select) AppendExpr(text []byte, args []any) ([]byte, []any) { 1129 bui := Bui{text, args} 1130 1131 bui.Str(`select * from`) 1132 bui.Set(self.From.AppendExpr(bui.Get())) 1133 1134 if self.Where != nil { 1135 bui.Str(`where`) 1136 bui.Set(And{self.Where}.AppendExpr(bui.Get())) 1137 } 1138 1139 return bui.Get() 1140 } 1141 1142 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1143 // encoding. 1144 func (self Select) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1145 1146 // Implement the `fmt.Stringer` interface for debug purposes. 1147 func (self Select) String() string { return exprString(self) } 1148 1149 // Shortcut for simple `insert into A (B) values (C)` expressions. 1150 // Also see `Insert` which appends `returning *`. 1151 type InsertVoid struct { 1152 Into Ident 1153 Fields any 1154 } 1155 1156 // Implement the `Expr` interface, making this a sub-expression. 1157 func (self InsertVoid) AppendExpr(text []byte, args []any) ([]byte, []any) { 1158 bui := Bui{text, args} 1159 1160 bui.Str(`insert into`) 1161 bui.Set(self.Into.AppendExpr(bui.Get())) 1162 bui.Set(StructInsert{self.Fields}.AppendExpr(bui.Get())) 1163 1164 return bui.Get() 1165 } 1166 1167 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1168 // encoding. 1169 func (self InsertVoid) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1170 1171 // Implement the `fmt.Stringer` interface for debug purposes. 1172 func (self InsertVoid) String() string { return exprString(self) } 1173 1174 // Shortcut for simple `insert into A (B) values (C) returning *` expressions. 1175 // See the examples. Also see `InsertVoid` which doesn't have `returning *`. 1176 type Insert InsertVoid 1177 1178 // Implement the `Expr` interface, making this a sub-expression. 1179 func (self Insert) AppendExpr(text []byte, args []any) ([]byte, []any) { 1180 text, args = InsertVoid(self).AppendExpr(text, args) 1181 text, args = ReturningAll{}.AppendExpr(text, args) 1182 return text, args 1183 } 1184 1185 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1186 // encoding. 1187 func (self Insert) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1188 1189 // Implement the `fmt.Stringer` interface for debug purposes. 1190 func (self Insert) String() string { return exprString(self) } 1191 1192 // Shortcut for simple `update A set B where C` expressions. 1193 // Also see `Update` which appends `returning *`. 1194 type UpdateVoid struct { 1195 What Ident 1196 Where any 1197 Fields any 1198 } 1199 1200 // Implement the `Expr` interface, making this a sub-expression. 1201 func (self UpdateVoid) AppendExpr(text []byte, args []any) ([]byte, []any) { 1202 bui := Bui{text, args} 1203 1204 bui.Str(`update`) 1205 bui.Set(self.What.AppendExpr(bui.Get())) 1206 1207 if self.Fields != nil { 1208 bui.Str(`set`) 1209 bui.Set(StructAssign{self.Fields}.AppendExpr(bui.Get())) 1210 } 1211 1212 // TODO: when empty, panic with `ErrEmptyAssign` (rename to `ErrEmpty`). 1213 if self.Where != nil { 1214 bui.Str(`where`) 1215 bui.Set(Cond{`null`, `and`, self.Where}.AppendExpr(bui.Get())) 1216 } 1217 1218 return bui.Get() 1219 } 1220 1221 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1222 // encoding. 1223 func (self UpdateVoid) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1224 1225 // Implement the `fmt.Stringer` interface for debug purposes. 1226 func (self UpdateVoid) String() string { return exprString(self) } 1227 1228 // Shortcut for simple `update A set B where C returning *` expressions. 1229 // See the examples. Also see `UpdateVoid` which doesn't have `returning *`. 1230 type Update UpdateVoid 1231 1232 // Implement the `Expr` interface, making this a sub-expression. 1233 func (self Update) AppendExpr(text []byte, args []any) ([]byte, []any) { 1234 text, args = UpdateVoid(self).AppendExpr(text, args) 1235 text, args = ReturningAll{}.AppendExpr(text, args) 1236 return text, args 1237 } 1238 1239 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1240 // encoding. 1241 func (self Update) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1242 1243 // Implement the `fmt.Stringer` interface for debug purposes. 1244 func (self Update) String() string { return exprString(self) } 1245 1246 // Shortcut for simple `delete from A where B` expressions. 1247 // Also see `Delete` which appends `returning *`. 1248 type DeleteVoid struct { 1249 From Ident 1250 Where any 1251 } 1252 1253 // Implement the `Expr` interface, making this a sub-expression. 1254 func (self DeleteVoid) AppendExpr(text []byte, args []any) ([]byte, []any) { 1255 bui := Bui{text, args} 1256 1257 bui.Str(`delete from`) 1258 bui.Set(self.From.AppendExpr(bui.Get())) 1259 1260 // TODO: when empty, panic with `ErrEmptyAssign` (rename to `ErrEmpty`). 1261 bui.Str(`where`) 1262 bui.Set(Cond{`null`, `and`, self.Where}.AppendExpr(bui.Get())) 1263 1264 return bui.Get() 1265 } 1266 1267 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1268 // encoding. 1269 func (self DeleteVoid) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1270 1271 // Implement the `fmt.Stringer` interface for debug purposes. 1272 func (self DeleteVoid) String() string { return exprString(self) } 1273 1274 // Shortcut for simple `delete from A where B returning *` expressions. 1275 // See the examples. Also see `DeleteVoid` which doesn't have `returning *`. 1276 type Delete DeleteVoid 1277 1278 // Implement the `Expr` interface, making this a sub-expression. 1279 func (self Delete) AppendExpr(text []byte, args []any) ([]byte, []any) { 1280 text, args = DeleteVoid(self).AppendExpr(text, args) 1281 text, args = ReturningAll{}.AppendExpr(text, args) 1282 return text, args 1283 } 1284 1285 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1286 // encoding. 1287 func (self Delete) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1288 1289 // Implement the `fmt.Stringer` interface for debug purposes. 1290 func (self Delete) String() string { return exprString(self) } 1291 1292 /* 1293 Represents an SQL upsert query like this: 1294 1295 insert into some_table 1296 (key_0, key_1, col_2, col_3) 1297 values 1298 ($1, $2, $3, $4) 1299 on conflict (key_0, key_1) 1300 do update set 1301 key_0 = excluded.key_0, 1302 key_1 = excluded.key_1, 1303 col_2 = excluded.col_2, 1304 col_3 = excluded.col_3 1305 1306 Notes: 1307 1308 * `.Keys` must be a struct. 1309 * `.Keys` supports `Sparse` and may be empty. 1310 * When `.Keys` is empty, this is equivalent to the `Insert` type. 1311 * `.Cols` must be a struct. 1312 * `.Cols` supports `Sparse` and may be empty. 1313 * `.Keys` provides names and values for key columns which participate 1314 in the `on conflict` clause. 1315 * `.Cols` provides names and values for other columns. 1316 1317 Also see `Upsert` which appends the `returning *` clause. 1318 */ 1319 type UpsertVoid struct { 1320 What Ident 1321 Keys any 1322 Cols any 1323 } 1324 1325 // Implement the `Expr` interface, making this a sub-expression. 1326 func (self UpsertVoid) AppendExpr(text []byte, args []any) ([]byte, []any) { 1327 keysIter := makeIter(self.Keys) 1328 if !keysIter.has() { 1329 return InsertVoid{self.What, self.Cols}.AppendExpr(text, args) 1330 } 1331 1332 bui := Bui{text, args} 1333 colsIter := makeIter(self.Cols) 1334 1335 bui.Str(`insert into`) 1336 bui.Set(self.What.AppendExpr(bui.Get())) 1337 1338 // Set of column names for insertion. 1339 // Adapted from `StructInsert`. 1340 { 1341 bui.Str(`(`) 1342 iterAppendCols(&bui, keysIter, false) 1343 iterAppendCols(&bui, colsIter, true) 1344 bui.Str(`)`) 1345 } 1346 1347 bui.Str(`values`) 1348 1349 // Set of column values for insertion. 1350 // Adapted from `StructInsert`. 1351 { 1352 bui.Str(`(`) 1353 iterAppendVals(&bui, keysIter, false) 1354 iterAppendVals(&bui, colsIter, true) 1355 bui.Str(`)`) 1356 } 1357 1358 // Conflict clause with key column names. 1359 { 1360 bui.Str(`on conflict (`) 1361 iterAppendCols(&bui, keysIter, false) 1362 bui.Str(`)`) 1363 } 1364 1365 // Assignment clauses for all columns. 1366 { 1367 bui.Str(`do update set`) 1368 upsertAppendAssignExcluded(&bui, keysIter, false) 1369 upsertAppendAssignExcluded(&bui, colsIter, true) 1370 } 1371 1372 return bui.Get() 1373 } 1374 1375 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1376 // encoding. 1377 func (self UpsertVoid) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1378 1379 // Implement the `fmt.Stringer` interface for debug purposes. 1380 func (self UpsertVoid) String() string { return exprString(self) } 1381 1382 // Same as `UpsertVoid` but also appends `returning *`. 1383 type Upsert UpsertVoid 1384 1385 // Implement the `Expr` interface, making this a sub-expression. 1386 func (self Upsert) AppendExpr(text []byte, args []any) ([]byte, []any) { 1387 text, args = UpsertVoid(self).AppendExpr(text, args) 1388 text, args = ReturningAll{}.AppendExpr(text, args) 1389 return text, args 1390 } 1391 1392 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1393 // encoding. 1394 func (self Upsert) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1395 1396 // Implement the `fmt.Stringer` interface for debug purposes. 1397 func (self Upsert) String() string { return exprString(self) } 1398 1399 func iterAppendCols(bui *Bui, iter iter, continued bool) { 1400 for iter.next() { 1401 if continued || !iter.first() { 1402 bui.Str(`,`) 1403 } 1404 Ident(FieldDbName(iter.field)).BuiAppend(bui) 1405 } 1406 } 1407 1408 func iterAppendVals(bui *Bui, iter iter, continued bool) { 1409 for iter.next() { 1410 if continued || !iter.first() { 1411 bui.Str(`,`) 1412 } 1413 bui.SubAny(iter.value.Interface()) 1414 } 1415 } 1416 1417 func upsertAppendAssignExcluded(bui *Bui, iter iter, continued bool) { 1418 for iter.next() { 1419 if continued || !iter.first() { 1420 bui.Str(`,`) 1421 } 1422 1423 name := Ident(FieldDbName(iter.field)) 1424 name.BuiAppend(bui) 1425 bui.Str(` = excluded.`) 1426 name.BuiAppend(bui) 1427 } 1428 } 1429 1430 /* 1431 Shortcut for selecting `count(*)` from an arbitrary sub-expression. Equivalent 1432 to `s.SelectString{expr, "count(*)"}`. 1433 */ 1434 type SelectCount [1]Expr 1435 1436 // Implement the `Expr` interface, making this a sub-expression. 1437 func (self SelectCount) AppendExpr(text []byte, args []any) ([]byte, []any) { 1438 return SelectString{self[0], `count(*)`}.AppendExpr(text, args) 1439 } 1440 1441 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1442 // encoding. 1443 func (self SelectCount) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1444 1445 // Implement the `fmt.Stringer` interface for debug purposes. 1446 func (self SelectCount) String() string { return exprString(self) } 1447 1448 /* 1449 Represents an SQL function call expression. The text prefix is optional and 1450 usually represents a function name. The args must be either nil, a single 1451 `Expr`, or a slice of arbitrary sub-expressions or arguments. 1452 */ 1453 type Call struct { 1454 Text string 1455 Args any 1456 } 1457 1458 // Implement the `Expr` interface, making this a sub-expression. 1459 func (self Call) AppendExpr(text []byte, args []any) ([]byte, []any) { 1460 bui := Bui{text, args} 1461 bui.Str(self.Text) 1462 1463 // TODO: when `self.Args` is a single expression, consider always additionally 1464 // parenthesizing it. `Comma` doesn't do that. 1465 bui.Str(`(`) 1466 bui.Set(Comma{self.Args}.AppendExpr(bui.Get())) 1467 bui.Str(`)`) 1468 1469 return bui.Get() 1470 } 1471 1472 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1473 // encoding. 1474 func (self Call) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1475 1476 // Implement the `fmt.Stringer` interface for debug purposes. 1477 func (self Call) String() string { return exprString(self) } 1478 1479 /* 1480 Represents the Postgres window function `row_number`: 1481 1482 RowNumberOver{} 1483 -> `0` 1484 1485 RowNumberOver{Ords{OrdDesc{Ident(`some_col`)}}} 1486 -> `row_number() over (order by "col" desc)` 1487 1488 When the inner expression is nil and the output is `0`, the Postgres query 1489 planner should be able to optimize it away. 1490 */ 1491 type RowNumberOver [1]Expr 1492 1493 // Implement the `Expr` interface, making this a sub-expression. 1494 func (self RowNumberOver) AppendExpr(text []byte, args []any) ([]byte, []any) { 1495 if self[0] == nil { 1496 return appendMaybeSpaced(text, `0`), args 1497 } 1498 1499 bui := Bui{text, args} 1500 bui.Str(`row_number() over (`) 1501 bui.Expr(self[0]) 1502 bui.Str(`)`) 1503 1504 return bui.Get() 1505 } 1506 1507 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1508 // encoding. 1509 func (self RowNumberOver) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1510 1511 // Implement the `fmt.Stringer` interface for debug purposes. 1512 func (self RowNumberOver) String() string { return exprString(self) } 1513 1514 /* 1515 Short for "string query". Represents an SQL query with parameters such as "$1" 1516 or ":param_name". Args may be a list of ordinal args (via `List`), a dictionary 1517 (via `Dict`), a struct (via `StructDict`), or an arbitrary user-defined 1518 implementation conforming to the interface. When generating the final 1519 expression, parameters are converted to Postgres-style ordinal parameters such 1520 as "$1". 1521 1522 Expressions/queries are composable. Named arguments that implement the `Expr` 1523 interface do not become ordinal parameters/arguments. Instead, they're treated 1524 as sub-expressions, and may include arbitrary text with their own arguments. 1525 Parameter collisions between outer and inner queries are completely avoided. 1526 1527 Uses `Preparse` to avoid redundant parsing. Each source string is parsed only 1528 once, and the resulting `Prep` is cached. As a result, `StrQ` has little 1529 measurable overhead. 1530 */ 1531 type StrQ struct { 1532 Text string 1533 Args ArgDict 1534 } 1535 1536 // Implement the `Expr` interface, making this a sub-expression. 1537 func (self StrQ) AppendExpr(text []byte, args []any) ([]byte, []any) { 1538 return Preparse(self.Text).AppendParamExpr(text, args, self.Args) 1539 } 1540 1541 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1542 // encoding. 1543 func (self StrQ) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1544 1545 // Implement the `fmt.Stringer` interface for debug purposes. 1546 func (self StrQ) String() string { return exprString(self) } 1547 1548 /* 1549 Short for "preparsed" or "prepared". Partially parsed representation of 1550 parametrized SQL expressions, suited for efficiently building SQL queries by 1551 providing arguments. Supports both ordinal and named parameters/arguments. To 1552 avoid redundant work, this should be parsed and cached only once for each SQL 1553 query; this deduplication is done by `Preparse` which is also used internally 1554 by `StrQ`. User code doesn't need to construct this. 1555 */ 1556 type Prep struct { 1557 Source string 1558 Tokens []Token 1559 HasParams bool 1560 } 1561 1562 // Parses `self.Source`, modifying the receiver. Panics if parsing fails. 1563 func (self *Prep) Parse() { 1564 /** 1565 This has all sorts of avoidable allocations, and could be significantly better 1566 optimized. However, parsing is ALWAYS slow. We cache the resulting `Prep` 1567 for each source string to avoid redundant parsing. 1568 */ 1569 1570 src := strings.TrimSpace(self.Source) 1571 tok := Tokenizer{Source: src, Transform: trimWhitespaceAndComments} 1572 1573 // Suboptimal, could be avoided. 1574 buf := make([]byte, 0, 128) 1575 1576 flush := func() { 1577 if len(buf) > 0 { 1578 // Suboptimal. It would be better to reslice the source string instead of 1579 // allocating new strings. 1580 self.Tokens = append(self.Tokens, Token{string(buf), TokenTypeText}) 1581 } 1582 buf = buf[:0] 1583 } 1584 1585 for { 1586 tok := tok.Next() 1587 if tok.IsInvalid() { 1588 break 1589 } 1590 1591 switch tok.Type { 1592 case TokenTypeOrdinalParam, TokenTypeNamedParam: 1593 flush() 1594 self.Tokens = append(self.Tokens, tok) 1595 self.HasParams = true 1596 1597 default: 1598 buf = append(buf, tok.Text...) 1599 } 1600 } 1601 1602 flush() 1603 } 1604 1605 // Implement the `ParamExpr` interface. Builds the expression by using the 1606 // provided named args. Used internally by `StrQ`. 1607 func (self Prep) AppendParamExpr(text []byte, args []any, dict ArgDict) ([]byte, []any) { 1608 if !self.HasParams { 1609 return self.appendUnparametrized(text, args, dict) 1610 } 1611 return self.appendParametrized(text, args, dict) 1612 } 1613 1614 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1615 // encoding. 1616 func (self Prep) AppendTo(text []byte) []byte { 1617 return Str(self.Source).AppendTo(text) 1618 } 1619 1620 // Implement the `fmt.Stringer` interface for debug purposes. 1621 func (self Prep) String() string { return self.Source } 1622 1623 func (self Prep) appendUnparametrized(text []byte, args []any, dict ArgDict) ([]byte, []any) { 1624 src := self.Source 1625 if !isNil(dict) { 1626 panic(errUnexpectedArgs(fmt.Sprintf(`non-parametrized expression %q`, src), dict)) 1627 } 1628 return Str(src).AppendExpr(text, args) 1629 } 1630 1631 func (self Prep) appendParametrized(text []byte, args []any, dict ArgDict) ([]byte, []any) { 1632 if dict == nil { 1633 panic(errMissingArgs(fmt.Sprintf(`parametrized expression %q`, self.Source))) 1634 } 1635 1636 bui := Bui{text, args} 1637 bui.Grow(len(self.Source), dict.Len()) 1638 1639 tracker := getArgTracker() 1640 defer tracker.put() 1641 1642 for _, tok := range self.Tokens { 1643 switch tok.Type { 1644 case TokenTypeOrdinalParam: 1645 // Parsing the token here is slightly suboptimal, we should preparse numbers. 1646 appendOrdinal(&bui, dict, tracker, tok.ParseOrdinalParam()) 1647 1648 case TokenTypeNamedParam: 1649 appendNamed(&bui, dict, tracker, tok.ParseNamedParam()) 1650 1651 default: 1652 bui.Text = append(bui.Text, tok.Text...) 1653 } 1654 } 1655 1656 if ValidateUnusedArguments { 1657 tracker.validate(dict) 1658 } 1659 return bui.Get() 1660 } 1661 1662 /** 1663 The implementation of both `appendOrdinal` and `appendNamed` should be roughly 1664 equivalent to `bui.Any(arg)`, but more efficient for parameters that occur more 1665 than once. We map each SOURCE PARAMETER to exactly one TARGET PARAMETER and one 1666 ARGUMENT. If it was simply appended via `bui.Any(arg)`, then every occurrence 1667 would generate another argument. 1668 1669 The cost of keeping track of found parameters is amortized by recycling them in 1670 a pool. It saves us the cost of redundant encoding of those arguments, which is 1671 potentially much larger, for example when an argument is a huge array. 1672 1673 Keeping track of found PARAMETERS also allows us to validate that all ARGUMENTS 1674 are used. 1675 */ 1676 func appendOrdinal(bui *Bui, args ArgDict, tracker *argTracker, key OrdinalParam) { 1677 arg, ok := args.GotOrdinal(key.Index()) 1678 if !ok { 1679 panic(errMissingOrdinal(key)) 1680 } 1681 1682 impl, _ := arg.(Expr) 1683 if impl != nil { 1684 // Allows validation of used args. 1685 tracker.SetOrdinal(key, 0) 1686 bui.Expr(impl) 1687 return 1688 } 1689 1690 ord, ok := tracker.GotOrdinal(key) 1691 if ok { 1692 bui.OrphanParam(ord) 1693 return 1694 } 1695 1696 ord = bui.OrphanArg(arg) 1697 bui.OrphanParam(ord) 1698 tracker.SetOrdinal(key, ord) 1699 } 1700 1701 func appendNamed(bui *Bui, args ArgDict, tracker *argTracker, key NamedParam) { 1702 arg, ok := args.GotNamed(key.Key()) 1703 if !ok { 1704 panic(errMissingNamed(key)) 1705 } 1706 1707 impl, _ := arg.(Expr) 1708 if impl != nil { 1709 // Allows validation of used args. 1710 tracker.SetNamed(key, 0) 1711 bui.Expr(impl) 1712 return 1713 } 1714 1715 ord, ok := tracker.GotNamed(key) 1716 if ok { 1717 bui.OrphanParam(ord) 1718 return 1719 } 1720 1721 ord = bui.OrphanArg(arg) 1722 bui.OrphanParam(ord) 1723 tracker.SetNamed(key, ord) 1724 } 1725 1726 // Represents an ordinal parameter such as "$1". Mostly for internal use. 1727 type OrdinalParam int 1728 1729 // Implement the `Expr` interface, making this a sub-expression. 1730 func (self OrdinalParam) AppendExpr(text []byte, args []any) ([]byte, []any) { 1731 return self.AppendTo(text), args 1732 } 1733 1734 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1735 // encoding. 1736 func (self OrdinalParam) AppendTo(text []byte) []byte { 1737 text = append(text, ordinalParamPrefix) 1738 text = strconv.AppendInt(text, int64(self), 10) 1739 return text 1740 } 1741 1742 // Implement the `fmt.Stringer` interface for debug purposes. 1743 func (self OrdinalParam) String() string { return AppenderString(&self) } 1744 1745 // Returns the corresponding Go index (starts at zero). 1746 func (self OrdinalParam) Index() int { return int(self) - 1 } 1747 1748 // Inverse of `OrdinalParam.Index`: increments by 1, converting index to param. 1749 func (self OrdinalParam) FromIndex() OrdinalParam { return self + 1 } 1750 1751 // Represents a named parameter such as ":blah". Mostly for internal use. 1752 type NamedParam string 1753 1754 // Implement the `Expr` interface, making this a sub-expression. 1755 func (self NamedParam) AppendExpr(text []byte, args []any) ([]byte, []any) { 1756 return self.AppendTo(text), args 1757 } 1758 1759 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1760 // encoding. 1761 func (self NamedParam) AppendTo(text []byte) []byte { 1762 text = append(text, namedParamPrefix) 1763 text = append(text, self...) 1764 return text 1765 } 1766 1767 // Implement the `fmt.Stringer` interface for debug purposes. 1768 func (self NamedParam) String() string { return AppenderString(&self) } 1769 1770 // Converts to the corresponding dictionary key, which is a plain string. This 1771 // is a free cast, used to increase code clarity. 1772 func (self NamedParam) Key() string { return string(self) } 1773 1774 /* 1775 Represents SQL expression "limit N" with an arbitrary argument or 1776 sub-expression. Implements `Expr`: 1777 1778 * If nil -> append nothing. 1779 * If expr -> append "limit (<sub-expression>)". 1780 * If val -> append "limit $N" with the corresponding argument. 1781 */ 1782 type Limit [1]any 1783 1784 // Implement the `Expr` interface, making this a sub-expression. 1785 func (self Limit) AppendExpr(text []byte, args []any) ([]byte, []any) { 1786 return appendPrefixSub(text, args, `limit`, self[0]) 1787 } 1788 1789 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1790 // encoding. 1791 func (self Limit) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1792 1793 // Implement the `fmt.Stringer` interface for debug purposes. 1794 func (self Limit) String() string { return AppenderString(&self) } 1795 1796 /* 1797 Represents SQL expression "offset N" with an arbitrary sub-expression. 1798 Implements `Expr`: 1799 1800 * If nil -> append nothing. 1801 * If expr -> append "offset (<sub-expression>)". 1802 * If val -> append "offset $N" with the corresponding argument. 1803 */ 1804 type Offset [1]any 1805 1806 // Implement the `Expr` interface, making this a sub-expression. 1807 func (self Offset) AppendExpr(text []byte, args []any) ([]byte, []any) { 1808 return appendPrefixSub(text, args, `offset`, self[0]) 1809 } 1810 1811 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1812 // encoding. 1813 func (self Offset) AppendTo(text []byte) []byte { return exprAppend(self, text) } 1814 1815 // Implement the `fmt.Stringer` interface for debug purposes. 1816 func (self Offset) String() string { return AppenderString(&self) } 1817 1818 /* 1819 Represents SQL expression "limit N" with a number. Implements `Expr`: 1820 1821 * If 0 -> append nothing. 1822 * Otherwise -> append literal "limit <N>" such as "limit 1". 1823 1824 Because this is uint64, you can safely and correctly decode arbitrary user input 1825 into this value, for example into a struct field of this type. 1826 */ 1827 type LimitUint uint64 1828 1829 // Implement the `Expr` interface, making this a sub-expression. 1830 func (self LimitUint) AppendExpr(text []byte, args []any) ([]byte, []any) { 1831 return self.AppendTo(text), args 1832 } 1833 1834 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1835 // encoding. 1836 func (self LimitUint) AppendTo(text []byte) []byte { 1837 return appendIntWith(text, `limit`, int64(self)) 1838 } 1839 1840 // Implement the `fmt.Stringer` interface for debug purposes. 1841 func (self LimitUint) String() string { return AppenderString(&self) } 1842 1843 /* 1844 Represents SQL expression "offset N" with a number. Implements `Expr`: 1845 1846 * If 0 -> append nothing. 1847 * Otherwise -> append literal "offset <N>" such as "offset 1". 1848 1849 Because this is uint64, you can safely and correctly decode arbitrary user input 1850 into this value, for example into a struct field of this type. 1851 */ 1852 type OffsetUint uint64 1853 1854 // Implement the `Expr` interface, making this a sub-expression. 1855 func (self OffsetUint) AppendExpr(text []byte, args []any) ([]byte, []any) { 1856 return self.AppendTo(text), args 1857 } 1858 1859 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1860 // encoding. 1861 func (self OffsetUint) AppendTo(text []byte) []byte { 1862 return appendIntWith(text, `offset`, int64(self)) 1863 } 1864 1865 // Implement the `fmt.Stringer` interface for debug purposes. 1866 func (self OffsetUint) String() string { return AppenderString(&self) } 1867 1868 // Represents the Postgres `returning *` clause. 1869 type ReturningAll struct{} 1870 1871 // Implement the `Expr` interface, making this a sub-expression. 1872 func (self ReturningAll) AppendExpr(text []byte, args []any) ([]byte, []any) { 1873 return self.AppendTo(text), args 1874 } 1875 1876 // Implement the `AppenderTo` interface, sometimes allowing more efficient text 1877 // encoding. 1878 func (self ReturningAll) AppendTo(text []byte) []byte { 1879 return appendMaybeSpaced(text, self.String()) 1880 } 1881 1882 // Implement the `fmt.Stringer` interface for debug purposes. 1883 func (ReturningAll) String() string { return `returning *` }