SET PATH *LIBL ; CREATE OR REPLACE FUNCTION RESTAPI.EXECUTE_SQL ( INAPPVER VARCHAR(10) DEFAULT 'v1' , INAPPNAME VARCHAR(128) DEFAULT '' , INAPPFUNC VARCHAR(128) DEFAULT '' , INSUBSTITUTE VARCHAR(10240) DEFAULT NULL ) RETURNS CLOB(2147483647) LANGUAGE SQL SPECIFIC RESTAPI.EXECUTE_SQL NOT DETERMINISTIC MODIFIES SQL DATA CALLED ON NULL INPUT NOT FENCED SET OPTION ALWBLK = *ALLREAD , ALWCPYDTA = *OPTIMIZE , COMMIT = *NONE , DBGVIEW = *SOURCE , DECRESULT = (31, 31, 00) , DYNDFTCOL = *NO , DYNUSRPRF = *OWNER , SRTSEQ = *HEX BEGIN DECLARE SQL_STATEMENT VARCHAR ( 32000 ) DEFAULT NULL ; DECLARE SQL_PARAMS VARCHAR ( 10240 ) DEFAULT NULL ; DECLARE SQL_REPLACEMENT VARCHAR ( 2048 ) DEFAULT NULL ; DECLARE SQL_CLOB CLOB ( 2 G ) DEFAULT NULL ; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN DECLARE V_SQLSTATE CHAR ( 5 ) ; DECLARE V_DB2_RETURN_CODE INT ; DECLARE V_DB2_MESSAGE_ID CHAR ( 7 ) ; DECLARE V_ERROR_MESSAGE CLOB ( 2048 ) ; GET DIAGNOSTICS CONDITION 1 V_DB2_RETURN_CODE = DB2_RETURNED_SQLCODE , V_SQLSTATE = RETURNED_SQLSTATE , V_ERROR_MESSAGE = MESSAGE_TEXT , V_DB2_MESSAGE_ID = DB2_MESSAGE_ID ; RETURN ( VALUES JSON_OBJECT ( 'success' VALUE 'false' , 'SQLInfo' VALUE JSON_OBJECT ( 'SQLState' VALUE V_SQLSTATE , 'SQLCode' VALUE V_DB2_RETURN_CODE , 'messageID' VALUE V_DB2_MESSAGE_ID , 'message' VALUE V_ERROR_MESSAGE , 'currentTimestamp' VALUE CURRENT_TIMESTAMP ) , 'SQLStatement' VALUE SQL_STATEMENT FORMAT JSON ) ) ; END ; -- Get SQL template SET SQL_STATEMENT = ( SELECT SQLSTMT FROM RESTAPI . SQLSTMTS WHERE ( APPVER , APPNAME , APPFUNC ) = ( INAPPVER , INAPPNAME , INAPPFUNC ) ) ; -- Normalize substitute JSON into array form SET SQL_PARAMS = INSUBSTITUTE ; IF SQL_PARAMS IS NOT NULL AND TRIM ( SQL_PARAMS ) <> '' THEN IF CISTOOLS . JSON_TYPE ( SQL_PARAMS ) <> 'array' THEN SET SQL_PARAMS = JSON_ARRAY ( INSUBSTITUTE FORMAT JSON ) ; END IF ; END IF ; -- Substitute parameters if we have both template and subs IF SQL_STATEMENT IS NOT NULL AND SQL_PARAMS IS NOT NULL THEN FOR SELECT APPPARAM FROM TABLE ( RESTAPI . GET_PARAM_PLACEHOLDERS ( INAPPVER , INAPPNAME , INAPPFUNC ) ) DO SET SQL_REPLACEMENT = COALESCE ( JSON_VALUE ( SQL_PARAMS , '$[*].' || TRIM ( APPPARAM ) ) , JSON_QUERY ( SQL_PARAMS , '$[*].' || TRIM ( APPPARAM ) ) ) ; -- Figure out type of this param SET SQL_STATEMENT = REPLACE ( SQL_STATEMENT , '{{' || TRIM ( APPPARAM ) || '}}' , IFNULL ( SQL_REPLACEMENT , '{{' || TRIM ( APPPARAM ) || '}}' ) ) ; END FOR ; END IF ; -- Execute dynamically SET CISTOOLS . SQL_STATEMENT = SQL_STATEMENT ; SET SQL_STATEMENT = 'Values ((' || SQL_STATEMENT || ')) Into ?' ; PREPARE SQL_ FROM SQL_STATEMENT ; EXECUTE SQL_ USING SQL_CLOB ; -- After Execute Sql_ Using SQL_CLOB; -- Detect if SQL_CLOB is already JSON object with success/data/result IF LEFT ( LTRIM ( SQL_CLOB ) , 1 ) = '{' AND ( LOCATE ( '"success"' , SQL_CLOB ) > 0 ) AND ( LOCATE ( '"data"' , SQL_CLOB ) > 0 OR LOCATE ( '"result"' , SQL_CLOB ) > 0 OR LOCATE ( '"SQLInfo"' , SQL_CLOB ) > 0 ) THEN -- Return raw JSON as is RETURN SQL_CLOB ; END IF ; -- Wrap in standard envelope RETURN JSON_OBJECT ( 'success' : 'true' , 'data' : SQL_CLOB FORMAT JSON ) ; END ; GRANT EXECUTE ON SPECIFIC FUNCTION RESTAPI.EXECUTE_SQL TO PUBLIC ; GRANT ALTER , EXECUTE ON SPECIFIC FUNCTION RESTAPI.EXECUTE_SQL TO QSECOFR WITH GRANT OPTION ;