OpenEdge 11 dropped backwards compatibility for can-do, func

Posted by cverbiest on 01-Jul-2013 03:31

In OpenEdge 11 Progress rewrote the manual entry for the can-do function, dropping the, otherwise excellent, backwards compatibility OpenEdge is know for.

can-do("@A@,@B@", "@A@") returns false from OpenEdge 11 onwards. In 10.2B and all earlier versions this returned true and was documented as such.

The 10.2B documentatie is now considered a documentation bug.

I do not yet know the impact of this change for our application but I find it very disturbing that such a change is made without offering an alternative for people who depend on the existing behaviour.

If Progress does this now for the can-do function which statement or function will be changed in the next release ?

Lookup is no alternative for can-do as it lacks the wildcard evaluation.

See also :

All Replies

Posted by Admin on 01-Jul-2013 03:55

Lookup is no alternative for can-do as it lacks the wildcard evaluation.


Progress (Gus repeatedly on the PEG) has always warned from using the CAN-DO for anything else than security checks against the USERID. As the @ seems to break the behavior it seems related to the multi-tenancy implementation.

Looks like it's time to implement your own CAN-DO like function that supports wildcards...

Posted by jmls on 01-Jul-2013 04:00

Mike and I are in agreement. Again.

this has to stop ...

Posted by Admin on 01-Jul-2013 04:20

this has to stop ...

NP: Put the function in an include file...

Just kidding. A static method should be fine.

Posted by cverbiest on 01-Jul-2013 04:51

Stopped, but still feeling let down that no alternative is offered.

I would gladly replace all occurrance of can-do by something else if it existed.

For now we'll leave it as is hoping that no-one will put @ in the strings and that the next release doesn't change the behaviour again.

Replacing 3000 occurances of can-do is not really an option.

I'll post an enhancement request for the regular expression evaluation as Tom Bascom suggested in 2004.

Posted by Michael Jacobs on 01-Jul-2013 04:54

Mike is correct.   The CAN-DO function's place in an application is for testing user-id against a permission list.   When multi tenancy went into OpenEdge all user-ids became two part fully qualified ids including both user-id and domain.   The CAN-DO function was updated to use the fully qualified id form like  all other user-id related statements and functions.  Not doing so would  have broken backwards compatibility with its intended function.

FYI: For backwards compatibility a user in the default 'blank' ("") domain may be declared explicitly as "user@" or in the short form "user".   CAN-DO allows you to use wildcards, independently, in both the user-id and domain parts to give you wider user-id pattern matching abilities.  CAN-DO will always suffix '@' to make an input id or permission list element fully qualified if '@' was not supplied in the input, thereby treating the entire input string as if it were the user-id.  In this way backwards compatibility is maintained with a mix of older non-qualified user-ids and the newer fully qualified user-ids.

Mike Jacobs

Posted by cverbiest on 01-Jul-2013 05:29

I can understand what the intended behaviour was and why the change was made.

I find it hard to understand that no alternative is provided for the pattern matching function of can-do that was documented in the past.

I have posted an enhancement request for regular expression evaluation as I think that is more productive.

Kind regards

Carl Verbiest

Posted by on 01-Jul-2013 06:35

for us, we used CAN-DO to replace INDEX() <> 0. Can't you switch to using INDEX instead?

I'm saying this, knowing I have to change 442 CAN-DO's in our code. Also CAN-DO seemed a more elegant solution then all those darn INDEX's.

>I'll post an enhancement request for the regular expression evaluation as Tom Bascom suggested in 2004.

That was 9 years ago, could be even Tom doesn't have this on his request roadmap.

Amusingly, in one of the directories I searched, I had the src for 11.1. There are 4000+ CAN-DO statements in there, almost all of them having nothing to do with userid.

Haven't checked 11.2 yet.

Posted by Etienne Begin on 05-Jul-2013 07:44

I kind of agree with Carl.  I understand the original intent of can-do, but this can be a dangerous path to take by Progress.  I just have a gut feeling Progress you could apply the same reasoning to other features, and "break" them.


Posted by jmls on 05-Jul-2013 07:55

