Oracle REST Parameter Collection - oracle

I have some Oracle databases that are exchanging HTTP calls, my central database in on 11g and using mod_plsql for GET and POST call.
I want to upgrade may database and start using ORDS without replacing my current code but having some issues when passing unknow number of parameters.
I have the following procedure
PROCEDURE my_post_proc(
name_array IN owa.vc_arr,
value_array IN owa.vc_arr
)
The HTTP call to this procedure is sending parameter using the URI (Query String) and in addition n number of parameters containing chunks of a long clob value
I was not a able successfully call this procedure by AutoREST enable the procedure so I created an handler using the APEX RESTful Service.
I was able to get into the parameters sent from the URI and I was able to get chunks of the clob parameter by specifically using the parameter name.
However this is not good enough as I have idea about the number of chunks I will get.
This is who my handler code is looking
declare
name_array owa.vc_arr;
value_array owa.vc_arr;
begin
name_array(1) := ('param_1');
name_array(2) := ('param_2');
name_array(3) := ('clob_chunk_1');
value_array(1) := (:param_1);
value_array(2) := (:param_2);
value_array(3) := (:clob_chunk_1); -- This is working but not what I am after as can be dynamic number of chunks
--Should be something more like
for i in 1..(some collection holding the parameters)
loop
name_array(i) := 'clob_chunk_'||i;
value_array(i) := Collection('clob_chunk_'||i);
end loop;
my_post_proc(name_array,value_array);
end;
Is this can be somehow achieved?

Related

How to return a SODA_DOCUMENT_T in ORDS as JSON/RESULTSET?

If I want to use PL/SQL to query my JSON documents in a Oracle database (configured for JSON database, using Autonomous JSON Database), how would I retrieve the desired document and send it back to the user in a JSON response?
I do notice that it's not possible to pass a JSON, JSON_OBJECT_T, or SODA_DOCUMENT_T directly, nor converting them into CLOB/BLOB and then pass, into a RESULTSET variable for output.
Using the SODA for PL/SQL package, you can construct a QBE filter string. This will get allow you to work with the SODA_DOCUMENT_T types. Once you've got the document you would like (or a collection to loop through), you can then serialise it to text and output that in your HTTP response.
Examples below assume you have a JSON database. You can more easily retrieve JSON column data using standard SQL.
DECLARE
collection SODA_COLLECTION_T;
doc SODA_DOCUMENT_T;
qbe VARCHAR2(64);
BEGIN
qbe := '{"id": {"$eq": ' || :id || '}}';
collection := DBMS_SODA.OPEN_COLLECTION('MYCOLLECTION');
doc := collection.find().filter(qbe).get_one();
OWA_UTIL.mime_header('application/json');
htp.P(JSON_SERIALIZE(doc.get_json));
END;
Alternatively, avoid using the SODA package altogether by using a standard cursor / RESULTSET output, although for each result in the RESULTSET output, there will be a 'json_document' key, and the actual document nested inside.
DECLARE
cur SYS_REFCURSOR;
BEGIN
OPEN cur for
select JSON_DOCUMENT
from "MYUSER"."MYCOLLECTION"
where JSON_EXISTS ( "JSON_DOCUMENT", '$?(#.id == $B0)' PASSING :id AS B0);
:result := cur;
END;

PL/SQL Select column value into a variable

I have a View that I've created and I need to extract some tokens from it.I read about BULK COLLECT but I don't think that it will work for me as later on I'll need the extracted values stored separately.
SELECT TOKEN FROM MAPPING_VIEW WHERE USERNAME='Peter'.
Here for example I'l get returned a number of tokens (the number of tokens returned can not be predicted).
I'm pretty new at pl/sql can someone give me directions on how to store the extracted tokens in different variables? As I mentioned I don't know how many tokens may be returned beforehand.
you can try this
DECLARE
TYPE rec_token IS TABLE OF VARCHAR2(100);
l_rec_token rec_token;
BEGIN
BEGIN
SELECT token
BULK COLLECT INTO l_rec_token
FROM mapping_view
WHERE username='Peter';
EXCEPTION
WHEN NO_DATA_FOUND THEN
l_rec_token := rec_token();
END ;
IF l_rec_token.COUNT >0 THEN
FOR i IN l_rec_token.FIRST..l_rec_token.LAST
LOOP
<doSomeThing>
END LOOP;
END IF;
END;

