Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

calling nested function to perform DML and wait for commit

jutzinMay 22 2013 — edited Jun 13 2013
Hi everybody,

I would like to do some DML -- an insert statement, to be specific -- in a function and have the function then return the numeric key of the newly added row. I call this function from another context and woud then be able to use the newly added data to do some stuff.

More specifically, what I am going to do is this: I have a graph consisting of source, destination and distance triplets in a table. A user should now be able to

1.) add a node 'A' to the graph,
2.) add a node 'B' to the graph
3.) get the shortest path from A to B through the graph.

I have an inner function
function INSERT_NEW_NODE(node_in in sdo_geometry, graph_in in integer) return integer
is  

pragma autonomous_transaction;

cursor node_cur is  
  select 
      source,
      source_geom
  from graph  
;
    
cursor edge_cur is
    select
        source,
        destination,
        distance,
        edge_geom
    from
      graph
    where
      sdo_geom.relate(edge_geom, 'anyinteract', node_in, .005) = 'TRUE';

begin

  -- check if identical with any existing node
  for node_rec in node_cur loop  
    if sdo_geom.relate(node_rec.source_geom, 'EQUAL', node_in, .005) = 'EQUAL' then
      return node_rec.source;
    end if;
  end loop;    
  
  -- get edges
  for edge_rec in edge_cur loop
     -- new_node-->edge.destination and vice versa
    insert into
      graph
      (
        ID,
        GRAPH,
        SOURCE,
        DESTINATION,
        DISTANCE,
        SOURCE_GEOM,
        DESTINATION_GEOM,
        EDGE_GEOM
      )
    values
    (
      graph_id_seq.nextval, --id
      graph_in, --graph
      morton(node_in.sdo_point.x, node_in.sdo_point.y),  -- source morton key
      edge_rec.source, -- destination morton key
      sdo_geom.sdo_distance(edge_rec.source_geom_marl2000, node_in, .005, 'unit=M'), -- distance
      node_in, -- source geom
      edge_rec.source_geom,  -- dest geom
      split_line(edge_rec.edge_geom_marl2000, node_in).segment1 -- edge geom
    );
    commit;
    --new_node-->edge.source and vice versa
    insert into
      gl_graph
      (
        ID,
        GRAPH,
        SOURCE,
        DESTINATION,
        DISTANCE,
        SOURCE_GEOM,
        DESTINATION_GEOM,
        EDGE_GEOM
      )
    values
    (
      graph_id_seq.nextval, --id
      graph_in, --graph
      edge_rec.source, -- source morton key
      morton(node_in.sdo_point.x, node_in.sdo_point.y), -- destination morton key
      sdo_geom.sdo_distance(edge_rec.source_geom, node_in, .005, 'unit=M'), -- distance
      edge_rec.source_geom,  -- source geom
      node_in, -- dest geom
      split_line(edge_rec.edge_geom, node_in).segment2 -- edge geom
    );
    commit;
  end loop
  ;
 
  return(morton(node_in.sdo_point.x, node_in.sdo_point.y));
  
end insert_new_node;
, which adds the new nodes to the graph, connects, calculates distances etc. and returns a handle to the newly added node. I call this function twice from another, outer function
function get_path (line_in in sdo_geometry, graph_in in integer) return sdo_geometry
is  

source number;
destination number;
source_geom mdsys.sdo_geometry;
destination_geom mdsys.sdo_geometry;
  
begin
  
  source := insert_new_node(get_firstvertex(line_in), graph_in);
  destination := insert_new_node(get_lastvertex(line_in), graph_in);
 
  -- source := insert_new_node(get_firstvertex(line_in), graph_in);
  -- destination := insert_new_node(get_lastvertex(line_in), graph_in);
  
  return(get_path_geom(source, destination)); --returns a geometry which is the shortest path between source and destination
  
end get_path;
; and I think, I have to use automous transaction in the inner function, so that the outer function can see any change performed by the inner one. However, this only works, when I call the inner function twice (i.e. remove the comment signs in front of the last two lines of code right before the return statement in the outer function.

So here's my questions: 1.) Why do I have to call the function twice to see the transaction complete? and 2.) How can I avoid that? Is there a way to wait with the execution of the return statement in the inner function until the insert is committed and can be seen by the outer function?

Cheers!
This post has been answered by jutzin on Jun 13 2013
Jump to Answer

Comments

Locked Post
New comments cannot be posted to this locked post.

Post Details

Locked on Jul 11 2013
Added on May 22 2013
8 comments
609 views