------------------------------------------------------------------
                     [BUG/PRB.] VFP 9.0 FIX - INVALID RELATIONALEXPR EXPRESSION
                                    January 2024
                 ------------------------------------------------------------------
                                        CCB



1. BUG:

     In vfp9 (and vfp6, vfp7, vfp8), if the RelationalExpr expression includes the EVALUATE() or TYPE() functions, vfp will crash.

     1, If the RelationalExpr expression includes the macro substitution,
     vfp will cause the error "Relational expression is not valid (Error 1555)".

     *PROC testrelationalexpr_macro

     SET STEP OFF
     SET ECHO OFF
     SET DEBUG OFF
     SET ESCAPE OFF
     SET TALK OFF
     SET SAFETY OFF

     _SCREEN.VISIBLE=.T.
     _SCREEN.WINDOWSTATE=2

     SET EXCLUSIVE OFF
     SET MULTILOCK ON
     SET COLLATE TO "MACHINE"

     CLOSE DATABASES ALL
     CLOSE TABLES ALL

     PUBLIC x1
     x1="CHR(65)"

     DO FORM testrelationalexpr_macro.scx

     CLOSE DATABASES ALL
     CLOSE TABLES ALL

     RETURN

     * END OF PROC TESTRELATIONALEXPR_MACRO.

     In the testrelationalexpr_macro.scx:

     relation1.RelationalExpr = "fld1+LEFT(&x1,0)"


     2, If the RelationalExpr expression includes the EVALUATE() or TYPE() functions, vfp will crash.

     *PROC testrelationalexpr_evaluate

     SET STEP OFF
     SET ECHO OFF
     SET DEBUG OFF
     SET ESCAPE OFF
     SET TALK OFF
     SET SAFETY OFF

     _SCREEN.VISIBLE=.T.
     _SCREEN.WINDOWSTATE=2

     SET EXCLUSIVE OFF
     SET MULTILOCK ON
     SET COLLATE TO "MACHINE"

     CLOSE DATABASES ALL
     CLOSE TABLES ALL

     DO FORM testrelationalexpr_evaluate.scx

     CLOSE DATABASES ALL
     CLOSE TABLES ALL

     RETURN

     * END OF PROC TESTRELATIONALEXPR_evaluate.

     In the testrelationalexpr_evaluate.scx:

     relation1.RelationalExpr = "fld1+EVALUATE('LEFT(CHR(65),0)')"


     3, If the RelationalExpr expression includes the user-defined function and the user-defined function
     includes EVALUATE() or TYPE() functions, vfp will crash too.

     *PROC testrelationalexpr_udf_evaluate

     SET STEP OFF
     SET ECHO OFF
     SET DEBUG OFF
     SET ESCAPE OFF
     SET TALK OFF
     SET SAFETY OFF

     _SCREEN.VISIBLE=.T.
     _SCREEN.WINDOWSTATE=2

     SET EXCLUSIVE OFF
     SET MULTILOCK ON
     SET COLLATE TO "MACHINE"

     CLOSE DATABASES ALL
     CLOSE TABLES ALL

     DO FORM testrelationalexpr_udf_evaluate.scx

     CLOSE DATABASES ALL
     CLOSE TABLES ALL

     RETURN

     FUNCTION testrelationalexpr_udf_evaluate2

     PRIVATE x2
     x2=EVALUATE('LEFT(CHR(65),0)')

     RETU ""

     * END OF FUNCTION TESTRELATIONALEXPR_UDF_EVALUATE2.

     * END OF PROC TESTRELATIONALEXPR_UDF_EVALUATE.

     In the testrelationalexpr_udf_evaluate.scx:

     relation1.RelationalExpr = "fld1+testrelationalexpr_udf_evaluate2()"


     4, If the RelationalExpr expression includes the user-defined function and the user-defined function
     does not include the EVALUATE() and TYPE() functions, vfp will run correctly.


     5, If we don't set RelationalExpr expression at design-time, we can set RelationalExpr expression at run time.
     For example,

     THISFORM.DATAENVIRONMENT.ADDOBJECT("Relation1","Relation")
     THISFORM.DATAENVIRONMENT.relation1.PARENTALIAS = "testa"
     THISFORM.DATAENVIRONMENT.relation1.RELATIONALEXPR = "fld1+EVALUATE('LEFT(CHR(65),0)')"
     THISFORM.DATAENVIRONMENT.relation1.CHILDALIAS = "testb"
     THISFORM.DATAENVIRONMENT.relation1.CHILDORDER = "fld1"

     vfp will not crash, BUT vfp will run incorrectly:
     now the RELATION(1) is not equal to "fld1+EVALUATE('LEFT(CHR(65),0)')",
     it is equal to "LEFT(CHR(65),0)" (the parameter passed to the EVALUATE() or TYPE() functions).


     6, If we don't use the relation object, we can use SET RELATION TO statement instead of the relation object,
     then there is no any problem.


2. CAUSE:

     There are some BUGs in the following code.