to be fair, Progress have been saying for 20+ years

"don't do that. One day it will bite you"

Just because you can, doesn't mean that you should.

Posted by Etienne Begin on 05-Jul-2013 08:12

I only know about this because I read the PEG, probably stumble upon it in the KB.  I was never compelled to use it for strings.

However, It is not mentioned in the language reference that using can-do for strings is not recommended.  I fact it states:

"An arbitrary list of string values. The function returns TRUE if the specified string value is contained in the list."


"In addition to performing security checks, you can use the CAN-DO function for looking up any value in a comma-separated list." (has a code example)


Posted by cverbiest on 05-Jul-2013 09:05

Tech support now calls this a documentation bug.

My 8.3 Manual also states the same as my 10.2B manual.

I don't find my V6 manual at the moment but I doubt it mentions can-do is security only.

From the 8.3 manual

In addition to performing security checks, you can use the CAN-DO function for looking up any value in a comma-separated list.

For example, the following procedure searches your PROPATH for your DLC directory.
MESSAGE "The DLC directory " +
        (IF CAN-DO(PROPATH, OS-GETENV("DLC")) THEN "is" ELSE "is NOT") +
        " in your PROPATH.".

I think they did a very sloppy job at warnings us not to use it.

Worst of all they provide no alternative for the people who believed the manual.

Posted by SJProgress on 05-Jul-2013 09:10

Vielen Dank für Ihre Nachricht!

Ich werde ab Mo. 15.07.2013 wieder im Büro sein und Ihre Email-Nachricht bearbeiten.

Mit freundlichen Grüssen

Josef Siegetsleitner, Easyrent Software Entwicklung

Thank you for your message!

I will return to my office on Monday July, 15th and will answer your email then.

Best regards

Josef Siegetsleitner - Easyrent Software Development

Posted by Thomas Mercer-Hursh on 05-Jul-2013 09:11

Carl, while may seem onerous to change the can-dos, there is also the point that it is the right thing to do.   There is no reason this couldn't be done by an automated process.

Posted by cverbiest on 05-Jul-2013 10:19

I don't mind changing our code but I do mind that no alternative is given.

Lookup lacks the pattern matching of can-do so it is not a valid replacement.

The lack of other string functions/methods is one of the things that made us use can-do.

This change makes an already small set of functions even smaller.

The only thing I have come up with so far is a 4GL function definition (see below) but that

  1. Is slow compared to can-do
  2. Invalid in where clauses
  3. Not fully tested

it would have been nice if the existing can-do had been renamed (e.g. to can-match) before the functionality was changed.

The documentation would then read (I'm dreaming aloud)

NOTE : as of version 11 can-do is only supported for security tests. Use can-match for the pattern matching previously offered by can-do.

function can-match returns logical (input i-candolist as char, input i-string as char).

    def var lCount as int no-undo.

    def var lResult as logical no-undo.

    def var lPattern as char no-undo.

    if num-entries(i-candolist) = 0 and i-candolist = i-string then return true.

    do lCount = 1 to num-entries(i-candolist):

        lPattern = entry(lCount, i-candolist).

        if lPattern begins "!"

        then assign

            lResult = no

            lPattern = substring(lPattern, 2).

        else lResult = yes.

        if i-string matches lPattern or i-string = lPattern

        then return lResult.


    return false. /* no match found */

end function.

Posted by Thomas Mercer-Hursh on 05-Jul-2013 11:14

Not much help now, I know, but one of the best practices I recommend is that whenever a language doesn't really have the feature one wants, then encapsulate the workaround so that when the language changes, one merely needs to change one place.   Of course, this principle applies to a lot more than just missing language features, but it is especially applicable when one has a language like ABL that keeps expanding.  Yes, I know that can-do did do what you wanted at one point, but I think there is a big clue that can-do is extremely weak in comparison to regular expression matching with which we are all familiar, so I think that is a clue that one should be encapsulating one's regular expression tests.  This lets one can take advavantage of new future additions to the language, provides a focus for providing expanded functionality, and insulates one from changes like the recent one.

This thread is closed