List of DDIC structures with invalid Enhancement Category

In this blog post, I propose a little program to detect all DDIC structures and tables with invalid Enhancement Categories. It’s largely inspired by the SAP program provided in the note 2205573 – Checking enhancement category for data dictionary objects with SAP tool, but this is a program to analyze one DDIC structure or table at a time.

The reason why I created this program was that after adding few more possible values to a custom DDIC domain and activating it, the activation log reported few standard DDIC structures with syntax errors, especially the DDIC structure PSHLP_CUSTFLDS_NTWK_ST. A check on it:
DDIC%20Structure%20check%20error

DDIC Structure check error

A fix is proposed by the note 1834868 – PSHLP: Syntax error in Customer field structures of HLP which consists in adjusting the Enhancement Category via SE11 > menu option Extras > Enhancement Category.

This syntax error didn’t seem to be a problem in production, but maybe this structure was actually never used. I created a little test program to use that DDIC structure, the program could activate, only a warning was reported by the Extended Check (SLIN).

I don’t know why it wasn’t detected earlier, so maybe we had other DDIC tables and structures in the same situation. It’s why I decided to extend the SAP program to detect all of them.

I named this custom program Z_CHECK_ENH_CAT_ALL.

The selection screen takes as input a list of packages, so you can type Z* to analyze all DDIC tables and structures which contain custom objects:

Selection%20screen%20of%20Z_CHECK_ENH_CAT_ALL

Selection screen of Z_CHECK_ENH_CAT_ALL

The result shows all analyzed DDIC tables and structures.

Just search “FAIL” to directly go to the errors.

Result%20of%20Z_CHECK_ENH_CAT_ALL

Result of Z_CHECK_ENH_CAT_ALL

In the example above, you can see that the Enhancement Category of ZBAPI_TE_DPR_PHASE is inconsistent. It’s because it includes BAPI_TE_DPR_PHASE whose Category is Can be Enhanced (without restriction), so ZBAPI_TE_DPR_PHASE Category should also be Can be Enhanced (at the time of the run it was Extensible alpha and numeric).

I hope this will help.

Program:

