SAP BOX

'26/10/15 UPDATE

ABAP / FIELD NOTES

Why Is IF name CS 'TEST' True for 'Contest'?

ABAP's CS and CP ignore case, and CS ignores word boundaries too, so CS 'TEST', meant to filter out test vendors, is also true for Contest Media GmbH. Using a fictional example, this note compares the case-sensitive CO, CA, FIND and contains( ), shows three ways to write the intended condition, and notes how the documentation wording differs between releases.

In a vendor list program you skip test vendors with IF lv_name CS 'TEST'. CONTINUE. ENDIF. Then the real vendor Contest Media GmbH disappears from the list. There is no uppercase TEST anywhere in that name, yet the condition is true. After reading this you will know that CS and CP ignore case and why, which comparison operators and search statements for character data do respect case, and how to choose a way of writing exactly the condition you meant.

In the example, lv_name is TYPE c LENGTH 30. The vendor names TEST VENDOR 01, Contest Media GmbH and Northwind Paper and the program ZDEMO_CS_CASE are fictional. The code was not run on a real system. The results given here follow from the rules on the ABAP Keyword Documentation pages for comparison operators for character-like data types (7.50, compared with 7.54 and 7.58), the additions of FIND and the contains functions.

CS does not distinguish case

CS (Contains String) is true if the content of the right operand is contained in the left operand. The 7.50 and 7.54 documentation states that this comparison is not case-sensitive and that trailing blanks in the left operand are respected. So the lowercase test starting at the fourth character of Contest Media GmbH counts as 'TEST'. The result is true, and the system field sy-fdpos holds the offset of the match, 3 (the first character is 0).

Two problems overlap here: case and position. CS does not care where the sequence occurs, even in the middle of a word. On a system that stores names in uppercase only, CONTEST MEDIA GMBH matches for the same reason. When the comparison is false, sy-fdpos holds the length of the left operand instead of an offset, so do not read sy-fdpos as a position after a false result.

SAP NOTES

CS 'TEST' against three names

Fictional example: lv_name is TYPE c LENGTH 30, the condition is IF lv_name CS 'TEST'

  • TEST VENDOR 01

    'TEST VENDOR 01' CS 'TEST'

    • TEST is at the very start
    • Result: true
    • sy-fdpos = 0
  • Contest Media GmbH

    'Contest Media GmbH' CS 'TEST'

    • Lowercase test sits inside a word
    • CS does not distinguish case
    • Result: true, sy-fdpos = 3
  • Northwind Paper

    'Northwind Paper' CS 'TEST'

    • No test sequence at all
    • Result: false
    • sy-fdpos = length of the left operand

Names and variables are fictional. The results follow from the CS rule in the ABAP Keyword Documentation (7.50 and 7.54); they are not run results.

CS 'TEST', written to filter out test vendors, is also true for the real vendor name Contest Media GmbH. CS does not distinguish case, and it does not look at word boundaries either.

Trying to imitate a word boundary with a blank in the right operand does not work either. The documentation says that, unless stated otherwise, trailing blanks of operands of type c, d, n and t are not respected, and for CS only the left operand's trailing blanks count. By that rule the single-quoted literal 'TEST ' behaves exactly like 'TEST'. The documentation names one more case: if the left operand is a c field containing only blanks or an initial string, the result is false, but if the right operand is empty in the same way, the result is always true. When a search variable sits on the right of CS, filter out the case where both are empty first.

CO and CA respect case, even among the same operators

The eight comparison operators for character data do not all follow the same rule. CO (contains only these characters) and CA (contains any of these characters) respect case, and they respect trailing blanks of both operands. CN and NA are the negations of CO and CA. By contrast, CS and its negation NS, and the pattern comparison CP and its negation NP, ignore case. For the same 'abc', 'abc' CS 'B' is true while 'abc' CA 'B' is false.

CP has a way to make case count. In the pattern, * stands for any character string including an empty one and + for any single character, and a character preceded by the escape character # is compared directly, respecting case. The documentation also notes that + never stands for an empty string, and that CP means "conforms to pattern", not "contains pattern", so the whole string has to fit the pattern. That is why the documentation's example uses '*<*>*', not '<*>', to find a tag.

The search statements have the opposite default. Without RESPECTING CASE or IGNORING CASE, FIND works as RESPECTING CASE and distinguishes case. The built-in functions contains( ) and find( ) are case-sensitive by default too, and ignore case only when you pass case = abap_false. The intention is the same, checking whether something is contained, yet CS ignores case while FIND and contains( ) respect it.

SAP NOTES

What respects case and what does not

