RESTful Deployment
published onI have been an enthusiastic APEX fan for years. And like every APEX fan, I also have a workspace on APEX apex.oracle.com.
Recently I read an article by Peter Raganitsch. Link: http://www.oracle-and-apex.com/streaming-flat-file-data-into-database
And what shall I say? It works! With my current favorite editor, Sublime Text 3, I can now send my source code for all kinds of stored procedures (triggers, procedures, functions, and packages) to my workspace, which is somewhere in the cloud, for example, at apex.oracle.com
First we create a RESTful service. In the SQL-Workshop we go to RESTful Services and click on Create. Now we define a RESTful service module.
Then we define a resource template.
Finally, we define a resource handler.
This resource handler is filled with the following lines as source.
Declare
v_source_code clob := rtrim(wwv_flow_utilities.blob_to_clob(:body),'/');
v_err_found boolean := false;
v_obj_name varchar2(1000) := regexp_substr(lower(dbms_lob.substr(v_source_code, 32000, 1)),
'create or replace (function|procedure|package body|package|trigger) ([^ (]*)', 1, 1, null, 2);
Begin
-- Prepare Header / Output
owa_util.mime_header('text/plain', true);
htp.p(''); -- empty
-- Execute / Compile Code
execute immediate v_source_code;
-- Everything is fine, let the user know it
htp.p('Result: success');
:status := 200;
Exception
when others then
-- Something went wrong
htp.p('Result: failure');
htp.p('Object: ' || v_obj_name);
htp.p('Error: ' || sqlerrm);
-- Maybe we get the object out of source
for cur in (select rownum idx, line, position, text
from user_errors
where name = upper(v_obj_name)
order by sequence)
loop
-- FirstRow, let's print heading
if cur.idx = 1 then
htp.p(' LINE | POSITION | TEXT');
v_err_found := true;
end if;
-- Print Message
htp.p(lpad(cur.line, 7, ' ')||' | '||lpad(cur.position, 8, ' ') ||' | '||cur.text);
end loop;
if not v_err_found then
htp.p(dbms_utility.format_error_backtrace);
htp.p(v_source_code);
end if;
:status := 400;
End;
Basically, these few lines are only about the fact that the content of the file is executed by “Execute Immediate”. If an error occurs, the system tries to determine the DB object and displays the corresponding error. Now all we have to do is upload our source code. I chose curl at this point. But I also think that wget should work. With the following command, we load the contents of the file my_stored_procedure. sql into the workspace my_workspace_name and run it there.
curl -X POST \
--header "Content-Type:text/xml;charset=UTF-8" \
--data-binary @my_stored_procedure.sql \
https://apex.oracle.com/pls/apex/my_workspace_name/deploy/compile/
To directly upload and compile the source code with Sublime Text 3, we create a batch file that is used by the build system of Sublime Text, for example as D: \my_rest_deploy. bat.
@echo off
REM -- For information only
echo File: %2
echo Path: %1
echo Url: %3
echo
REM -- Change to the directory where the sublime file is
cd %1
REM -- Deploy to https://apex.oracle.com/pls/apex/my_workspace_name/deploy/compile/
curl -X POST --header "Content-Type:text/xml;charset=UTF-8" --data-binary @%2 %3
Then we create a new build system with the following content in Sublime Text under “Tools / Build System / New Build System…”
{
"cmd":["D:/my_rest_deploy.bat", // Script
"$file_path", // %1
"$file_name", // %2
"https://apex.oracle.com/pls/apex/die21/deploy/compile/" // %3 = RestURL
],
"selector": "source.plsql.oracle",
"shell":"true"
}
And if I now edit my code and have chosen the appropriate build system, a simple Ctrl+B is enough to bring my package or whatever into the cloud. This is very useful if you want to write a skill for ALEXA, for example, but can only access the DB via a web interface.
The solution is not perfect and you should never do this on a productive environment. Whoever knows this URL is in the worst case master of your database!
At this point I would like to thank Peter and KrisRice, who brought me to this idea…