Why in Oracle forms (based on procedure) query does not return any values?

I have made a data block in oracle forms using Data Block Wizzard, however query does not populate the form. Even though cursor returns values and enters the loop in query procedure:
Here is the code of query procedure:
PROCEDURE PD_PDT_SCHEDULE_TYPES_QUERY(par_pd_pdt_schedule_types_tbl IN OUT gt_pd_pdt_schedule_types_tbl) IS
lc_err_msg VARCHAR2(2000);
lc_add_rec VARCHAR2(1);
lc_search_ok VARCHAR2(1);
CURSOR c_pd_pdt_schedule_types IS
SELECT pst_code,
pst_prty,
pst_mnemo,
pst_name,
pst_crt_mandatory,
pst_pdt_mnemo,
pst_type,
pst_purpose,
pst_purpose_det,
pst_ref_mnemo,
pst_hidden,
pst_ref_show,
pst_payment_show
FROM s_pd_pdt_schedule_types where pst_pdt_mnemo = 'SOME_PRODUCT';
ln_idx NUMBER := 1;
BEGIN
FOR i IN c_pd_pdt_schedule_types
LOOP
par_pd_pdt_schedule_types_tbl(ln_idx) := i;
ln_idx := ln_idx + 1;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
lc_err_msg := 'FRL_184.PD_PDT_SCHEDULE_TYPES_QUERY error: ' || SQLERRM;
RAISE_APPLICATION_ERROR(-20555, SUBSTR(lc_err_msg, 1, 2000));
END PD_PDT_SCHEDULE_TYPES_QUERY;
Here is the code of form trigger Query-Procedure:
DECLARE
bk_data FRL_184.GT_PD_PDT_SCHEDULE_TYPES_TBL;
BEGIN
frl_184.PD_PDT_SCHEDULE_TYPES_QUERY(bk_data);
PLSQL_TABLE.POPULATE_BLOCK(bk_data, 'S_PD_PDT_SCHEDULE_TYPES');
END;
First of all, make sure that PD_PDT_SCHEDULE_TYPES_QUERY actually does something - test it in SQL*Plus (or SQL Developer or any other tool you use).
QUERY-PROCEDURE trigger is created by the Wizard; it is as is, there's nothing you should do about it. Forms says that you shouldn't modify it anyway.
In order to make it work, you should edit data block's properties - go to the Palette, navigate to the "Database" section and open Query data source columns - in there, you should enter ALL columns returned by the procedure, i.e. pst_code, pst_prty, etc., along with their datatypes, length, precision ... depending on the datatype itself.
Also, modify Query data source arguments property. As your procedure doesn't accept any IN parameters, it would be just one argument (TABLE type, write its name, mode is IN OUT). If you passed some parameters to the procedure, you'd put them in here as well.
That would be it, I think.

Error when a named parameter used multiple times in JDBC PL/SQL block

