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 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 ;