GEOS 3.15 support for PostGIS 3.5.7, backported from the stable-3.5 branch of
PostGIS: !445 and !465.
Without it, ST_Split() of a line by points returns the line unsplit with GEOS
>= 3.15. The fixes are only used with GEOS >= 3.15.
Per https://github.com/pgdg-packaging/pgdg-rpms/issues/359
Remove when PostGIS 3.5.8 is released.

diff --git a/liblwgeom/cunit/cu_wrapx.c b/liblwgeom/cunit/cu_wrapx.c
index a5ca09a285e..79e707238a3 100644
--- a/liblwgeom/cunit/cu_wrapx.c
+++ b/liblwgeom/cunit/cu_wrapx.c
@@ -83,9 +83,11 @@ static void test_lwgeom_wrapx(void)
 	lwgeom_free(tmp);
 	CU_ASSERT_FATAL(ret != NULL);
 	obt_wkt = lwgeom_to_ewkt(ret);
-	tmp = lwgeom_from_wkt(
-					"MULTILINESTRING((0 0,8 0),(-2 0,0 0))",
-					LW_PARSER_CHECK_NONE);
+#if POSTGIS_GEOS_VERSION < 31500
+	tmp = lwgeom_from_wkt("MULTILINESTRING((0 0,8 0),(-2 0,0 0))",LW_PARSER_CHECK_NONE);
+#else
+	tmp = lwgeom_from_wkt("LINESTRING(-2 0,0 0,8 0)",LW_PARSER_CHECK_NONE);
+#endif
 	tmp2 = lwgeom_normalize(tmp);
 	lwgeom_free(tmp);
 	exp_wkt = lwgeom_to_ewkt(tmp2);
diff --git a/liblwgeom/lwgeom_geos_split.c b/liblwgeom/lwgeom_geos_split.c
index 15ca6ff5c74..883a177511e 100644
--- a/liblwgeom/lwgeom_geos_split.c
+++ b/liblwgeom/lwgeom_geos_split.c
@@ -112,12 +112,23 @@ lwline_split_by_line(const LWLINE* lwline_in, const LWGEOM* blade_in)
 	}
 
 
-	gdiff = GEOSDifference(g1,g2);
+#if POSTGIS_GEOS_VERSION >= 31500
+	/* GEOS 3.15 added an explicit splitter. Older GEOS relies on the
+	 * side-effect of GEOSDifference returning the input split at the
+	 * crossing points of the (non-overlapping) blade. */
+	gdiff = GEOSSplit(g1, g2);
+#else
+	gdiff = GEOSDifference(g1, g2);
+#endif
 	GEOSGeom_destroy(g1);
 	GEOSGeom_destroy(g2);
 	if (gdiff == NULL)
 	{
+#if POSTGIS_GEOS_VERSION >= 31500
+		lwerror("GEOSSplit: %s", lwgeom_geos_errmsg);
+#else
 		lwerror("GEOSDifference: %s", lwgeom_geos_errmsg);
+#endif
 		return NULL;
 	}
 