I get an error when use named parameter to call PL/SQL block, when all named parameters are used only once, then my code works fine, but when I dupplicate the SQL marked with "// the SQL". then all named parameters (starts with colon, :q) are used twice, now I get a SQL Exception, it says: The number of parameter names does not match the number of registered praremeters.
It seems that JDBC driver or DB think there is 2 parameters, but only 1 parameters are registered? why we cannot use a named parameter multiple times? is JDBC driver don't required to support this case?
How I get an alternative (exeption rewriting PL/SQL block to stored procedure)?
My Oracle JDBC Driver is latest version 11.2.0.3.0.
Because my project have many PL/SQL block, I try my best to avoid rewrite SQL to a stored procedure, running raw PL/SQL block with named parameter (just treat it as a procedure) is preferred. I tested convert the PL/SQL block to a stored procedure, then only 1 parameters exported, but I don't want to rewrite all PL/SQL blocks, it takes more efforts.
thanks for any hints.
My Java code:
CallableStatement stmt = ...;
stmt.registerOutParameter("q", Types.VARCHAR);
stmt.execute();
String v1 = stmt.getString("q");
SQL as below:
BEGIN
select DUMMY into :q from dual where dummy = 'X';
select DUMMY into :q from dual where dummy = 'X';
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
I just found that "Execute Immediate" can be used for my case, when the dynamic SQL is a PL/SQL block (quoted with begin and end), then the named parameters with a name can be referenced by all occurrences. i.e. SQL attached below, in this block, parameter 'q' is used only once,
but now I have another 2 questions,
Q1: I don't know if the parameter 'q' is IN, OUT or both IN and OUT. If I give wrong IN/OUT mode, error got, how we test if the parameter is IN/OUT or both of them? I want to scan the SQL for ':q :=' and 'into :q', it seems that it is not good method.
Q2: Why I can't fetch result of parameter 'q' when it is assigned IN OUT mode? only if it is OUT, I can get its value. when it is both IN OUT, I get NULL.
begin
execute immediate 'begin select dummy into :q from dual where :q is not null; end;'
using in out :q;
end;
Oh, I get a workaround for NULL when parameter is IN OUT mode, I just treat it is a bug of Oracle JDBC driver, I split IN/OUT role of the named parameter 'q' into 2 parts, first is IN, second is OUT, using a variable to keep its value returned by 'using in out :q' clause, and then assign variable to 2nd role, like below-attached, in JDBC we treat it both IN OUT, only use exact IN,OUT or IN OUT in USING clause after scanning ' :q := ' and ' into :q '.
declare
p varchar2(100);
q varchar2(100);
begin
p := ?;
q := ?;
execute immediate 'begin if :p is null then :p := ''X''; else :p := ''Y''; :q := ''Z''; end if; end;' using in out p, out q;
? := p;
? := q;
end;
You can't use one bind parameter multiple times in SQL statement. You must provide a value for each occurrence of parameter. This is because Oracle ignores bind parameter name and only a colon symbol is taken into account.
Oracle docs

how do I execute a function from TOAD for Oracle and bind the result to a data grid

I have a function that takes as one of it's arguments a VARRAY of pl/sql Objects. How do I execute this stored procedure and bind the resultset that it returns to a data grid in TOAD for Oracle?
After some searching around, I found the answer to my own problem. Say your varray type was called varchar_pair_array and the objects stored in this array were called varchar_pair_object. varchar_pair_object is a simple object that has two varchars as it's members.
Here is the code for executing a proc that takes in a varray of varchar_pair_object (s):
DECLARE
RetVal SYS_REFCURSOR;
a_simplevalue VARCHAR2(200);
another_simplevalue VARCHAR2(200);
my_array_of_varchar_pairs VARCHAR_PAIR_ARRAY; -- assume varchar_pair_array is defined somewhere else
my_obj VARCHAR_PAIR_OBJECT; -- assume varchar_pair_object is defined somewhere else
my_other_obj VARCHAR_PAIR_OBJECT;
BEGIN
a_simplevalue := 'hello';
another_simplevalue := 'there';
my_obj := VARCHAR_PAIR_OBJECT('nice to meet you', 'greetings');
my_other_obj := VARCHAR_PAIR_OBJECT('goodbye', 'ciao');
my_array_of_varchar_pairs := VARCHAR_PAIR_ARRAY();
my_array_of_varchar_pairs.EXTEND(2); -- this should be the number of objects you plan to put into the array
my_array_of_varchar_pairs(1) := my_obj;
my_array_of_varchar_pairs(2) := my_other_obj;
RetVal := my_function ( a_simplevalue, another_simplevalue, my_array_of_varchar_pairs); -- assuming your array takes two varchars and one array of VARCHAR_PAIR_OBJECT (s)
:to_grid := RetVal;
END;
Copy paste this code in TOAD's sql editor and change it to adapt to your function and types and hit F9. TOAD will ask you the type of the :to_grid variable. Select cursor (assuming your function returns a ref cursor) and hit enter. TOAD will bind the result set to a data grid.
Links that helped me:
http://www.smart-soft.co.uk/Oracle/oracle-plsql-tutorial-part-11.htm (good tutorial on collections)
http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96624/10_objs.htm#1972 (especially useful in this case is the section on declaring and initializing objects)
With very little change the same can be done with a procedure.

Resources