SET PATH *LIBL ; 

CREATE OR REPLACE FUNCTION RESTAPI.GENERATE_DBML_INLINE ( 
	INAPPVER VARCHAR(10) , 
	INAPPNAME VARCHAR(128) ) 
	RETURNS CLOB(2147483647)   
	LANGUAGE SQL 
	SPECIFIC RESTAPI.GENERATE_DBML_INLINE 
	NOT DETERMINISTIC 
	READS SQL DATA 
	CALLED ON NULL INPUT 
	SET OPTION  ALWBLK = *ALLREAD , 
	ALWCPYDTA = *OPTIMIZE , 
	COMMIT = *NONE , 
	DBGVIEW = *SOURCE , 
	DECRESULT = (31, 31, 00) , 
	DYNDFTCOL = *NO , 
	DYNUSRPRF = *OWNER , 
	SRTSEQ = *HEX   
	BEGIN 
DECLARE V_RESULT CLOB ( 2 G ) ; 
WITH 
-- 1) endpoints you want (one-time maintenance here) 
ENDPOINTS ( APPVER , APPNAME , APPFUNC , PATH_TEMPLATE , HTTP_METHOD , 
CONSUMES , PRODUCES , SUCCESS_CODE ) AS ( 
VALUES ( INAPPVER , INAPPNAME , 'assignUserRoles' , 
'/sailPoint/users/mapics/{envId}/{userName}/roles/assign' , 
'POST' , '*/*' , 'application/json' , '200' ) , ( INAPPVER , 
INAPPNAME , 'changeIbmIUser' , 
'/sailPoint/users/ibmi/{authorizationName}/change' , 
'POST' , '*/*' , 'application/json' , '200' ) , ( INAPPVER , 
INAPPNAME , 'createIbmIUser' , 
'/sailPoint/users/ibmi/create' , 'POST' , '*/*' , 
'application/json' , '201' ) , ( INAPPVER , INAPPNAME , 
'createMapicsUser' , 
'/sailPoint/users/mapics/{envId}/create' , 'POST' , 
'*/*' , 'application/json' , '201' ) , ( INAPPVER , 
INAPPNAME , 'disableIbmIUser' , 
'/sailPoint/users/ibmi/{authorizationName}/disable' , 
'POST' , '*/*' , 'application/json' , '200' ) , ( INAPPVER , 
INAPPNAME , 'enableIbmIUser' , 
'/sailPoint/users/ibmi/{authorizationName}/enable' , 
'POST' , '*/*' , 'application/json' , '200' ) , ( INAPPVER , 
INAPPNAME , 'getAllAppUsers' , 
'/sailPoint/users/mapics/{envId}' , 'POST' , '*/*' , 
'application/json' , '200' ) , ( INAPPVER , INAPPNAME , 
'getAllMapicsRoles' , 
'/sailPoint/roles/mapics/{envId}' , 'POST' , '*/*' , 
'application/json' , '200' ) , ( INAPPVER , INAPPNAME , 
'getAllUsers' , '/sailPoint/users/all' , 'POST' , '*/*' , 
'application/json' , '200' ) , ( INAPPVER , INAPPNAME , 
'getAppUserInfo' , 
'/sailPoint/users/mapics/{envId}/{userName}' , 'POST' , 
'*/*' , 'application/json' , '200' ) , ( INAPPVER , 
INAPPNAME , 'getIbmIUserInfo' , 
'/sailPoint/users/ibmi/{userName}' , 'POST' , '*/*' , 
'application/json' , '200' ) , ( INAPPVER , INAPPNAME , 
'removeUserRoles' , 
'/sailPoint/users/mapics/{envId}/{userName}/roles/remove' , 
'POST' , '*/*' , 'application/json' , '200' ) 
) , 
-- 2) placeholders discovered in your SQL 
PARAMS AS ( 
SELECT P . APPVER , P . APPNAME , P . APPFUNC , P . APPPARAM , P . PARAMPOS 
FROM TABLE ( 
RESTAPI . GET_PARAM_PLACEHOLDERS ( 
INAPPVER , INAPPNAME , NULL ) 
) AS P 
) , 
-- 3) nice path label renames (optional, one-time) 
PARAM_RENAME ( APPFUNC , APPPARAM , RESTNAME ) AS ( 
VALUES ( 'assignUserRoles' , 'envid' , 'envId' ) , 
( 'assignUserRoles' , 'userName' , 'userName' ) , 
( 'removeUserRoles' , 'envid' , 'envId' ) , 
( 'removeUserRoles' , 'userName' , 'userName' ) , 
( 'createMapicsUser' , 'envid' , 'envId' ) , 
( 'getAllAppUsers' , 'environment' , 'envId' ) , 
( 'getAllMapicsRoles' , 'envid' , 'envId' ) , 
( 'getAppUserInfo' , 'environment' , 'envId' ) , 
( 'getAppUserInfo' , 'nameOrId' , 'userName' ) , 
( 'getIbmIUserInfo' , 'nameOrId' , 'userName' ) 
) , 
-- 4) param location + final REST name (no aggregates here) 
PL AS ( 
SELECT P . APPVER , P . APPNAME , P . APPFUNC , P . APPPARAM , P . PARAMPOS , 
COALESCE ( R . RESTNAME , P . APPPARAM ) AS RESTNAME , 
CASE 
WHEN 
LOCATE ( 
'{' || UPPER ( COALESCE ( R . RESTNAME , P . APPPARAM ) ) 
|| '}' , UPPER ( E . PATH_TEMPLATE ) ) > 0 
THEN 'PATH' 
WHEN UPPER ( P . APPPARAM ) = 'INENVLIST' THEN 'QUERY' 
ELSE 'FORM' 
END AS LOCATION 
FROM PARAMS P 
JOIN ENDPOINTS E 
ON E . APPVER = P . APPVER 
AND E . APPNAME = P . APPNAME 
AND E . APPFUNC = P . APPFUNC 
LEFT JOIN PARAM_RENAME R 
ON R . APPFUNC = P . APPFUNC 
AND UPPER ( R . APPPARAM ) = UPPER ( P . APPPARAM ) 
) , 
-- 5) pre-aggregate the Json_Object parameter list (avoids nested aggregates) 
PARAM_STR AS ( 
SELECT P . APPVER , P . APPNAME , P . APPFUNC , 
LISTAGG ( 
'''' || P . APPPARAM || ''':' || '?' , ', ' ) 
WITHIN GROUP ( ORDER BY P . PARAMPOS ) AS PARAMS_TXT 
FROM PARAMS P 
GROUP BY P . APPVER , P . APPNAME , P . APPFUNC 
) , 
-- 6) pre-aggregate the <data .../> XML per program (avoids nested aggregates)
DATA_XML AS ( 
SELECT PL . APPVER , PL . APPNAME , PL . APPFUNC , 
XMLAGG ( XMLELEMENT ( NAME "data" , 
XMLATTRIBUTES ( '1208' AS "ccsid" , PL . APPPARAM AS "name" , 
'true' AS "nullable" , '2147483647' AS "precision" , 
CASE 
WHEN PL . LOCATION = 'PATH' THEN PL . RESTNAME 
END AS "restInPathParam" , 
CASE 
WHEN PL . LOCATION = 'QUERY' THEN PL . RESTNAME 
END AS "restInQueryParam" , 
CASE 
WHEN PL . LOCATION = 'FORM' THEN PL . RESTNAME 
END AS "restInFormParam" , 'CLOB' AS "type" , 
'input' AS "usage" ) ) ORDER BY PL . PARAMPOS ) 
AS DATA_FRAGMENT 
FROM PL PL 
GROUP BY PL . APPVER , PL . APPNAME , PL . APPFUNC 
) 
SELECT XMLSERIALIZE ( CONTENT XMLELEMENT ( NAME "dbml" , XMLATTRIBUTES ( 
'/v1' AS "restUriPathTemplate" , '1.0' AS "version" ) , XMLAGG ( 
XMLELEMENT ( NAME "program" , XMLATTRIBUTES ( '' AS "errormessage" , 
'*NONE' AS "httpheaders" , '500' AS "httpstatusonfailure" , 
E . SUCCESS_CODE AS "httpstatusonsuccess" , 'get' || 
UPPER ( SUBSTR ( E . APPFUNC , 1 , 1 ) ) || SUBSTR ( E . APPFUNC , 2 ) || 
'Input' AS "inputWrapperIdentifier" , 'get' || 
UPPER ( SUBSTR ( E . APPFUNC , 1 , 1 ) ) || SUBSTR ( E . APPFUNC , 2 ) AS 
"name" , 'get' || UPPER ( SUBSTR ( E . APPFUNC , 1 , 1 ) ) || 
SUBSTR ( E . APPFUNC , 2 ) || 'Result' AS 
"outputWrapperIdentifier" , 'media-resource' AS "querytype" , 
E . CONSUMES AS "restConsumes" , E . HTTP_METHOD AS 
"restHttpRequestMethod" , E . PRODUCES AS "restProduces" , 
E . PATH_TEMPLATE AS "restUriPathTemplate" , '*ERRORS' AS 
"returnsqlstate" , 'true' AS "treatwarningaserror" , '*TRAILING' 
AS "trimmode" , 'false' AS "wrapInputParams" , 'true' AS 
"wrapOutputParam" ) 
, XMLELEMENT ( NAME "sql" , XMLATTRIBUTES ( 
'Values Restapi.Execute_Sql(''' || E . APPVER || ''',''' || 
E . APPNAME || ''',''' || E . APPFUNC || 
''', Cast(Json_Object(' || COALESCE ( PS . PARAMS_TXT , '' ) || 
' ) As Varchar(10240) CCSID 37))' AS "statement" ) 
, DX . DATA_FRAGMENT ) ) ORDER BY E . APPFUNC ) ) AS CLOB ( 2 G ) ) 
INTO V_RESULT 
FROM ENDPOINTS E 
LEFT JOIN PARAM_STR PS 
ON PS . APPVER = E . APPVER 
AND PS . APPNAME = E . APPNAME 
AND PS . APPFUNC = E . APPFUNC 
LEFT JOIN DATA_XML DX 
ON DX . APPVER = E . APPVER 
AND DX . APPNAME = E . APPNAME 
AND DX . APPFUNC = E . APPFUNC ; 
RETURN V_RESULT ; 
END  ; 

GRANT ALTER , EXECUTE   
ON SPECIFIC FUNCTION RESTAPI.GENERATE_DBML_INLINE 
TO AMAPICS WITH GRANT OPTION ; 

GRANT EXECUTE   
ON SPECIFIC FUNCTION RESTAPI.GENERATE_DBML_INLINE 
TO PUBLIC ; 

