현상
Tibero6에서 Tibero7.2.3으로 업그레이드한 이후, 아래와 같은 계층형 쿼리를 수행할 경우 Internal Error [Code: OPT_D2OF2J] with condition '!list_empty(paths) || !list_empty(&or_exp_paths)'가 발생했습니다.
수행 쿼리
SELECT
CLASS_ID||'^'||NODE_TYPE||'^'||DECODE(LEAF,1,'true','false')||'^'||ENTITY_TYPE AS ID
,CLASS_ID AS NODE_ID
,CLASS_NM AS TEXT
,NVL(UP_CLASS_ID,'N/A') AS UP_NODE_ID
,DECODE(CONNECT_BY_ISLEAF,1,'true','false') AS LEAF
,TO_CHAR(LEVEL) AS NODE_LEVEL
,TO_CHAR(DISPLAY_NO) AS DISPLAY_NO
FROM (
SELECT
CLASS_ID
,CLASS_NM
,UP_CLASS_ID
,DISPLAY_NO
,USE_YN
,NODE_TYPE
,LEAF
,ENTITY_TYPE
FROM(
SELECT
CLASS_ID
,CLASS_NM
,UP_CLASS_ID
,DISPLAY_NO
,USE_YN
,'C' NODE_TYPE
,CONNECT_BY_ISLEAF AS LEAF
,'' ENTITY_TYPE
FROM
(
SELECT
CLASS_ID AS CLASS_ID
,CLASS_NM
,UP_CLASS_ID
,DISPLAY_NO
,USE_YN
,UPD_USER_ID
,CLASS_TYPE
FROM
AM_CLASS A
WHERE
USE_YN = 'Y'
UNION ALL
SELECT
CLASS_ID||'-0' AS CLASS_ID
,CLASS_NM||'(논리)' AS CLASS_NM
,UP_CLASS_ID,DISPLAY_NO+0.1 AS DISPLYAY_NO
,USE_YN
,UPD_USER_ID
,CLASS_TYPE
FROM
AM_CLASS
WHERE
USE_YN = 'Y'
AND LOGICAL_YN='Y'
) A
START WITH CLASS_ID = '0'
CONNECT BY PRIOR CLASS_ID = UP_CLASS_ID
ORDER SIBLINGS BY TO_NUMBER(DISPLAY_NO)
)UNION ALL(
SELECT
ENTITY_ID
,ENTITY_NM
,UP_ENTITY_ID
,SORT_ORDER
,USE_YN
,'E'
,0
,ENTITY_TYPE
FROM
AM_ENTITY)
)
START WITH CLASS_ID = '0'
CONNECT BY PRIOR CLASS_ID = UP_CLASS_ID
ORDER SIBLINGS BY TO_NUMBER(DISPLAY_NO)
/
SQL
복사
out 파일
================================
[1557] 2025/04/24 11:32:53.556 Internal Error [Code:OPT_D2OF2J] with condition '!list_empty(paths) || !list_empty(&or_exp_paths)' (0 args) (build_path.c:153:build_path) (pid=55424, sessid=1557, tid=1557, os_thr_id=57173)
[1557] client : ip [10.238.3.110] process [JDBC Thin Client] logon time : [2025/04/24 10:55:49]
[1557] prev sql : "
SELECT
DECODE(MOD_YN,'N','R',AUTH_TYPE) AS AUTH_TYPE
FROM(
SELECT
DISTINCT AUTH_TYPE
,( SELECT MOD_YN FROM AM_ENTITY WHERE ENTITY_ID = A.ENTITY_ID) AS MOD_YN
FROM
AM_ATTR_USER_GRP_MAPPING A
WHERE
ENTITY_ID = ?
AND USER_GRP_ID IN (SELECT AUTH_ID FROM SYS_USERGRP_TO_AUTH WHERE USER_GRP_ID IN (SELECT USER_GRP_ID FROM SYS_USERGRP_TO_USER WHERE USER_ID = ?))
)
"
[1557] current sql : "SELECT /*+ no_outline */ NAME, ID FROM SYS.SQLOBJ$ SO WHERE SO.SIGNATURE = :b0 AND SO.CATEGORY = :b1 AND SO.OBJ_TYPE = 1 AND SO.FLAGS = 1;"
[220] *** 2025/04/24 11:32:53.556 ***
[220] callstack dump from tbsvr_AGNT for [WTHR, 1557, 57173/55424]
[220] SEE DUMP tbsvr.callstack.55424 (lwpid 57173) BY PSTACK
================================
SQL
복사
원인
315625a 패치의 사이드 이펙트로 인해, 해당 패치에서는 siblings order by 절에 사용된 컬럼들을 새로 추가된 order 리스트에 넣어 처리하도록 로직이 수정되었습니다.
그러나 쿼리에서 사용되지 않는 컬럼인지 확인하는 최적화 룰을 수행할 때, 해당 리스트에 대한 체크 로직이 누락되어 불필요한 컬럼으로 판단되면서 Internal Error가 발생하게 되었습니다.
이번 쿼리의 경우에는 USE_YN 컬럼이 최종 SELECT 문에 사용되지 않아 불필요한 컬럼으로 처리되었고, 이로 인해 최적화 과정에서 Internal Error가 발생하였습니다.
해결
Internal Error가 발생한 원인은 USE_YN 컬럼이 최종 SELECT 문에 사용되지 않아 발생한 것이므로, 해당 컬럼을 최종 SELECT 문에 포함시키는 방식으로 쿼리를 수정하여 우회가 가능합니다.
또한, connected by 절의 마지막에 not null 조건 등 쿼리 수행 결과에 영향을 주지 않는 조건을 추가하거나, 최종 SELECT 문에서 USE_YN을 출력하도록 구성하는 방법으로도 동일하게 우회할 수 있습니다.
주의
티맥스티베로에서 제공하는 기술지원을 통해 패치를 적용합니다.
CONNECTED BY 절 수정 예시
START WITH CLASS_ID = '0'
CONNECT BY PRIOR CLASS_ID = UP_CLASS_ID
ORDER SIBLINGS BY TO_NUMBER(DISPLAY_NO)
/
=>
START WITH CLASS_ID = '0'
CONNECT BY PRIOR CLASS_ID = UP_CLASS_ID
--and CLASS_NM is not null
and USE_YN is not null
--and NODE_TYPE is not null
--and LEAF is not null
--and ENTITY_TYPE is not null
ORDER SIBLINGS BY TO_NUMBER(DISPLAY_NO)
SQL
복사
SELECT 대상 수정 예시
SELECT
CLASS_ID||'^'||NODE_TYPE||'^'||DECODE(LEAF,1,'true','false')||'^'||ENTITY_TYPE AS ID
,CLASS_ID AS NODE_ID
,CLASS_NM AS TEXT
,NVL(UP_CLASS_ID,'N/A') AS UP_NODE_ID
,DECODE(CONNECT_BY_ISLEAF,1,'true','false') AS LEAF
,TO_CHAR(LEVEL) AS NODE_LEVEL
,TO_CHAR(DISPLAY_NO)
=>
SELECT
CLASS_ID||'^'||NODE_TYPE||'^'||DECODE(LEAF,1,'true','false')||'^'||ENTITY_TYPE AS ID
,CLASS_ID AS NODE_ID
,CLASS_NM AS TEXT
,NVL(UP_CLASS_ID,'N/A') AS UP_NODE_ID
,DECODE(CONNECT_BY_ISLEAF,1,'true','false') AS LEAF
,TO_CHAR(LEVEL) AS NODE_LEVEL
,TO_CHAR(DISPLAY_NO) AS DISPLAY_NO
,USE_YN
SQL
복사