Bug #3173
use of DYNAMIC-FUNCTION() in the WHERE clause of a dynamic query silently fails to find a record in the 4GL while P2J acts as one would expect
Status:
New
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
Due date:
% Done:
0%
billable:
No
vendor_id:
GCD
case_num:
version:
History
#1 Updated by Greg Shah over 7 years ago
Please see uast/dynamic-queries/p2488-a.p
which is heavily annotated.
The following is the code as of this moment:
DEFINE TEMP-TABLE tt FIELD af AS INTEGER. CREATE tt. tt.af = 11. FUNCTION f RETURNS INTEGER (INPUT i AS INTEGER): RETURN i. END FUNCTION. FORM book.book-id WITH FRAME f-static-output DOWN. /* ------------------ static for each -----------------------*/ FOR EACH book, EACH tt WHERE BUFFER tt:NAME = book.isbn: /* this will never get executed unless there is an isbn "number" that is "tt" */ /* (which should not happen) */ DISPLAY book-id WITH FRAME f-static-output. DOWN WITH FRAME f-static-output. END. FOR EACH book, EACH tt WHERE BUFFER tt::af <> book.book-id: DISPLAY book-id WITH FRAME f-static-output. DOWN WITH FRAME f-static-output. END. FOR EACH book, EACH tt WHERE BUFFER tt::af <> f(book.book-id): DISPLAY book-id WITH FRAME f-static-output. DOWN WITH FRAME f-static-output. END. /* static results */ /* ┌────────┐ │ Book ID│ │────────│ │00000001│ │00000002│ │00000003│ │00000004│ │00000005│ │00000006│ │00000007│ │00000008│ │00000009│ │00000010│ │00000011│ <--- THIS IS WIERD, SEE #3171 │00000012│ │00000013│ │00099999│ │00000001│ │00000002│ │00000003│ │00000004│ │00000005│ │00000006│ │00000007│ │00000008│ │00000009│ │00000010│ │00000011│ <--- THIS IS WIERD, SEE #3171 │00000012│ │00000013│ │00099999│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────┘ Press space bar to continue. */ /* can't use DEFINE FRAME here because it won't open a scope and the nest uses */ /* below require the scope to already be open at the external proc level else */ /* there is a compile error */ FORM book WITH FRAME f-dyn-output DOWN. /* ------------------ dynamic for each -----------------------*/ DEFINE VARIABLE hQuery AS HANDLE NO-UNDO. CREATE QUERY hQuery. hQuery:SET-BUFFERS(BUFFER book:HANDLE, BUFFER tt:HANDLE). hQuery:QUERY-PREPARE("FOR EACH book, EACH tt WHERE BUFFER tt:NAME = book.isbn"). hQuery:QUERY-OPEN. REPEAT: hQuery:GET-NEXT(). IF available book THEN DO: /* this never gets executed because the where clause above is silly */ DISPLAY book WITH FRAME f-dyn-output. DOWN WITH FRAME f-dyn-output. END. ELSE LEAVE. END. hQuery:QUERY-CLOSE(). DELETE OBJECT hQuery. CREATE QUERY hQuery. hQuery:SET-BUFFERS(BUFFER book:HANDLE, BUFFER tt:HANDLE). /* We add the INTEGER() call here otherwise we get ** Incompatible data types in expression or assignment. (223) */ /* when trying to use the :: operator which is has a polymorphic type */ hQuery:QUERY-PREPARE("FOR EACH book, EACH tt WHERE INTEGER(BUFFER tt::af) <> book.book-id"). hQuery:QUERY-OPEN. REPEAT: hQuery:GET-NEXT(). IF available book THEN DO: DISPLAY book WITH FRAME f-dyn-output. DOWN WITH FRAME f-dyn-output. END. ELSE LEAVE. END. hQuery:QUERY-CLOSE(). DELETE OBJECT hQuery. CREATE QUERY hQuery. hQuery:SET-BUFFERS(BUFFER book:HANDLE, BUFFER tt:HANDLE). /* Must use DYNAMIC-FUNCTION() to execute user-defined functions, cannot call them directly, else we get this */ /* list of errors at runtime: */ /* ** Unable to understand after -- "::af) <> f". (247) */ /* PREPARE syntax is: {FOR | PRESELECT} EACH OF.. WHERE ... etc". (7324) */ /* In this case, evidently the 4GL allows the use of the polymorphic :: operator since it is being compared to */ /* the polymorphic dynamic-function builtin. We don't get an ** Incompatible data types in expression or assignment. (223) */ /* something happens differently with the execution of DYNAMIC-FUNCTION() such that */ /* this query will never retrieve any records; I would guess that the DYNAMIC-FUNCTION() */ /* is only executed once is otherwise not working right */ hQuery:QUERY-PREPARE("FOR EACH book, EACH tt WHERE BUFFER tt::af <> DYNAMIC-FUNCTION('f', book.book-id)"). hQuery:QUERY-OPEN. REPEAT: hQuery:GET-NEXT(). IF available book THEN DO: /* never executes in the 4GL */ DISPLAY book WITH FRAME f-dyn-output. DOWN WITH FRAME f-dyn-output. END. ELSE LEAVE. END. hQuery:QUERY-CLOSE(). DELETE OBJECT hQuery. /* dynamic results (all this output is generated by the 2nd dynamic query, the 1st and 3rd have no output) */ /* ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Book ID Title Publisher ISBN On Hand Cost Pub Date Author ID Sold Price│ │──────── ─────────────────────────────────── ──────────────────── ─────────────── ─────── ────────── ────────── ───────── ───── ──────────│ │00000001 Progress Programming Atlantis 1-111111-11-1 00005 24.95 08/01/1997 0000000 3 29.95│ │00000002 Java Programming Sun 2-222222-22-2 00035 18.95 01/01/2000 0000000 1,200 24.95│ │00000003 Ruby Programming Gems 3-333333-33-3 00020 21.95 01/01/2004 0000000 350 27.00│ │00000004 Perl Programming Gems 4-444444-44-4 01250 15.00 01/01/2003 0000000 650 19.95│ │00000005 Python Programming Animals 5-555555-55-5 00023 18.95 01/01/2004 0000000 220 21.95│ │00000006 PHP Programming Web 6-666666-66-6 00045 12.95 01/01/2002 0000000 425 14.95│ │00000007 HTML Programming Web 7-777777-77-7 00020 16.00 01/01/1998 0000000 3,500 19.95│ │00000008 Javascript Programming Sun 8-888888-88-8 00012 14.95 01/01/2001 0000000 1,800 17.95│ │00000009 Cobol Programming Atlantis 9-999999-99-9 03000 32.50 01/01/1990 0000000 32 35.00│ │00000010 Eclipse Programming Sun 1-123456-78-9 00055 24.95 01/01/2003 0000000 200 28.95│ │00000011 Visual Basic Programming Borg 1-222222-33-4 03500 12.95 01/01/1998 0000000 2,000 14.95│ │00000012 XML Programming Web 2-333333-44-5 00012 24.95 01/01/2001 0000000 1,200 29.95│ │00000013 Smalltalk Programming Sun 9-777999-7-9 01000 18.95 03/31/1992 0000000 2 24.95│ │00099999 Bogus Programming ECF abcdefghij 05000 80.00 02/26/2006 0000999 0 100.00│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ Procedure complete. Press space bar to continue. */
In P2J the last dynamic query generates a full set of results that are added to the frame. In the 4GL, that does not happen. The difference seems to be in how (or how often) the DYNAMIC-FUNCTION is evaluated in this case.
Interestingly, this article describes some of the internal sub-expression evaluation going on (read the sample code carefully). I wonder if in the 4GL, they somehow evaluate this once only.