github.com/yongjacky/phoenix-go-orm-builder@v0.3.5/builder_limit.go (about)

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