如何解决展平/统一表行,其中条件与 ABAP 或 SQL
我正在尝试将表展平为数组(或结构)。我的实现是在 SAP ABAP 中;但是,我相信这个问题与代码无关。我想知道是否有我不知道的算法或我想要实现的简单解决方案。我将接受任何语言或伪代码作为可接受的答案。
我正在从存储在数据库中的“用户限制”(即lt_restrictions)表中进行选择,例如:
这是 SAP BSP MVC Web 应用程序所必需的。当应用程序加载时,我正在执行用户授权检查以填充“用户角色”(即,mt_user_roles)本地表/数组(即,MVC 模型类上的属性).
授权检查涉及常规 ABAP -- 使用 IF 语句有条件地填充“用户角色”表,例如:
AUTHORITY-CHECK OBJECT 'PROGRAM_MANAGER_AUTH' ID 'xxx' FIELD 'yyy'.
IF ( sy-subrc = 0 ).
APPEND VALUE #( low = 'program_manager' ) TO me->mt_user_roles.
ENDIF.
如果用户同时拥有项目经理和进入用户权限,则此“用户角色”表/数组如下所示:
对于上面两个表,如果用户具有项目经理和入门用户角色,则唯一的限制是转换;因此,我需要填充“限制列表”(即ms_restrictions),如下所示:
否则,如果用户只有例如入口用户角色:
...有 2 个限制(释放和转换),所以我需要像这样填充“限制列表”(即 ms_restrictions):
我觉得有一个我可以使用的标准算法,或者这可以在 SELECT 语句中使用 SQL 完成,我的数据库表 WHERE 限制 = NULL(例如,WHERE save = ' ')或使用 {{3} },也许,如果“限制列表”是一个SELECT ... WHERE x IN clause?
我应该提一下,我已经有了一个不受欢迎的部分解决方案,它涉及遍历数据库表并为每个限制条件设置多个 IF 语句。 “限制列表”被命名为ms_restrictions,它是一个ABAP STRUCTURE类型的类属性(对于ABAP新手来说,这基本上是一个一维大小的数组):
LOOP AT lt_restrictions INTO DATA(ls_restriction).
LOOP AT mt_user_roles INTO DATA(ls_user_role).
"Check save restriction
IF (
ls_restriction-role = ls_user_role-role AND
ls_user_role = 'save'
).
ms_restrictions-save = 'x'.
ENDIF.
"Check release restriction
IF (
ls_restriction-role = ls_user_role-role AND
ls_user_role = 'release'
).
ms_restrictions-release = 'x'.
ENDIF.
"Check other restrictions
"......
ENDLOOP.
ENDLOOP.
上述解决方案的问题是我必须为每个限制编写一个 IF 语句。更重要的是,它没有考虑 2 个或多个角色限制之间是否存在冲突,例如,项目经理只有 1 个限制,而 入口用户 有 2。我上面的逻辑可以扩展到考虑到这一点——好吧——甚至更多的 IF 语句:-( ..我想知道是否有不同的方法我可以拿?
另外,我应该提到。在我看来,禁用 HTML 按钮需要生成的“限制列表”,即 mt_restrictions,例如:
<button value = 'Save' disabled = '//model/mt_restrictions-save' />
<button value = 'Release' disabled = '//model/mt_restrictions-release' />
<button value = 'Convert' disabled = '//model/mt_restrictions-convert' />
<button ... />
解决方法
我想出的解决方案涉及使用 ABAP FIELD-SYMBOL> 的数据类型和 OpenSQL FOR ALL ENTRIES IN SELECT
语句添加。
通过使用 <FIELD-SYMBOL>
,您可以避免任何硬编码的属性和/或结构组件名称。现在,限制规则可以增长,而无需将来修改任何代码。
通过使用 FOR ALL ENTRIES IN
,您可以将 Roles 表与 Restrictions 表同步。添加此子句允许您从透明的 Role/Restrictions 数据库表 SELECT
中INTO
一个表,仅包括适用于 AUTH-CHECK
中找到的角色的角色(因为 mt_user_roles
为每个真正的 AUTH-CHECK
填充一个新行)。
方法 is_standard_user( )
是 AUTH-CHECK
发生的地方。如果它等于 ABAP_TRUE
,则应用所有限制——假设 ms_restrictions
结构组件的值都默认为 ABAP_TRUE
。
动态循环遍历ms_restrictions
的每个结构组件,可以READ
对应值的限制表。如果 value 等于 SPACE
,则表示当前行没有限制。因此,将结构组件值标记为 SPACE
(因为它可能已在之前的迭代中标记为 ABAP_TRUE
)——这解决了“角色冲突问题”。
"perform authorization checks
IF ( NOT me->is_standard_user( ) ).
"see if roles found
IF ( lines( me->mt_user_roles ) > 0 ).
"find pertaining restrictions for roles found in auth checks
SELECT
*
FROM
zmm_apr_roles
FOR ALL ENTRIES IN "select only rows applicable to auth-check
@me->mt_user_roles
WHERE
role = @me->mt_user_roles-role
INTO TABLE
@DATA(lt_restrictions).
"dynamically populate restriction list from multi-role restriction table
DATA: lr_descr_struc TYPE REF TO data.
DATA: lo_structdescr TYPE REF TO cl_abap_structdescr.
CREATE DATA lr_descr_struc LIKE ms_restrictions.
lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( p_data_ref = lr_descr_struc ).
LOOP AT lo_structdescr->components ASSIGNING FIELD-SYMBOL(<lv_component>).
ASSIGN COMPONENT <lv_component>-name OF STRUCTURE ms_restrictions TO FIELD-SYMBOL(<lv_field>).
IF ( <lv_field> IS ASSIGNED ).
"non-restricted value overwrites restricted value
READ TABLE lt_restrictions WITH KEY (<lv_component>-name) = space TRANSPORTING NO FIELDS.
IF ( sy-subrc = 0 ).
<lv_field> = space.
ENDIF.
ENDIF.
ENDLOOP.
ENDIF.
ENDIF.
要添加新限制,只需:
- 向
zmm_apr_roles
和相应的数据字典组件添加新角色 - 为
ms_restrictions
的相应组件添加新的限制
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。