[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0alpha1-110-gecae381

git at osgeo.org git at osgeo.org
Fri May 8 09:16:55 PDT 2020


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, master has been updated
       via  ecae381d1b69ae00bb663ef76edf0d24ee7a950a (commit)
      from  3cf8e87779a6657c95b094abca76ebd9419e3e08 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit ecae381d1b69ae00bb663ef76edf0d24ee7a950a
Author: Sandro Santilli <strk at kbt.io>
Date:   Fri May 8 16:55:54 2020 +0200

    Implement GetRingEdges in C
    
    Closes #4675

diff --git a/NEWS b/NEWS
index 7203935..44b4f23 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,7 @@ Only tickets not included in 3.1.0alpha1
   -
 
 * Enhancements *
+  - #4675, topology.GetRingEdges now implemented in C (Sandro Santilli)
   - #4681, ST_GetFaceGeometry: print corruption information (Sandro Santilli)
   - #4651: ST_Simplify: Don't copy if nothing is removed (Raúl Marín)
   - #4657: Avoid De-TOASTing where possible (Paul Ramsey)
diff --git a/topology/postgis_topology.c b/topology/postgis_topology.c
index 46c245d..832f367 100644
--- a/topology/postgis_topology.c
+++ b/topology/postgis_topology.c
@@ -4951,3 +4951,130 @@ Datum TopoGeo_AddPolygon(PG_FUNCTION_ARGS)
 
   SRF_RETURN_NEXT(funcctx, result);
 }