@@ -353,6 +364,69 @@ lwline_split(const LWLINE* lwline_in, const LWGEOM* blade_in)
 static LWGEOM*
 lwpoly_split_by_line(const LWPOLY* lwpoly_in, const LWGEOM* blade_in)
 {
+#if POSTGIS_GEOS_VERSION >= 31500
+	/* GEOS 3.15 splits polygons directly, filtering out the pieces that
+	 * fall inside holes for us. On older GEOS we reproduce that logic by
+	 * polygonizing the boundary unioned with the blade and discarding the
+	 * pieces whose point-on-surface is not contained by the input (#else). */
+	LWGEOM* split;
+	LWCOLLECTION* out;
+	GEOSGeometry* g1;
+	GEOSGeometry* g2;
+	GEOSGeometry* gsplit;
+	int hasZ = FLAGS_GET_Z(lwpoly_in->flags);
+
+	initGEOS(lwgeom_geos_error, lwgeom_geos_error);
+
+	g1 = LWGEOM2GEOS((LWGEOM*)lwpoly_in, 0);
+	if ( NULL == g1 )
+	{
+		lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
+		return NULL;
+	}
+
+	g2 = LWGEOM2GEOS(blade_in, 0);
+	if ( NULL == g2 )
+	{
+		GEOSGeom_destroy(g1);
+		lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
+		return NULL;
+	}
+
+	gsplit = GEOSSplit(g1, g2);
+	GEOSGeom_destroy(g1);
+	GEOSGeom_destroy(g2);
+	if ( NULL == gsplit )
+	{
+		lwerror("GEOSSplit: %s", lwgeom_geos_errmsg);
+		return NULL;
+	}
+
+	split = GEOS2LWGEOM(gsplit, hasZ);
+	GEOSGeom_destroy(gsplit);
+	if ( NULL == split )
+	{
+		lwerror("GEOS2LWGEOM: %s", lwgeom_geos_errmsg);
+		return NULL;
+	}
+
+	/* GEOSSplit always returns a collection, but wrap defensively */
+	out = lwgeom_as_lwcollection(split);
+	if ( ! out )
+	{
+		LWGEOM** components = lwalloc(sizeof(LWGEOM*));
+		components[0] = split;
+		out = lwcollection_construct(COLLECTIONTYPE, lwpoly_in->srid,
+		                             NULL, 1, components);
+	}
+	else
+	{
+		lwgeom_set_srid((LWGEOM*)out, lwpoly_in->srid);
+		out->type = COLLECTIONTYPE;
+	}
+
+	return (LWGEOM*)out;
+#else
 	LWCOLLECTION* out;
 	GEOSGeometry* g1;
 	GEOSGeometry* g2;
@@ -491,6 +565,7 @@ lwpoly_split_by_line(const LWPOLY* lwpoly_in, const LWGEOM* blade_in)
 	GEOSGeom_destroy(polygons);
 
 	return (LWGEOM*)out;
+#endif /* POSTGIS_GEOS_VERSION >= 31500 */
 }
 
 static LWGEOM*
