From: Sandro Santilli Date: Mon, 27 Jan 2014 11:32:20 +0000 (+0000) Subject: Reduce calls to geometry::text during topology population (#2616) X-Git-Tag: 2.2.0rc1~1270 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9bbbb584fc979b7b556d43fc0a335facc080a166;p=postgis Reduce calls to geometry::text during topology population (#2616) git-svn-id: http://svn.osgeo.org/postgis/trunk@12194 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/topology/sql/populate.sql.in b/topology/sql/populate.sql.in index 657f60eb3..34c0b2cfa 100644 --- a/topology/sql/populate.sql.in +++ b/topology/sql/populate.sql.in @@ -116,9 +116,8 @@ BEGIN -- FOR rec IN EXECUTE 'SELECT node_id FROM ' || quote_ident(atopology) || '.node ' || - 'WHERE geom && ' || quote_literal(apoint::text) || '::geometry' - ||' AND ST_X(geom) = ST_X('||quote_literal(apoint::text)||'::geometry)' - ||' AND ST_Y(geom) = ST_Y('||quote_literal(apoint::text)||'::geometry)' + 'WHERE geom && $1 AND ST_X(geom) = ST_X($1) AND ST_Y(geom) = ST_Y($1)' + USING apoint LOOP RETURN rec.node_id; END LOOP; @@ -129,13 +128,10 @@ BEGIN -- FOR rec IN EXECUTE 'SELECT edge_id FROM ' || quote_ident(atopology) || '.edge ' - || 'WHERE ST_DWithin(' - || quote_literal(apoint::text) - || ', geom, 0) AND NOT ST_Equals(' - || quote_literal(apoint::text) - || ', ST_StartPoint(geom)) AND NOT ST_Equals(' - || quote_literal(apoint::text) - || ', ST_EndPoint(geom))' + || 'WHERE ST_DWithin($1, geom, 0) AND ' + || 'NOT ST_Equals($1, ST_StartPoint(geom)) AND ' + || 'NOT ST_Equals($1, ST_EndPoint(geom))' + USING apoint LOOP IF allowEdgeSplitting THEN RETURN ST_ModEdgeSplit(atopology, rec.edge_id, apoint); @@ -169,8 +165,8 @@ BEGIN -- EXECUTE 'INSERT INTO ' || quote_ident(atopology) || '.node(node_id, containing_face, geom) - VALUES(' || nodeid || ',' || coalesce(containing_face::text, 'NULL') || ',' - || quote_literal(apoint::text) || ')'; + VALUES(' || nodeid || ',' || coalesce(containing_face::text, 'NULL') + || ',$1)' USING apoint; RETURN nodeid; @@ -255,9 +251,8 @@ BEGIN -- FOR rec IN EXECUTE 'SELECT node_id FROM ' || quote_ident(atopology) || '.node ' - || 'WHERE ST_Crosses(' - || quote_literal(aline::text) || '::geometry, geom' - || ')' + || 'WHERE ST_Crosses($1, geom)' + USING aline LOOP RAISE EXCEPTION 'Edge crosses node %', rec.node_id; END LOOP; @@ -281,14 +276,9 @@ BEGIN -- FF1 F0F 1F2 -- FF1 F** 1*2 <-- our match -- - FOR rec IN EXECUTE 'SELECT edge_id, geom, ST_Relate(' - || quote_literal(aline::text) - || '::geometry, geom, 2) as im' - || ' FROM ' - || quote_ident(atopology) || '.edge ' - || 'WHERE ' - || quote_literal(aline::text) || '::geometry && geom' - + FOR rec IN EXECUTE 'SELECT edge_id, geom, ST_Relate($1, geom, 2) as im FROM ' + || quote_ident(atopology) || '.edge WHERE $1 && geom' + USING aline LOOP IF ST_RelateMatch(rec.im, 'FF1F**1*2') THEN @@ -343,16 +333,12 @@ BEGIN -- start_node || 'topology.addNode(' || quote_literal(atopology) - || ', ST_StartPoint(' - || quote_literal(aline::text) - || ')) ,' + || ', ST_StartPoint($1)), ' -- end_node || 'topology.addNode(' || quote_literal(atopology) - || ', ST_EndPoint(' - || quote_literal(aline::text) - || ')) ,' + || ', ST_EndPoint($1)), ' -- next_left_edge || -edgeid ||',' @@ -367,8 +353,8 @@ BEGIN || '0,' -- geom - ||quote_literal(aline::text) - || ')'; + || '$1)' + USING aline; RETURN edgeid; @@ -459,15 +445,12 @@ BEGIN -- bounds = ST_Boundary(rrec.geom); - sql := 'SELECT e.geom, e.edge_id, ' - || 'e.left_face, e.right_face FROM ' - || quote_ident(atopology) || '.edge e, (SELECT ' - || quote_literal(bounds::text) - || '::geometry as geom) r WHERE ' - || 'r.geom && e.geom' + sql := 'SELECT e.geom, e.edge_id, e.left_face, e.right_face FROM ' + || quote_ident(atopology) + || '.edge e, (SELECT $1 as geom) r WHERE r.geom && e.geom' ; -- RAISE DEBUG 'SQL: %', sql; - FOR rec IN EXECUTE sql + FOR rec IN EXECUTE sql USING bounds LOOP -- { --RAISE DEBUG 'Edge % has bounding box intersection', rec.edge_id; @@ -612,8 +595,8 @@ BEGIN -- face_id || faceid || ',' -- minimum bounding rectangle - || quote_literal(ST_Envelope(apoly)::text) - || ')'; + || '$1)' + USING ST_Envelope(apoly); -- -- Update all edges having this face on the left @@ -651,9 +634,8 @@ BEGIN || quote_literal(faceid) || ', left_face = ' || quote_literal(faceid) - || ' WHERE ST_Contains(' - || quote_literal(apoly::text) - || ', geom)'; + || ' WHERE ST_Contains($1, geom)' + USING apoly; -- -- Set containing_face of any contained node @@ -662,9 +644,8 @@ BEGIN || quote_ident(atopology) || '.node SET containing_face = ' || quote_literal(faceid) - || ' WHERE containing_face IS NOT NULL AND ST_Contains(' - || quote_literal(apoly::text) - || ', geom)'; + || ' WHERE containing_face IS NOT NULL AND ST_Contains($1, geom)' + USING apoly; RETURN faceid; @@ -710,17 +691,13 @@ BEGIN -- and if so pick the closest sql := 'SELECT a.node_id FROM ' || quote_ident(atopology) - || '.node as a WHERE ST_DWithin(a.geom,' - || quote_literal(apoint::text) || '::geometry,' - || tol || ') AND ST_Distance(' - || quote_literal(apoint::text) - || '::geometry, a.geom) < ' || tol || ' ORDER BY ST_Distance(' - || quote_literal(apoint::text) - || '::geometry, a.geom) LIMIT 1;'; + || '.node as a WHERE ST_DWithin(a.geom,$1,' + || tol || ') AND ST_Distance($1, a.geom) < ' || tol + || ' ORDER BY ST_Distance($1, a.geom) LIMIT 1'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - EXECUTE sql INTO id; + EXECUTE sql INTO id USING apoint; IF id IS NOT NULL THEN RETURN id; END IF; @@ -733,15 +710,12 @@ BEGIN -- and if so split it by a point projected on it sql := 'SELECT a.edge_id, a.geom FROM ' || quote_ident(atopology) - || '.edge as a WHERE ST_DWithin(a.geom,' - || quote_literal(apoint::text) || '::geometry,' - || tol || ') ORDER BY ST_Distance(' - || quote_literal(apoint::text) - || '::geometry, a.geom) LIMIT 1;'; + || '.edge as a WHERE ST_DWithin(a.geom,$1,' + || tol || ') ORDER BY ST_Distance($1, a.geom) LIMIT 1'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - EXECUTE sql INTO rec; + EXECUTE sql INTO rec USING apoint; IF rec IS NOT NULL THEN -- project point to line, split edge by point prj := ST_ClosestPoint(rec.geom, apoint); @@ -841,14 +815,12 @@ BEGIN -- 2. Node to edges falling within tol distance sql := 'WITH nearby AS ( SELECT e.geom FROM ' || quote_ident(atopology) - || '.edge e WHERE ST_DWithin(e.geom, ' - || quote_literal(noded::text) - || '::geometry, ' - || tol || ') ) SELECT st_collect(geom) FROM nearby;'; + || '.edge e WHERE ST_DWithin(e.geom, $1,' + || tol || ') ) SELECT st_collect(geom) FROM nearby'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - EXECUTE sql INTO iedges; + EXECUTE sql INTO iedges USING noded; IF iedges IS NOT NULL THEN #ifdef POSTGIS_TOPOLOGY_DEBUG @@ -886,14 +858,12 @@ BEGIN -- TODO: check if we should be only considering _isolated_ nodes! sql := 'WITH nearby AS ( SELECT n.geom FROM ' || quote_ident(atopology) - || '.node n WHERE ST_DWithin(n.geom, ' - || quote_literal(noded::text) - || '::geometry, ' + || '.node n WHERE ST_DWithin(n.geom, $1, ' || tol || ') ) SELECT st_collect(geom) FROM nearby;'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - EXECUTE sql INTO inodes; + EXECUTE sql INTO inodes USING noded; IF inodes IS NOT NULL THEN -- { #ifdef POSTGIS_TOPOLOGY_DEBUG @@ -986,12 +956,11 @@ BEGIN -- Check if the so-snapped edge _now_ exists sql := 'SELECT edge_id FROM ' || quote_ident(atopology) - || '.edge_data WHERE ST_Equals(geom, ' || quote_literal(snapped::text) - || '::geometry)'; + || '.edge_data WHERE ST_Equals(geom, $1)'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - EXECUTE sql INTO id; + EXECUTE sql INTO id USING snapped; IF id IS NULL THEN id := topology.ST_AddEdgeModFace(atopology, start_node, end_node, snapped); @@ -1057,13 +1026,11 @@ BEGIN -- 3. Find faces covered by input polygon -- NOTE: potential snapping changed polygon edges sql := 'SELECT DISTINCT f.face_id FROM ' || quote_ident(atopology) - || '.face f WHERE f.mbr && ' - || quote_literal(apoly::text) - || '::geometry'; + || '.face f WHERE f.mbr && $1'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - FOR rec IN EXECUTE sql LOOP + FOR rec IN EXECUTE sql USING apoly LOOP -- check for actual containment fgeom := ST_PointOnSurface(ST_GetFaceGeometry(atopology, rec.face_id)); IF NOT ST_Covers(apoly, fgeom) THEN diff --git a/topology/sql/sqlmm.sql.in b/topology/sql/sqlmm.sql.in index dbb0a2778..9b9d92e7d 100644 --- a/topology/sql/sqlmm.sql.in +++ b/topology/sql/sqlmm.sql.in @@ -78,18 +78,14 @@ BEGIN sql := 'WITH er2 AS ( ' || 'WITH er AS ( SELECT ' || 'min(e.edge_id) over (), count(*) over () as cnt, e.edge_id, ' - || 'ST_LineLocatePoint(' - || quote_literal(bounds::text) + || 'ST_LineLocatePoint($1' || ', ST_LineInterpolatePoint(e.geom, 0.2)) as pos' - || ', ST_LineLocatePoint(' - || quote_literal(bounds::text) + || ', ST_LineLocatePoint($1' || ', ST_LineInterpolatePoint(e.geom, 0.8)) as pos2 FROM ' || quote_ident(toponame) || '.edge e WHERE ( e.left_face = ' || face_id || ' OR e.right_face = ' || face_id - || ') AND ST_Covers(' - || quote_literal(bounds::text) - || ', e.geom)'; + || ') AND ST_Covers($1, e.geom)'; IF face_id = 0 THEN sql := sql || ' ORDER BY POS ASC) '; ELSE @@ -103,7 +99,7 @@ BEGIN --RAISE DEBUG 'SQL: %', sql; - FOR rec IN EXECUTE sql + FOR rec IN EXECUTE sql USING bounds LOOP #ifdef POSTGIS_TOPOLOGY_DEBUG @@ -343,8 +339,8 @@ BEGIN || ',' || rec.next_right_edge || ',' || rec.left_face || ',' || rec.right_face - || ',' || quote_literal(rec.geom::text) - || ')'; + || ', $1)' + USING rec.geom; -- End of new edge insertion } -- Update next_left_edge/next_right_edge for @@ -623,14 +619,15 @@ BEGIN e2sign = 1; END IF; EXECUTE 'UPDATE ' || quote_ident(toponame) - || '.edge_data SET geom = ' || quote_literal(rec.geom::text) + || '.edge_data SET geom = $1' || ', start_node = ' || rec.start_node || ', end_node = ' || rec.end_node || ', next_left_edge = ' || rec.next_left_edge || ', abs_next_left_edge = ' || abs(rec.next_left_edge) || ', next_right_edge = ' || rec.next_right_edge || ', abs_next_right_edge = ' || abs(rec.next_right_edge) - || ' WHERE edge_id = ' || e1id; + || ' WHERE edge_id = ' || e1id + USING rec.geom; -- End of first edge update } -- Update next_left_edge/next_right_edge for @@ -1486,8 +1483,9 @@ BEGIN -- We use index AND x/y equality -- FOR rec IN EXECUTE 'SELECT node_id FROM ' - || quote_ident(atopology) || '.node ' || - 'WHERE ST_Equals(geom, ' || quote_literal(apoint::text) || '::geometry)' + || quote_ident(atopology) + || '.node WHERE ST_Equals(geom, $1)' + USING apoint LOOP RAISE EXCEPTION 'SQL/MM Spatial exception - coincident node'; @@ -1499,8 +1497,8 @@ BEGIN -- FOR rec IN EXECUTE 'SELECT edge_id FROM ' || quote_ident(atopology) || '.edge ' - || 'WHERE ST_Intersects(geom, ' || quote_literal(apoint::text) - || '::geometry)' + || 'WHERE ST_Intersects(geom, $1)' + USING apoint LOOP RAISE EXCEPTION 'SQL/MM Spatial exception - edge crosses node.'; @@ -1513,13 +1511,11 @@ BEGIN -- sql := 'SELECT f.face_id FROM ' || quote_ident(atopology) - || '.face f WHERE f.face_id > 0 AND f.mbr && ' - || quote_literal(apoint::text) - || '::geometry AND ST_Contains(topology.ST_GetFaceGeometry(' + || '.face f WHERE f.face_id > 0 AND f.mbr && $1' + || ' AND ST_Contains(topology.ST_GetFaceGeometry(' || quote_literal(atopology) - || ', f.face_id), ' - || quote_literal(apoint::text) - || '::geometry)'; + || ', f.face_id), $1)' + ; IF aface IS NOT NULL AND aface != 0 THEN sql := sql || ' AND f.face_id = ' || aface; END IF; @@ -1527,7 +1523,7 @@ BEGIN #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - EXECUTE sql INTO containingface; + EXECUTE sql INTO containingface USING apoint; -- If aface was specified, check that it was correct IF aface IS NOT NULL THEN -- { @@ -1555,15 +1551,14 @@ BEGIN || quote_ident(atopology) || '.node(node_id, geom, containing_face) SELECT nextval(' || quote_literal( quote_ident(atopology) || '.node_node_id_seq' ) - || '),' - ||quote_literal(apoint::text) - || '::geometry,' || containingface + || '), $1, ' + || containingface || ' RETURNING node_id'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - EXECUTE sql INTO nodeid; + EXECUTE sql INTO nodeid USING apoint; RETURN nodeid; EXCEPTION @@ -1623,10 +1618,10 @@ BEGIN -- We use index AND x/y equality -- FOR rec IN EXECUTE 'SELECT node_id FROM ' - || quote_ident(atopology) || '.node ' || - 'WHERE geom && ' || quote_literal(apoint::text) || '::geometry' - ||' AND ST_X(geom) = ST_X('||quote_literal(apoint::text)||'::geometry)' - ||' AND ST_Y(geom) = ST_Y('||quote_literal(apoint::text)||'::geometry)' + || quote_ident(atopology) + || '.node WHERE geom && $1 ' + ||' AND ST_X(geom) = ST_X($1) AND ST_Y(geom) = ST_Y($1)' + USING apoint LOOP RAISE EXCEPTION 'SQL/MM Spatial exception - coincident node'; @@ -1637,10 +1632,9 @@ BEGIN -- I used _intersects_ here to include boundaries (endpoints) -- FOR rec IN EXECUTE 'SELECT edge_id FROM ' - || quote_ident(atopology) || '.edge ' - || 'WHERE geom && ' || quote_literal(apoint::text) - || ' AND ST_Intersects(geom, ' || quote_literal(apoint::text) - || '::geometry)' + || quote_ident(atopology) + || '.edge WHERE ST_Intersects(geom, $1)' + USING apoint LOOP RAISE EXCEPTION 'SQL/MM Spatial exception - edge crosses node.'; @@ -1650,8 +1644,8 @@ BEGIN -- Update node point -- EXECUTE 'UPDATE ' || quote_ident(atopology) || '.node ' - || ' SET geom = ' || quote_literal(apoint::text) - || ' WHERE node_id = ' || anode; + || ' SET geom = $1 WHERE node_id = $2' + USING apoint, anode; RETURN 'Isolated Node ' || anode || ' moved to location ' || ST_X(apoint) || ',' || ST_Y(apoint); @@ -1854,13 +1848,9 @@ BEGIN -- Check if a coincident node already exists -- FOR rec IN EXECUTE 'SELECT node_id FROM ' - || quote_ident(atopology) || '.node ' - || 'WHERE geom && ' - || quote_literal(apoint::text) || '::geometry' - || ' AND ST_X(geom) = ST_X(' - || quote_literal(apoint::text) || '::geometry)' - || ' AND ST_Y(geom) = ST_Y(' - || quote_literal(apoint::text) || '::geometry)' + || quote_ident(atopology) || '.node WHERE geom && $1 ' + || ' AND ST_X(geom) = ST_X($1) AND ST_Y(geom) = ST_Y($1)' + USING apoint LOOP RAISE EXCEPTION 'SQL/MM Spatial exception - coincident node'; @@ -1881,16 +1871,15 @@ BEGIN -- Add the new node -- EXECUTE 'INSERT INTO ' || quote_ident(atopology) - || '.node(node_id, geom) - VALUES(' || nodeid || ',' - || quote_literal(apoint::text) - || ')'; + || '.node(node_id, geom) VALUES($1, $2)' + USING nodeid, apoint; -- -- Delete the old edge -- - EXECUTE 'DELETE FROM ' || quote_ident(atopology) || '.edge_data ' - || ' WHERE edge_id = ' || anedge; + EXECUTE 'DELETE FROM ' || quote_ident(atopology) + || '.edge_data WHERE edge_id = $1' + USING anedge; -- -- Compute new edges @@ -1942,8 +1931,8 @@ BEGIN END || ',' || oldedge.left_face -- left_face || ',' || oldedge.right_face -- right_face - || ',' || quote_literal(edge1::text) -- geom - ||')'; + || ',$1)' -- geom + USING edge1; EXECUTE 'INSERT INTO ' || quote_ident(atopology) || '.edge VALUES(' @@ -1964,8 +1953,8 @@ BEGIN || ',' || -edgeid1 -- next_right_edge || ',' || oldedge.left_face -- left_face || ',' || oldedge.right_face -- right_face - || ',' || quote_literal(edge2::text) -- geom - ||')'; + || ',$1)' -- geom + USING edge2; -- -- Update all next edge references to match new layout @@ -2151,13 +2140,9 @@ BEGIN -- Check if a coincident node already exists -- FOR rec IN EXECUTE 'SELECT node_id FROM ' - || quote_ident(atopology) || '.node ' || - 'WHERE geom && ' - || quote_literal(apoint::text) || '::geometry' - ||' AND ST_X(geom) = ST_X(' - || quote_literal(apoint::text) || '::geometry)' - ||' AND ST_Y(geom) = ST_Y(' - ||quote_literal(apoint::text)||'::geometry)' + || quote_ident(atopology) || '.node WHERE geom && $1' + ||' AND ST_X(geom) = ST_X($1) AND ST_Y(geom) = ST_Y($1)' + USING apoint LOOP RAISE EXCEPTION 'SQL/MM Spatial exception - coincident node'; @@ -2178,9 +2163,8 @@ BEGIN -- Add the new node -- EXECUTE 'INSERT INTO ' || quote_ident(atopology) - || '.node(node_id, geom) - VALUES('||nodeid||','||quote_literal(apoint::text)|| - ')'; + || '.node(node_id, geom) VALUES($1, $2)' + USING nodeid,apoint; -- -- Compute new edge @@ -2224,20 +2208,16 @@ BEGIN || ',' || -anedge -- next_right_edge || ',' || oldedge.left_face -- left_face || ',' || oldedge.right_face -- right_face - || ',' || quote_literal(newedge2::text) -- geom - ||')'; + || ',$1)' --geom + USING newedge2; -- -- Update the old edge -- - EXECUTE 'UPDATE ' || quote_ident(atopology) || '.edge_data ' - || ' SET geom = ' || quote_literal(newedge1::text) - || ',' - || ' next_left_edge = ' || newedgeid - || ', abs_next_left_edge = ' || newedgeid - || ',' - || ' end_node = ' || nodeid - || ' WHERE edge_id = ' || anedge; + EXECUTE 'UPDATE ' || quote_ident(atopology) + || '.edge_data SET geom = $1, next_left_edge = $2, ' + || 'abs_next_left_edge = $2, end_node = $3 WHERE edge_id = $4' + USING newedge1, newedgeid, nodeid, anedge; -- @@ -2444,9 +2424,8 @@ BEGIN -- FOR rec IN EXECUTE 'SELECT node_id FROM ' || quote_ident(atopology) || '.node ' - || ' WHERE geom && ' || quote_literal(acurve::text) - || ' AND ST_Contains(' || quote_literal(acurve::text) - || ',geom)' + || ' WHERE ST_Contains($1, geom)' + USING acurve LOOP RAISE EXCEPTION 'SQL/MM Spatial exception - geometry crosses a node'; @@ -2457,7 +2436,8 @@ BEGIN -- FOR rec IN EXECUTE 'SELECT * FROM ' || quote_ident(atopology) || '.edge_data - WHERE ST_Intersects(geom, ' || quote_literal(acurve::text) || '::geometry)' + WHERE ST_Intersects(geom, $1)' + USING acurve LOOP RAISE EXCEPTION 'SQL/MM Spatial exception - geometry intersects an edge'; END LOOP; @@ -2483,8 +2463,8 @@ BEGIN || '.edge VALUES(' || edgeid || ',' || anode || ',' || anothernode || ',' || (-edgeid) || ',' || edgeid || ',' - || aface || ',' || aface || ',' - || quote_literal(acurve::text) || ')'; + || aface || ',' || aface || ',$1)' + USING acurve; -- -- Update Node containing_face values @@ -2652,14 +2632,12 @@ BEGIN -- g) Check if curve crosses any node -- FOR rec IN EXECUTE - 'SELECT node_id, ST_Relate(geom, ' - || quote_literal(acurve::text) || '::geometry, 2) as relate FROM ' + 'SELECT node_id, ST_Relate(geom, $1, 2) as relate FROM ' || quote_ident(atopology) - || '.node WHERE geom && ' - || quote_literal(acurve::text) - || '::geometry AND node_id NOT IN (' + || '.node WHERE geom && $1 AND node_id NOT IN (' || oldedge.start_node || ',' || oldedge.end_node || ')' + USING acurve LOOP IF ST_RelateMatch(rec.relate, 'T********') THEN RAISE EXCEPTION 'SQL/MM Spatial exception - geometry crosses a node'; @@ -2669,13 +2647,10 @@ BEGIN -- -- h) Check if this geometry has any interaction with any existing edge -- - sql := 'SELECT edge_id, ST_Relate(geom,' - || quote_literal(acurve::text) - || '::geometry, 2) as im FROM ' + sql := 'SELECT edge_id, ST_Relate(geom, $1, 2) as im FROM ' || quote_ident(atopology) - || '.edge_data WHERE edge_id != ' || anedge || ' AND geom && ' - || quote_literal(acurve::text) || '::geometry'; - FOR rec IN EXECUTE sql LOOP -- { + || '.edge_data WHERE edge_id != $2 AND geom && $1'; + FOR rec IN EXECUTE sql USING acurve, anedge LOOP -- { --RAISE DEBUG 'IM=%',rec.im; @@ -2712,15 +2687,14 @@ BEGIN sql := 'SELECT ST_Collect(geom) as nodes, ' || 'null::geometry as r1, null::geometry as r2 FROM ' || quote_ident(atopology) - || '.node WHERE geom && ' - || quote_literal(ST_Collect(ST_Envelope(oldedge.geom), - ST_Envelope(acurve))::text) - || '::geometry AND node_id NOT IN ( ' + || '.node WHERE geom && $1 AND node_id NOT IN ( ' || oldedge.start_node || ',' || oldedge.end_node || ')'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - EXECUTE sql INTO rng_info; + EXECUTE sql INTO rng_info USING ST_Collect(ST_Envelope(oldedge.geom), + ST_Envelope(acurve)) + ; -- There's no collision if there's no nodes in the combined -- bbox of old and new edges. @@ -2812,8 +2786,8 @@ BEGIN -- Update edge geometry -- EXECUTE 'UPDATE ' || quote_ident(atopology) || '.edge_data ' - || ' SET geom = ' || quote_literal(acurve::text) - || ' WHERE edge_id = ' || anedge; + || ' SET geom = $1 WHERE edge_id = $2' + USING acurve, anedge; -- -- Check edge adjacency after @@ -2852,20 +2826,20 @@ BEGIN -- would be larger than the old face MBR... -- IF oldedge.left_face != 0 THEN - sql := 'UPDATE ' || quote_ident(atopology) || '.face ' - || ' SET mbr = ' || quote_literal( - ST_Envelope(ST_GetFaceGeometry(atopology, oldedge.left_face))::text - ) - || '::geometry WHERE face_id = ' || oldedge.left_face; - EXECUTE sql; + sql := 'UPDATE ' || quote_ident(atopology) + || '.face SET mbr = $1 WHERE face_id = $2' ; + EXECUTE sql USING + ST_Envelope(ST_GetFaceGeometry(atopology, oldedge.left_face)), + oldedge.left_face + ; END IF; IF oldedge.right_face != 0 AND oldedge.right_face != oldedge.left_face THEN - sql := 'UPDATE ' || quote_ident(atopology) || '.face ' - || ' SET mbr = ' || quote_literal( - ST_Envelope(ST_GetFaceGeometry(atopology, oldedge.right_face))::text - ) - || '::geometry WHERE face_id = ' || oldedge.right_face; - EXECUTE sql; + sql := 'UPDATE ' || quote_ident(atopology) + || '.face SET mbr = $1 WHERE face_id = $2'; + EXECUTE sql USING + ST_Envelope(ST_GetFaceGeometry(atopology, oldedge.right_face)), + oldedge.right_face + ; END IF; @@ -2939,14 +2913,17 @@ BEGIN RAISE DEBUG 'Edge % splitted face %', anedge, oface; #endif - sql := 'WITH ids as ( select row_number() over () as seq, edge from unnest(' - || quote_literal(fan.newring_edges::text) - || '::int[] ) u(edge) ), edges AS ( select CASE WHEN i.edge < 0 THEN ST_Reverse(e.geom) ELSE e.geom END as g FROM ids i left join ' - || quote_ident(atopology) || '.edge_data e ON(e.edge_id = abs(i.edge)) ORDER BY seq) SELECT ST_MakePolygon(ST_MakeLine(g.g)) FROM edges g;'; + sql := 'WITH ids as ( select row_number() over () as seq, edge ' + || 'from unnest($1) u(edge) ), edges AS ( select CASE WHEN i.edge < 0 ' + || 'THEN ST_Reverse(e.geom) ELSE e.geom END as g FROM ids i left join ' + || quote_ident(atopology) || '.edge_data e ON(e.edge_id = abs(i.edge)) ' + || 'ORDER BY seq) SELECT ST_MakePolygon(ST_MakeLine(g.g)) FROM edges g'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG '%', sql; #endif - EXECUTE sql INTO fan.shell; + EXECUTE sql INTO fan.shell USING + fan.newring_edges + ; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG 'got shell'; @@ -2971,13 +2948,15 @@ BEGIN -- Update old face mbr (nothing to do if we're opening an hole) IF isccw THEN -- { sql := 'UPDATE ' - || quote_ident(atopology) || '.face SET mbr = ' - || quote_literal(ST_Envelope(fan.shell)::text) - || '::geometry WHERE face_id = ' || oface; + || quote_ident(atopology) + || '.face SET mbr = $1 WHERE face_id = $2'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG 'Updating old face mbr'; #endif - EXECUTE sql; + EXECUTE sql USING + ST_Envelope(fan.shell), + oface + ; END IF; -- } RETURN NULL; END IF; @@ -2991,16 +2970,14 @@ BEGIN || ' RETURNING face_id'; ELSE sql := 'INSERT INTO ' - || quote_ident(atopology) || '.face(mbr) VALUES (' - || quote_literal(ST_Envelope(fan.shell)::text) - || '::geometry) RETURNING face_id'; + || quote_ident(atopology) || '.face(mbr) VALUES ($1) RETURNING face_id'; END IF; -- } -- Insert new face #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG 'Inserting new face'; #endif - EXECUTE sql INTO STRICT newface; + EXECUTE sql INTO STRICT newface USING ST_Envelope(fan.shell); -- Update forward edges sql := 'UPDATE ' @@ -3052,14 +3029,13 @@ BEGIN )::text ) || ') AND '; IF ishole THEN sql := sql || 'NOT '; END IF; - sql := sql || '( ' || quote_literal(fan.shell::text) - || ' && geom AND _ST_Contains(' || quote_literal(fan.shell::text) + sql := sql || '($1 && geom AND _ST_Contains($1' -- We only need to check a single point, but must not be an endpoint - || '::geometry, ST_LineInterpolatePoint(geom, 0.2)) )'; + || ', ST_LineInterpolatePoint(geom, 0.2)) )'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG 'Updating edges bounding the old face: %', sql; #endif - EXECUTE sql; + EXECUTE sql USING fan.shell; -- Update isolated nodes in new new face sql := 'UPDATE ' @@ -3067,11 +3043,11 @@ BEGIN || ' WHERE containing_face = ' || oface || ' AND '; IF ishole THEN sql := sql || 'NOT '; END IF; - sql := sql || 'ST_Contains(' || quote_literal(fan.shell::text) || '::geometry, geom)'; + sql := sql || 'ST_Contains($1, geom)'; #ifdef POSTGIS_TOPOLOGY_DEBUG RAISE DEBUG 'Updating isolated nodes in old face'; #endif - EXECUTE sql; + EXECUTE sql USING fan.shell; RETURN newface; @@ -3244,12 +3220,10 @@ BEGIN -- Check if this geometry crosses any node -- FOR rec IN EXECUTE - 'SELECT node_id, ST_Relate(geom, ' - || quote_literal(acurve::text) || '::geometry, 2) as relate FROM ' + 'SELECT node_id, ST_Relate(geom, $1, 2) as relate FROM ' || quote_ident(atopology) - || '.node WHERE geom && ' - || quote_literal(acurve::text) - || '::geometry' + || '.node WHERE geom && $1' + USING acurve LOOP IF ST_RelateMatch(rec.relate, 'T********') THEN RAISE EXCEPTION 'SQL/MM Spatial exception - geometry crosses a node'; @@ -3259,12 +3233,10 @@ BEGIN -- -- Check if this geometry has any interaction with any existing edge -- - FOR rec IN EXECUTE 'SELECT edge_id, ST_Relate(geom,' - || quote_literal(acurve::text) - || '::geometry, 2) as im FROM ' + FOR rec IN EXECUTE 'SELECT edge_id, ST_Relate(geom, $1, 2) as im FROM ' || quote_ident(atopology) - || '.edge_data WHERE geom && ' - || quote_literal(acurve::text) || '::geometry' + || '.edge_data WHERE geom && $1' + USING acurve LOOP --RAISE DEBUG 'IM=%',rec.im; @@ -3320,11 +3292,10 @@ BEGIN IF newedge.isclosed THEN sql := sql || ' UNION SELECT ' || newedge.edge_id || ',' || newedge.end_node - || ',-1,0,0,' -- pretend we start elsewhere - || quote_literal(newedge.cleangeom::text); + || ',-1,0,0,$1'; -- pretend we start elsewhere END IF; i := 0; - FOR rec IN EXECUTE sql + FOR rec IN EXECUTE sql USING newedge.cleangeom LOOP -- incident edges { i := i + 1; @@ -3447,11 +3418,10 @@ BEGIN IF newedge.isclosed THEN sql := sql || ' UNION SELECT ' || newedge.edge_id || ',' || -1 -- pretend we end elsewhere - || ',' || newedge.start_node || ',0,0,' - || quote_literal(newedge.cleangeom::text); + || ',' || newedge.start_node || ',0,0,$1'; END IF; i := 0; - FOR rec IN EXECUTE sql + FOR rec IN EXECUTE sql USING newedge.cleangeom LOOP -- incident edges { i := i + 1; @@ -3580,8 +3550,9 @@ BEGIN || ',' || newedge.next_right_edge || ',' || newedge.left_face || ',' || newedge.right_face - || ',' || quote_literal(newedge.geom::geometry::text) - || ')'; + || ',$1)' + USING newedge.geom + ; -- Link prev_left_edge to us -- (if it's not us already) @@ -3873,12 +3844,10 @@ BEGIN -- Check if this geometry crosses any node -- FOR rec IN EXECUTE - 'SELECT node_id, ST_Relate(geom, ' - || quote_literal(acurve::text) || '::geometry, 2) as relate FROM ' + 'SELECT node_id, ST_Relate(geom, $1, 2) as relate FROM ' || quote_ident(atopology) - || '.node WHERE geom && ' - || quote_literal(acurve::text) - || '::geometry' + || '.node WHERE geom && $1' + USING acurve LOOP IF ST_RelateMatch(rec.relate, 'T********') THEN RAISE EXCEPTION 'SQL/MM Spatial exception - geometry crosses a node'; @@ -3888,12 +3857,10 @@ BEGIN -- -- Check if this geometry has any interaction with any existing edge -- - FOR rec IN EXECUTE 'SELECT edge_id, ST_Relate(geom,' - || quote_literal(acurve::text) - || '::geometry, 2) as im FROM ' + FOR rec IN EXECUTE 'SELECT edge_id, ST_Relate(geom, $1, 2) as im FROM ' || quote_ident(atopology) - || '.edge_data WHERE geom && ' - || quote_literal(acurve::text) || '::geometry' + || '.edge_data WHERE geom && $1' + USING acurve LOOP --RAISE DEBUG 'IM=%',rec.im; @@ -4209,8 +4176,9 @@ BEGIN || ',' || newedge.next_right_edge || ',' || newedge.left_face || ',' || newedge.right_face - || ',' || quote_literal(newedge.geom::geometry::text) - || ')'; + || ',$1)' + USING newedge.geom + ; -- Link prev_left_edge to us -- (if it's not us already)