+
+/*  GetRingEdges(atopology, anedge, maxedges default null) */
+Datum GetRingEdges(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(GetRingEdges);
+Datum GetRingEdges(PG_FUNCTION_ARGS)
+{
+  text* toponame_text;
+  char* toponame;
+  LWT_ELEMID edge_id;
+  int maxedges = 0;
+  uint64_t nelems;
+  LWT_ELEMID *elems;
+  LWT_BE_TOPOLOGY *topo;
+  FuncCallContext *funcctx;
+  MemoryContext oldcontext, newcontext;
+  FACEEDGESSTATE *state;
+  Datum result;
+  HeapTuple tuple;
+  Datum ret[2];
+  bool isnull[2] = {0,0}; /* needed to say neither value is null */
+
+  if (SRF_IS_FIRSTCALL())
+  {
+    POSTGIS_DEBUG(1, "GetRingEdges first call");
+    funcctx = SRF_FIRSTCALL_INIT();
+    newcontext = funcctx->multi_call_memory_ctx;
+
+
+    if ( PG_ARGISNULL(0) )
+    {
+      lwpgerror("GetRingEdges: topology name cannot be null");
+      PG_RETURN_NULL();
+    }
+    toponame_text = PG_GETARG_TEXT_P(0);
+    toponame = text_to_cstring(toponame_text);
+    PG_FREE_IF_COPY(toponame_text, 0);
+
+    if ( PG_ARGISNULL(1) )
+    {
+      lwpgerror("GetRingEdges: edge id cannot be null");
+      PG_RETURN_NULL();
+    }
+    edge_id = PG_GETARG_INT32(1) ;
+
+    if ( ! PG_ARGISNULL(2) )
+    {
+      maxedges = PG_GETARG_INT32(2) ;
+    }
+
+    if ( SPI_OK_CONNECT != SPI_connect() )
+    {
+      lwpgerror("Could not connect to SPI");
+      PG_RETURN_NULL();
+    }
+
+    {
+      int pre = be_data.topoLoadFailMessageFlavor;
+      be_data.topoLoadFailMessageFlavor = 1;
+      topo = cb_loadTopologyByName(&be_data, toponame);
+      be_data.topoLoadFailMessageFlavor = pre;
+    }
+    oldcontext = MemoryContextSwitchTo( newcontext );
+    pfree(toponame);
+    if ( ! topo )
+    {
+      /* should never reach this point, as lwerror would raise an exception */
+      SPI_finish();
+      PG_RETURN_NULL();
+    }
+
+    POSTGIS_DEBUG(1, "Calling cb_getRingEdges");
+    elems = cb_getRingEdges(topo, edge_id, &nelems, maxedges);
+    POSTGIS_DEBUG(1, "cb_getRingEdges returned");
+    cb_freeTopology(topo);
+
+    if ( ! elems )
+    {
+      /* should never reach this point, as lwerror would raise an exception */
+      SPI_finish();
+      PG_RETURN_NULL();
+    }
+
+    state = lwalloc(sizeof(FACEEDGESSTATE));
+    state->elems = elems;
+    state->nelems = nelems;
+    state->curr = 0;
+    funcctx->user_fctx = state;
+
+    POSTGIS_DEBUG(1, "GetRingEdges calling SPI_finish");
+
+    /*
+     * Get tuple description for return type
+     */
+    get_call_result_type(fcinfo, 0, &funcctx->tuple_desc);
+    BlessTupleDesc(funcctx->tuple_desc);
+
+    MemoryContextSwitchTo(oldcontext);
+
+    SPI_finish();
+  }
+
+  POSTGIS_DEBUG(1, "Per-call invocation");
+
+  /* stuff done on every call of the function */
+  funcctx = SRF_PERCALL_SETUP();
+
+  /* get state */
+  state = funcctx->user_fctx;
+
+  if ( state->curr == state->nelems )
+  {
+    POSTGIS_DEBUG(1, "We're done, cleaning up all");
+    SRF_RETURN_DONE(funcctx);
+  }
+
+  edge_id = state->elems[state->curr++];
+  POSTGIS_DEBUGF(1, "GetRingEdges: cur:%d, val:%" LWTFMT_ELEMID,
+                 state->curr-1, edge_id);
+
+
+  ret[0] = Int32GetDatum(state->curr);
+  ret[1] = Int64GetDatum(edge_id);
+  tuple = heap_form_tuple(funcctx->tuple_desc, ret, isnull);
+  result = HeapTupleGetDatum(tuple);
+
+  SRF_RETURN_NEXT(funcctx, result);
+}
diff --git a/topology/sql/query/GetRingEdges.sql.in b/topology/sql/query/GetRingEdges.sql.in
index 7b85ee5..8670adb 100644
--- a/topology/sql/query/GetRingEdges.sql.in
+++ b/topology/sql/query/GetRingEdges.sql.in
@@ -38,43 +38,7 @@
 -- GetRingEdges(atopology, anedge, [maxedges])
 --
 CREATE OR REPLACE FUNCTION topology.GetRingEdges(atopology varchar, anedge int, maxedges int DEFAULT null)
-	RETURNS SETOF topology.GetFaceEdges_ReturnType
-AS
-$$
-DECLARE
-  rec RECORD;
-  retrec topology.GetFaceEdges_ReturnType;
-  n int;
-  sql text;
-BEGIN
-  sql := 'WITH RECURSIVE edgering AS ( SELECT '
-    || anedge
-    || ' as signed_edge_id, edge_id, next_left_edge, next_right_edge FROM '
-    || quote_ident(atopology)
-    || '.edge_data WHERE edge_id = '
-    || abs(anedge)
-    || ' UNION '
-    || ' SELECT CASE WHEN p.signed_edge_id < 0 THEN p.next_right_edge '
-    || ' ELSE p.next_left_edge END, e.edge_id, e.next_left_edge, e.next_right_edge '
-    || ' FROM ' || quote_ident(atopology)
-    || '.edge_data e, edgering p WHERE e.edge_id = CASE WHEN p.signed_edge_id < 0 '
-    || 'THEN abs(p.next_right_edge) ELSE abs(p.next_left_edge) END ) SELECT * FROM edgering';
-
-  n := 1;
-  FOR rec IN EXECUTE sql
-  LOOP
-    retrec.sequence := n;
-    retrec.edge := rec.signed_edge_id;
-    RETURN NEXT retrec;
-
-    n := n + 1;
-
-    IF n > maxedges THEN
-      RAISE EXCEPTION 'Max traversing limit hit: %', maxedges;
-    END IF;
-  END LOOP;
-
-END
-$$
-LANGUAGE 'plpgsql' STABLE;
+	RETURNS SETOF topology.GetFaceEdges_ReturnType AS
+	'MODULE_PATHNAME', 'GetRingEdges'
+LANGUAGE 'c' STABLE;
 --} GetRingEdges

-----------------------------------------------------------------------

Summary of changes:
 NEWS                                   |   1 +
 topology/postgis_topology.c            | 127 +++++++++++++++++++++++++++++++++
 topology/sql/query/GetRingEdges.sql.in |  42 +----------
 3 files changed, 131 insertions(+), 39 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list