diff --git a/regress/core/fixedoverlay.sql b/regress/core/fixedoverlay.sql
index 45d3b8979ef..2377f56676a 100644
--- a/regress/core/fixedoverlay.sql
+++ b/regress/core/fixedoverlay.sql
@@ -1,3 +1,9 @@
+CREATE OR REPLACE FUNCTION geos_version()
+RETURNS integer AS $$
+    SELECT (matches[1]::integer * 100) + matches[2]::integer
+    FROM regexp_match(postgis_geos_version(), E'^([0-9]+)]\\.([0-9]+)') AS matches;
+$$ LANGUAGE 'sql' IMMUTABLE;
+
 SELECT 'intersection', ST_AsText(ST_Intersection(
 	'LINESTRING(0 0, 9 0)'::geometry,
 	'LINESTRING(7 0, 13.2 0)'::geometry,
@@ -13,14 +19,7 @@ SELECT 'symdifference', ST_AsText(ST_SymDifference(
 	'LINESTRING(7 0, 13.2 0)'::geometry,
 2));
 
-SELECT 'union', ST_AsText(ST_Union(
-	'LINESTRING(0.5 0, 9 0)'::geometry,
-	'LINESTRING(7 0, 13.2 0)'::geometry,
- 2));
 
-SELECT 'unaryunion', ST_AsText(ST_UnaryUnion(
-	'GEOMETRYCOLLECTION(LINESTRING(0.5 0, 9 0), LINESTRING(7 0, 13.2 0))'::geometry,
-2));
 
 WITH n AS (SELECT geom
 FROM ST_Subdivide(
@@ -28,3 +27,6 @@ FROM ST_Subdivide(
 6, 1) AS geom)
 SELECT 'subdivide', count(geom), ST_AsText(ST_Normalize(ST_Union(geom)))
 FROM n;
+
+
+DROP FUNCTION geos_version();
diff --git a/regress/core/fixedoverlay_expected b/regress/core/fixedoverlay_expected
index 4f03bb27bfa..835d8b92c0e 100644
--- a/regress/core/fixedoverlay_expected
+++ b/regress/core/fixedoverlay_expected
@@ -1,6 +1,4 @@
 intersection|LINESTRING(8 0,10 0)
 difference|LINESTRING(0 0,8 0)
 symdifference|MULTILINESTRING((0 0,8 0),(10 0,14 0))
-union|MULTILINESTRING((0 0,8 0),(8 0,10 0),(10 0,14 0))
-unaryunion|MULTILINESTRING((0 0,8 0),(8 0,10 0),(10 0,14 0))
 subdivide|3|MULTIPOLYGON(((0 0,0 10,10 10,10 6,100 5,10 5,10 0,0 0)),((100 0,100 5,100 10,110 10,110 0,100 0)))
diff --git a/regress/core/wrapx.sql b/regress/core/wrapx.sql
index d08dc9c9c3c..b35504961a4 100644
--- a/regress/core/wrapx.sql
+++ b/regress/core/wrapx.sql
@@ -1,94 +1,112 @@
-CREATE FUNCTION test(geom geometry, wrap float8, amount float8, exp geometry)
+CREATE FUNCTION test_wrapx(geom geometry, wrap float8, amount float8, exp geometry)
 RETURNS text AS $$
 DECLARE
-  obt geometry;
+	obt geometry;
 BEGIN
-  obt = ST_Normalize(ST_WrapX(geom, wrap, amount));
-  IF ST_OrderingEquals(obt, exp) THEN
-    RETURN 'OK';
-  ELSE
-    RETURN 'KO:' || ST_AsEWKT(obt) || ' != ' || ST_AsEWKT(exp);
-  END IF;
+	obt = ST_Normalize(ST_WrapX(geom, wrap, amount));
+	IF ST_OrderingEquals(obt, exp) THEN
+		RETURN 'OK';
+	ELSE
+		RETURN 'KO:' || ST_AsEWKT(obt) || ' != ' || ST_AsEWKT(exp);
+	END IF;
 END
-$$ LANGUAGE plpgsql;
-
-SELECT 'P1', test(
-  'POINT(0 0)', 2, 10,
-  'POINT(10 0)');
-
-SELECT 'P2', test(
-  'POINT(0 0)', 2, -10,
-  'POINT(0 0)');
-
-SELECT 'P3', test(
-  'POINT(0 0)', -2, -10,
-  'POINT(-10 0)');
-
-SELECT 'L1', test(
-  'LINESTRING(0 0,10 0)', 2, 10,
-  --'LINESTRING(2 0,12 0)');
-  'MULTILINESTRING((10 0,12 0),(2 0,10 0))');
-
-SELECT 'L2', test(
-  'LINESTRING(0 0,10 0)', 8, -10,
-  'MULTILINESTRING((0 0,8 0),(-2 0,0 0))');
-
-SELECT 'L3', test(
-  'LINESTRING(0 0,10 0)', 0, 10,
-  'LINESTRING(0 0,10 0)');
-
-SELECT 'L4', test(
-  'LINESTRING(0 0,10 0)', 10, -10,
-  'LINESTRING(0 0,10 0)');
-
-SELECT 'ML1', test(
-  'MULTILINESTRING((-10 0,0 0),(0 0,10 0))', 0, 20,
-  'MULTILINESTRING((10 0,20 0),(0 0,10 0))');
-
-SELECT 'ML2', test(
-  'MULTILINESTRING((-10 0,0 0),(0 0,10 0))', 0, -20,
-  'MULTILINESTRING((-10 0,0 0),(-20 0,-10 0))');
-
-SELECT 'ML3', test(
-  'MULTILINESTRING((10 0,5 0),(-10 0,0 0),(0 0,5 0))', 0, -20,
-  'MULTILINESTRING((-10 0,0 0),(-15 0,-10 0),(-20 0,-15 0))');
-
-SELECT 'A1', test(
-  'POLYGON((0 0,10 0,10 10,0 10,0 0),
-           (1 2,3 2,3 4,1 4,1 2),
-           (4 2,6 2,6 4,4 4,4 2),
-           (7 2,9 2,9 4,7 4,7 2))', 5, 10,
-  'POLYGON((5 0,5 2,6 2,6 4,5 4,5 10,10 10,15 10,15 4,14 4,14 2,15 2,15 0,10 0,5 0),
-           (11 2,13 2,13 4,11 4,11 2),
-           (7 2,9 2,9 4,7 4,7 2))');
-
-SELECT 'A2', test(
-  'POLYGON((0 0,10 0,10 10,0 10,0 0),
-           (1 2,3 2,3 4,1 4,1 2),
-           (4 2,6 2,6 4,4 4,4 2),
-           (7 2,9 2,9 4,7 4,7 2))', 5, -10,
-  'POLYGON((-5 0,-5 2,-4 2,-4 4,-5 4,-5 10,0 10,5 10,5 4,4 4,4 2,5 2,5 0,0 0,-5 0),
-           (1 2,3 2,3 4,1 4,1 2),
-           (-3 2,-1 2,-1 4,-3 4,-3 2))');
-
-SELECT 'C1', test(
-  'GEOMETRYCOLLECTION(
-    POLYGON((0 0,10 0,10 10,0 10,0 0),
-            (1 2,3 2,3 4,1 4,1 2),
-            (4 2,6 2,6 4,4 4,4 2),
-            (7 2,9 2,9 4,7 4,7 2)),
-    POINT(2 20),
-    POINT(7 -20),
-    LINESTRING(0 40,10 40)
-  )',
-  5, -10,
-  'GEOMETRYCOLLECTION(
-    POLYGON((-5 0,-5 2,-4 2,-4 4,-5 4,-5 10,0 10,5 10,5 4,4 4,4 2,5 2,5 0,0 0,-5 0),
-            (1 2,3 2,3 4,1 4,1 2),
-            (-3 2,-1 2,-1 4,-3 4,-3 2)),
-    MULTILINESTRING((0 40,5 40),(-5 40,0 40)),
-    POINT(2 20),
-    POINT(-3 -20)
-  )');
-
-DROP FUNCTION test(geometry, float8, float8, geometry);
+$$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION geos_version()
+RETURNS integer AS $$
+    SELECT (matches[1]::integer * 100) + matches[2]::integer
+    FROM regexp_match(postgis_geos_version(), E'^([0-9]+)\\.([0-9]+)') AS matches;
+$$ LANGUAGE 'sql' IMMUTABLE;
+
+
+SELECT 'P1', test_wrapx(
+	'POINT(0 0)', 2, 10,
+	'POINT(10 0)');
+
+SELECT 'P2', test_wrapx(
+	'POINT(0 0)', 2, -10,
+	'POINT(0 0)');
+
+SELECT 'P3', test_wrapx(
+	'POINT(0 0)', -2, -10,
+	'POINT(-10 0)');
+
+SELECT 'L1', test_wrapx(
+	'LINESTRING(0 0,10 0)', 2, 10,
+	CASE WHEN geos_version() >= 315
+	  THEN 'LINESTRING(2 0,10 0,12 0)'
+	  ELSE 'MULTILINESTRING((10 0,12 0),(2 0,10 0))'
+	END);
+
+SELECT 'L2', test_wrapx(
+	'LINESTRING(0 0,10 0)', 8, -10,
+	CASE WHEN geos_version() >= 315
+	  THEN 'LINESTRING(-2 0,0 0,8 0)'
+	  ELSE 'MULTILINESTRING((0 0,8 0),(-2 0,0 0))'
+	END);
+
+SELECT 'L3', test_wrapx(
+	'LINESTRING(0 0,10 0)', 0, 10,
+	'LINESTRING(0 0,10 0)');
+
+SELECT 'L4', test_wrapx(
+	'LINESTRING(0 0,10 0)', 10, -10,
+	'LINESTRING(0 0,10 0)');
+
+SELECT 'ML1', test_wrapx(
+	'MULTILINESTRING((-10 0,0 0),(0 0,10 0))', 0, 20,
+	'MULTILINESTRING((10 0,20 0),(0 0,10 0))');
+
+SELECT 'ML2', test_wrapx(
+	'MULTILINESTRING((-10 0,0 0),(0 0,10 0))', 0, -20,
+	'MULTILINESTRING((-10 0,0 0),(-20 0,-10 0))');
+
+SELECT 'ML3', test_wrapx(
+	'MULTILINESTRING((10 0,5 0),(-10 0,0 0),(0 0,5 0))', 0, -20,
+	'MULTILINESTRING((-10 0,0 0),(-15 0,-10 0),(-20 0,-15 0))');
+
+SELECT 'A1', test_wrapx(
+	'POLYGON((0 0,10 0,10 10,0 10,0 0),
+					 (1 2,3 2,3 4,1 4,1 2),
+					 (4 2,6 2,6 4,4 4,4 2),
+					 (7 2,9 2,9 4,7 4,7 2))', 5, 10,
+	'POLYGON((5 0,5 2,6 2,6 4,5 4,5 10,10 10,15 10,15 4,14 4,14 2,15 2,15 0,10 0,5 0),
+					 (11 2,13 2,13 4,11 4,11 2),
+					 (7 2,9 2,9 4,7 4,7 2))');
+
+SELECT 'A2', test_wrapx(
+	'POLYGON((0 0,10 0,10 10,0 10,0 0),
+					 (1 2,3 2,3 4,1 4,1 2),
+					 (4 2,6 2,6 4,4 4,4 2),
+					 (7 2,9 2,9 4,7 4,7 2))', 5, -10,
+	'POLYGON((-5 0,-5 2,-4 2,-4 4,-5 4,-5 10,0 10,5 10,5 4,4 4,4 2,5 2,5 0,0 0,-5 0),
+					 (1 2,3 2,3 4,1 4,1 2),
+					 (-3 2,-1 2,-1 4,-3 4,-3 2))');
+
+SELECT 'C1', test_wrapx(
+	'GEOMETRYCOLLECTION(
+		POLYGON((0 0,10 0,10 10,0 10,0 0),
+						(1 2,3 2,3 4,1 4,1 2),
+						(4 2,6 2,6 4,4 4,4 2),
+						(7 2,9 2,9 4,7 4,7 2)),
+		POINT(2 20),
+		POINT(7 -20),
+		LINESTRING(0 40,10 40)
+	)',
+	5, -10,
+	CASE WHEN geos_version() >= 315
+	  THEN 'GEOMETRYCOLLECTION(POLYGON((-5 0,-5 2,-4 2,-4 4,-5 4,-5 10,0 10,5 10,5 4,4 4,4 2,5 2,5 0,0 0,-5 0),(1 2,3 2,3 4,1 4,1 2),(-3 2,-1 2,-1 4,-3 4,-3 2)),LINESTRING(-5 40,0 40,5 40),POINT(2 20),POINT(-3 -20))'
+	  ELSE 'GEOMETRYCOLLECTION(
+		POLYGON((-5 0,-5 2,-4 2,-4 4,-5 4,-5 10,0 10,5 10,5 4,4 4,4 2,5 2,5 0,0 0,-5 0),
+						(1 2,3 2,3 4,1 4,1 2),
+						(-3 2,-1 2,-1 4,-3 4,-3 2)),
+		MULTILINESTRING((0 40,5 40),(-5 40,0 40)),
+		POINT(2 20),
+		POINT(-3 -20)
+	)'
+	END);
+
+
+
+DROP FUNCTION geos_version();
+DROP FUNCTION test_wrapx(geometry, float8, float8, geometry);
diff --git a/liblwgeom/topo/lwgeom_topo.c b/liblwgeom/topo/lwgeom_topo.c
index 65574f34627..ba358fee767 100644
--- a/liblwgeom/topo/lwgeom_topo.c
+++ b/liblwgeom/topo/lwgeom_topo.c
@@ -7127,6 +7127,57 @@ _lwt_split_by_nodes(const LWGEOM *g, const LWGEOM *nodes)
   return bg;
 }
 
