Dynamically adding attribute based on PL/SQL function

I've been tasked with dynamically applying security to an XMLType input sample as a post XML generation process (on an 11g R2 DB) based on several parameters. The best way to describe it is with an example block of code, I need to write ApplySecurity....
declare
  vXML XMLType;
  BONUS_SEC constant integer := 24; -- Security identifier for Bonus
  function ApplySecurity(pXML        XMLType,
                         pSecurityID integer,    -- A Security identifier
                         pDataIDPath varchar2,   -- Absolute XPath to the data id which is passed to value
                         pAttribPath varchar2    -- Relative XPath to pDataIDPath where we want the security result attribute stored
                         ) return XMLType is
  begin
      for all DataIDs found in pDataIDPath
        Call an PL/SQL function GetSecurityDesc(pSecurityID, pDataID)
          Store the result of this back in the XML in the pAttribPath as SECURITY attribute
  end;
begin
  vXML := ApplySecurity(XMLType('<ROWSET>
                                   <ROW>                                
                                     <BONUS_ID>8</BONUS_ID>
                                     <DESCRIPTION>Test Bonus</DESCRIPTION>                                                                           
                                   </ROW>
                                   <ROW>                                
                                     <BONUS_ID>9</BONUS_ID>
                                     <DESCRIPTION>Another Bonus</DESCRIPTION>                                                                           
                                   </ROW>                         
                                   <ROW>                                
                                     <BONUS_ID>10</BONUS_ID>
                                     <DESCRIPTION>April Bonus</DESCRIPTION>                                                                           
                                   </ROW>                         
                                 </ROWSET>'),
                         BONUS_SEC,       
                         '/ROWSET/ROW/BONUS_ID',
end;
/* Example of the Desired Output =
<ROWSET>
  <ROW>                                
    <BONUS_ID SECURITY="HIDDEN">8</BONUS_ID>
    <DESCRIPTION>Test Bonus</DESCRIPTION>                                                                           
  </ROW>
  <ROW>                                
    <BONUS_ID SECURITY="READONLY">9</BONUS_ID>
    <DESCRIPTION>Another Bonus</DESCRIPTION>                                                                           
  </ROW>                         
  <ROW>                                
    <BONUS_ID SECURITY="NONE">10</BONUS_ID>
    <DESCRIPTION>April Bonus</DESCRIPTION>                                                                           
  </ROW>                         
</ROWSET>
*/I have tried several approaches like iterating using a dynamically created XMLTable and calling InsertChildXML for each iteration, but that seems messy and inefficient as the call to InsertChildXML will have to locate the correct node each time. Ideally I think the best solution would be to do it with XQuery, but online examples are few and far between and I don't know how I'd call a PL/SQL function as part of an XQuery iteration as well as passing in the path information.
Anyone have any ideas? Thanks!

A funnier option, adapted from http://odieweblog.wordpress.com/2012/06/19/how-to-update-xml-nodes-with-values-from-same-doc/ :
declare
  BONUS_SEC  constant integer := 24;
  vXML XMLType := XMLType(
'<ROWSET>
  <ROW>                                
    <BONUS_ID>8</BONUS_ID>
    <DESCRIPTION>Test Bonus</DESCRIPTION>                                                                           
  </ROW>
  <ROW>                                
    <BONUS_ID>9</BONUS_ID>
    <DESCRIPTION>Another Bonus</DESCRIPTION>                                                                           
  </ROW>                         
  <ROW>                                
    <BONUS_ID>10</BONUS_ID>
    <DESCRIPTION>April Bonus</DESCRIPTION>                                                                           
  </ROW>                         
</ROWSET>');
  pSecurityID integer      := BONUS_SEC;
  pDataIDPath varchar2(80) := '/ROWSET/ROW/BONUS_ID';
  pAttribPath varchar2(80) := '.';
  queryString varchar2(4000);
begin
  queryString :=
q'~select xmlpatch(
         :b1
       , xmlelement("xd:xdiff"
         , xmlattributes(
             'http://www.w3.org/2001/XMLSchema-instance' as "xmlns:xsi"
           , 'http://xmlns.oracle.com/xdb/xdiff.xsd http://xmlns.oracle.com/xdb/xdiff.xsd' as "xsi:schemaLocation"
           , 'http://xmlns.oracle.com/xdb/xdiff.xsd' as "xmlns:xd"
         , xmlpi("oracle-xmldiff", 'operations-in-docorder="true" output-model="current"')
         , xmlagg(
             xmlelement("xd:append-node"
             , xmlattributes(
                 'attribute' as "xd:node-type"
               , '(#DATA-ID-PATH#)[' || x.NodeOrder || ']' as "xd:parent-xpath"
               , 'SECURITY' as "xd:attr-local"
             , xmlelement("xd:content", GetSecurityDesc(:b2, x.DataID))
from xmltable('#DATA-ID-PATH#'
       passing :b3
       columns DataID    integer path '#ATTRIB-PATH#'
             , NodeOrder for ordinality ) x~';
  queryString := replace(queryString, '#DATA-ID-PATH#', pDataIDPath);
  queryString := replace(queryString, '#ATTRIB-PATH#', pAttribPath);
  execute immediate queryString into vXML using vXML, BONUS_SEC, vXML ;
  dbms_output.put_line(vXML.getclobval);
end;
/probably slower though.

Similar Messages

  • Materialized View with column based on PL/SQL function returning object

    I have the following problem - it is known that materialized view wants PL/SQL functions used in it to be DETERMINISTIC. And it appears that a function which returns SDO_GEOMETRY cannot be DETERMINISTIC - I can add DETERMINISTIC modifier to my function which returns sdo_geometry based on USNG grid ID and save the package, and it compiles and runs fine with regular queries, but when it comes to materialized view (mview), the following error is thrown:
    ORA-12018: following error encountered during code generation for "SCHEMA"."MVIEW_NAME"
    ORA-00932: inconsistent datatypes: expected NUMBER got MDSYS.SDO_GEOMETRY
    Looks like DETERMINISTIC modifier is not fully supported for object types. I have tried to use SDO_CS.FROM_USNG Oracle's function, and it appeared that this function is also non-deterministic - I cannot refresh mview with P or F on-demand refresh method (see http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14223/refresh.htm#i1008349 for a list of on-demand refresh methods). Without that function I can refresh mview with P or F flags.

    Hi,
    Yes, the Chart Series can be based on "Function Returing SQL Query" and the "SQL" would be something like:
    DECLARE
    vSQL VARCHAR2(1000);
    BEGIN
    vSQL := 'SELECT NULL LINK, ENAME LABEL, SAL VALUE FROM EMP ORDER BY ENAME';
    RETURN vSQL;
    END;You should tick the "Save query without validation" underneath that. Without this, there is a validation error - the ; at the end is required to get the chart to function correctly but the validator sees this as an error.
    You would need to create this separately from the report. No matter how you did it, the chart would still run a SQL statement to generate the output. If you wanted to use the "same data", then you could create a collection using the PL/SQL and base both the report and the chart on the collection instead.
    Andy

  • SVG multiline chart based on PL/SQL function

    Dear all -
    Having trawled this forum and with a fair bit of experimentation I've concluded that:
    1. Generating an SVG line series using a PL/SQL function returning a SQL statement is perfectly possible;
    BUT
    2. It only works for a single series. Adding further series blanks out the SVG chart area and nothing at all is displayed.
    Can anyone tell me if this is right or am I missing a trick? The usual problems such as ordering, nulls etc. don't apply in this case.
    Thanks for your time.
    John.

    On some, but not all SVG line charts, I had trouble when some values are ZERO.
    Putting a CASE WHEN var = 0 then 0.05 ELSE var END in the select statement
    fixed those situations.
    I had missing lines when the number of data points in a series exceeded the default number of 15, and I did not set in the series configuration to a number equal to or higher that the number of data points in that series.
    And I had one instance, where a couple missing lines reappeared when I exited
    the browser and app completely and restarted the app.
    All these comments apply to ver 1.6x and 2.0x

  • Interactive Report based on pl/sql function body

    Can an interactive report be based on a pl/sql function body returning the query sql? Or does it have to be based directly on the SQL?
    Thanks

    Hello "unknown user",
    As far is I know an Interactive Report can only be based on 'regular' SQL. If you have a Report based on a 'PL/SQL function body returning SQL' the option to migrate the report to an interactive report is not there.
    Regards,
    Roel
    http://roelhartman.blogspot.com/
    http://www.bloggingaboutoracle.org/
    http://www.logica.com/

  • Javascript based on PL/SQL function.

    Hey all,
    I'm developing an application with Apex and have run into a problem.
    I have a form page with the standard create, delete and cancel buttons. I need to be able to click the Create button, which will run a PL/SQL query, and based on the return of the function, either just continue the Insert to the table, or generate a popup warning, and then complete the table insert.
    I was thinking of having a Process that ran the javascript, and was conditional on the PL/SQL query, however i haven't had much luck.
    Any help appreciated.
    Thanks,
    Brett Crowley.

    Hello Brett,
    >> I was thinking of having a Process that ran the javascript, and was conditional on the PL/SQL query, however i haven't had much luck.
    APEX Processes are server-side resources, while JavaScript is a client-side resource. As such, you can’t invoke JavaScript code from within a PL/SQL code. However, the reverse direction – invoking PL/SQL code from a JavaScript code – is possible by using AJAX. In general, using AJAX allows you to call to an APEX on-demand PL/SQL (application) process, which in turn can return a result to the calling JavaScript code. In this point, based on the returned result, you can decide whether to issue an alert box or (programmatically) submit the page for further processing.
    This forum includes many example of using AJAX, and I believe that the following article can also be a helpful starting point.
    http://www.packtpub.com/article/ajax-implementation-apex
    Regards,
    Arie.
    &diams; Please remember to mark appropriate posts as correct/helpful. For the long run, it will benefit us all.
    &diams; Author of Oracle Application Express 3.2 – The Essentials and More

  • Webservice based on PL/SQL function - ORA-04068

    Hi,
    we have a problem here with PL/SQL based webservices. If the PL/SQL package gets invalid then the very first request to the webservice results in:
    java.sql.SQLException:
    ORA-04068: existing state of packages has been discarded
    ORA-04061: existing state of package "TUG_NEW.WBSERVICES" has been invalidated
    ORA-04065: not executed, altered or dropped package "TUG_NEW.WBSERVICES"
    ORA-06508: PL/SQL: could not find program unit being called ORA-06512: at line 1
    Any workarounds? Shouldn't the package become recompiled automatically when it was invalid?
    Thanks, Christian

    the caller gets an error on the first request. from the second request on it works ... indicates the package is not yet recompiled when the first request is sent. When the second request is sent, the package has been recompiled.

  • Plugin - PL/SQL Function Body attribute

    How do I use an attribute of the "PL/SQL Function Body" type in my plugin code?
    If I just print the contents of the attribute it will print the actual text in the attribute. I expected it to print the result of the function body.

    Use the relevant function in the apex_plugin_util api: APEX_PLUGIN_UTIL.GET_PLSQL_FUNCTION_RESULT

  • Application Report Missing PL/SQL Functional Area

    All,
    I just wanted to bring to the ApEx developers something I just noticed... I use the Shared Components > Database Object Dependencies report to make sure all is well before moving applications into production.
    The Parsing Errors feature of that report is WONDERFUL! But it seems to be overlooking buttons that use a conditional display based on PL/SQL Function Body Returning a Boolean.
    Dan

    Hi Dan,
    I think the place is perfect, but I read once somewhere that "Bug" or "Bug Report" should be in the subject so that's easier to find for the Oracle guys.
    Patrick
    My APEX Blog: http://inside-apex.blogspot.com
    The ApexLib Framework: http://apexlib.sourceforge.net
    The APEX Builder Plugin: http://sourceforge.net/projects/apexplugin/

  • Set label of an item dynamically through pl/sql function

    Hi ,
    How Can I get the label of an item dynamically through a pl/sql function.
    I have a table that stores the label name for these items.
    I want to set the label for the item based on the value in my table ?
    Is it possible ?
    any ideas ?
    Thanks in advance,
    Dippy
    Edited by: Dippy on Feb 23, 2010 11:02 AM
    Edited by: Dippy on Feb 23, 2010 11:02 AM

    If I understand you correctly, you are using a standard report region, but want to dynamically name the column headers? The only way I've been able to get this to work is to create hidden items for each column header, calculate the value you want for each item, then reference the item in the column header using &item_X. for the column header name.
    The problem is that at this point, APEX doesn't allow for dynamic column naming unless you want to do everything yourself using a PL/SQL process that builds the report table manually. I've done that for certain complex reporting tools.
    I understand it's tedious to create all the column header items; I have one report that has over 72 items used in this way. It was a pain, but it got the job done.

  • Dynamic action setvalue from pl/sql function

    Hi,
    I have a currency table with exchange rate column.
    I created a form that allow user to select currency from the table and get the rate into Px_RATE page items.
    I would like to implement it using Dynamic action in apex 4
    Please help me on this case
    Thanks & regards

    Hi,
    You can achieve this by defining a dynamic action as follows...
    #1 - Right click on the page item used to select the currency (let's call it P1_CURRENCY for purposes of this example) and select 'Create Dynamic Action'
    #2 - Select 'Advanced' as we're going to use the 'Set Value' dynamic action type, which is not available in the 'Standard' branch of the wizard.
    #3 - Name your dynamic action, say 'GET RATE', click 'Next'.
    #4 - Leave the 'When' attributes as default, this just defines that the dynamic action will fire whenever the currency item changes, click 'Next'.
    #5 - For the 'True Action > Action' select 'Set Value'
    #6 - Think about whether you want to set the value on page load from the dynamic action also, if so leave the 'Fire on Page Load' checkbox checked.
    #7 - [Assuming you have a simple PL/SQL API that returns the rate, say get_rate for example] Select 'Set Type' of 'PL/SQL Function Body'
    #8 - For 'PL/SQL Function Body' specify something like: return get_rate(:P1_CURRENCY);#9 - For 'Page Items to Submit', specify the currency item P1_CURRENCY and click 'Next'
    #10 - For the 'Affected Elements' specify 'Item' and then select the page item where you want to return the rate value, say P1_RATE.
    #11 - Click 'Create'.
    Let me know if this works for you or if you have any further questions.
    Regards,
    Anthony.

  • Reports based on PL/SQL Procedure/Function

    Hi all,
    After some serious Google and forum searches, it appears as if this is something that just isn't possible (or easy to do).
    I've been charged with creating an APEX application that displays reports. There are a series of Procedures that will be written to return a result set, updated to take into account some filters that a user would provide. The key here is that the report won't be displayed until AFTER a user inputs some filters on a form and hits a Submit button. The project requires this functionality - allowing the report to be displayed and THEN filtered using the APEX IR Control is not desired (not my decision).
    There doesn't seem to be an easy way to define a report in this manner. It appears that the query for a report query needs to be known ahead of time.
    So, with that setup - is there a way to define an APEX report based on the return result of a PL/SQL function? OR is there a way to define a report using a SQL Query that is built based on user inputs?
    Any help would be appreciated.
    - Pedro

    Hi,
    Check if this post help you.
    Dynamic html table
    And normal reports can be also created from select that function is returning.
    http://www.oracle.com/technology/products/database/application_express/howtos/dynamic_report.html
    Br, Jari
    Edit:
    Maybe useful
    http://www.apex-blog.com/oracle-apex/dynamic-report-regions-tutorial-32.html
    http://www.oracleapplicationexpress.com/2009/02/interactive-report-based-on-plsql.html
    Edited by: jarola on Sep 9, 2009 5:14 PM

  • Dynamically adding more attributes to cube dimension in SSAS 2008 R2

    I need to dynamically add more attributes to cube dimension in SSAS 2008 R2 because the dimension table the cube is based on is updated using dynamic pivoting and there is need to update the cube dimension attributes as more columns are added to the dimension
    table without making the changes through BIDS. Is there a way to dynamically adding more attributes to cube dimension in SSAS 2008 R2?
    Thanks
    BI Developer

    Definitely. You can use AMO to add dimension attributes on the server. I have definitely done this a few times for different clients of mine. Here is a generic AMO sample:
    http://msftasprodsamples.codeplex.com/wikipage?title=SS2008%21Readme_AMOAdventureWorks&referringTitle=Home
    Notice the parts which add attributes to a dimension.
    http://artisconsulting.com/Blogs/GregGalloway

  • Why data are not getting poulated in dynamically added tab in a tab navigator???

    Hi All,
    I am facing a very strange problem and need you expert opinion on this. Ok so the problem goes like this:
    In my application i have a tab navigator where i have 2 fixed tabs say tab A and tab B. In tab B I have a data grid where All the user name are getting populated. Once the user clicks on any datagrid row i am dynamically adding a new tab based on username , so if in my datagrid u1,u2 and u3 are getting displayed then once you clik on u1 a new tab called u1 is getting displayed. Code for this goes like this:
    var vbox1: VBox= new VBox();
    box1.label=mydatagrid.selectedItem.uName;
    var sde:* = new searchDetails();
    vbox1.addChild(sde);
    myTabnavigator.addChild(vBox1);
    Application.application.searchdetails.displayall();
    I have created a component called searchDetails where i have designed the page wit various fields for this tab.This also has a method called displayall() which is populating the data in all fields using php an my sql where i have designed the page wit various fields for this tab.
    New tab is getting displayed perfectly. My problem is once the tab is getting displayed fields are not getting populated with data.
    Please let me know what wrong i am doing. I am really struggling

    Hmm.. you have to assign text to the labelfields on creation complete not before that, the fllow will be like this
    var vbox1: VBox= new VBox();
    var sde:* = new searchDetails();
    vbox1.addEventListener(creationcompleteevent,function);
    vbox1.addChild(sde);
    myTabnavigator.addChild(vBox1);
    function(e:event):void{
    box1.label = "text";

  • Data passed from Java to a PL/SQL function

    OK, I am at the beginner-to-intermediate level when it comes to PL/SQL...and a virtual novice when it comes to Java, so please forgive me if my question seems strange or naive.
    We are developing a Java-based web app. Some of the screens are reminiscent of a spreadsheet-type layout--potentially LOTS of rows and LOTS of columns (actually, an open-ended # of rows/columns--the rows represent a particular 'thing' and the columns represent the dates on which that 'thing' occurred), where the user can check off any and all the cells that apply. We are also 'auditing' all database activity (who did what to the data, and when). The approach we have chosen is as follows: When the user clicks save, the first thing we do is 'inactivate' all of the existing active rows in the db for that screen, whether or not they have changed(i.e., there is an 'active' flag that we set to false & we also save the user id of the person making the change and the date time of the change). Then the Java code calls the database once per row/contiguous column unit. For instance, on a single row, if the user checks off columns 1-4 and 7-15 and column 21 the Java code will send three calls to the database for that row with info about the start/stop column for each unit.
    OK--here is my concern...the majority of the time there will be a reasonably small #of 'units'. Occasionally there will be a moderate, and once in awhile a LARGE # of 'units'. So, let's take an extreme case and say that currently the db has 200 such row/contiguous column units for a given screen. The user goes into that screen and adds the 201st unit, then clicks Save. Java calls the db to first inactivate the 200 rows. Then one by one Java calls the db to add the rows back in, only on row #40, the internet connection is lost. The only way the user can tell what happened is to look at the entire screen and reverify ALL the data in order to tell what got saved/resaved and what didn't. Obviously this is a bad situation that we want to avoid.
    I should add that the reason this approach was chosen is that the Java developers thought it would be way too complex in this situation to track the changes the user made on the screen, sort out what has been added/modified/deleted, and only call the db for changes.
    So given this background, can anyone offer any suggestions/ideas on how we can prevent unintended data loss given the auditing constraints and concern about minimizing complexity on the Java side (redesigning the GUI screen is NOT an option, as the users are very attached to this design)?
    Is there a way for Java to pass a multidimensional (& variable-sized) array to a PL/SQL function? Can Oracle's complex (row, table) data types be used in a function's parameter string, and if so...how?...Or else is there some way we can send a single call to the db on a screen like this one? We thought of calling the db once and sending one very large string packed with all the data (could get very big, not sure of Oracle's limatations on passed data--is it 32K for varchar2? )
    Advice, ideas, even random thoughts would be greatly appreciated!

    Tracy,
    <quote>… only on row #40, the internet connection is lost. The only way the user can tell what happened is to look at the entire screen and reverify ALL the data in order to tell what got saved/resaved and what didn't</quote>
    That would be "the only way" if the Java programmers had decided to totally bury the error … what should happen here is the end-user should get a proper error message … no need to re-verify at this point since all bets are off (in fact, nothing should’ve been changed in the database).
    Nonetheless, your concerns regarding the chosen approach are valid … making multiple calls to the database after a Save makes controlling a business transaction rather complex (in an n-tier system) … they should make one call only to the database passing in all the data to be saved … one database transaction … either all changes get applied or none.
    The fact that lots of data may need to be passed in for one Save is of no relevance … if you have to carry 500Kb of data for that screen then, well, you have to do it … 1 bucket of 500Kb or 50 buckets of 10Kb? … it doesn’t really matter as far as the actual transport part is concerned.
    As already answered, one can pass complex types in pl/sql … so one database call per Save would be my first random thought. There are lots of suspect things in here … some things you didn’t mentioned at all … like how is concurrency addressed? … have you/they implemented some sort of optimistic locking mechanism? Of course the architecture of your system won’t be solved in a forum … so, finding a good system/data/Oracle architect on site for the project would be my second random thought.
    PS. One last random thought … fight off that idea of packing and sending large strings (XML or not) … if the data is structured then contemplate XML for no more than few seconds.

  • Query on Reoprts-pl/sql function body returning sql query

    Hi,
    I am facing a starnge problem.. and would like to know the reason for it.
    The situation is as follows:
    I have a report (pl/sql function body returning sql query based). My query is as follows:
    declare
    l_query1 varchar2(2000);
    begin
    if (:P102_min_value is not null and :P102_max_value is null) then
    l_query1 := 'select decode(:P102_date,'1',date1) Transaction_Date, decode(:P102_first_name,'2',first_name) First_Name from (
    select * from MORTGAGE_LOAN_LEADS where APPRX_LOAN_AMOUNT >=:P102_min_value
    return (l_query1);
    end if;
    end;
    This returns the error as :
    1 error has occurred
    Function returning SQL query: Query cannot be parsed within the Builder. If you believe your query is syntactically correct, check the generic columns checkbox below the region source to proceed without parsing.
    (ORA-06550: line 7, column 20: PLS-00103: Encountered the symbol "1" when expecting one of the following: * & = - + ; < / > at in is mod remainder not rem <> or != or ~= >= <= <> and or like LIKE2_ LIKE4_ LIKEC_ between || multiset member SUBMULTISET_)
    How do i correct this? am i right in thinking that the single quotes indicating a string within a select query is creating the problem? Beacuse if i use an sql query report and use the following query, it is working fine...
    select
    decode(:P102_date,'1',date1) Transaction_Date,
    decode(:P102_first_name,'2',first_name) First_Name
    from (
    select * from MORTGAGE_LOAN_LEADS where APPRX_LOAN_AMOUNT >=:P102_min_value
    But i need to write pl/sql function, so that multiple report can be returned based on different conditions. Please guide me.
    Thanks,
    Sumana

    Does that mean that both in if and else we need to have same columns selected?
    if thats the case.. any idea how i can implement it in my code. The situation here is that the columns that need to be selected are dynamic and keep on changing...
    if i try to implement like this and run the page, it gives the following error:
    Query is:
    declare
    l_query1 varchar2(4000);
    begin
    if apex_application.get_current_flow_sgid(:APP_ID) = apex_application.get_sgid then
    if (:P102_min_value is not null and :P102_max_value is null) then
    l_query1 := 'select decode(' || :P102_date|| ',''1'',date1) Transaction_Date, decode(' || :P102_first_name || ',''2'',first_name) First_Name from (
    select * from MORTGAGE_LOAN_LEADS where APPRX_LOAN_AMOUNT >=' || :P102_min_value ||'
    elsif (:P102_min_value is null and :P102_max_value is not null) then
    l_query1 := 'select decode(' || :P102_date|| ',''1'',date1) Transaction_Date, decode(' || :P102_first_name || ',''2'',first_name) First_Name from (
    select * from MORTGAGE_LOAN_LEADS where APPRX_LOAN_AMOUNT >=' || :P102_max_value ||'
    else
    l_query1 := 'select date1,first_name from MORTGAGE_LOAN_LEADS where rownum = 1';
    end if;
    else
    l_query1 := 'select date1,first_name from MORTGAGE_LOAN_LEADS where rownum = 1';
    end if;
    return l_query1;
    --dbms_output.put_line( l_query1);
    end;
    The Error is:
    failed to parse SQL query:
    ORA-00936: missing expression
    If i try to run the same in command prompt, it always goes to the else part... (else of outer if)

Maybe you are looking for