@@ -3188,6 +3188,115 @@ describe('FirestorePipeline', function () {
31883188 } ) ;
31893189 } ) ;
31903190
3191+ describe ( 'exit frame and receiver expression lowering coverage' , function ( ) {
3192+ it ( 'lowers vector distance receiver chains with expression vector operands' , async function ( ) {
3193+ const { execute, field, cosineDistance, dotProduct } = firestorePipelinesModular ;
3194+ const { getFirestore, doc, setDoc, vector } = firestoreModular ;
3195+ const db = getFirestore ( DATABASE_ID ) ;
3196+ const docPath = `${ COLLECTION } /${ Utils . randString ( 12 , '#aA' ) } ` ;
3197+
3198+ await setDoc ( doc ( db , docPath ) , {
3199+ embedding : vector ( [ 1.0 , 0.0 , 0.0 ] ) ,
3200+ query : vector ( [ 0.0 , 1.0 , 0.0 ] ) ,
3201+ } ) ;
3202+
3203+ const snapshot = await execute (
3204+ db
3205+ . pipeline ( )
3206+ . documents ( [ docPath ] )
3207+ . select (
3208+ cosineDistance ( field ( 'embedding' ) , field ( 'query' ) ) . as ( 'globalCosDist' ) ,
3209+ field ( 'embedding' ) . dotProduct ( field ( 'query' ) ) . as ( 'fluentDot' ) ,
3210+ field ( 'embedding' ) . euclideanDistance ( field ( 'query' ) ) . as ( 'fluentEuclid' ) ,
3211+ dotProduct ( field ( 'embedding' ) , field ( 'query' ) ) . as ( 'globalDot' ) ,
3212+ ) ,
3213+ ) ;
3214+
3215+ snapshot . results . should . have . length ( 1 ) ;
3216+ const data = snapshot . results [ 0 ] . data ( ) ;
3217+ should ( data . globalCosDist ) . be . approximately ( 1 , 0.0001 ) ;
3218+ should ( data . fluentDot ) . be . approximately ( 0 , 0.0001 ) ;
3219+ should ( data . fluentEuclid ) . be . approximately ( Math . sqrt ( 2 ) , 0.0001 ) ;
3220+ should ( data . globalDot ) . be . approximately ( 0 , 0.0001 ) ;
3221+ } ) ;
3222+
3223+ it ( 'lowers fluent receiver exit frames with expression map, array, and extrema operands' , async function ( ) {
3224+ const { execute, field, logicalMaximum, logicalMinimum } = firestorePipelinesModular ;
3225+ const { getFirestore, doc, setDoc } = firestoreModular ;
3226+ const db = getFirestore ( DATABASE_ID ) ;
3227+ const docPath = `${ COLLECTION } /${ Utils . randString ( 12 , '#aA' ) } ` ;
3228+
3229+ await setDoc ( doc ( db , docPath ) , {
3230+ metadata : { theme : 'dark' , locale : 'en' } ,
3231+ keyName : 'theme' ,
3232+ scores : [ 10 , 25 , 40 ] ,
3233+ idx : 1 ,
3234+ bidA : 100 ,
3235+ bidB : 150 ,
3236+ bidC : 120 ,
3237+ askA : 200 ,
3238+ askB : 175 ,
3239+ askC : 190 ,
3240+ } ) ;
3241+
3242+ const snapshot = await execute (
3243+ db
3244+ . pipeline ( )
3245+ . documents ( [ docPath ] )
3246+ . select (
3247+ field ( 'metadata' ) . mapGet ( field ( 'keyName' ) ) . as ( 'fluentMapGet' ) ,
3248+ field ( 'scores' ) . arrayGet ( field ( 'idx' ) ) . as ( 'fluentArrayGet' ) ,
3249+ field ( 'bidA' ) . logicalMaximum ( field ( 'bidB' ) , field ( 'bidC' ) ) . as ( 'fluentMaxBid' ) ,
3250+ field ( 'askA' ) . logicalMinimum ( field ( 'askB' ) , field ( 'askC' ) ) . as ( 'fluentMinAsk' ) ,
3251+ logicalMaximum ( field ( 'bidA' ) , field ( 'bidB' ) , field ( 'bidC' ) ) . as ( 'globalMaxBid' ) ,
3252+ logicalMinimum ( field ( 'askA' ) , field ( 'askB' ) , field ( 'askC' ) ) . as ( 'globalMinAsk' ) ,
3253+ ) ,
3254+ ) ;
3255+
3256+ snapshot . results . should . have . length ( 1 ) ;
3257+ const data = snapshot . results [ 0 ] . data ( ) ;
3258+ data . fluentMapGet . should . equal ( 'dark' ) ;
3259+ data . fluentArrayGet . should . equal ( 25 ) ;
3260+ data . fluentMaxBid . should . equal ( 150 ) ;
3261+ data . fluentMinAsk . should . equal ( 175 ) ;
3262+ data . globalMaxBid . should . equal ( 150 ) ;
3263+ data . globalMinAsk . should . equal ( 175 ) ;
3264+ } ) ;
3265+
3266+ it ( 'lowers boolean receiver and logical exit frames with expression operands' , async function ( ) {
3267+ const { execute, field, or, and } = firestorePipelinesModular ;
3268+ const { getFirestore, collection, doc, setDoc } = firestoreModular ;
3269+ const db = getFirestore ( DATABASE_ID ) ;
3270+ const coll = collection (
3271+ db ,
3272+ `${ COLLECTION } /${ Utils . randString ( 12 , '#aA' ) } /boolean-receiver-exit-frames` ,
3273+ ) ;
3274+
3275+ await Promise . all ( [
3276+ setDoc ( doc ( coll , 'match-a' ) , { score : 12 , threshold : 10 , tier : 'gold' , region : 'EU' } ) ,
3277+ setDoc ( doc ( coll , 'match-b' ) , { score : 12 , threshold : 10 , tier : 'silver' , region : 'US' } ) ,
3278+ setDoc ( doc ( coll , 'skip' ) , { score : 3 , threshold : 10 , tier : 'bronze' , region : 'APAC' } ) ,
3279+ ] ) ;
3280+
3281+ const snapshot = await execute (
3282+ db
3283+ . pipeline ( )
3284+ . collection ( coll )
3285+ . where (
3286+ and (
3287+ field ( 'score' ) . greaterThan ( field ( 'threshold' ) ) ,
3288+ or ( field ( 'tier' ) . equal ( 'gold' ) , field ( 'region' ) . equal ( 'US' ) ) ,
3289+ ) ,
3290+ )
3291+ . select ( 'score' , 'tier' , 'region' ) ,
3292+ ) ;
3293+
3294+ snapshot . results . should . have . length ( 2 ) ;
3295+ const tiers = snapshot . results . map ( row => row . data ( ) . tier ) . sort ( ) ;
3296+ tiers . should . eql ( [ 'gold' , 'silver' ] ) ;
3297+ } ) ;
3298+ } ) ;
3299+
31913300 describe ( 'operand mode rhs shape coverage' , function ( ) {
31923301 it ( 'coerces string, array, and boolean rhs shapes in comparisons and arithmetic' , async function ( ) {
31933302 const { execute, field, constant, add, multiply, mod, equal, equalAny, greaterThan, and } =
0 commit comments