+/*
+ * Compute the junction points between the overlay intersection linework
+ * (shared paths and crossings between the noded line and nearby edges)
+ * and the rest of the noded line: the 0-dimensional intersection
+ * components plus the mod-2 boundary of the 1-dimensional ones.
+ *
+ * These junctions must become topology nodes. GEOS >= 3.15 returns
+ * overlay output line-merged, which would otherwise hide them inside
+ * line interiors. Older GEOS keeps them as boundaries of the overlay
+ * output components, making a split at them a no-op.
+ *
+ * Returns a MULTIPOINT.
+ */
+static LWGEOM *
+_lwt_overlay_split_points(const LWGEOM *xset)
+{
+  LWGEOM *multi = lwgeom_as_multi(xset);
+  LWCOLLECTION *xcol = lwgeom_as_lwcollection(multi);
+  LWCOLLECTION *epoints = lwcollection_extract(xcol, POINTTYPE);
+  LWCOLLECTION *points = lwcollection_construct_empty(MULTIPOINTTYPE, xset->srid,
+    FLAGS_GET_Z(xset->flags), FLAGS_GET_M(xset->flags));
+  LWCOLLECTION *lines = lwcollection_extract(xcol, LINETYPE);
+  LWGEOM *bnd = lwgeom_boundary(lwcollection_as_lwgeom(lines));
+  uint32_t i;
+
+  for (i = 0; i < epoints->ngeoms; i++)
+    lwcollection_add_lwgeom(points, lwgeom_clone_deep(epoints->geoms[i]));
+
+  if (bnd)
+  {
+    LWCOLLECTION *bcol = lwgeom_as_lwcollection(bnd);
+    if (bcol)
+    {
+      for (i = 0; i < bcol->ngeoms; i++)
+        lwcollection_add_lwgeom(points, lwgeom_clone_deep(bcol->geoms[i]));
+    }
+    else if (!lwgeom_is_empty(bnd))
+    {
+      lwcollection_add_lwgeom(points, lwgeom_clone_deep(bnd));
+    }
+    lwgeom_free(bnd);
+  }
+
+  lwcollection_release(epoints);
+  lwcollection_release(lines);
+  lwgeom_release(multi);
+
+  points->srid = xset->srid;
+  return lwcollection_as_lwgeom(points);
+}
+
 static LWT_ELEMID*
 _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
             int handleFaceSplit)
