PSA - Passing groups to UNBIND is almost certainly a bug

TLDR: Passing groups to UNBIND is wrong and will lead to hard to find bugs. It also seems like it should work if you don’t read the manual carefully.

For quite some time we had a problem with views randomly failing for no apparent reason, and with crazy error messages like:

  • Bind has not been called for OR
  • Bind has not been called for AND

This weird behavior cost us quite some manhours chasing all sorts of red herrings, but at long last we’ve pinpointed the root cause of the problem. It turns out BIND and UNBIND are not quite symmetric and while you can BIND a group whole, you can’t do the same thing with UNBIND. As groups are treated like strings, the compiler can’t warn you that you are doing something rather silly, and happily accepts the group as input causing (almost) random things to be unbound.

The moral of the story is that you can’t read the manual too many times, and reading comprehension matters. Also pay attention when passing groups to procedures that take strings as input.

PS. example illustrating our bug:

DemoGroup                       Group
foo                                 CSTRING(20)
                                END
DemoGroup2                      Group
charA                               BYTE(65)
charN                               BYTE(78)
charD                               BYTE(68)
                                END

    MAP
    END

    CODE

    DO Test
    DO BreakStuff
    DO Test

!----------------------------------------------------------------------------------------------------------------------------------------------------    
BreakStuff                      ROUTINE
    
    BIND(DemoGroup)
    BIND(DemoGroup2)
    DemoGroup.foo = 'OR'
    UNBIND(DemoGroup)
    UNBIND(DemoGroup2)

!----------------------------------------------------------------------------------------------------------------------------------------------------    
Test                            ROUTINE
    
    MESSAGE(EVALUATE('CHOOSE(0 OR 1,''TRUE'',''FALSE'')')&ERROR())  ! TRUE  | Bind has not been called for OR
    MESSAGE(EVALUATE('CHOOSE(0 AND 1,''TRUE'',''FALSE'')')&ERROR()) ! FALSE | Bind has not been called for AND
       
!----------------------------------------------------------------------------------------------------------------------------------------------------
2 Likes

Interesting. I guess I never hit that issue because I tend to use PUSHBIND/POPBIND instead of UNBIND.

3 Likes