builder_limit.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Copyright 2018 The Xorm Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package builder
  5. import (
  6. "fmt"
  7. "strings"
  8. )
  9. func (b *Builder) limitWriteTo(w Writer) error {
  10. if strings.TrimSpace(b.dialect) == "" {
  11. return ErrDialectNotSetUp
  12. }
  13. if b.limitation != nil {
  14. limit := b.limitation
  15. if limit.offset < 0 || limit.limitN <= 0 {
  16. return ErrInvalidLimitation
  17. }
  18. // erase limit condition
  19. b.limitation = nil
  20. ow := w.(*BytesWriter)
  21. switch strings.ToLower(strings.TrimSpace(b.dialect)) {
  22. case ORACLE:
  23. if len(b.selects) == 0 {
  24. b.selects = append(b.selects, "*")
  25. }
  26. var final *Builder
  27. selects := b.selects
  28. b.selects = append(selects, "ROWNUM RN")
  29. var wb *Builder
  30. if b.optype == unionType {
  31. wb = Dialect(b.dialect).Select("at.*", "ROWNUM RN").
  32. From(b, "at")
  33. } else {
  34. wb = b
  35. }
  36. if limit.offset == 0 {
  37. final = Dialect(b.dialect).Select(selects...).From(wb, "at").
  38. Where(Lte{"at.RN": limit.limitN})
  39. } else {
  40. sub := Dialect(b.dialect).Select("*").
  41. From(b, "at").Where(Lte{"at.RN": limit.offset + limit.limitN})
  42. final = Dialect(b.dialect).Select(selects...).From(sub, "att").
  43. Where(Gt{"att.RN": limit.offset})
  44. }
  45. return final.WriteTo(ow)
  46. case SQLITE, MYSQL, POSTGRES:
  47. // if type UNION, we need to write previous content back to current writer
  48. if b.optype == unionType {
  49. b.WriteTo(ow)
  50. }
  51. if limit.offset == 0 {
  52. fmt.Fprint(ow, " LIMIT ", limit.limitN)
  53. } else {
  54. fmt.Fprintf(ow, " LIMIT %v OFFSET %v", limit.limitN, limit.offset)
  55. }
  56. case MSSQL:
  57. if len(b.selects) == 0 {
  58. b.selects = append(b.selects, "*")
  59. }
  60. var final *Builder
  61. selects := b.selects
  62. b.selects = append(append([]string{fmt.Sprintf("TOP %d %v", limit.limitN+limit.offset, b.selects[0])},
  63. b.selects[1:]...), "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN")
  64. var wb *Builder
  65. if b.optype == unionType {
  66. wb = Dialect(b.dialect).Select("*", "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN").
  67. From(b, "at")
  68. } else {
  69. wb = b
  70. }
  71. if limit.offset == 0 {
  72. final = Dialect(b.dialect).Select(selects...).From(wb, "at")
  73. } else {
  74. final = Dialect(b.dialect).Select(selects...).From(wb, "at").Where(Gt{"at.RN": limit.offset})
  75. }
  76. return final.WriteTo(ow)
  77. default:
  78. return ErrNotSupportType
  79. }
  80. }
  81. return nil
  82. }