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!