You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

builder_limit.go 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. defer func() {
  21. b.limitation = limit
  22. }()
  23. ow := w.(*BytesWriter)
  24. switch strings.ToLower(strings.TrimSpace(b.dialect)) {
  25. case ORACLE:
  26. if len(b.selects) == 0 {
  27. b.selects = append(b.selects, "*")
  28. }
  29. var final *Builder
  30. selects := b.selects
  31. b.selects = append(selects, "ROWNUM RN")
  32. var wb *Builder
  33. if b.optype == setOpType {
  34. wb = Dialect(b.dialect).Select("at.*", "ROWNUM RN").
  35. From(b, "at")
  36. } else {
  37. wb = b
  38. }
  39. if limit.offset == 0 {
  40. final = Dialect(b.dialect).Select(selects...).From(wb, "at").
  41. Where(Lte{"at.RN": limit.limitN})
  42. } else {
  43. sub := Dialect(b.dialect).Select("*").
  44. From(b, "at").Where(Lte{"at.RN": limit.offset + limit.limitN})
  45. final = Dialect(b.dialect).Select(selects...).From(sub, "att").
  46. Where(Gt{"att.RN": limit.offset})
  47. }
  48. return final.WriteTo(ow)
  49. case SQLITE, MYSQL, POSTGRES:
  50. // if type UNION, we need to write previous content back to current writer
  51. if b.optype == setOpType {
  52. if err := b.WriteTo(ow); err != nil {
  53. return err
  54. }
  55. }
  56. if limit.offset == 0 {
  57. fmt.Fprint(ow, " LIMIT ", limit.limitN)
  58. } else {
  59. fmt.Fprintf(ow, " LIMIT %v OFFSET %v", limit.limitN, limit.offset)
  60. }
  61. case MSSQL:
  62. if len(b.selects) == 0 {
  63. b.selects = append(b.selects, "*")
  64. }
  65. var final *Builder
  66. selects := b.selects
  67. b.selects = append(append([]string{fmt.Sprintf("TOP %d %v", limit.limitN+limit.offset, b.selects[0])},
  68. b.selects[1:]...), "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN")
  69. var wb *Builder
  70. if b.optype == setOpType {
  71. wb = Dialect(b.dialect).Select("*", "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN").
  72. From(b, "at")
  73. } else {
  74. wb = b
  75. }
  76. if limit.offset == 0 {
  77. final = Dialect(b.dialect).Select(selects...).From(wb, "at")
  78. } else {
  79. final = Dialect(b.dialect).Select(selects...).From(wb, "at").Where(Gt{"at.RN": limit.offset})
  80. }
  81. return final.WriteTo(ow)
  82. default:
  83. return ErrNotSupportType
  84. }
  85. }
  86. return nil
  87. }