@@ -776,23 +776,16 @@ func (v ViewOptions) BuildWhere(args *[]any) []string {
776776 case ViewDesignDocs :
777777 where = append (where , `view.key LIKE '"_design/%'` )
778778 }
779- if v .endkey != "" {
779+ where = append (where , v .PaginationOptions .BuildWhere (args )... )
780+ if v .endkey != "" && v .endkeyDocID != "" {
780781 op := endKeyOp (v .descending , v .inclusiveEnd )
781- where = append (where , fmt .Sprintf ("view.key %s $%d" , op , len (* args )+ 1 ))
782- * args = append (* args , v .endkey )
783- if v .endkeyDocID != "" {
784- where = append (where , fmt .Sprintf ("view.id %s $%d" , op , len (* args )+ 1 ))
785- * args = append (* args , v .endkeyDocID )
786- }
782+ where = append (where , fmt .Sprintf ("view.id %s $%d" , op , len (* args )+ 1 ))
783+ * args = append (* args , v .endkeyDocID )
787784 }
788- if v .startkey != "" {
785+ if v .startkey != "" && v . startkeyDocID != "" {
789786 op := startKeyOp (v .descending )
790- where = append (where , fmt .Sprintf ("view.key %s $%d" , op , len (* args )+ 1 ))
791- * args = append (* args , v .startkey )
792- if v .startkeyDocID != "" {
793- where = append (where , fmt .Sprintf ("view.id %s $%d" , op , len (* args )+ 1 ))
794- * args = append (* args , v .startkeyDocID )
795- }
787+ where = append (where , fmt .Sprintf ("view.id %s $%d" , op , len (* args )+ 1 ))
788+ * args = append (* args , v .startkeyDocID )
796789 }
797790 if v .key != "" {
798791 where = append (where , "view.key = $" + strconv .Itoa (len (* args )+ 1 ))
@@ -807,19 +800,6 @@ func (v ViewOptions) BuildWhere(args *[]any) []string {
807800 return where
808801}
809802
810- // BuildOrderBy returns an ORDER BY clause based on the provided configuration.
811- func (v ViewOptions ) BuildOrderBy (moreColumns ... string ) string {
812- if v .sorted {
813- direction := descendingToDirection (v .descending )
814- conditions := make ([]string , 0 , len (moreColumns )+ 1 )
815- for _ , col := range append ([]string {"key" }, moreColumns ... ) {
816- conditions = append (conditions , "view." + col + " " + direction )
817- }
818- return "ORDER BY " + strings .Join (conditions , ", " )
819- }
820- return ""
821- }
822-
823803// ReduceGroupLevel returns the calculated groupLevel value to pass to
824804// [github.com/go-kivik/kivik/v4/x/sqlite/reduce.Reduce].
825805//
@@ -838,18 +818,13 @@ func (v ViewOptions) ReduceGroupLevel() int {
838818//
839819// See https://docs.couchdb.org/en/stable/api/ddoc/views.html#api-ddoc-view
840820type ViewOptions struct {
821+ PaginationOptions
841822 view string
842- limit int64
843- skip int64
844- descending bool
845823 includeDocs bool
846824 conflicts bool
847825 reduce * bool
848826 group bool
849827 groupLevel uint64
850- endkey string
851- startkey string
852- inclusiveEnd bool
853828 attachments bool
854829 update string
855830 updateSeq bool
@@ -918,10 +893,12 @@ func FindOptions(query any) (*ViewOptions, error) {
918893 }
919894
920895 v := & ViewOptions {
896+ PaginationOptions : PaginationOptions {
897+ limit : - 1 ,
898+ },
921899 view : ViewAllDocs ,
922900 conflicts : conflicts ,
923901 includeDocs : true ,
924- limit : - 1 ,
925902 findLimit : limit ,
926903 findSkip : skip ,
927904 selector : s .Selector ,
@@ -935,11 +912,7 @@ func FindOptions(query any) (*ViewOptions, error) {
935912
936913// ViewOptions returns the viewOptions for the given view name.
937914func (o Map ) ViewOptions (view string ) (* ViewOptions , error ) {
938- limit , err := o .Limit ()
939- if err != nil {
940- return nil , err
941- }
942- skip , err := o .Skip ()
915+ pagination , err := o .PaginationOptions (false )
943916 if err != nil {
944917 return nil , err
945918 }
@@ -967,18 +940,6 @@ func (o Map) ViewOptions(view string) (*ViewOptions, error) {
967940 if err != nil {
968941 return nil , err
969942 }
970- descending , err := o .Descending ()
971- if err != nil {
972- return nil , err
973- }
974- endkey , err := o .EndKey ()
975- if err != nil {
976- return nil , err
977- }
978- startkey , err := o .StartKey ()
979- if err != nil {
980- return nil , err
981- }
982943 includeDocs , err := o .IncludeDocs ()
983944 if err != nil {
984945 return nil , err
@@ -987,10 +948,6 @@ func (o Map) ViewOptions(view string) (*ViewOptions, error) {
987948 if err != nil {
988949 return nil , err
989950 }
990- inclusiveEnd , err := o .InclusiveEnd ()
991- if err != nil {
992- return nil , err
993- }
994951 update , err := o .Update ()
995952 if err != nil {
996953 return nil , err
@@ -1015,7 +972,7 @@ func (o Map) ViewOptions(view string) (*ViewOptions, error) {
1015972 if err != nil {
1016973 return nil , err
1017974 }
1018- if len (keys ) > 0 && (key != "" || endkey != "" || startkey != "" ) {
975+ if len (keys ) > 0 && (key != "" || pagination . endkey != "" || pagination . startkey != "" ) {
1019976 return nil , & internal.Error {Status : http .StatusBadRequest , Message : "`keys` is incompatible with `key`, `start_key` and `end_key`" }
1020977 }
1021978 sorted , err := o .Sorted ()
@@ -1028,40 +985,33 @@ func (o Map) ViewOptions(view string) (*ViewOptions, error) {
1028985 }
1029986
1030987 v := & ViewOptions {
1031- view : view ,
1032- limit : limit ,
1033- skip : skip ,
1034- descending : descending ,
1035- includeDocs : includeDocs ,
1036- conflicts : conflicts ,
1037- reduce : reduce ,
1038- group : group ,
1039- groupLevel : groupLevel ,
1040- endkey : endkey ,
1041- startkey : startkey ,
1042- inclusiveEnd : inclusiveEnd ,
1043- attachments : attachments ,
1044- update : update ,
1045- updateSeq : updateSeq ,
1046- endkeyDocID : endkeyDocID ,
1047- startkeyDocID : startkeyDocID ,
1048- key : key ,
1049- keys : keys ,
1050- sorted : sorted ,
1051- attEncodingInfo : attEncodingInfo ,
988+ PaginationOptions : * pagination ,
989+ view : view ,
990+ includeDocs : includeDocs ,
991+ conflicts : conflicts ,
992+ reduce : reduce ,
993+ group : group ,
994+ groupLevel : groupLevel ,
995+ attachments : attachments ,
996+ update : update ,
997+ updateSeq : updateSeq ,
998+ endkeyDocID : endkeyDocID ,
999+ startkeyDocID : startkeyDocID ,
1000+ key : key ,
1001+ keys : keys ,
1002+ sorted : sorted ,
1003+ attEncodingInfo : attEncodingInfo ,
10521004 }
10531005 return v , v .Validate ()
10541006}
10551007
10561008// Validate returns an error if the options are invalid.
10571009func (v ViewOptions ) Validate () error {
1058- descendingModifier := 1
1059- if v .descending {
1060- descendingModifier = - 1
1061- }
1062- if v .endkey != "" && v .startkey != "" && couchdbCmpString (v .startkey , v .endkey )* descendingModifier > 0 {
1063- return & internal.Error {Status : http .StatusBadRequest , Message : fmt .Sprintf ("no rows can match your key range, reverse your start_key and end_key or set descending=%v" , ! v .descending )}
1010+ if err := v .PaginationOptions .Validate (); err != nil {
1011+ return err
10641012 }
1013+ descendingModifier := v .descendingModifier ()
1014+
10651015 if v .key != "" {
10661016 startFail := v .startkey != "" && couchdbCmpString (v .key , v .startkey )* descendingModifier < 0
10671017 endFail := v .endkey != "" && couchdbCmpString (v .key , v .endkey )* descendingModifier > 0
@@ -1100,13 +1050,6 @@ func startKeyOp(descending bool) string {
11001050 return ">="
11011051}
11021052
1103- func descendingToDirection (descending bool ) string {
1104- if descending {
1105- return "DESC"
1106- }
1107- return "ASC"
1108- }
1109-
11101053func isBuiltinView (view string ) bool {
11111054 switch view {
11121055 case ViewAllDocs , ViewLocalDocs , ViewDesignDocs :
0 commit comments