*This program is an extension of program in note 2205573, copyright SAP.
*https://launchpad.support.sap.com/#/notes/2205573
*2205573 - Checking enhancement category for data dictionary objects with SAP tool REPORT z_check_enh_cat_all LINE-SIZE 500. TABLES tdevc.
SELECT-OPTIONS: s_devcl FOR tdevc-devclass DEFAULT 'Z*' OPTION CP. TYPES: ty_tables TYPE STANDARD TABLE OF tabname WITH DEFAULT KEY. TYPES: BEGIN OF ty_include, precfield TYPE char30, fieldname TYPE char30, rollname TYPE char30, END OF ty_include, BEGIN OF ty_message, precfield TYPE char200, END OF ty_message. DATA: g_wa_message TYPE ty_message, gt_message TYPE TABLE OF ty_message, gv_deep TYPE n. START-OF-SELECTION. * 1. FIND ALL TABLES AND STRUCTURES TO BE CHECKED " starting from data elements SELECT dd03l~tabname FROM tadir INNER JOIN tdevc ON tdevc~devclass = tadir~devclass INNER JOIN dd03l ON dd03l~rollname = tadir~obj_name AND dd03l~as4local = 'A' AND dd03l~as4vers = 0 WHERE tadir~devclass IN @s_devcl AND tadir~pgmid = 'R3TR' AND tadir~object = 'DTEL' UNION SELECT dd03l_2~tabname FROM tadir INNER JOIN tdevc ON tdevc~devclass = tadir~devclass INNER JOIN dd03l ON dd03l~rollname = tadir~obj_name AND dd03l~as4local = 'A' AND dd03l~as4vers = 0 INNER JOIN dd03l AS dd03l_2 ON dd03l_2~precfield = dd03l~tabname AND dd03l_2~fieldname LIKE '.INCLU%' AND dd03l_2~as4local = 'A' AND dd03l_2~as4vers = 0 WHERE tadir~devclass IN @s_devcl AND tadir~pgmid = 'R3TR' AND tadir~object = 'DTEL' UNION SELECT dd03l_3~tabname FROM tadir INNER JOIN tdevc ON tdevc~devclass = tadir~devclass INNER JOIN dd03l ON dd03l~rollname = tadir~obj_name AND dd03l~as4local = 'A' AND dd03l~as4vers = 0 INNER JOIN dd03l AS dd03l_2 ON dd03l_2~precfield = dd03l~tabname AND dd03l_2~fieldname LIKE '.INCLU%' AND dd03l_2~as4local = 'A' AND dd03l_2~as4vers = 0 INNER JOIN dd03l AS dd03l_3 ON dd03l_3~precfield = dd03l_2~tabname AND dd03l_3~fieldname LIKE '.INCLU%' AND dd03l_3~as4local = 'A' AND dd03l_3~as4vers = 0 WHERE tadir~devclass IN @s_devcl AND tadir~pgmid = 'R3TR' AND tadir~object = 'DTEL' " starting from domains UNION SELECT dd03l~tabname FROM tadir INNER JOIN tdevc ON tdevc~devclass = tadir~devclass INNER JOIN dd03l ON dd03l~domname = tadir~obj_name AND dd03l~as4local = 'A' AND dd03l~as4vers = 0 WHERE tadir~devclass IN @s_devcl AND tadir~pgmid = 'R3TR' AND tadir~object = 'DOMA' UNION SELECT dd03l_2~tabname FROM tadir INNER JOIN tdevc ON tdevc~devclass = tadir~devclass INNER JOIN dd03l ON dd03l~domname = tadir~obj_name AND dd03l~as4local = 'A' AND dd03l~as4vers = 0 INNER JOIN dd03l AS dd03l_2 ON dd03l_2~precfield = dd03l~tabname AND dd03l_2~fieldname LIKE '.INCLU%' AND dd03l_2~as4local = 'A' AND dd03l_2~as4vers = 0 WHERE tadir~devclass IN @s_devcl AND tadir~pgmid = 'R3TR' AND tadir~object = 'DOMA' UNION SELECT dd03l_3~tabname FROM tadir INNER JOIN tdevc ON tdevc~devclass = tadir~devclass INNER JOIN dd03l ON dd03l~domname = tadir~obj_name AND dd03l~as4local = 'A' AND dd03l~as4vers = 0 INNER JOIN dd03l AS dd03l_2 ON dd03l_2~precfield = dd03l~tabname AND dd03l_2~fieldname LIKE '.INCLU%' AND dd03l_2~as4local = 'A' AND dd03l_2~as4vers = 0 INNER JOIN dd03l AS dd03l_3 ON dd03l_3~precfield = dd03l_2~tabname AND dd03l_3~fieldname LIKE '.INCLU%' AND dd03l_3~as4local = 'A' AND dd03l_3~as4vers = 0 WHERE tadir~devclass IN @s_devcl AND tadir~pgmid = 'R3TR' AND tadir~object = 'DOMA' " starting from tables UNION SELECT dd03l~tabname FROM tadir INNER JOIN tdevc ON tdevc~devclass = tadir~devclass INNER JOIN dd03l ON dd03l~precfield = tadir~obj_name AND dd03l~fieldname LIKE '.INCLU%' AND dd03l~as4local = 'A' AND dd03l~as4vers = 0 WHERE tadir~devclass IN @s_devcl AND tadir~pgmid = 'R3TR' AND tadir~object = 'TABL' UNION SELECT dd03l_2~tabname FROM tadir INNER JOIN tdevc ON tdevc~devclass = tadir~devclass INNER JOIN dd03l ON dd03l~precfield = tadir~obj_name AND dd03l~fieldname LIKE '.INCLU%' AND dd03l~as4local = 'A' AND dd03l~as4vers = 0 INNER JOIN dd03l AS dd03l_2 ON dd03l_2~precfield = dd03l~tabname AND dd03l_2~fieldname LIKE '.INCLU%' AND dd03l_2~as4local = 'A' AND dd03l_2~as4vers = 0 WHERE tadir~devclass IN @s_devcl AND tadir~pgmid = 'R3TR' AND tadir~object = 'TABL' INTO TABLE @DATA(tables). LOOP AT tables ASSIGNING FIELD-SYMBOL(<table>). WRITE / <table>-tabname COLOR 5. PERFORM check_one_table USING <table>-tabname. ENDLOOP. ASSERT 1 = 1. " debug helper FORM check_one_table USING p_table TYPE tabname. SELECT COUNT(*) FROM dd02l WHERE tabname = p_table AND as4local = 'A'. IF sy-subrc = 4. WRITE 'Table not found!'. ELSE. gt_message = VALUE #( ). PERFORM check_enhancements USING p_table ''. IF NOT gt_message[] IS INITIAL. LOOP AT gt_message INTO g_wa_message. WRITE: 'FAIL', g_wa_message. NEW-LINE NO-SCROLLING. ENDLOOP. WRITE 'The check was completed successfully!'. ELSE. WRITE 'No errors found!'. ENDIF. ENDIF. ENDFORM. FORM check_enhancements USING p_main_obj TYPE char30 p_prev_obj TYPE char30. DATA: lv_sub_ex TYPE n, "EXCLASS/ ENHANCEMENT CATEGORY lv_main_ex TYPE n, wa_includes TYPE ty_include, ls_includes TYPE TABLE OF ty_include, lv_curr_obj TYPE char30. lv_curr_obj = p_main_obj. SELECT SINGLE exclass FROM dd02l INTO lv_main_ex "Get the main structure WHERE tabname = lv_curr_obj AND as4local = 'A'. SELECT precfield fieldname rollname FROM dd03l "Get the fields INTO CORRESPONDING FIELDS OF wa_includes WHERE tabname = lv_curr_obj AND precfield <> '' AND as4local = 'A'. "( rollname = '' or datatype = 'STRU' ) AND AS4LOCAL = 'A'. APPEND wa_includes TO ls_includes. ENDSELECT. LOOP AT ls_includes INTO wa_includes. IF wa_includes-precfield <> ''. SELECT SINGLE exclass FROM dd02l INTO lv_sub_ex WHERE tabname = wa_includes-precfield AND as4local = 'A'. IF sy-subrc = 0 AND lv_main_ex < lv_sub_ex AND lv_main_ex <> 0 . "Check if will write PERFORM format_message USING p_main_obj wa_includes-precfield lv_sub_ex. ENDIF. PERFORM check_enhancements USING wa_includes-precfield "p_main_obj lv_curr_obj. "previous ELSEIF wa_includes-rollname <> '' . SELECT SINGLE exclass FROM dd02l INTO lv_sub_ex WHERE tabname = wa_includes-rollname AND as4local = 'A' . IF sy-subrc = 0 AND lv_main_ex < lv_sub_ex AND lv_main_ex <> 0. "Check if will write PERFORM format_message USING p_main_obj wa_includes-rollname lv_sub_ex. ENDIF. PERFORM check_enhancements USING wa_includes-fieldname "p_main_obj lv_curr_obj. "previous ENDIF. ENDLOOP. ENDFORM. FORM format_message USING p_main_obj TYPE tabname p_sub_obj TYPE tabname p_obj_ex TYPE n. DATA lw_message TYPE ty_message. CONCATENATE lw_message p_sub_obj INTO lw_message. CONCATENATE lw_message 'has a bigger enhancement category than' p_main_obj INTO lw_message SEPARATED BY space. CONCATENATE lw_message '.' INTO lw_message. CONCATENATE lw_message p_sub_obj 'is set to ' INTO lw_message SEPARATED BY space. IF p_obj_ex = 1. CONCATENATE lw_message '(Cannot be enhanced)' INTO lw_message SEPARATED BY space. ELSEIF p_obj_ex = 2. CONCATENATE lw_message '(Can be enhanced (character-type)' INTO lw_message SEPARATED BY space. ELSEIF p_obj_ex = 3. CONCATENATE lw_message '(Can be enhanced (character-type or numeric))' INTO lw_message SEPARATED BY space. ELSEIF p_obj_ex = 4. CONCATENATE lw_message '(Can Be Enhanced (DEEP))' INTO lw_message SEPARATED BY space. ENDIF. APPEND lw_message TO gt_message. CLEAR lw_message. ENDFORM.