@@ -153,24 +153,68 @@ describe(`createDeduplicatedLoadSubset`, () => {
153153 } ,
154154 ]
155155
156+ const whereClause = gt ( ref ( `age` ) , val ( 10 ) )
157+
156158 // First call: age > 10, orderBy age asc, limit 10
157159 await deduplicated . loadSubset ( {
158- where : gt ( ref ( `age` ) , val ( 10 ) ) ,
160+ where : whereClause ,
159161 orderBy : orderBy1 ,
160162 limit : 10 ,
161163 } )
162164 expect ( callCount ) . toBe ( 1 )
163165
164- // Second call: age > 20, orderBy age asc, limit 5 (subset)
166+ // Second call: SAME where clause, same orderBy, smaller limit (subset)
167+ // For limited queries, where clauses must be EQUAL for subset relationship
165168 const result = await deduplicated . loadSubset ( {
166- where : gt ( ref ( `age` ) , val ( 20 ) ) ,
169+ where : whereClause , // Same where clause
167170 orderBy : orderBy1 ,
168171 limit : 5 ,
169172 } )
170173 expect ( result ) . toBe ( true )
171174 expect ( callCount ) . toBe ( 1 ) // Should not call - subset of first
172175 } )
173176
177+ it ( `should NOT dedupe limited calls with different where clauses` , async ( ) => {
178+ let callCount = 0
179+ const mockLoadSubset = ( ) => {
180+ callCount ++
181+ return Promise . resolve ( )
182+ }
183+
184+ const deduplicated = new DeduplicatedLoadSubset ( {
185+ loadSubset : mockLoadSubset ,
186+ } )
187+
188+ const orderBy1 : OrderBy = [
189+ {
190+ expression : ref ( `age` ) ,
191+ compareOptions : {
192+ direction : `asc` ,
193+ nulls : `last` ,
194+ stringSort : `lexical` ,
195+ } ,
196+ } ,
197+ ]
198+
199+ // First call: age > 10, orderBy age asc, limit 10
200+ await deduplicated . loadSubset ( {
201+ where : gt ( ref ( `age` ) , val ( 10 ) ) ,
202+ orderBy : orderBy1 ,
203+ limit : 10 ,
204+ } )
205+ expect ( callCount ) . toBe ( 1 )
206+
207+ // Second call: DIFFERENT where clause (age > 20) - should NOT be deduped
208+ // even though age > 20 is "more restrictive" than age > 10,
209+ // the top 5 of age > 20 might not be in the top 10 of age > 10
210+ await deduplicated . loadSubset ( {
211+ where : gt ( ref ( `age` ) , val ( 20 ) ) ,
212+ orderBy : orderBy1 ,
213+ limit : 5 ,
214+ } )
215+ expect ( callCount ) . toBe ( 2 ) // Should call - different where clause
216+ } )
217+
174218 it ( `should call underlying for non-subset limited calls` , async ( ) => {
175219 let callCount = 0
176220 const mockLoadSubset = ( ) => {
@@ -671,17 +715,20 @@ describe(`createDeduplicatedLoadSubset`, () => {
671715 } ,
672716 ]
673717
718+ const whereClause = gt ( ref ( `age` ) , val ( 10 ) )
719+
674720 // First limited call
675721 await deduplicated . loadSubset ( {
676- where : gt ( ref ( `age` ) , val ( 10 ) ) ,
722+ where : whereClause ,
677723 orderBy : orderBy1 ,
678724 limit : 10 ,
679725 } )
680726 expect ( callCount ) . toBe ( 1 )
681727
682- // Second limited call is a subset (stricter where and smaller limit)
728+ // Second limited call is a subset (SAME where clause and smaller limit)
729+ // For limited queries, where clauses must be EQUAL for subset relationship
683730 const subsetOptions = {
684- where : gt ( ref ( `age` ) , val ( 20 ) ) ,
731+ where : whereClause , // Same where clause
685732 orderBy : orderBy1 ,
686733 limit : 5 ,
687734 }
@@ -741,4 +788,98 @@ describe(`createDeduplicatedLoadSubset`, () => {
741788 expect ( onDeduplicate ) . toHaveBeenCalledWith ( subsetOptions )
742789 } )
743790 } )
791+
792+ describe ( `limited queries with different where clauses` , ( ) => {
793+ // When a query has a limit, only the top N rows (by orderBy) are loaded.
794+ // A subsequent query with a different where clause cannot reuse that data,
795+ // even if the new where clause is "more restrictive", because the filtered
796+ // top N might include rows outside the original unfiltered top N.
797+
798+ it ( `should NOT dedupe when where clause differs on limited queries` , async ( ) => {
799+ let callCount = 0
800+ const calls : Array < LoadSubsetOptions > = [ ]
801+ const mockLoadSubset = ( options : LoadSubsetOptions ) => {
802+ callCount ++
803+ calls . push ( options )
804+ return Promise . resolve ( )
805+ }
806+
807+ const deduplicated = new DeduplicatedLoadSubset ( {
808+ loadSubset : mockLoadSubset ,
809+ } )
810+
811+ const orderByCreatedAt : OrderBy = [
812+ {
813+ expression : ref ( `created_at` ) ,
814+ compareOptions : {
815+ direction : `desc` ,
816+ nulls : `last` ,
817+ stringSort : `lexical` ,
818+ } ,
819+ } ,
820+ ]
821+
822+ // First query: top 10 items with no filter
823+ await deduplicated . loadSubset ( {
824+ where : undefined ,
825+ orderBy : orderByCreatedAt ,
826+ limit : 10 ,
827+ } )
828+ expect ( callCount ) . toBe ( 1 )
829+
830+ // Second query: top 10 items WITH a filter
831+ // This requires a separate request because the filtered top 10
832+ // might include items outside the unfiltered top 10
833+ const searchWhere = and ( eq ( ref ( `title` ) , val ( `test` ) ) )
834+ await deduplicated . loadSubset ( {
835+ where : searchWhere ,
836+ orderBy : orderByCreatedAt ,
837+ limit : 10 ,
838+ } )
839+
840+ expect ( callCount ) . toBe ( 2 )
841+ expect ( calls [ 1 ] ?. where ) . toEqual ( searchWhere )
842+ } )
843+
844+ it ( `should dedupe when where clause is identical on limited queries` , async ( ) => {
845+ let callCount = 0
846+ const mockLoadSubset = ( ) => {
847+ callCount ++
848+ return Promise . resolve ( )
849+ }
850+
851+ const deduplicated = new DeduplicatedLoadSubset ( {
852+ loadSubset : mockLoadSubset ,
853+ } )
854+
855+ const orderByCreatedAt : OrderBy = [
856+ {
857+ expression : ref ( `created_at` ) ,
858+ compareOptions : {
859+ direction : `desc` ,
860+ nulls : `last` ,
861+ stringSort : `lexical` ,
862+ } ,
863+ } ,
864+ ]
865+
866+ // First query: top 10 items with no filter
867+ await deduplicated . loadSubset ( {
868+ where : undefined ,
869+ orderBy : orderByCreatedAt ,
870+ limit : 10 ,
871+ } )
872+ expect ( callCount ) . toBe ( 1 )
873+
874+ // Second query: same where clause (undefined), smaller limit
875+ // The top 5 are contained within the already-loaded top 10
876+ const result = await deduplicated . loadSubset ( {
877+ where : undefined ,
878+ orderBy : orderByCreatedAt ,
879+ limit : 5 ,
880+ } )
881+ expect ( result ) . toBe ( true )
882+ expect ( callCount ) . toBe ( 1 )
883+ } )
884+ } )
744885} )
0 commit comments