---------------------------------------------------------------------------------- [ENHANCED] VFP 9.0 FIX - RUSHMORE QUERY OPTIMIZATION IN THE WHERE CLAUSE September 2024 ---------------------------------------------------------------------------------- CCB 1. BUG: In vfp9 (and vfp6, vfp7, vfp8), we can use SET OPTIMIZE ON|OFF to globally enable or disable Rushmore Query Optimization in the FOR clause, it always enables Rushmore Query Optimization in the WHERE clause. In VFP Advanced, we can use SET OPTIMIZE ON|OFF to globally enable or disable Rushmore Query Optimization in the FOR clause, we can also use SYS(9166,1|0) to globally enable or disable Rushmore Query Optimization in the WHERE clause. 2. CAUSE: There are some BUGs in the following code. 3. RESOLUTION: We can write some code to fix the BUG. CallBack5379e0 :: ; proc near mov ecx , edi ;0x005379e0 : 8bcf Label5379e2 :: mov edx , dword ptr [ ebx + 0C4h ] ;0x005379e2 : 8b93c4000000 lea ecx , dword ptr [ ecx + 8 * ecx ] ;0x005379e8 : 8d0cc9 lea esi , dword ptr [ edx + 4 * ecx ] ;0x005379eb : 8d348a mov edx , dword ptr [ edx + eax ] ;0x005379ee : 8b1402 cmp byte ptr [edx] , 0D1h ;0x005379f1 : 803ad1 mov ecx , dword ptr [ esi + 8 ] ;0x005379f4 : 8b4e08 mov esi , dword ptr [ esi + 12 ] ;0x005379f7 : 8b760c je Label5cd133 ;0x005379fa : 0f8433570900 Label537a00 :: test ecx , ecx ;0x00537a00 : 85c9 jl Label5cd13d ;0x00537a02 : 0f8c35570900 Label537a08 :: mov edx , dword ptr [ esp + 24 ] ;0x00537a08 : 8b542418 push ecx ;0x00537a0c : 51 push ebp ;0x00537a0d : 55 mov ecx , ebx ;0x00537a0e : 8bcb call Fun53234e ;0x00537a10 : e839a9ffff mov ecx , dword ptr [ ebp + 0 ] ;0x00537a15 : 8b4d00 mov eax , dword ptr [ ecx - 4 ] ;0x00537a18 : 8b41fc lea edx , dword ptr [ eax - 8 ] ;0x00537a1b : 8d50f8 call Fun5320f8 ;0x00537a1e : e8d5a6ffff ; ; ----------------------------------------------------------------------- ; VFP 9.0 FIX - RUSHMORE QUERY OPTIMIZATION IN THE WHERE CLAUSE ; September 2024 ; ----------------------------------------------------------------------- ; CCB ; ; In vfp9 (and vfp6, vfp7, vfp8), if the expression includes UDFs (user-defined functions) ; or some functions which support an optional alias or work area in the WHERE clause, ; it is an optimizable expression, sometimes it returns incorrect data! ; In Visual FoxPro Advanced, if the expression includes UDFs (user-defined functions) ; or some functions which support an optional alias or work area in the WHERE clause, ; we can set SYS(9166,0) to globally disable Rushmore Query Optimization in the WHERE clause (as a temporary solution), ; it is not an optimizable expression, it returns correct data. ; ; 2024/9/2, by ccb ; Label537a20_start :: cmp dword ptr vfpa_sys9166_data,00h jne Label537a20_end inc eax jmp Label537a23 Label537a20_end :: Label537a23 :: mov edi , eax ;0x00537a23 : 8bf8 dec edi ;0x00537a25 : 4f test esi , esi ;0x00537a26 : 85f6 jl Label4d379c ;0x00537a28 : 0f8c6ebdf9ff mov edx , dword ptr [ esp + 20 ] ;0x00537a2e : 8b542414 push esi ;0x00537a32 : 56 mov esi , dword ptr [ esp + 20 ] ;0x00537a33 : 8b742414 push esi ;0x00537a37 : 56 mov ecx , ebx ;0x00537a38 : 8bcb call Fun53234e ;0x00537a3a : e80fa9ffff mov ecx , dword ptr [esi] ;0x00537a3f : 8b0e mov eax , dword ptr [ ecx - 4 ] ;0x00537a41 : 8b41fc lea edx , dword ptr [ eax - 8 ] ;0x00537a44 : 8d50f8 call Fun5320f8 ;0x00537a47 : e8aca6ffff ; ; ----------------------------------------------------------------------- ; VFP 9.0 FIX - RUSHMORE QUERY OPTIMIZATION IN THE WHERE CLAUSE ; September 2024 ; ----------------------------------------------------------------------- ; CCB ; ; In vfp9 (and vfp6, vfp7, vfp8), if the expression includes UDFs (user-defined functions) ; or some functions which support an optional alias or work area in the WHERE clause, ; it is an optimizable expression, sometimes it returns incorrect data! ; In Visual FoxPro Advanced, if the expression includes UDFs (user-defined functions) ; or some functions which support an optional alias or work area in the WHERE clause, ; we can set SYS(9166,0) to globally disable Rushmore Query Optimization in the WHERE clause (as a temporary solution), ; it is not an optimizable expression, it returns correct data. ; ; 2024/9/2, by ccb ; Label537a49_start :: cmp dword ptr vfpa_sys9166_data,00h jne Label537a49_end inc eax jmp Label537a4c Label537a49_end :: Label537a4c :: dec eax ;0x00537a4c : 48 Label537a4d :: test edi , edi ;0x00537a4d : 85ff je Label4d377b ;0x00537a4f : 0f8426bdf9ff test eax , eax ;0x00537a55 : 85c0 jne Label537eb2 ;0x00537a57 : 0f8555040000 Label537a5d :: mov esi , dword ptr [ esp + 36 ] ;0x00537a5d : 8b742424 mov edx , dword ptr [ ebx + 0CCh ] ;0x00537a61 : 8b93cc000000 imul esi , esi , 02Ch ;0x00537a67 : 6bf62c mov dword ptr [ esi + edx ] , 03h ;0x00537a6a : c7041603000000 Label537a71 :: mov eax , dword ptr [ esp + 16 ] ;0x00537a71 : 8b442410 mov ecx , dword ptr [ ebp + 0 ] ;0x00537a75 : 8b4d00 mov eax , dword ptr [eax] ;0x00537a78 : 8b00 mov edx , dword ptr [ ecx - 4 ] ;0x00537a7a : 8b51fc mov edi , dword ptr [ eax - 4 ] ;0x00537a7d : 8b78fc sub edx , 08h ;0x00537a80 : 83ea08 sub edi , 08h ;0x00537a83 : 83ef08 cmp edx , edi ;0x00537a86 : 3bd7 jb Label537a8c ;0x00537a88 : 7202 mov edx , edi ;0x00537a8a : 8bd7 Label537a8c :: add edx , eax ;0x00537a8c : 03d0 cmp eax , edx ;0x00537a8e : 3bc2 jnb Label537aa0 ;0x00537a90 : 730e Label537a92 :: mov edi , dword ptr [eax] ;0x00537a92 : 8b38 or dword ptr [ecx] , edi ;0x00537a94 : 0939 add eax , 04h ;0x00537a96 : 83c004 add ecx , 04h ;0x00537a99 : 83c104 cmp eax , edx ;0x00537a9c : 3bc2 jb Label537a92 ;0x00537a9e : 72f2 Label537aa0 :: mov ecx , dword ptr [ ebx + 0CCh ] ;0x00537aa0 : 8b8bcc000000 mov dword ptr [ esi + ecx + 36 ] , ebp ;0x00537aa6 : 896c0e24 mov ecx , dword ptr [ esp + 16 ] ;0x00537aaa : 8b4c2410 mov eax , ebx ;0x00537aae : 8bc3 call Fun541571 ;0x00537ab0 : e8bc9a0000 mov edx , dword ptr [ esp + 20 ] ;0x00537ab5 : 8b542414 mov ebp , dword ptr [ esp + 24 ] ;0x00537ab9 : 8b6c2418 mov eax , dword ptr [edx] ;0x00537abd : 8b02 mov edi , dword ptr [ ebp + 0 ] ;0x00537abf : 8b7d00 mov ecx , dword ptr [ edi - 4 ] ;0x00537ac2 : 8b4ffc mov edx , dword ptr [ eax - 4 ] ;0x00537ac5 : 8b50fc sub ecx , 08h ;0x00537ac8 : 83e908 sub edx , 08h ;0x00537acb : 83ea08 cmp ecx , edx ;0x00537ace : 3bca jb Label537ad4 ;0x00537ad0 : 7202 mov ecx , edx ;0x00537ad2 : 8bca Label537ad4 :: add ecx , eax ;0x00537ad4 : 03c8 cmp eax , ecx ;0x00537ad6 : 3bc1 jnb Label537aeb ;0x00537ad8 : 7311 lea esp , dword ptr [ esp ] ;0x00537ada : 8d2424 Label537add :: mov edx , dword ptr [eax] ;0x00537add : 8b10 or dword ptr [edi] , edx ;0x00537adf : 0917 add eax , 04h ;0x00537ae1 : 83c004 add edi , 04h ;0x00537ae4 : 83c704 cmp eax , ecx ;0x00537ae7 : 3bc1 jb Label537add ;0x00537ae9 : 72f2 Label537aeb :: mov eax , dword ptr [ ebx + 0CCh ] ;0x00537aeb : 8b83cc000000 mov ecx , dword ptr [ esp + 20 ] ;0x00537af1 : 8b4c2414 mov dword ptr [ esi + eax + 32 ] , ebp ;0x00537af5 : 896c0620 mov eax , ebx ;0x00537af9 : 8bc3 call Fun541571 ;0x00537afb : e8719a0000 mov ecx , dword ptr [ esp + 32 ] ;0x00537b00 : 8b4c2420 mov edx , dword ptr [ ebx + 0C8h ] ;0x00537b04 : 8b93c8000000 imul ecx , ecx , 0A4h ;0x00537b0a : 69c9a4000000 mov eax , dword ptr [ edx + ecx + 24 ] ;0x00537b10 : 8b440a18 test eax , eax ;0x00537b14 : 85c0 jne Label5cd144 ;0x00537b16 : 0f8528560900 Label537b1c :: mov edx , dword ptr [ ebx + 0C8h ] ;0x00537b1c : 8b93c8000000 mov ecx , dword ptr [ ecx + edx + 28 ] ;0x00537b22 : 8b4c111c test ecx , ecx ;0x00537b26 : 85c9 jne Label5cd17a ;0x00537b28 : 0f854c560900 Label537b2e :: pop edi ;0x00537b2e : 5f pop esi ;0x00537b2f : 5e pop ebp ;0x00537b30 : 5d pop ebx ;0x00537b31 : 5b add esp , 0Ch ;0x00537b32 : 83c40c ret 08h ;0x00537b35 : c20800 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. IMPORTANT NOTE: In VFP Advanced and vfp9 (and vfp6, vfp7, vfp8), if the expression includes UDFs (user-defined functions) or some functions which support an optional alias or work area in the WHERE clause: ALIAS() function BOF() function DELETED() function EOF() function FCOUNT() function FIELD() function FLOCK() function FOUND() function LUPDATE() function NDX() function RECCOUNT() function RECNO() function RECSIZE() function RLOCK() function ORDER() function FILTER() function HEADER() function USED() function ISBLANK() function GETFLDSTATE() function it is an optimizable expression, sometimes it returns incorrect data! For example, SELECT * FROM tmp1 WHERE fld1=test_subproc("aaa") INTO CURSOR tmp2 nofilter && it returns incorrect data! SELECT * FROM tmp1 WHERE fld1=REPL(CHR(97+RECN()-1),3) INTO CURSOR tmp2 nofilter && it returns incorrect data! In VFP Advanced, we can set SYS(9166,0) to globally disable Rushmore Query Optimization in the WHERE clause (as a temporary solution) to fix the bug: PRIVATE m.q_oldsys9166 m.q_oldsys9166=VAL(SYS(9166)) =SYS(9166,0) && Disables Rushmore Query Optimization in the WHERE clause (as a temporary solution) SELECT * FROM tmp1 WHERE fld1=test_subproc("aaa") INTO CURSOR tmp2 nofilter && it returns correct data. SELECT * FROM tmp1 WHERE fld1=REPL(CHR(97+RECN()-1),3) INTO CURSOR tmp2 nofilter && it returns correct data. =SYS(9166,m.q_oldsys9166) 5. REFERENCE WEBSITES: 1, baiyujia.com: http://www.baiyujia.com http://www.baiyujia.com/vfpdocuments/f_vfp9fix340.asp http://www.baiyujia.com/vfpdocuments/f_vfp9fix326.asp http://www.baiyujia.com/vfpdocuments/f_vfp9fix327.asp http://www.baiyujia.com/vfpdocuments/f_vfp9fix328.asp http://www.baiyujia.com/vfpdocuments/f_vfp9fix329.asp http://www.baiyujia.com/vfpdocuments/f_vfp9fix330.asp 6. OTHER: For reference only, there is no guarantees. Any questions or suggestions, please send me an email at ccb2000@163.com. |