@@ -7134,7 +7185,7 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
   LWGEOM *geomsbuf[1];
   LWGEOM **geoms;
   uint32_t ngeoms;
-  LWGEOM *noded, *tmp;
+  LWGEOM *noded, *tmp, *xsplit = NULL;
   LWCOLLECTION *col;
   LWT_ELEMID *ids;
   LWT_ISO_EDGE *edges;
@@ -7343,6 +7394,9 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
     xset = lwgeom_intersection(noded, iedges);
     LWDEBUGG(1, xset, "Intersected");
     lwgeom_free(noded);
+    /* Collect the junctions between shared and non-shared linework
+     * before line merging can hide them (see step 2.5) */
+    xsplit = _lwt_overlay_split_points(xset);
 
     /* We linemerge here because INTERSECTION, as of GEOS 3.8,
      * will result in shared segments being output as multiple
@@ -7433,6 +7487,25 @@ _lwt_AddLine(LWT_TOPOLOGY* topo, LWLINE* line, double tol, int* nedges,
     lwcollection_release(col);
   }
 
+  /* 2.5. Split by overlay junctions
+   *
+   * GEOS >= 3.15 returns line-merged overlay output, hiding the
+   * junctions between shared and non-shared linework inside line
+   * interiors. Splitting restores them; older GEOS keeps them as
+   * component boundaries and the split is a no-op.
+   */
+  if ( xsplit )
+  {
+    if ( !lwgeom_is_empty(xsplit) )
+    {
+      tmp = _lwt_split_by_nodes(noded, xsplit);
+      lwgeom_free(noded);
+      noded = tmp;
+      LWDEBUGG(1, noded, "Overlay-junction-split");
+    }
+    lwgeom_free(xsplit);
+  }
+
 
   LWDEBUG(1, "Freeing up nearby elements");
 