Default behaviour of character comparison operators and search syntax

  • Ignores case

    'abc' CS 'B' → true

    • CS · NS: contains a string
    • CP · NP: matches a pattern (* +)
    • Only characters marked with # respect case
  • Respects case

    'abc' CA 'B' → false

    • CO · CN: consists only of these characters
    • CA · NA: contains any of these characters
    • Trailing blanks of both operands count too
  • Respects case by default

    FIND 'B' IN 'abc' → sy-subrc 4

    • FIND: RESPECTING CASE is the default
    • contains( ), find( ): case-sensitive by default
    • Turn off with IGNORING CASE or case = abap_false

Based on the ABAP Keyword Documentation pages for comparison operators, FIND, contains and string_func - case. Results in the code samples follow from the rules.

Both are 'contains' checks, yet CS ignores case while FIND and contains( ) respect it by default. CO and CA compare character by character and respect case.

Write the condition you actually mean

The fix starts with deciding what a test vendor is. Say that in this example it means a name that starts with TEST followed by a blank. Then you can compare three ways of writing it on the same three names.

First, with FIND 'TEST' IN lv_name. the name Contest Media GmbH no longer matches, and since nothing is found sy-subrc is 4. The position problem remains, though, so an uppercase CONTEST is still found. Only the case problem is solved. The documentation also says that FIND and the search functions can be faster than CS by some magnitude, which is one more reason to switch inside a long loop.

Second, contains( val = lv_name start = `TEST` ) looks only at a match at the beginning and respects case. It does not reject a name like TESTA, where a letter follows directly. Third, lv_name CP '#T#E#S#T *' marks all four letters with #, so it accepts only an uppercase TEST, and it requires the blank after it. By the rules, only TEST VENDOR 01 of the three names is true.

SAP NOTES

To pick only names that start with TEST

Three ways of writing it, applied to the same three fictional names

  1. Switch to FIND

    FIND 'TEST' IN lv_name.

    • Contest Media GmbH: not found
    • An uppercase CONTEST would still match
    • Fixes case only
  2. contains( start = )

    contains( val = lv_name start = `TEST` )

    • Looks only at TEST at the start
    • Case-sensitive by default
    • Does not reject TESTA-style names
  3. Mark characters with # in CP

    lv_name CP '#T#E#S#T *'

    • #T#E#S#T: uppercase TEST only
    • Requires the blank after it
    • Only TEST VENDOR 01 is true

Names are fictional and the code was not run. Results follow from the documented FIND, contains and CP rules. contains( ) exists from ABAP 7.0 EhP2.

Switching to FIND removes the case problem, but a TEST inside a word still matches. If what you want is 'names that start with TEST', write exactly that condition in the code.

The editor example below collects this on one screen: ① the declaration, ② the CS line that skips a real vendor, ③ the case-sensitive FIND, ④ contains( ) looking only at the start, and ⑤ CP with #. In existing code, an uppercase literal after CS or CP is worth a second look: did the author expect case to count?

SAP GUI ABAP Editor with five numbered markers: 1, lv_name declared as TYPE c LENGTH 30; 2, IF lv_name CS 'TEST' with the comment that it is also true for 'Contest Media GmbH'; 3, FIND 'TEST' IN lv_name with the comment that RESPECTING CASE is the default; 4, IF contains( val = lv_name start = `TEST` ); 5, IF lv_name CP '#T#E#S#T *' with the comment that only 'TEST VENDOR 01' is true.
An example editor view collecting the CS line in a loop that skips test vendors and three alternatives. ZDEMO_CS_CASE and the vendor names are fictional; the code was not run, and the results in the comments follow from the documented rules.

The documentation wording differs between releases

The release difference shows up in the documentation before it shows up in behaviour. The 7.50 and 7.54 English documentation states plainly that CS is not case-sensitive, and the 7.54 German documentation likewise says that case is not respected while trailing blanks of the left operand are. In the 7.57 and 7.58 English documentation, however, the CS sentence now reads as "uppercase and lowercase characters and trailing blanks in the left operand are respected". On the same 7.58 page, the CP entry still says it is not case-sensitive, and the CS example is described as showing the position of 'H' in a lowercase alphabet string, which only makes sense if case is ignored.

The wording alone does not settle which reading is right, and this note was not checked on a real system. So the safe step is to test it yourself with one line on your system: IF 'abc' CS 'B'. If it is true, your system behaves as described here, and sy-fdpos is 1. Character functions such as contains( ) and find( ) arrived in ABAP 7.0 EhP2, so on older systems FIND or CP with # are the options available.

Remember one thing. Checking "contains" with CS ignores both case and word boundaries. If case must count or the position matters, write that condition directly in the code with FIND, contains( ) or CP with #.

THE END
RSS feedBack to the library
COMMENTS BOX

Add your perspective.

Share a question, another approach, or something you have tried.

Newest first

Checking sign-in…

Loading comments…