3. RESOLUTION:

     We can write some code to fix the BUG.

     Label722b1b ::
             mov  ecx , dword ptr [ Data937f94 ]                             ;0x00722b1b :        8b0d947f9300
             pushd 00h                                                       ;0x00722b21 :        6a00
             lea edx ,  dword ptr [ esp + 02124h ]                           ;0x00722b23 :        8d942424210000
             push edx                                                        ;0x00722b2a :        52
             call Fun434500                                                  ;0x00722b2b :        e8d019d1ff
             test eax , eax                                                  ;0x00722b30 :        85c0
             jle Label722b59                                                 ;0x00722b32 :        7e25
             pushd 00h                                                       ;0x00722b34 :        6a00
             pushd 01h                                                       ;0x00722b36 :        6a01
             pushd 00h                                                       ;0x00722b38 :        6a00
             lea eax ,  dword ptr [ esp + 0212Ch ]                           ;0x00722b3a :        8d84242c210000
             push eax                                                        ;0x00722b41 :        50
             call Fun430428                                                  ;0x00722b42 :        e8e1d8d0ff
             test eax , eax                                                  ;0x00722b47 :        85c0
             jne Label722b59                                                 ;0x00722b49 :        750e


     ;
     ;                 -------------------------------------------------------
     ;                     VFP 9.0 FIX - INVALID RELATIONALEXPR EXPRESSION
     ;                                    January 2018
     ;                 -------------------------------------------------------
     ;                                        CCB
     ;
     ; If the RelationalExpr expression includes the EVALUATE() or TYPE() functions, vfp will crash.
     ;
     ; 2018/1/23, by ccb
     ;

             mov dword ptr vfpa_relationalexpr_flag,01h

             mov eax,dword ptr [ Data937f94 ]
             cmp byte ptr [eax],0FDh
             je Label722b4a
     Label722b49 ::
             call Fun4360e0
             cmp byte ptr [eax],0FDh
             jne Label722b49
     Label722b4a ::
             sub eax,dword ptr [ Data937f94 ]
             inc eax
             mov dword ptr vfpa_relationalexpr_len,eax
             cmp dword ptr vfpa_relationalexpr_len,100h
             jae Label722b4b
             push ecx
             push esi
             push edi
             mov ecx,dword ptr vfpa_relationalexpr_len
             mov esi,dword ptr [ Data937f94 ]
             lea edi,dword ptr vfpa_relationalexpr_data
             cld
             rep movsb
             pop edi
             pop esi
             pop ecx


     Label722b4b ::
             mov eax ,  dword ptr [ Data937f94 ]                             ;0x00722b4b :        a1947f9300
             push esi                                                        ;0x00722b50 :        56
             push ebx                                                        ;0x00722b51 :        53
             call Fun44df4c                                                  ;0x00722b52 :        e8f5b3d2ff


     ;
     ;                 -------------------------------------------------------
     ;                     VFP 9.0 FIX - INVALID RELATIONALEXPR EXPRESSION
     ;                                    January 2018
     ;                 -------------------------------------------------------
     ;                                        CCB
     ;
     ; If the RelationalExpr expression includes the EVALUATE() or TYPE() functions, vfp will crash.
     ;
     ; 2018/1/23, by ccb
     ;

             mov dword ptr vfpa_relationalexpr_flag,00h


             jmp Label722b63                                                 ;0x00722b57 :        eb0a


     We can also use the EXECSCRIPT() function instead of the EVALUATE() function,
     and use the VARTYPE() function instead of the TYPE() function, and then vfp will run correctly.

     For example,
     RelationalExpr = "fld1+EVALUATE('LEFT(CHR(65),0)')"
     we can change it to:
     RelationalExpr = "fld1+EXECSCRIPT('RETURN '+'LEFT(CHR(65),0)')"

     VFP C++ Compiler frequently uses the _Evaluate() and _Execute() API functions,
     so if the RelationalExpr expression includes the user-defined function,
     recommend to set VFP C++ Compiler does not compile the user-defined function.
     For example, we can change it to:

     FUNCTION testrelationalexpr_udf_evaluate2

     =[FOXRUN OFF]

     PRIVATE x2
     x2=EVALUATE('LEFT(CHR(65),0)')

     RETU ""

     =[FOXRUN ON]

     * END OF FUNCTION TESTRELATIONALEXPR_UDF_EVALUATE2.


4. APPLIES TO:

     VFP 6.0.8167.0
     VFP 6.0.8961.0 (SP5)

     VFP 7.0.0.9262
     VFP 7.0.0.9465 (SP1)

     VFP 8.0.0.2521
     VFP 8.0.0.3117 (SP1)

     VFP 9.0.0.2412
     VFP 9.0.0.3504 (SP1)
     VFP 9.0.0.4611 (SP2)
     VFP 9.0.0.5015 (SP2)
     VFP 9.0.0.5411 (SP2)
     VFP 9.0.0.5721 (SP2)
     VFP 9.0.0.5815 (SP2)
     VFP 9.0.0.6303 (SP2)
     VFP 9.0.0.6602 (SP2)
     VFP 9.0.0.7423 (SP2)

     The bug has been fixed in VFP Advanced.


5. REFERENCE WEBSITES:

     1, baiyujia.com:
     http://www.baiyujia.com


6. OTHER:

     For reference only, there is no guarantees.

     Any questions or suggestions, please send me an email at ccb2000@163.com.