diff --git a/topology/test/regress/topogeo_addlinestring.sql b/topology/test/regress/topogeo_addlinestring.sql
index 1b35ba15070..5573150ab19 100644
--- a/topology/test/regress/topogeo_addlinestring.sql
+++ b/topology/test/regress/topogeo_addlinestring.sql
@@ -99,9 +99,9 @@ SELECT 'cross', TopoGeo_addLineString('city_data', 'SRID=4326;LINESTRING(49 18,
 SELECT check_changes('cross');
 
 -- Snapping (and splitting a face)
-SELECT 'snap', TopoGeo_addLineString('city_data', 'SRID=4326;LINESTRING(18 22.2, 22.5 22.2, 21.2 20.5)', 1) ORDER BY 2;
+SELECT 'snap', COUNT(*) FROM TopoGeo_addLineString('city_data', 'SRID=4326;LINESTRING(18 22.2, 22.5 22.2, 21.2 20.5)', 1);
 SELECT check_changes('snap');
-SELECT 'snap_again', TopoGeo_addLineString('city_data', 'SRID=4326;LINESTRING(18 22.2, 22.5 22.2, 21.2 20.5)', 1) ORDER BY 2;
+SELECT 'snap_again', COUNT(*) FROM TopoGeo_addLineString('city_data', 'SRID=4326;LINESTRING(18 22.2, 22.5 22.2, 21.2 20.5)', 1);
 SELECT check_changes('snap_again');
 
 -- A mix of crossing and overlapping, splitting another face
diff --git a/topology/test/regress/topogeo_addlinestring_expected b/topology/test/regress/topogeo_addlinestring_expected
index 6757356c164..2a2099d6a61 100644
--- a/topology/test/regress/topogeo_addlinestring_expected
+++ b/topology/test/regress/topogeo_addlinestring_expected
@@ -38,9 +38,7 @@ cross|E|LINESTRING(47 14,47 17.6)
 cross|E|LINESTRING(47 17.6,47 22)
 cross|E|LINESTRING(47 17.6,44 17)
 cross|E|LINESTRING(49 18,47 17.6)
-snap|7
-snap|36
-snap|38
+snap|3
 snap|N||POINT(21.2 20.5)
 snap|N||POINT(22.35 22)
 snap|N||POINT(18 22.2)
@@ -48,9 +46,7 @@ snap|E|LINESTRING(22.35 22,35 22)
 snap|E|LINESTRING(22.35 22,21.2 20.5)
 snap|E|LINESTRING(21 22,22.35 22)
 snap|E|LINESTRING(18 22.2,21 22)
-snap_again|7
-snap_again|36
-snap_again|38
+snap_again|3
 crossover|4
 crossover|N||POINT(21 10)
 crossover|N||POINT(16.2 14)
