@@ -223,15 +223,28 @@ export class ExpressionWriter {
223223    } 
224224
225225    private  writeCollectionPredicate ( expr : BinaryExpr ,  operator : string )  { 
226-         this . block ( ( )  =>  { 
227-             this . writeFieldCondition ( 
228-                 expr . left , 
229-                 ( )  =>  { 
230-                     this . write ( expr . right ) ; 
231-                 } , 
232-                 operator  ===  '?'  ? 'some'  : operator  ===  '!'  ? 'every'  : 'none' 
233-             ) ; 
234-         } ) ; 
226+         // check if the operand should be compiled to a relation query 
227+         // or a plain expression 
228+         const  compileToRelationQuery  = 
229+             ( this . isPostGuard  &&  this . isFutureMemberAccess ( expr . left ) )  || 
230+             ( ! this . isPostGuard  &&  ! this . isFutureMemberAccess ( expr . left ) ) ; 
231+ 
232+         if  ( compileToRelationQuery )  { 
233+             this . block ( ( )  =>  { 
234+                 this . writeFieldCondition ( 
235+                     expr . left , 
236+                     ( )  =>  { 
237+                         // inner scope of collection expression is always compiled as non-post-guard 
238+                         const  innerWriter  =  new  ExpressionWriter ( this . writer ,  false ) ; 
239+                         innerWriter . write ( expr . right ) ; 
240+                     } , 
241+                     operator  ===  '?'  ? 'some'  : operator  ===  '!'  ? 'every'  : 'none' 
242+                 ) ; 
243+             } ) ; 
244+         }  else  { 
245+             const  plain  =  this . plainExprBuilder . transform ( expr ) ; 
246+             this . writer . write ( `${ plain } ${ TRUE } ${ FALSE }  ) ; 
247+         } 
235248    } 
236249
237250    private  isFieldAccess ( expr : Expression ) : boolean  { 
@@ -275,6 +288,19 @@ export class ExpressionWriter {
275288        } 
276289    } 
277290
291+     private  writeIdFieldsCheck ( model : DataModel ,  value : Expression )  { 
292+         const  idFields  =  this . requireIdFields ( model ) ; 
293+         idFields . forEach ( ( idField ,  idx )  =>  { 
294+             // eg: id: user.id 
295+             this . writer . write ( `${ idField . name }  ) ; 
296+             this . plain ( value ) ; 
297+             this . writer . write ( `.${ idField . name }  ) ; 
298+             if  ( idx  !==  idFields . length  -  1 )  { 
299+                 this . writer . write ( ',' ) ; 
300+             } 
301+         } ) ; 
302+     } 
303+ 
278304    private  writeComparison ( expr : BinaryExpr ,  operator : ComparisonOperator )  { 
279305        const  leftIsFieldAccess  =  this . isFieldAccess ( expr . left ) ; 
280306        const  rightIsFieldAccess  =  this . isFieldAccess ( expr . right ) ; 
@@ -298,7 +324,7 @@ export class ExpressionWriter {
298324            operator  =  this . negateOperator ( operator ) ; 
299325        } 
300326
301-         if  ( isMemberAccessExpr ( fieldAccess )   &&   isFutureExpr ( fieldAccess . operand ) )  { 
327+         if  ( this . isFutureMemberAccess ( fieldAccess ) )  { 
302328            // future().field should be treated as the "field" directly, so we 
303329            // strip 'future().' and synthesize a reference expr 
304330            fieldAccess  =  { 
@@ -338,8 +364,6 @@ export class ExpressionWriter {
338364                            // right now this branch only serves comparison with `auth`, like 
339365                            //     @@allow ('all', owner == auth()) 
340366
341-                             const  idFields  =  this . requireIdFields ( dataModel ) ; 
342- 
343367                            if  ( operator  !==  '=='  &&  operator  !==  '!=' )  { 
344368                                throw  new  PluginError ( name ,  'Only == and != operators are allowed' ) ; 
345369                            } 
@@ -354,25 +378,13 @@ export class ExpressionWriter {
354378                            } 
355379
356380                            this . block ( ( )  =>  { 
357-                                 idFields . forEach ( ( idField ,  idx )  =>  { 
358-                                     const  writeIdsCheck  =  ( )  =>  { 
359-                                         // id: user.id 
360-                                         this . writer . write ( `${ idField . name }  ) ; 
361-                                         this . plain ( operand ) ; 
362-                                         this . writer . write ( `.${ idField . name }  ) ; 
363-                                         if  ( idx  !==  idFields . length  -  1 )  { 
364-                                             this . writer . write ( ',' ) ; 
365-                                         } 
366-                                     } ; 
367- 
368-                                     if  ( isThisExpr ( fieldAccess )  &&  operator  ===  '!=' )  { 
369-                                         // wrap a not 
370-                                         this . writer . writeLine ( 'NOT:' ) ; 
371-                                         this . block ( ( )  =>  writeIdsCheck ( ) ) ; 
372-                                     }  else  { 
373-                                         writeIdsCheck ( ) ; 
374-                                     } 
375-                                 } ) ; 
381+                                 if  ( isThisExpr ( fieldAccess )  &&  operator  ===  '!=' )  { 
382+                                     // negate 
383+                                     this . writer . writeLine ( 'isNot:' ) ; 
384+                                     this . block ( ( )  =>  this . writeIdFieldsCheck ( dataModel ,  operand ) ) ; 
385+                                 }  else  { 
386+                                     this . writeIdFieldsCheck ( dataModel ,  operand ) ; 
387+                                 } 
376388                            } ) ; 
377389                        }  else  { 
378390                            if  ( this . equivalentRefs ( fieldAccess ,  operand ) )  { 
@@ -386,7 +398,13 @@ export class ExpressionWriter {
386398                                        // we should generate a field reference (comparing fields in the same model) 
387399                                        this . writeFieldReference ( operand ) ; 
388400                                    }  else  { 
389-                                         this . plain ( operand ) ; 
401+                                         if  ( dataModel  &&  this . isModelTyped ( operand ) )  { 
402+                                             // the comparison is between model types, generate id fields comparison block 
403+                                             this . block ( ( )  =>  this . writeIdFieldsCheck ( dataModel ,  operand ) ) ; 
404+                                         }  else  { 
405+                                             // scalar value, just generate the plain expression 
406+                                             this . plain ( operand ) ; 
407+                                         } 
390408                                    } 
391409                                } ) ; 
392410                            } 
@@ -400,6 +418,10 @@ export class ExpressionWriter {
400418        ) ; 
401419    } 
402420
421+     private  isFutureMemberAccess ( expr : Expression ) : expr  is MemberAccessExpr  { 
422+         return  isMemberAccessExpr ( expr )  &&  isFutureExpr ( expr . operand ) ; 
423+     } 
424+ 
403425    private  requireIdFields ( dataModel : DataModel )  { 
404426        const  idFields  =  getIdFields ( dataModel ) ; 
405427        if  ( ! idFields  ||  idFields . length  ===  0 )  { 
0 commit comments