@@ -21,6 +21,7 @@ import {
2121 aggregate ,
2222 buildFieldRef ,
2323 buildJoinPairs ,
24+ ensureArray ,
2425 flattenCompoundUniqueFilters ,
2526 getDelegateDescendantModels ,
2627 getIdFields ,
@@ -58,6 +59,54 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
5859 return result ;
5960 }
6061
62+ buildFilterSortTake (
63+ model : GetModels < Schema > ,
64+ args : FindArgs < Schema , GetModels < Schema > , true > ,
65+ query : SelectQueryBuilder < any , any , { } > ,
66+ ) {
67+ let result = query ;
68+
69+ // where
70+ if ( args . where ) {
71+ result = result . where ( ( eb ) => this . buildFilter ( eb , model , model , args ?. where ) ) ;
72+ }
73+
74+ // skip && take
75+ let negateOrderBy = false ;
76+ const skip = args . skip ;
77+ let take = args . take ;
78+ if ( take !== undefined && take < 0 ) {
79+ negateOrderBy = true ;
80+ take = - take ;
81+ }
82+ result = this . buildSkipTake ( result , skip , take ) ;
83+
84+ // orderBy
85+ result = this . buildOrderBy (
86+ result ,
87+ model ,
88+ model ,
89+ args . orderBy ,
90+ skip !== undefined || take !== undefined ,
91+ negateOrderBy ,
92+ ) ;
93+
94+ // distinct
95+ if ( 'distinct' in args && ( args as any ) . distinct ) {
96+ const distinct = ensureArray ( ( args as any ) . distinct ) as string [ ] ;
97+ if ( this . supportsDistinctOn ) {
98+ result = result . distinctOn ( distinct . map ( ( f ) => sql . ref ( `${ model } .${ f } ` ) ) ) ;
99+ } else {
100+ throw new QueryError ( `"distinct" is not supported by "${ this . schema . provider . type } " provider` ) ;
101+ }
102+ }
103+
104+ if ( args . cursor ) {
105+ result = this . buildCursorFilter ( model , result , args . cursor , args . orderBy , negateOrderBy ) ;
106+ }
107+ return result ;
108+ }
109+
61110 buildFilter (
62111 eb : ExpressionBuilder < any , any > ,
63112 model : string ,
@@ -117,6 +166,47 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
117166 return result ;
118167 }
119168
169+ private buildCursorFilter (
170+ model : string ,
171+ query : SelectQueryBuilder < any , any , any > ,
172+ cursor : FindArgs < Schema , GetModels < Schema > , true > [ 'cursor' ] ,
173+ orderBy : FindArgs < Schema , GetModels < Schema > , true > [ 'orderBy' ] ,
174+ negateOrderBy : boolean ,
175+ ) {
176+ const _orderBy = orderBy ?? makeDefaultOrderBy ( this . schema , model ) ;
177+
178+ const orderByItems = ensureArray ( _orderBy ) . flatMap ( ( obj ) => Object . entries < SortOrder > ( obj ) ) ;
179+
180+ const eb = expressionBuilder < any , any > ( ) ;
181+ const cursorFilter = this . buildFilter ( eb , model , model , cursor ) ;
182+
183+ let result = query ;
184+ const filters : ExpressionWrapper < any , any , any > [ ] = [ ] ;
185+
186+ for ( let i = orderByItems . length - 1 ; i >= 0 ; i -- ) {
187+ const andFilters : ExpressionWrapper < any , any , any > [ ] = [ ] ;
188+
189+ for ( let j = 0 ; j <= i ; j ++ ) {
190+ const [ field , order ] = orderByItems [ j ] ! ;
191+ const _order = negateOrderBy ? ( order === 'asc' ? 'desc' : 'asc' ) : order ;
192+ const op = j === i ? ( _order === 'asc' ? '>=' : '<=' ) : '=' ;
193+ andFilters . push (
194+ eb (
195+ eb . ref ( `${ model } .${ field } ` ) ,
196+ op ,
197+ eb . selectFrom ( model ) . select ( `${ model } .${ field } ` ) . where ( cursorFilter ) ,
198+ ) ,
199+ ) ;
200+ }
201+
202+ filters . push ( eb . and ( andFilters ) ) ;
203+ }
204+
205+ result = result . where ( ( eb ) => eb . or ( filters ) ) ;
206+
207+ return result ;
208+ }
209+
120210 private isLogicalCombinator ( key : string ) : key is ( typeof LOGICAL_COMBINATORS ) [ number ] {
121211 return LOGICAL_COMBINATORS . includes ( key as any ) ;
122212 }
@@ -722,7 +812,7 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
722812 // aggregations
723813 if ( [ '_count' , '_avg' , '_sum' , '_min' , '_max' ] . includes ( field ) ) {
724814 invariant ( value && typeof value === 'object' , `invalid orderBy value for field "${ field } "` ) ;
725- for ( const [ k , v ] of Object . entries < string > ( value ) ) {
815+ for ( const [ k , v ] of Object . entries < SortOrder > ( value ) ) {
726816 invariant ( v === 'asc' || v === 'desc' , `invalid orderBy value for field "${ field } "` ) ;
727817 result = result . orderBy (
728818 ( eb ) =>
0 commit comments