From git at osgeo.org Sat Aug 1 09:49:40 2026 From: git at osgeo.org (git at osgeo.org) Date: Sat, 1 Aug 2026 09:49:40 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-158-g1df65a1b92 Message-ID: <20260801164940.4FE4C1E09E9@trac.osgeo.org> 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 1df65a1b92af4bd5162d08c5fbc4fa3133ae46c8 (commit) via fbb6766c8a62c39fb5a329c6c88201e6dbaf786d (commit) from bdbf14c2043c5ae19c8a22bccca96ac1419ba2b1 (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 1df65a1b92af4bd5162d08c5fbc4fa3133ae46c8 Merge: bdbf14c204 fbb6766c8a Author: Darafei Praliaskouski Date: Sat Aug 1 09:49:38 2026 -0700 Merge pull request 'ci: disable autovacuum in armhf portability tests' (!626) from Komzpa/postgis:ci/armhf-portability-disable-autovacuum-20260730 into master The armhf QEMU portability job runs a single-client regression upgrade, but the PostgreSQL instance still allowed autovacuum to start a second backend. Under emulation that backend can overlap the extension upgrade and form a real lock cycle. This keeps the armhf upgrade check in place and starts only that job's temporary PostgreSQL server with autovacuum disabled, matching the regression harness's deterministic test-table policy without weakening 32-bit coverage. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/626 commit fbb6766c8a62c39fb5a329c6c88201e6dbaf786d Author: Darafei Praliaskouski Date: Thu Jul 30 03:28:25 2026 +0400 ci: disable autovacuum in armhf portability tests diff --git a/.woodpecker/portability.yml b/.woodpecker/portability.yml index 85f9bae8e0..d653af7629 100644 --- a/.woodpecker/portability.yml +++ b/.woodpecker/portability.yml @@ -59,7 +59,7 @@ variables: runuser -u postgres -- initdb -D "$${PGDATA}" -A trust --no-sync runuser -u postgres -- pg_ctl -D "$${PGDATA}" \ -l "$${PGROOT}/postgresql.log" \ - -o "-F -k $${PGHOST} -c synchronous_commit=off -c full_page_writes=off" \ + -o "-F -k $${PGHOST} -c synchronous_commit=off -c full_page_writes=off $${PORTABILITY_PG_SETTINGS:-}" \ -w start trap 'runuser -u postgres -- pg_ctl -D "$${PGDATA}" -m fast -w stop || true' EXIT psql -c 'select version()' template1 @@ -155,6 +155,7 @@ steps: - uname -m | grep -E '^(armv7l|armv8l)$' - export PORTABILITY_TIER=armhf-berrie-qemu - export PORTABILITY_CFLAGS="-O2 -Wall -Werror -fno-omit-frame-pointer" + - export PORTABILITY_PG_SETTINGS="-c autovacuum=off" - *prepare-debian - *abi-env - *start-postgresql ----------------------------------------------------------------------- Summary of changes: .woodpecker/portability.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) hooks/post-receive -- PostGIS From git at osgeo.org Sat Aug 1 11:10:43 2026 From: git at osgeo.org (git at osgeo.org) Date: Sat, 1 Aug 2026 11:10:43 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-160-gc1e91f8b1e Message-ID: <20260801181043.5F2951E49F0@trac.osgeo.org> 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 c1e91f8b1e5612e8d7ec50b3a7705cab232103db (commit) via 8c966a0071b95040e96c741e2ee13e977c5d4b40 (commit) from 1df65a1b92af4bd5162d08c5fbc4fa3133ae46c8 (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 c1e91f8b1e5612e8d7ec50b3a7705cab232103db Merge: 1df65a1b92 8c966a0071 Author: Darafei Praliaskouski Date: Sat Aug 1 11:10:36 2026 -0700 Merge pull request 'liblwgeom: validate serialized NURBS invariants' (!640) from Komzpa/postgis:oss-fuzz-4885548695879680 into master Reject malformed GSERIALIZED v2 NURBS payloads before they can reach curve evaluation and bbox calculation. The validator now mirrors the constructor invariants for degree, control-point count, optional weight count, optional knot count, finite positive weights, and finite nondecreasing knots. This fixes the OSS-Fuzz gserialized_from_bytea_fuzzer testcase that reached lwnurbscurve_evaluate via lwgeom_calculate_gbox_cartesian. Affected releases: this is on the unreleased 3.7 development line. The maintained stable branches stable-3.2 through stable-3.6 do not contain the NURBS curve code path, and there is currently no stable-3.7 branch to backpatch. Validation: - clang ASAN focused build: ./configure CC=clang CXX=clang++ --without-raster --without-topology --without-sfcgal CFLAGS="-g3 -O0 -fno-omit-frame-pointer -fsanitize=address" CXXFLAGS="-g3 -O0 -fno-omit-frame-pointer -fsanitize=address" LDFLAGS="-fsanitize=address" - ./liblwgeom/cunit/cu_tester "serialization/deserialization v2" ? 16 passed, 0 failed, 462 asserts - ./liblwgeom/cunit/cu_tester test_gserialized2_malformed_nurbs_degree ? 9 asserts passed - tmp-fuzz-out/gserialized_from_bytea_fuzzer clusterfuzz-testcase-minimized-gserialized_from_bytea_fuzzer-4885548695879680 ? exit 0 Credit to OSS-Fuzz: https://oss-fuzz.com/testcase?key=4885548695879680 Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/640 commit 8c966a0071b95040e96c741e2ee13e977c5d4b40 Author: Darafei Praliaskouski Date: Sat Aug 1 22:07:06 2026 +0400 liblwgeom: validate serialized NURBS invariants Reject malformed GSERIALIZED v2 NURBS curves before deserialization can hand inconsistent degree, point, weight, or knot counts to curve evaluation and bbox calculation. Credit to OSS-Fuzz: https://oss-fuzz.com/testcase?key=4885548695879680 diff --git a/NEWS b/NEWS index 34c494e701..1443dee89a 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ These are only changes since 3.7.0beta1. * Bug Fixes * + - [liblwgeom] Reject malformed GSERIALIZED NURBS before curve + evaluation (Darafei Praliaskouski) - Make the computed-columns regression test assert the query plan instead of racing two stopwatches, so it no longer fails at random under CI load (Darafei Praliaskouski) diff --git a/liblwgeom/cunit/cu_gserialized2.c b/liblwgeom/cunit/cu_gserialized2.c index 44be675094..c02c5b2f83 100644 --- a/liblwgeom/cunit/cu_gserialized2.c +++ b/liblwgeom/cunit/cu_gserialized2.c @@ -527,6 +527,8 @@ gserialized2_from_hexbytes(const char *hex) return g; } +static void assert_gserialized2_malformed_rejected(GSERIALIZED *g); + static void test_gserialized2_malformed_collection_count(void) { @@ -545,6 +547,28 @@ test_gserialized2_malformed_collection_count(void) lwfree(g); } +static void +test_gserialized2_malformed_nurbs_degree(void) +{ + LWGEOM *lwgeom = lwgeom_from_wkt("NURBSCURVE(2, (0 0, 1 1, 2 0))", LW_PARSER_CHECK_NONE); + GSERIALIZED *g; + uint32_t *payload; + + CU_ASSERT_PTR_NOT_NULL_FATAL(lwgeom); + g = gserialized2_from_lwgeom(lwgeom, NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL(g); + + payload = (uint32_t *)gserialized2_get_geometry_p(g); + CU_ASSERT_EQUAL(payload[0], NURBSCURVETYPE); + CU_ASSERT_EQUAL(payload[1], 3); + payload[2] = 3; /* Three control points cannot support a degree-3 curve. */ + + assert_gserialized2_malformed_rejected(g); + + lwgeom_free(lwgeom); + lwfree(g); +} + static void assert_gserialized2_malformed_rejected(GSERIALIZED *g) { @@ -658,6 +682,7 @@ void gserialized2_suite_setup(void) PG_ADD_TEST(suite, test_gserialized2_extended_flags); PG_ADD_TEST(suite, test_gserialized2_peek_first_point); PG_ADD_TEST(suite, test_gserialized2_malformed_collection_count); + PG_ADD_TEST(suite, test_gserialized2_malformed_nurbs_degree); PG_ADD_TEST(suite, test_gserialized2_malformed_declared_size); PG_ADD_TEST(suite, test_gserialized2_malformed_short_allocation); PG_ADD_TEST(suite, test_gserialized2_wkb_roundtrip_float_rounded_box); diff --git a/liblwgeom/gserialized2.c b/liblwgeom/gserialized2.c index 813098c77a..7a89593c6d 100644 --- a/liblwgeom/gserialized2.c +++ b/liblwgeom/gserialized2.c @@ -68,6 +68,77 @@ static int gserialized2_read_gbox_p(const GSERIALIZED *g, GBOX *gbox); static int gserialized2_payload_bounds(const GSERIALIZED *g, uint8_t **start, uint8_t **end); static int gserialized2_validate_geometry_buffer(uint8_t *data_ptr, uint8_t *data_end, lwflags_t lwflags, size_t *size); +static int +gserialized2_validate_nurbs(uint32_t npoints, + uint32_t degree, + uint32_t nweights, + uint32_t nknots, + const double *weights, + const double *knots) +{ + uint32_t i; + size_t expected_nknots; + + if (degree < 1 || degree > 10) + { + lwerror("NURBS: degree %u outside valid range [1,10]", degree); + return LW_FAILURE; + } + + if (npoints == 0) + { + if (nweights != 0 || nknots != 0) + { + lwerror("NURBS: empty curve cannot declare weights or knots"); + return LW_FAILURE; + } + return LW_SUCCESS; + } + + if (npoints < degree + 1) + { + lwerror("NURBS: npoints (%u) must be at least degree + 1 (%u)", npoints, degree + 1); + return LW_FAILURE; + } + + if (nweights > 0 && nweights != npoints) + { + lwerror("NURBS: nweights (%u) must equal number of control points (%u)", nweights, npoints); + return LW_FAILURE; + } + + expected_nknots = (size_t)npoints + degree + 1; + if (nknots > 0 && nknots != expected_nknots) + { + lwerror("NURBS: nknots (%u) must equal npoints + degree + 1 (%zu)", nknots, expected_nknots); + return LW_FAILURE; + } + + for (i = 0; i < nweights; i++) + { + if (!isfinite(weights[i]) || weights[i] <= 0.0) + { + lwerror("NURBS: weight[%u] = %g must be finite and > 0", i, weights[i]); + return LW_FAILURE; + } + } + + for (i = 1; i < nknots; i++) + { + if (!isfinite(knots[i]) || knots[i] < knots[i - 1]) + { + lwerror("NURBS: knot[%u] = %g must be finite and >= knot[%u] = %g", + i, + knots[i], + i - 1, + knots[i - 1]); + return LW_FAILURE; + } + } + + return LW_SUCCESS; +} + static size_t gserialized2_buffer_size(const GSERIALIZED *g) { @@ -441,14 +512,16 @@ gserialized2_validate_geometry_buffer(uint8_t *data_ptr, uint8_t *data_end, lwfl } case NURBSCURVETYPE: { - uint32_t nweights, nknots; + uint32_t degree, nweights, nknots; size_t weight_bytes, knot_bytes, point_bytes; + const uint8_t *weights_ptr, *knots_ptr; consumed = 6 * sizeof(uint32_t); if (!gserialized2_range_available(data_ptr, data_end, consumed)) { lwerror("%s: GSERIALIZED NURBS header exceeds payload size", __func__); return LW_FAILURE; } + degree = gserialized2_read_uint32_checked(data_ptr + 2 * sizeof(uint32_t), data_end, "NURBS degree"); nweights = gserialized2_read_uint32_checked(data_ptr + 3 * sizeof(uint32_t), data_end, "NURBS weight count"); nknots = @@ -468,6 +541,12 @@ gserialized2_validate_geometry_buffer(uint8_t *data_ptr, uint8_t *data_end, lwfl lwerror("%s: GSERIALIZED NURBS size overflows", __func__); return LW_FAILURE; } + weights_ptr = data_ptr + 6 * sizeof(uint32_t); + knots_ptr = weights_ptr + weight_bytes; + if (gserialized2_validate_nurbs( + count, degree, nweights, nknots, (const double *)weights_ptr, (const double *)knots_ptr) == + LW_FAILURE) + return LW_FAILURE; break; } @@ -2219,6 +2298,17 @@ lwnurbscurve_from_gserialized2_buffer(uint8_t *data_ptr, lwflags_t lwflags, size /* Skip 4-byte pad to align following doubles (weights/knots/coords) */ data_ptr += sizeof(uint32_t); + if (gserialized2_validate_nurbs(npoints, + degree, + nweights, + nknots, + (const double *)data_ptr, + (const double *)(data_ptr + sizeof(double) * nweights)) == LW_FAILURE) + { + lwfree(curve); + return NULL; + } + /* * VARIABLE SECTION 1: Read weight values (if any) * ----------------------------------------------------------------------- Summary of changes: NEWS | 2 + liblwgeom/cunit/cu_gserialized2.c | 25 +++++++++++ liblwgeom/gserialized2.c | 92 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 118 insertions(+), 1 deletion(-) hooks/post-receive -- PostGIS From git at osgeo.org Sat Aug 1 14:45:30 2026 From: git at osgeo.org (git at osgeo.org) Date: Sat, 1 Aug 2026 14:45:30 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-162-gb53607dc54 Message-ID: <20260801214531.836C91B4D44@trac.osgeo.org> 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 b53607dc54ae72020767e27c09c7ca800921f7f1 (commit) via dd94d63816748a6107945fe61851593a4f285fbd (commit) from c1e91f8b1e5612e8d7ec50b3a7705cab232103db (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 b53607dc54ae72020767e27c09c7ca800921f7f1 Merge: c1e91f8b1e dd94d63816 Author: Darafei Praliaskouski Date: Sat Aug 1 14:45:24 2026 -0700 Merge pull request 'Move retired Trac guidance to canonical documentation' (!637) from Komzpa/postgis:ai/trac-final-22-migration-20260731 into master Move useful material out of the remaining non-Notes Trac wiki pages by refactoring it into the existing PostGIS documentation that owns each topic. * document raster coverage semantics, table arrangements, constraints, and indexed raster/vector analysis in the raster manual and existing raster internals page * retain the two diagrams that explain the maintained coverage and raster-table models, without importing obsolete architecture diagrams or draft specifications * preserve the durable raster/vector analysis choices in the manual: candidate tile selection, raster-space aggregation versus area-weighted partial cells, and the tile-size trade-off * keep genuinely actionable unimplemented ideas in the existing development TODO instead of a historical specification or migration ledger * add practical examples for closest-point insertion, ellipse construction, DMS conversion, and desktop GIS query layers to their existing manual pages * credit the early raster contributors, diagrams, tutorial, and funding in the manual credits * remove the dead `WKTRaster` URL from raster source headers and replace other obsolete wiki pointers with their maintained owners The ISO 19125 draft review does not belong in PostGIS API policy, so this change removes the previously imported standards-review checklist. The original review remains a dated historical note in [PostGIS Trac](https://trac.osgeo.org/postgis/wiki/Notes/2010/ISO19125DraftReview) rather than being imported into another repository. This branch does not add a wiki archive, migration map, standalone project history, historical tutorial, or parallel raster API. Obsolete design records remain historical; current behavior stays in the manual, source, RFCs, and maintained developer documentation. `Notes/*` remains on Trac. The companion website cleanup is [postgis/postgis.net pull request 27](https://gitea.osgeo.org/postgis/postgis.net/pulls/27). Validation: * `git diff --check upstream/master` * `xmllint --noout doc/postgis.xml` * `make -C doc check` (39 DocBook QA tests, schema and Relax NG validation, and generated HTML checks) * verified that tracked source no longer references the removed history pages, archive-only assets, or `trac.osgeo.org/postgis/wiki/WKTRaster` Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/637 commit dd94d63816748a6107945fe61851593a4f285fbd Author: Darafei Praliaskouski Date: Sun Aug 2 01:11:06 2026 +0400 doc: move retired wiki guidance to canonical owners diff --git a/LICENSE.TXT b/LICENSE.TXT index b862867db1..403c98bb6d 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -37,6 +37,17 @@ These are under a BSD-3-Clause license - refer to doc/xsl/LICENSE file -- liblwgeom/lookup3.c is released under Public Domain by Bob Jenkins, May 2006. +-- Files under macros/ are imported third-party build macros. Where a file +contains a copyright, copying notice, or special exception, that file notice is +authoritative for redistribution. macros/gtk-2.0.m4 contains Owen Taylor's +AM_PATH_GTK_2_0 macro and currently carries author attribution but no embedded +copying notice. + +-- extras/ogc_test_suite/1_schema.sql and 2_queries.sql are adapted from the +1998 Open GIS Consortium Simple Features conformance test suite. The files +retain the OGC copyright and adaptation notice, which refers to a separate OGC +license that is not included in this source tree. + -- extensions/address_goecoder is released under MIT License by Stephen Woodbridge & Walter Bruce Sinclair, 2006-2013 -- deps/ryu (see LICENSE in folder) is released under the Apache 2.0 license; @@ -61,6 +72,6 @@ Data used in documentation falls in one of the following categories - data or snapshots generated by community - many images autogenerated by PostGIS documentation generator (which utilizes ImageMagick) as described - http://trac.osgeo.org/postgis/wiki/DevWikiDocNewFeature + https://postgis.net/development/docs/manual/ - PostGIS raster output functions such as the ST_AsPNG etc. - raster/vector data from MassGIS: http://www.mass.gov/mgis/laylist.htm diff --git a/SECURITY.md b/SECURITY.md index 43116e9ba6..bcd561752e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -36,6 +36,6 @@ Upon receiving a vulnerability report, the security team will: including the fix. Please note that issues in unsupported releases -(https://trac.osgeo.org/postgis/wiki/UsersWikiPostgreSQLPostGIS) +(https://postgis.net/development/compatibility/) will likely not be addressed, and issues with third party dependencies need to be reported to the team maintaining them. diff --git a/doc/credits.xml b/doc/credits.xml index dbc890e93b..8f3517223d 100644 --- a/doc/credits.xml +++ b/doc/credits.xml @@ -212,6 +212,38 @@ +
+ PostGIS Raster Origins + PostGIS raster discussions date to 2002 and included early PGCHIP + experiments. Xing Lin developed the geotiff2pgraster + PGRaster prototype during Google Summer of Code 2007. The WKT Raster project + began in 2008, Jorge Ar?valo developed the first GDAL driver prototype during + Google Summer of Code 2009, and the 2010 FOSS4G code sprint agreed to make WKT + Raster the PostGIS raster type. Raster support shipped as part of PostGIS 2.0 + in 2012. + The early implementation team included Pierre Racine, Mateusz Loskot, + Sandro Santilli, Jorge Ar?valo, Bborie Park, David Zwarg, and Regina Obe. + Their work established the raster type, loader, GDAL integration, + raster/vector operations, map algebra, documentation, and testing that became + the current raster subsystem. + Other recorded contributions include Jeff Adams's early sprint work, + Qing Liu's raster distance analysis, Maur?cio Carvalho Mathias de Paulo's + QGIS raster plugin and related paper with Lubia Vinhas, and Ignacio Brodin's + gvSIG raster plugin and presentation with Jorge Sanz. Bryce L. Nordgren + created early raster coverage and seamless-architecture diagrams. Pierre + Racine wrote the original raster/vector tutorial and + created its walkthrough and early API diagrams. + The historical project planning record credits Steve Cumming and + Universit? Laval with funding Pierre Racine's work from June 2008 through + July 2012; Martin Daly and Cadcorp with funding about six months of Mateusz + Loskot's work through June 2009; Tyler Erickson and Michigan Tech Research + Institute with a $1,200 USD contribution; Miguel Lizondo and Deimos Space + with support for about two years of Jorge Ar?valo's work through June 2011; + and the Center for + Vectorborne Diseases at UC Davis with funding Bborie Park's work from March + 2010 through July 2012. +
+
Other Contributors @@ -303,6 +335,7 @@ Haribabu Kommi Harrissou Sant-anna Havard Tveite + Ignacio Brodin IIDA Tetsushi Ingvild Nystuen Jackie Leng @@ -342,6 +375,7 @@ Luca S. Percich Lucas C. Villa Real Ludovic Hirlimann + Lubia Vinhas Maksim Korotkov Manuel Morillo Maria Arias de Reyna @@ -352,6 +386,7 @@ Matt Amos Matt Bretl Matthias Bay + Maur?cio Carvalho Mathias de Paulo Maxim Kochetkov Maxime Guillaud Maxime van Noppen @@ -375,6 +410,7 @@ Pawel Ostrowski Peter Nguyen Pierre Cardinal + Qing Liu Rafal Magda Ralph Mason R?mi Cura @@ -389,6 +425,7 @@ Shinichi Sugiyama Shoaib Burq Silvio Grosso + Simon Greener Stefan Corneliu Petrea Steffen Macke Stepan Kuzmin @@ -409,6 +446,7 @@ Vincent Mora Vincent Picavet Volf Tom?? + Xing Lin Yoichi Kayama Yuri Astrakhan Zuo Chenwei diff --git a/doc/development/internals/images/raster-storage/coverage-concepts.png b/doc/development/internals/images/raster-storage/coverage-concepts.png new file mode 100644 index 0000000000..0f3bb3a7f2 Binary files /dev/null and b/doc/development/internals/images/raster-storage/coverage-concepts.png differ diff --git a/doc/development/internals/images/raster-storage/raster-table-arrangements.gif b/doc/development/internals/images/raster-storage/raster-table-arrangements.gif new file mode 100644 index 0000000000..5e78fc3249 Binary files /dev/null and b/doc/development/internals/images/raster-storage/raster-table-arrangements.gif differ diff --git a/doc/development/internals/raster-gdal-driver.md b/doc/development/internals/raster-gdal-driver.md index 037053ee93..819716197e 100644 --- a/doc/development/internals/raster-gdal-driver.md +++ b/doc/development/internals/raster-gdal-driver.md @@ -11,9 +11,7 @@ developer documentation here should explain the boundary and the PostGIS-side contracts rather than republish old GDAL driver working notes as current code documentation. -The old Trac `WKTRaster/GDALDriverSpecificationWorking`, -`WKTRaster/ThirdPartySupport`, and `WKTRasterGSoC` pages are useful mostly as -provenance for that boundary. Their current lessons are: +The current lessons for that boundary are: * GDAL opens PostGIS raster data through the external `PostGISRaster` driver, not through code maintained in this repository. diff --git a/doc/development/internals/raster-storage.md b/doc/development/internals/raster-storage.md index 02661e6e8f..376916b3de 100644 --- a/doc/development/internals/raster-storage.md +++ b/doc/development/internals/raster-storage.md @@ -1,5 +1,5 @@ --- -title: "Raster storage and WKB" +title: "Raster storage, coverages, and WKB" date: 2026-06-26 weight: 70 geekdocHidden: false @@ -15,11 +15,113 @@ PostGIS Raster has three related representations that are easy to confuse: * The on-disk PostgreSQL value is the serialized form built by `rt_raster_serialize()` and read by `rt_raster_deserialize()`. -The old Trac `WKTRaster/RFC/RFC1_V0SerialFormat`, -`WKTRaster/RFC/RFC2_V0WKBFormat`, `WKTRaster/RFC/RFC3_V1SerialFormat`, and -`WKTRaster/Specification*` pages describe early versions of those formats. -They are useful as implementation history, but current work should start from -the source files named below. +Early design records describe prior versions of those formats. They are useful +as implementation history, but current work should start from the source files +named below. + +## Coverage Model And Table Arrangements + +A coverage is a mapping from a domain, usually locations and sometimes time, to +a consistent range of values. Conceptually it provides an evaluation operation: + +```text +value = evaluate(location [, time]) +``` + +Some coverages also support an inverse operation, such as returning an isotherm +for a requested temperature. The mapping is separate from its storage: it may +be calculated, interpolated from observations, stored as geometry/value rows, +or stored as cells in one or more rasters. + +![Coverage concepts and PostGIS representations](images/raster-storage/coverage-concepts.png) + +### Continuous And Discrete Coverages + +A continuous coverage can calculate a value for every location. Solar elevation +as a function of location and time is one example. An interpolated temperature +surface is another: the observations are discrete, but an interpolation method +such as inverse-distance weighting evaluates locations between weather +stations. In PostGIS this model can be expressed as a function over a geometry +and, where needed, a timestamp. + +A discrete coverage is backed by a collection whose values change at item or +cell boundaries. It commonly needs operations equivalent to finding the nearest +item, selecting items in a region, and listing the collection. Vector tables +and rasters are different representations of this model; the coverage is the +mapping and access contract, not merely the table or raster value that stores +its observations. + +### Table-Backed Vector Coverages + +A table can back a vector coverage when one geometry column supplies the domain +and one or more other columns supply the range. Each row associates the entire +geometry with that row's selected values. The same table can therefore support +different coverages by choosing different range columns. If the table has more +than one geometry column, the coverage must explicitly choose the domain +column. + +The vector range need not be numeric or primitive: it can include text or +another spatial value. It must still have a consistent meaning and type wherever +the coverage is defined. + +This row relationship cannot associate different array elements or attributes +with separate parts of one geometry. Such associations need separate rows or a +more explicit value type. + +### Raster Coverage Semantics + +A raster uses its grid and georeference to associate cell locations with one or +more numeric band values. This has several consequences that differ from a +geometry column: + +1. One raster value contains many location/value associations. Other columns in + the same row describe the raster as a whole; they do not attach separate + values to its individual cells. +2. A PostgreSQL `raster` column alone does not guarantee that different rows + have compatible SRIDs, alignment, dimensions, band counts, pixel types, or + NODATA conventions. A logical tiled coverage must enforce the invariants it + requires through constraints and controlled loading. +3. Rendering or analysing a raster coverage uses the raster bands. Other row + columns can identify, group, or filter images and tiles, but are not bands in + the rendered coverage. +4. A table-level lookup is normally two-stage: use the raster hull and spatial + index to find candidate rows, then inspect the relevant cells and bands in + those raster values. + +A coverage may fit in one raster value and need no table-level tiling. A table +may also legitimately index unrelated rasters, but that does not make all rows +one coverage. + +### Geometry/Value Collections + +The `geomval` composite type makes one geometry and one numeric value +association explicit. `ST_DumpAsPolygons` returns `geomval` rows by grouping +same-valued raster cells into polygons. Those geometries can participate in +ordinary vector operations, but polygonizing many cells is expensive, so +queries should first restrict the raster rows and cells that need conversion. + +A raster column does not by itself say how rows relate to each other. The rows +may be unrelated images, tiles of one logical coverage, separate tiled images, +or rasterized spatial objects. + +![Common raster table arrangements](images/raster-storage/raster-table-arrangements.gif) + +The table arrangement determines which invariants matter: + +* An image warehouse permits unrelated extents, dimensions, alignments, and + overlaps. +* An irregular tiled coverage permits gaps and variable tile dimensions while + treating non-overlapping rows as one logical layer. +* A regular tiled coverage shares alignment and tile dimensions without + overlap; a rectangular regular coverage also fills its extent without gaps. +* Separate tiled images preserve image identity in separate tables or + partitions even when each image is internally regular. +* A raster-object coverage stores rasterized features whose dimensions and + extents may differ or overlap. + +Current PostGIS records common SRID, scale, alignment, band, extent, and +regular-blocking properties through raster constraints and `raster_columns`. +Applications still need to define any stronger relationship between rows. ## Serialized PostgreSQL Value diff --git a/doc/development/internals/spatial-collections.md b/doc/development/internals/spatial-collections.md index fe7f5c1aeb..f6aaf28f7f 100644 --- a/doc/development/internals/spatial-collections.md +++ b/doc/development/internals/spatial-collections.md @@ -5,14 +5,10 @@ weight: 40 geekdocHidden: false --- -The historical `DevWikiSpatialCollectionTutorial` page described an internal -`SPATIAL_COLLECTION` abstraction intended to erase the difference between -vector geometries and rasters. That abstraction is not present in the current -source tree: there are no remaining `sc_create_*`, `SPATIAL_COLLECTION`, or -`sc_sampling_engine` implementation paths. - -The useful idea is still worth keeping: PostGIS has two kinds of collection -work that should not be confused. +PostGIS does not implement a shared `SPATIAL_COLLECTION` abstraction for +vector geometries and rasters: there are no `sc_create_*`, +`SPATIAL_COLLECTION`, or `sc_sampling_engine` implementation paths. It has two +kinds of collection work that should not be confused. * Geometry collections are real geometry values: `MULTI*`, `GEOMETRYCOLLECTION`, curves, TINs, and polyhedral surfaces. @@ -20,8 +16,7 @@ work that should not be confused. and overlay workflows that move values between rasters and geometries. Current code keeps those areas separate. When changing collection behavior, -check which side of that boundary the function is on before reusing examples -from the old spatial-collection tutorial. +check which side of that boundary the function is on. ## Geometry Collections @@ -117,7 +112,7 @@ or SQL `NULL`. Those are four different questions. ## Raster/Vector Crossings -The old spatial-collection abstraction tried to model both raster and vector +A shared raster/vector abstraction would need to model both raster and vector objects as things that can answer: 1. Does point `P` belong to this object? @@ -143,9 +138,8 @@ rows are intersected with the input geometry using the normal geometry `ST_Intersection`. Raster-returning variants and clipping paths instead construct or modify raster cells. -This is close to the old tutorial's intent, but the implementation boundary is -different. There is no single current "spatial collection" object that a caller -wraps around a raster or geometry and samples through a shared interface. +There is no single current "spatial collection" object that a caller wraps +around a raster or geometry and samples through a shared interface. ## Practical Guidance @@ -158,7 +152,7 @@ When touching code near this topic: C files, especially `raster/rt_pg/rtpostgis.sql.in`, `raster/rt_pg/rtpg_geometry.c`, `raster/rt_pg/rtpg_mapalgebra.c`, and `raster/rt_pg/rtpg_spatial_relationship.c`. -3. Do not revive the old `SPATIAL_COLLECTION` API without a new design review. +3. Do not introduce a `SPATIAL_COLLECTION` API without a design review. Current code has evolved around explicit SQL functions rather than a shared internal wrapper. 4. Preserve the distinction between container operations and topology @@ -167,6 +161,3 @@ When touching code near this topic: 5. Preserve the distinction between raster values and geometry membership. Raster workflows often carry a numeric `geomval`; geometry collections do not have a generic per-point value vector. - -The old tutorial remains useful as design history, but maintained developer -documentation should describe the current implementation boundary first. diff --git a/doc/development/release/api.md b/doc/development/release/api.md index ee984937fc..7dac30387d 100644 --- a/doc/development/release/api.md +++ b/doc/development/release/api.md @@ -32,37 +32,3 @@ documented SQL expression. When a setting is still the right interface, document the default, scope, supported values, and upgrade impact in the manual, and add regression coverage for the default behavior. - -## Standards Conformance - -When a patch changes constructors, parsers, serializers, predicates, -measurements, validity, simplicity, overlay, or dimensional behavior, review -the change against the standards and PostGIS extensions that define the -current public contract. - -Check the user-visible behavior against the relevant OGC/SFS, ISO 19125, -SQL/MM, WKT, WKB, EWKT, EWKB, SRID, and SQL/MM type-code expectations. PostGIS -also has deliberate extensions and historical compatibility behavior, so do -not normalize behavior only because one standard spelling exists. Document -the chosen behavior in the manual when it can surprise users. - -Specific review points: - -* Keep empty-geometry behavior documented and tested for constructors, - predicates, validity checks, accessors, measurements, and overlay or - constructive functions. See - [Empty geometry semantics](../internals/empty-geometry.md) for the current - implementation map. -* Be explicit when a spatial predicate, overlay, or measurement intentionally - uses 2D semantics for higher-dimensional input. Add or point to a separate - 3D function when users need true 3D behavior. -* Keep validity and simplicity documentation explicit about geometry-type - criteria, repeated points, invalid input handling, parser acceptance, and - repair guidance. -* Treat precision-model changes as API changes. Current ordinary geometries do - not carry inferred precision metadata; explicit overlay grid size, topology - precision, MVT quantization, and tolerance arguments are separate API - surfaces. See - [Precision and tolerance internals](../internals/precision-tolerance.md). -* When changing WKT/WKB parsing or output, test OGC, ISO, SQL/MM, EWKT, EWKB, - SRID, empty-geometry, dimensionality, and type-code compatibility together. diff --git a/doc/development/todo.md b/doc/development/todo.md index 8b5a2c1836..597258a4ce 100644 --- a/doc/development/todo.md +++ b/doc/development/todo.md @@ -5,18 +5,16 @@ weight: 35 geekdocHidden: false --- -This page records high-level development ideas that survived the Trac/wiki -documentation migration but are not accepted designs, release blockers, or -scheduled work. Move an item to a Trac ticket, design document, or pull request -when someone takes ownership of it. +This page records high-level development ideas that are not accepted designs, +release blockers, or scheduled work. Move an item to a ticket, design document, +or pull request when someone takes ownership of it. ## Geometry And Precision -* Investigate polygon partitioning below a maximum vertex budget. The old - `SomeSplitting` discussion called this a `SplitToMaxN`-style operation: - produce area-covering polygon pieces without adding unnecessary segment split - points. A future design should consider tessellation plus a GiST - picksplit-inspired partitioning strategy. +* Investigate polygon partitioning below a maximum vertex budget: produce + area-covering polygon pieces without adding unnecessary segment split points. + A future design should consider tessellation plus a GiST picksplit-inspired + partitioning strategy. * Investigate PostGIS precision-model policy for ordinary geometries. Decide whether inferred or metadata-backed precision should ever exist outside topology-specific precision and operation-local tools such as overlay @@ -29,15 +27,16 @@ when someone takes ownership of it. dimensions, validity flags, typmod-only compact point storage, and complete mutable `liblwgeom` point-array and collection APIs. Current `GSERIALIZED` storage, typmods, TWKB output, and PostGIS 3 flag changes cover only parts of - this historical discussion. Source provenance: `PostGIS3` and - `DevelopmentDiscussion` in the Trac import, plus the serialization discussion - in `UsersWikiSprint2009Notes`; local import commit `7fee744c33af`. + this design space. * Investigate sparse-polygon containment performance. Current PostGIS has - selectivity estimators and user-visible tools such as `ST_Subdivide`, but the - old wishlist asked for better selectivity or decomposition strategies for - large sparse polygons where the bounding box is a poor proxy for occupied - area. Source provenance: `UsersWikiWishList`; local import commit - `7fee744c33af`. + selectivity estimators and user-visible tools such as `ST_Subdivide`, but + better selectivity or decomposition strategies could help with large sparse + polygons where the bounding box is a poor proxy for occupied area. +* Investigate bounded-memory spatial pipelines for very large inputs, such as + an index-ordered feature stream that can emit completed output while noding + lines, polygonizing coverages, triangulating point sets, or performing + unions. Current set-returning functions and aggregates own the operation + semantics, but there is no general streaming API with that contract. ## Indexing And Planner @@ -47,19 +46,14 @@ when someone takes ownership of it. summaries for complex geometries, and adding nested boxes for `GEOMETRYCOLLECTION` trees. Current GiST/SP-GiST support and PostgreSQL 15+ sort support cover adjacent work, but not these storage/index-tuple designs. - Source provenance: `PostGIS3`, with SRID mismatch context linked there to - ; local import commit - `7fee744c33af`. * Investigate geography indexing based on S2-style cells or another cell-based strategy, including whether a fast geography `ST_Intersects` GIN index is - possible and useful. Current geography indexes remain GiST-oriented. Source - provenance: `PostGIS3`; local import commit `7fee744c33af`. + possible and useful. Current geography indexes remain GiST-oriented. * Investigate PostgreSQL-core-dependent spatial index build and clustering improvements, such as building GiST pages from spatially adjacent tuple runs or preserving heap clustering by inserting near index sibling tuples. Current PostGIS sort support addresses part of index build ordering, but these ideas - remain broader PostgreSQL storage/index research. Source provenance: - `PostGIS3`; local import commit `7fee744c33af`. + remain broader PostgreSQL storage/index research. ## Backend Libraries And Robustness @@ -68,67 +62,37 @@ when someone takes ownership of it. PostGIS point arrays, moving suitable algorithms such as build-area or validity repair into upstream GEOS/SFCGAL/CGAL, and adding LWGEOM adapters to external geometry-library types. Current SFCGAL/GEOS integration covers many - operations, but not these ownership and architecture changes. Source - provenance: `PostGIS3` and `DevelopmentDiscussion`; local import commit - `7fee744c33af`. + operations, but not these ownership and architecture changes. * Investigate stronger robustness guarantees for predicates and overlays. The old planning notes proposed validity-aware guarantees, cached validity state, fallback or retry through another backend library after robustness failures, and empirical performance/cost frameworks for regression and planner-cost testing. Current GEOS/SFCGAL behavior, validity functions, and regression - suites do not make this a settled design. Source provenance: `PostGIS3` and - `DevelopmentDiscussion`; local import commit `7fee744c33af`. + suites do not make this a settled design. * Investigate curve-completeness policy: which curve operations should become complete in core, which should linearize explicitly, and which should remain - unsupported until GEOS/SFCGAL or another backend owns the operation. Source - provenance: `DevelopmentDiscussion`; local import commit `7fee744c33af`. + unsupported until GEOS/SFCGAL or another backend owns the operation. ## Raster * Investigate raster density-surface generation from point or line coverages. - The historical `GoogleSummerCode` page proposed `ST_AsDensity`: count point or - line features into raster pixels and then apply a smoothing filter using + Count features into raster pixels and optionally smooth the result with neighborhood map algebra. Current PostGIS has `ST_InterpolateRaster` for interpolation from input points, but this density-surface workflow is not a - maintained first-class raster API. Trac provenance: the item was already - present in `GoogleSummerCode` version 1, authored by `robe` on - 2013-04-02 15:34:22 -0700. Local import provenance: commit `7fee744c33af` - imported the source Trac page into this repository on - 2026-06-17 07:58:14 +0400. -* Investigate internal sub-tiling for very large rasters. The historical - `WKTRaster/SpecificationWorking03` roadmap described this as sub-tiling of - rasters for PostGIS 3.0, or possibly a new raster type: rewrite the raster - type so big rasters stored in one row, up to the PostgreSQL 1GB datum limit, - are internally tiled and quickly accessed. Current PostGIS has table-level - raster tiling, out-db rasters, and ordinary PostgreSQL TOAST storage, but no - currently open pull request checked on 2026-06-28 owns this one-row - internal-tiling storage redesign. Trac provenance: version 211 was the first - version found with the sub-tiling item, authored by `pracine` on - 2012-07-25 06:42:29 -0700. Local import provenance: commit `7fee744c33af` - imported the source Trac page into this repository on - 2026-06-17 07:58:14 +0400. -* Investigate first-class raster coverage validation helpers. The historical - `WKTRaster/SpecificationWorking03` roadmap introduced this as Objective FV.20: - being able to determine topological characteristics of a coverage, with - proposed helpers such as `ST_HasOverlaps`, `ST_HasGaps`, - `ST_HasTileSameSize`, `ST_HasTileAligned`, and `ST_IsRegularlyTiled`. - Adjacent open raster pull requests exist for tiling, alignment, constraints, - and overviews, but no currently open pull request checked on 2026-06-28 owns - this coverage-validation proposal. Trac provenance: version 173 was the first - version found with the objective, authored by `pracine` on - 2011-11-11 07:51:13 -0800. Local import provenance: commit `7fee744c33af` - imported the source Trac page into this repository on - 2026-06-17 07:58:14 +0400. -* Investigate named raster bands. The historical - `WKTRaster/SpecificationWorking03` roadmap introduced this as Objective FV.17: - being able to refer to a band by textual name, later described as "band by - name" for PostGIS 3.0. It proposed an 8-character band name in the base raster - WKB format, importer support for assigning band names, and overloads so raster - functions can address bands by name. Trac provenance: version 31 was the first - version found with the objective, authored by `pracine` on - 2010-09-21 06:53:05 -0700. Local import provenance: commit `7fee744c33af` - imported the source Trac page into this repository on - 2026-06-17 07:58:14 +0400. + maintained first-class raster API. +* Investigate internal sub-tiling for very large raster values. A single raster + datum can approach PostgreSQL's 1 GB value limit, while current PostGIS tiles + only at the table-row level and relies on ordinary TOAST storage inside one + value. A future design would need fast window access without changing the + public raster semantics or duplicating table-level tiling. +* Investigate first-class validation for tiled raster coverages, including + overlap, gap, common tile-size, alignment, and regular-tiling checks. Current + raster constraints and `ST_SameAlignment` cover portions of this model, but + there is no complete maintained function family for validating a selected + coverage as a whole. +* Investigate named raster bands. A design must cover on-disk and WKB storage, + loader assignment, duplicate and missing names, upgrades, and overloads that + address a band by name without weakening existing integer-band APIs. * Investigate first-class raster distance surfaces, historically proposed as `ST_EuclideanDistance` for nearest-source distance rasters and `ST_CostDistance` for cost-weighted distance over a cost raster. Compare that @@ -136,10 +100,7 @@ when someone takes ownership of it. downstream processing. * Investigate weighted raster summary/statistics functions beyond the existing weighted map-algebra masks and ordinary `ST_SummaryStats` / - `ST_SummaryStatsAgg` aggregates. The historical sprint notes kept this as an - open raster analysis idea after the core statistics aggregates existed. - Source provenance: `DevFOSS4GCodeSprintNotes`; local import commit - `7fee744c33af`. + `ST_SummaryStatsAgg` aggregates. ## 3D And Output Formats @@ -149,14 +110,11 @@ when someone takes ownership of it. union, and difference. Historical notes still leave broader questions around 3D validity semantics, point-in-polyhedra or 3D relationship models, centroid behavior, line-of-sight or visibility APIs, and interchange behavior - that should be either designed or explicitly declared out of scope. Source - provenance: `DevelopmentDiscussion`, `DevFOSS4GCodeSprintNotes`, and - `UsersWikiSprint2009Notes`; local import commit `7fee744c33af`. -* Investigate richer `ST_AsKML` output metadata. The old wishlist asked for KML + that should be either designed or explicitly declared out of scope. +* Investigate richer `ST_AsKML` output metadata, including KML `extrude`, `tessellate`, and altitude-mode support. Current `ST_AsKML` signatures accept geometry or geography, precision, and namespace prefix, and - current KML parsing code explicitly does not handle `kml:extrude`. Source - provenance: `UsersWikiWishList`; local import commit `7fee744c33af`. + current KML parsing code explicitly does not handle `kml:extrude`. ## Extension Packaging @@ -164,49 +122,23 @@ when someone takes ownership of it. installing PostGIS into a dedicated `postgis` schema, then later marked it as lower priority because the core extensions are not movable. Current `postgis`, `postgis_raster`, and `postgis_topology` extension control files - remain `relocatable = false`, while `postgis_sfcgal` is relocatable. Source - provenance: `PostGIS3` and `UsersWikiWishList`; local import commit - `7fee744c33af`. + remain `relocatable = false`, while `postgis_sfcgal` is relocatable. ## Topology -* Investigate topology-aware shapefile loader and dumper workflows. The - historical `GoogleSummerCode` page proposed loading TopoGeometries directly - with `shp2pgsql`; the later `GoogleSummerCode2022` page expanded this into +* Investigate topology-aware shapefile loader and dumper workflows, including `shp2pgsql`/`pgsql2shp` support for topology elements and TopoGeometries. Current maintained tools include `pgtopo_export` and `pgtopo_import`, and `pgsql2shp` can export ordinary query results, but the shapefile loader/dumper still documents geometry and geography rather than topology - element or TopoGeometry modes. Trac provenance: the original loader idea was - already present in `GoogleSummerCode` version 1, authored by `robe` on - 2013-04-02 15:34:22 -0700; the broader 2022 framing first appeared in - `GoogleSummerCode2022` version 7, authored by `robe` on - 2022-02-19 14:23:10 -0800. Local import provenance: commit `7fee744c33af` - imported both source Trac pages into this repository on - 2026-06-17 07:58:14 +0400. -* Investigate a no-new-primitives mode for `toTopoGeom`. The historical - `GoogleSummerCode` page proposed an extra argument allowing `toTopoGeom` to - fail instead of adding topology primitives when the input cannot be expressed + element or TopoGeometry modes. +* Investigate a no-new-primitives mode for `toTopoGeom`, allowing it to fail + instead of adding topology primitives when the input cannot be expressed using existing edges, nodes, and faces. Current `toTopoGeom` signatures accept geometry, topology/layer or TopoGeometry target, and tolerance, but no - primitive-creation policy flag. Trac provenance: the item was already present - in `GoogleSummerCode` version 1, authored by `robe` on - 2013-04-02 15:34:22 -0700. Local import provenance: commit `7fee744c33af` - imported the source Trac page into this repository on - 2026-06-17 07:58:14 +0400. -* Investigate topology-aware `ST_EstimatedExtent`. The historical - `GoogleSummerCode` page proposed making `ST_EstimatedExtent` recognize a - schema/table/column that refers to a `topology.layer` entry and return a useful - layer extent estimate instead of only reading ordinary geometry/geography - table statistics. Current `ST_EstimatedExtent` is documented and implemented - against geometry/geography columns and table statistics. Trac provenance: the - item was already present in `GoogleSummerCode` version 1, authored by `robe` - on 2013-04-02 15:34:22 -0700. Local import provenance: commit `7fee744c33af` - imported the source Trac page into this repository on - 2026-06-17 07:58:14 +0400. + primitive-creation policy flag. * Investigate topology import paths for OSM and E00-style coverage sources. Historical planning notes asked for an `osm2topology` converter and for importing E00 coverage/topology data. Current in-tree topology tools focus on SQL/topology management and `pgtopo_export` / `pgtopo_import`; OSM, E00, and - routing-specific import design remains unowned. Source provenance: - `PostGIS3` and `UsersWikiWishList`; local import commit `7fee744c33af`. + routing-specific import design remains unowned. diff --git a/doc/introduction.xml b/doc/introduction.xml index dc650b878a..70bfde4b1d 100644 --- a/doc/introduction.xml +++ b/doc/introduction.xml @@ -146,6 +146,17 @@ relationships and index-aware query patterns, and for common performance problems. + + If you are connecting a desktop GIS + Use the client's current database documentation for its + user interface and supported geometry types. For example, the + QGIS + DB Manager lesson covers PostgreSQL connections, table layers, + SQL query layers, import, and export. A query layer should return a + stable unique identifier and a geometry column with a known SRID and + geometry type. Expensive read-only queries can be exposed through a + view or materialized view and indexed as appropriate. + If you need a particular function Use or diff --git a/doc/reference_lrs.xml b/doc/reference_lrs.xml index 2e9db17567..5f09ab1f6e 100644 --- a/doc/reference_lrs.xml +++ b/doc/reference_lrs.xml @@ -332,6 +332,7 @@ FROM (SELECT 'LINESTRING(1 2,4 5,6 7)'::geometry As the_line) As foo; - segment_number | distance | closest_point -----------------+----------+-------------------- - 2 | 0.071 | POINT(15.05 15.05) + segment_number | distance | closest_point | line_with_closest_point +----------------+----------+--------------------+---------------------------------------------------- + 2 | 0.071 | POINT(15.05 15.05) | LINESTRING(0 0,10 10,15.05 15.05,20 20,30 30) See Also - , , , , + , , , , , diff --git a/doc/reference_output.xml b/doc/reference_output.xml index bdb9b938c3..c88d7ecd3f 100644 --- a/doc/reference_output.xml +++ b/doc/reference_output.xml @@ -1078,6 +1078,24 @@ SELECT ST_AsGML( Decimal degrees. SELECT (ST_AsLatLonText('POINT (-3.2342342 -2.32498)', 'D.DDDD degrees C')); 2.3250 degrees S 3.2342 degrees W +To convert parsed degree, minute, and second components to decimal +degrees, apply the cardinal-direction sign explicitly. + + Excessively large values are normalized. SELECT (ST_AsLatLonText('POINT (-302.2342342 -792.32498)')); 72?19'29.928"S 57?45'56.757"E diff --git a/doc/reference_transformation.xml b/doc/reference_transformation.xml index b5f696f27e..9588c23d86 100644 --- a/doc/reference_transformation.xml +++ b/doc/reference_transformation.xml @@ -439,13 +439,34 @@ SELECT ST_Scale('LINESTRING(1 2 3 4,1 1 1 1)', This example scales X and Y values using a false origin. SELECT ST_Scale('LINESTRING(1 1,2 2)', 'POINT(2 2)', 'POINT(1 1)'::geometry); LINESTRING(1 1,3 3) + + This example constructs an ellipse centered at (10, 20), with X radius 8, + Y radius 4, and rotated 30 degrees counter-clockwise. Scaling and rotation use + the center as their origin, so the ellipse keeps both its position and SRID. + WITH params AS ( + SELECT + ST_SetSRID(ST_Point(10, 20), 3857) AS center, + 8.0 AS x_radius, + 4.0 AS y_radius, + radians(30) AS angle +) +SELECT ST_Rotate( + ST_Scale( + ST_Buffer(center, 1, 'quad_segs=32'), + ST_MakePoint(x_radius, y_radius), + center + ), + angle, + center + ) AS ellipse +FROM params; See Also - , + , , , , diff --git a/doc/using_raster_dataman.xml b/doc/using_raster_dataman.xml index f3e78eddd6..eeca120365 100644 --- a/doc/using_raster_dataman.xml +++ b/doc/using_raster_dataman.xml @@ -482,6 +482,104 @@ AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+
+ Raster Coverages and Raster/Vector Analysis + A coverage is a way to interpret spatial data as a mapping from a + domain of locations to a range of + values. Evaluating a coverage means asking for the value at a location; + an inverse query asks for the locations whose values match a condition. + PostGIS does not expose a generic ISO 19123 coverage SQL type, but geometry + tables and raster values provide the building blocks for both directions. + A coverage can be continuous, with values calculated or interpolated + for arbitrary locations, or discrete, with values supplied by stored spatial + objects or grid cells. The coverage model describes how locations map to + values, independently of whether those values come from an equation, a table, + or one or more raster values. A time column or function argument can add a + temporal dimension without changing that distinction. + In a vector coverage, a geometry column supplies the domain and other + columns supply attributes in the range. A vector range can contain text, + numbers, or another spatial value, provided its meaning and type are + consistent wherever the coverage is defined. In a raster, each cell location + is part of the domain and the band values at that cell form the range. Other + columns in the same table row describe the raster value or tile as a whole; + they do not attach separate values to individual cells. + A logical raster coverage may be stored as one raster value or as many + tiles in a table. Tiles that belong to one coverage should have compatible + SRIDs, scales, alignment, band counts, pixel types, and NODATA conventions. + The constraints exposed by record and + validate those properties. + + Raster table arrangements. + A raster column can represent an image warehouse, a tiled coverage, + or a collection of rasterized objects. These arrangements have different + assumptions about tile size, alignment, gaps, and overlaps. PostGIS does + not infer the intended arrangement from the column type alone. + + + + + ArrangementRow relationshipTypical use + + + Image warehouseIndependent rasters; sizes, + alignment, and extents may differ or overlapCataloging + unrelated source images + Irregular tiled coverageOne logical coverage + with gaps allowed, variable tile sizes, and normally no overlapIncremental or + source-driven mosaics + Regular tiled coverageOne alignment and tile + size with no overlap; gaps may remain at the boundary or inside the coverage + Indexed analysis over a large coverage + Rectangular regular coverageEqual aligned + tiles fill a rectangular extent without gaps or overlapsPredictable + block processing and overview generation + Separate tiled imagesEach image is internally + regular but stored in its own table or partitionKeeping + source-image identity and lifecycle separate + Raster-object coverageEach row is a rasterized + feature; extents and sizes may differ and overlapObject + models where cells replace or supplement vector geometry + + + + Use to record common + SRID, scale, alignment, band, extent, and regular-blocking properties, and + use spatial indexes and application constraints for relationships that the + catalog cannot express. + Queries against a tiled coverage normally have two stages: + + Use the raster spatial index and + to select candidate tiles. + Read, clip, aggregate, or vectorize values inside those + tiles with functions such as , + , + , and + . + + returns + rows that pair geometries with cell values. This + allows ordinary geometry overlay and filtering to answer inverse coverage + queries, but polygonizing many cells is usually more expensive than keeping + the operation in raster space. + Choose boundary semantics deliberately. Clipping and aggregating raster + pixels is usually the shorter and faster path. If a partial boundary cell must + contribute in proportion to its covered area, intersect the geometry with the + rows and calculate an area-weighted result in an + appropriate projected coordinate system. That exact partial-cell method costs + more because it vectorizes the selected cells. + Tile size affects both sides of the indexed query: smaller tiles reduce + the amount of raster data inspected for each candidate row, while increasing + row and index overhead. Benchmark representative queries instead of treating + one tile size as a universal default. + For a current end-to-end raster/vector pattern, load and tile data with + , then see the building example in + . It selects intersecting tiles, clips + them to each polygon, and combines per-tile statistics into one result per + feature. For point observations such as animal locations, first buffer the + points in an appropriate projected coordinate system, then apply the same + tile selection, clipping, and aggregation pattern to an elevation or other + continuous raster coverage. +
Raster Catalogs There are two raster catalog views that come packaged with PostGIS. Both views utilize information embedded in the constraints of the raster tables. As a result diff --git a/postgis/lwgeom_geos.c b/postgis/lwgeom_geos.c index 25688680b6..89d0501f56 100644 --- a/postgis/lwgeom_geos.c +++ b/postgis/lwgeom_geos.c @@ -2370,9 +2370,7 @@ Datum ST_Snap(PG_FUNCTION_ARGS) * from Regione Toscana - Sistema Informativo per il Governo * del Territorio e dell'Ambiente (RT-SIGTA). * - * Thanks to the PostGIS community for sharing poly/line ideas [1] - * - * [1] http://trac.osgeo.org/postgis/wiki/UsersWikiSplitPolygonWithLineString + * Thanks to the PostGIS community for sharing poly/line ideas. * */ Datum ST_Split(PG_FUNCTION_ARGS); diff --git a/raster/loader/raster2pgsql.c b/raster/loader/raster2pgsql.c index c093a412ee..e0575a5926 100644 --- a/raster/loader/raster2pgsql.c +++ b/raster/loader/raster2pgsql.c @@ -1,7 +1,6 @@ /* * * PostGIS raster loader - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright 2001-2003 Refractions Research Inc. * Copyright 2009 Paul Ramsey diff --git a/raster/loader/raster2pgsql.h b/raster/loader/raster2pgsql.h index a18e76ea88..1ca2baca92 100644 --- a/raster/loader/raster2pgsql.h +++ b/raster/loader/raster2pgsql.h @@ -1,7 +1,6 @@ /* * * PostGIS Raster loader - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright 2001-2003 Refractions Research Inc. * Copyright 2009 Paul Ramsey diff --git a/raster/rt_core/librtcore.h b/raster/rt_core/librtcore.h index 97cc83bff7..5e0e19fef8 100644 --- a/raster/rt_core/librtcore.h +++ b/raster/rt_core/librtcore.h @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/librtcore_internal.h b/raster/rt_core/librtcore_internal.h index 32ff7ec9df..827399f118 100644 --- a/raster/rt_core/librtcore_internal.h +++ b/raster/rt_core/librtcore_internal.h @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/rt_band.c b/raster/rt_core/rt_band.c index c9738782be..d086647934 100644 --- a/raster/rt_core/rt_band.c +++ b/raster/rt_core/rt_band.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2018 Bborie Park * Copyright (C) 2011-2013 Regents of the University of California diff --git a/raster/rt_core/rt_context.c b/raster/rt_core/rt_context.c index 8ee187cc49..6483e5f50d 100644 --- a/raster/rt_core/rt_context.c +++ b/raster/rt_core/rt_context.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/rt_gdal.c b/raster/rt_core/rt_gdal.c index f41c246f42..93f238ba42 100644 --- a/raster/rt_core/rt_gdal.c +++ b/raster/rt_core/rt_gdal.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2021 Paul Ramsey * Copyright (C) 2025 Darafei Praliaskouski diff --git a/raster/rt_core/rt_geometry.c b/raster/rt_core/rt_geometry.c index 1eb2b87f67..8b3fdd4f83 100644 --- a/raster/rt_core/rt_geometry.c +++ b/raster/rt_core/rt_geometry.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/rt_mapalgebra.c b/raster/rt_core/rt_mapalgebra.c index ec56a5ada3..82201de2dd 100644 --- a/raster/rt_core/rt_mapalgebra.c +++ b/raster/rt_core/rt_mapalgebra.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/rt_pixel.c b/raster/rt_core/rt_pixel.c index 15793e82e1..2ad38115ea 100644 --- a/raster/rt_core/rt_pixel.c +++ b/raster/rt_core/rt_pixel.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/rt_raster.c b/raster/rt_core/rt_raster.c index 9d5fe7c388..3bfe0b9ae4 100644 --- a/raster/rt_core/rt_raster.c +++ b/raster/rt_core/rt_raster.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2013 Bborie Park * Copyright (C) 2026 Darafei Praliaskouski diff --git a/raster/rt_core/rt_serialize.c b/raster/rt_core/rt_serialize.c index dbb7cd5270..91b4796c66 100644 --- a/raster/rt_core/rt_serialize.c +++ b/raster/rt_core/rt_serialize.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/rt_serialize.h b/raster/rt_core/rt_serialize.h index bef32904ca..a424751f56 100644 --- a/raster/rt_core/rt_serialize.h +++ b/raster/rt_core/rt_serialize.h @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/rt_spatial_relationship.c b/raster/rt_core/rt_spatial_relationship.c index 0388a8ff13..625b2ead26 100644 --- a/raster/rt_core/rt_spatial_relationship.c +++ b/raster/rt_core/rt_spatial_relationship.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/rt_statistics.c b/raster/rt_core/rt_statistics.c index 8be627161d..af6b89a97e 100644 --- a/raster/rt_core/rt_statistics.c +++ b/raster/rt_core/rt_statistics.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/rt_util.c b/raster/rt_core/rt_util.c index 95f4eb8f3f..0c698fc280 100644 --- a/raster/rt_core/rt_util.c +++ b/raster/rt_core/rt_util.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_core/rt_warp.c b/raster/rt_core/rt_warp.c index 8058529ba2..f029f70a39 100644 --- a/raster/rt_core/rt_warp.c +++ b/raster/rt_core/rt_warp.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2013 Bborie Park * Copyright (C) 2011-2013 Regents of the University of California diff --git a/raster/rt_core/rt_wkb.c b/raster/rt_core/rt_wkb.c index 86efe1e744..4f6632b552 100644 --- a/raster/rt_core/rt_wkb.c +++ b/raster/rt_core/rt_wkb.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_band_properties.c b/raster/rt_pg/rtpg_band_properties.c index 8ec500a9a6..c5ea9060b7 100644 --- a/raster/rt_pg/rtpg_band_properties.c +++ b/raster/rt_pg/rtpg_band_properties.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_create.c b/raster/rt_pg/rtpg_create.c index f69865af3f..f6e0cfe7fa 100644 --- a/raster/rt_pg/rtpg_create.c +++ b/raster/rt_pg/rtpg_create.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_gdal.c b/raster/rt_pg/rtpg_gdal.c index 1c10aa1e0c..fdc3333fd2 100644 --- a/raster/rt_pg/rtpg_gdal.c +++ b/raster/rt_pg/rtpg_gdal.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_geometry.c b/raster/rt_pg/rtpg_geometry.c index 474aa62b77..fc66359542 100644 --- a/raster/rt_pg/rtpg_geometry.c +++ b/raster/rt_pg/rtpg_geometry.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_inout.c b/raster/rt_pg/rtpg_inout.c index b959cf204c..ec251dbfe6 100644 --- a/raster/rt_pg/rtpg_inout.c +++ b/raster/rt_pg/rtpg_inout.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_internal.c b/raster/rt_pg/rtpg_internal.c index 630b6c82cb..706b984b34 100644 --- a/raster/rt_pg/rtpg_internal.c +++ b/raster/rt_pg/rtpg_internal.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_internal.h b/raster/rt_pg/rtpg_internal.h index 8a6dc4ec68..ceca24fb7e 100644 --- a/raster/rt_pg/rtpg_internal.h +++ b/raster/rt_pg/rtpg_internal.h @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_mapalgebra.c b/raster/rt_pg/rtpg_mapalgebra.c index 601c795e6c..bd27a2abca 100644 --- a/raster/rt_pg/rtpg_mapalgebra.c +++ b/raster/rt_pg/rtpg_mapalgebra.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_pixel.c b/raster/rt_pg/rtpg_pixel.c index 3791353f35..2685ae6669 100644 --- a/raster/rt_pg/rtpg_pixel.c +++ b/raster/rt_pg/rtpg_pixel.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_raster_properties.c b/raster/rt_pg/rtpg_raster_properties.c index c2717585e0..dc37f6cbae 100644 --- a/raster/rt_pg/rtpg_raster_properties.c +++ b/raster/rt_pg/rtpg_raster_properties.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_spatial_relationship.c b/raster/rt_pg/rtpg_spatial_relationship.c index 4a83d76d53..1278512989 100644 --- a/raster/rt_pg/rtpg_spatial_relationship.c +++ b/raster/rt_pg/rtpg_spatial_relationship.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_statistics.c b/raster/rt_pg/rtpg_statistics.c index 03219f74ee..5053b5d4ca 100644 --- a/raster/rt_pg/rtpg_statistics.c +++ b/raster/rt_pg/rtpg_statistics.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2013 Bborie Park * Copyright (C) 2011-2013 Regents of the University of California diff --git a/raster/rt_pg/rtpg_utility.c b/raster/rt_pg/rtpg_utility.c index d0293e7467..8dffcf2c53 100644 --- a/raster/rt_pg/rtpg_utility.c +++ b/raster/rt_pg/rtpg_utility.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpg_wkb.c b/raster/rt_pg/rtpg_wkb.c index 6cf2b8a95b..d7474649de 100644 --- a/raster/rt_pg/rtpg_wkb.c +++ b/raster/rt_pg/rtpg_wkb.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2018-2018 Bborie Park * Copyright (C) 2011-2013 Regents of the University of California diff --git a/raster/rt_pg/rtpostgis.c b/raster/rt_pg/rtpostgis.c index 76327b1970..4c8bd1a3fa 100644 --- a/raster/rt_pg/rtpostgis.c +++ b/raster/rt_pg/rtpostgis.c @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2011-2013 Regents of the University of California * diff --git a/raster/rt_pg/rtpostgis.h b/raster/rt_pg/rtpostgis.h index bef763e15c..d2a77cabad 100644 --- a/raster/rt_pg/rtpostgis.h +++ b/raster/rt_pg/rtpostgis.h @@ -1,7 +1,6 @@ /* * * WKTRaster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2010-2011 Jorge Arevalo * Copyright (C) 2010-2011 David Zwarg diff --git a/raster/rt_pg/rtpostgis.sql.in b/raster/rt_pg/rtpostgis.sql.in index 704deecc32..29d79ce7e5 100644 --- a/raster/rt_pg/rtpostgis.sql.in +++ b/raster/rt_pg/rtpostgis.sql.in @@ -2,7 +2,6 @@ -- -- -- PostGIS Raster - Raster Type for PostGIS --- http://trac.osgeo.org/postgis/wiki/WKTRaster -- -- Copyright (c) 2015-2017 Regina Obe -- Copyright (c) 2009-2024 Sandro Santilli diff --git a/raster/rt_pg/rtpostgis_drop.sql.in b/raster/rt_pg/rtpostgis_drop.sql.in index 284281cf0a..450ba90849 100644 --- a/raster/rt_pg/rtpostgis_drop.sql.in +++ b/raster/rt_pg/rtpostgis_drop.sql.in @@ -2,7 +2,6 @@ -- -- -- PostGIS Raster - Raster Type for PostGIS --- http://trac.osgeo.org/postgis/wiki/WKTRaster -- -- Copyright (C) 2011 Regina Obe -- Copyright (C) 2011-2012 Regents of the University of California diff --git a/raster/rt_pg/rtpostgis_legacy.sql.in b/raster/rt_pg/rtpostgis_legacy.sql.in index b2a73b226c..eb80fb3b71 100644 --- a/raster/rt_pg/rtpostgis_legacy.sql.in +++ b/raster/rt_pg/rtpostgis_legacy.sql.in @@ -2,7 +2,6 @@ -- -- -- PostGIS Raster - Raster Type for PostGIS --- http://trac.osgeo.org/postgis/wiki/WKTRaster -- -- Copyright (C) 2012 Regents of the University of California -- diff --git a/raster/rt_pg/rtpostgis_upgrade_cleanup.sql.in b/raster/rt_pg/rtpostgis_upgrade_cleanup.sql.in index 654729567d..a307c01643 100644 --- a/raster/rt_pg/rtpostgis_upgrade_cleanup.sql.in +++ b/raster/rt_pg/rtpostgis_upgrade_cleanup.sql.in @@ -2,7 +2,6 @@ -- -- -- PostGIS Raster - Raster Type for PostGIS --- http://trac.osgeo.org/postgis/wiki/WKTRaster -- -- Copyright (c) 2011 Regina Obe -- Copyright (C) 2011 Regents of the University of California diff --git a/raster/scripts/python/raster2pgsql.py b/raster/scripts/python/raster2pgsql.py index 82423568d2..a2773064ec 100755 --- a/raster/scripts/python/raster2pgsql.py +++ b/raster/scripts/python/raster2pgsql.py @@ -4,8 +4,6 @@ # This is a simple utility used to dump GDAL dataset into HEX WKB stream. # It's considered as a prototype of raster2pgsql tool planned to develop # in future. -# For more details about raster2pgsql tool, see Specification page: -# http://trac.osgeo.org/postgis/wiki/WKTRaster # # The script requires Python bindings for GDAL. # Available at http://trac.osgeo.org/gdal/wiki/GdalOgrInPython diff --git a/raster/test/cunit/cu_band_basics.c b/raster/test/cunit/cu_band_basics.c index 6a67f5d281..a33c860105 100644 --- a/raster/test/cunit/cu_band_basics.c +++ b/raster/test/cunit/cu_band_basics.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2018 Bborie Park * Copyright (C) 2012 Regents of the University of California diff --git a/raster/test/cunit/cu_band_misc.c b/raster/test/cunit/cu_band_misc.c index f3af3f0a42..0ee752395c 100644 --- a/raster/test/cunit/cu_band_misc.c +++ b/raster/test/cunit/cu_band_misc.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2012 Regents of the University of California * diff --git a/raster/test/cunit/cu_band_stats.c b/raster/test/cunit/cu_band_stats.c index 499f37afcf..e2af35bd0b 100644 --- a/raster/test/cunit/cu_band_stats.c +++ b/raster/test/cunit/cu_band_stats.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2012 Regents of the University of California * diff --git a/raster/test/cunit/cu_gdal.c b/raster/test/cunit/cu_gdal.c index 67fdaf55c0..66282f57cb 100644 --- a/raster/test/cunit/cu_gdal.c +++ b/raster/test/cunit/cu_gdal.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2012 Regents of the University of California * diff --git a/raster/test/cunit/cu_mapalgebra.c b/raster/test/cunit/cu_mapalgebra.c index 553cc7c361..491042a685 100644 --- a/raster/test/cunit/cu_mapalgebra.c +++ b/raster/test/cunit/cu_mapalgebra.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2012 Regents of the University of California * diff --git a/raster/test/cunit/cu_misc.c b/raster/test/cunit/cu_misc.c index 791d701362..a9506e313c 100644 --- a/raster/test/cunit/cu_misc.c +++ b/raster/test/cunit/cu_misc.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2013 Regents of the University of California * diff --git a/raster/test/cunit/cu_pixtype.c b/raster/test/cunit/cu_pixtype.c index 6ef05cd64e..0e5008d3e5 100644 --- a/raster/test/cunit/cu_pixtype.c +++ b/raster/test/cunit/cu_pixtype.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2012 Regents of the University of California * diff --git a/raster/test/cunit/cu_raster_basics.c b/raster/test/cunit/cu_raster_basics.c index e8eac73a7e..385c076619 100644 --- a/raster/test/cunit/cu_raster_basics.c +++ b/raster/test/cunit/cu_raster_basics.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2012 Regents of the University of California * diff --git a/raster/test/cunit/cu_raster_geometry.c b/raster/test/cunit/cu_raster_geometry.c index 97ebb40f4e..d3340d04d4 100644 --- a/raster/test/cunit/cu_raster_geometry.c +++ b/raster/test/cunit/cu_raster_geometry.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2012-2013 Regents of the University of California * diff --git a/raster/test/cunit/cu_raster_misc.c b/raster/test/cunit/cu_raster_misc.c index 0487491933..1cb68a42c3 100644 --- a/raster/test/cunit/cu_raster_misc.c +++ b/raster/test/cunit/cu_raster_misc.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2012 Regents of the University of California * diff --git a/raster/test/cunit/cu_raster_wkb.c b/raster/test/cunit/cu_raster_wkb.c index e1e6219e11..c210e2d64b 100644 --- a/raster/test/cunit/cu_raster_wkb.c +++ b/raster/test/cunit/cu_raster_wkb.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2012 Regents of the University of California * diff --git a/raster/test/cunit/cu_spatial_relationship.c b/raster/test/cunit/cu_spatial_relationship.c index 7438367e45..6cca6bb157 100644 --- a/raster/test/cunit/cu_spatial_relationship.c +++ b/raster/test/cunit/cu_spatial_relationship.c @@ -1,6 +1,5 @@ /* * PostGIS Raster - Raster Types for PostGIS - * http://trac.osgeo.org/postgis/wiki/WKTRaster * * Copyright (C) 2012 Regents of the University of California * diff --git a/regress/core/empty.sql b/regress/core/empty.sql index d07ce252a3..91c4fd33d7 100644 --- a/regress/core/empty.sql +++ b/regress/core/empty.sql @@ -30,7 +30,7 @@ SELECT 'T3.16', ST_AsGML(3,'MULTIPOLYGON EMPTY'::geometry); SELECT 'T3.17', ST_AsGML(3,'MULTILINESTRING EMPTY'::geometry); SELECT 'T3.18', ST_AsGML(3,'GEOMETRYCOLLECTION EMPTY'::geometry); --- See http://trac.osgeo.org/postgis/wiki/DevWikiEmptyGeometry +-- See https://postgis.net/development/docs/internals/empty-geometry/ WITH inp AS (SELECT 'POLYGON EMPTY'::geometry as empty, diff --git a/utils/check_all_upgrades.sh b/utils/check_all_upgrades.sh index 14e9b51f77..90550c9f14 100755 --- a/utils/check_all_upgrades.sh +++ b/utils/check_all_upgrades.sh @@ -148,7 +148,7 @@ minimum_postgis_version_for_postgresql_major_version() supportfile=${TMPDIR}/minimum_supported_version_for_postgresql if ! test -e ${supportfile}; then - # Source: https://trac.osgeo.org/postgis/wiki/UsersWikiPostgreSQLPostGIS + # Source: https://postgis.net/development/compatibility/ cat > ${supportfile} < 70063 bytes .../raster-storage/raster-table-arrangements.gif | Bin 0 -> 148699 bytes doc/development/internals/raster-gdal-driver.md | 4 +- doc/development/internals/raster-storage.md | 114 ++++++++++++++- doc/development/internals/spatial-collections.md | 27 ++-- doc/development/release/api.md | 34 ----- doc/development/todo.md | 162 ++++++--------------- doc/introduction.xml | 11 ++ doc/reference_lrs.xml | 12 +- doc/reference_output.xml | 18 +++ doc/reference_transformation.xml | 23 ++- doc/using_raster_dataman.xml | 98 +++++++++++++ postgis/lwgeom_geos.c | 4 +- raster/loader/raster2pgsql.c | 1 - raster/loader/raster2pgsql.h | 1 - raster/rt_core/librtcore.h | 1 - raster/rt_core/librtcore_internal.h | 1 - raster/rt_core/rt_band.c | 1 - raster/rt_core/rt_context.c | 1 - raster/rt_core/rt_gdal.c | 1 - raster/rt_core/rt_geometry.c | 1 - raster/rt_core/rt_mapalgebra.c | 1 - raster/rt_core/rt_pixel.c | 1 - raster/rt_core/rt_raster.c | 1 - raster/rt_core/rt_serialize.c | 1 - raster/rt_core/rt_serialize.h | 1 - raster/rt_core/rt_spatial_relationship.c | 1 - raster/rt_core/rt_statistics.c | 1 - raster/rt_core/rt_util.c | 1 - raster/rt_core/rt_warp.c | 1 - raster/rt_core/rt_wkb.c | 1 - raster/rt_pg/rtpg_band_properties.c | 1 - raster/rt_pg/rtpg_create.c | 1 - raster/rt_pg/rtpg_gdal.c | 1 - raster/rt_pg/rtpg_geometry.c | 1 - raster/rt_pg/rtpg_inout.c | 1 - raster/rt_pg/rtpg_internal.c | 1 - raster/rt_pg/rtpg_internal.h | 1 - raster/rt_pg/rtpg_mapalgebra.c | 1 - raster/rt_pg/rtpg_pixel.c | 1 - raster/rt_pg/rtpg_raster_properties.c | 1 - raster/rt_pg/rtpg_spatial_relationship.c | 1 - raster/rt_pg/rtpg_statistics.c | 1 - raster/rt_pg/rtpg_utility.c | 1 - raster/rt_pg/rtpg_wkb.c | 1 - raster/rt_pg/rtpostgis.c | 1 - raster/rt_pg/rtpostgis.h | 1 - raster/rt_pg/rtpostgis.sql.in | 1 - raster/rt_pg/rtpostgis_drop.sql.in | 1 - raster/rt_pg/rtpostgis_legacy.sql.in | 1 - raster/rt_pg/rtpostgis_upgrade_cleanup.sql.in | 1 - raster/scripts/python/raster2pgsql.py | 2 - raster/test/cunit/cu_band_basics.c | 1 - raster/test/cunit/cu_band_misc.c | 1 - raster/test/cunit/cu_band_stats.c | 1 - raster/test/cunit/cu_gdal.c | 1 - raster/test/cunit/cu_mapalgebra.c | 1 - raster/test/cunit/cu_misc.c | 1 - raster/test/cunit/cu_pixtype.c | 1 - raster/test/cunit/cu_raster_basics.c | 1 - raster/test/cunit/cu_raster_geometry.c | 1 - raster/test/cunit/cu_raster_misc.c | 1 - raster/test/cunit/cu_raster_wkb.c | 1 - raster/test/cunit/cu_spatial_relationship.c | 1 - regress/core/empty.sql | 2 +- utils/check_all_upgrades.sh | 2 +- 69 files changed, 375 insertions(+), 241 deletions(-) create mode 100644 doc/development/internals/images/raster-storage/coverage-concepts.png create mode 100644 doc/development/internals/images/raster-storage/raster-table-arrangements.gif hooks/post-receive -- PostGIS From git at osgeo.org Sat Aug 1 14:50:58 2026 From: git at osgeo.org (git at osgeo.org) Date: Sat, 1 Aug 2026 14:50:58 -0700 (PDT) Subject: [SCM] postgis.net branch website updated. clarity-final-241-ga5c2c88 Message-ID: <20260801215058.AB72B1B8D1B@trac.osgeo.org> 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.net". The branch, website has been updated via a5c2c889acde7b0a12358829e5fb09faea05f8e1 (commit) via e2100077fedbc828b71e6a3bf1fee236cc9eb976 (commit) via cc6b0486f8f40ad2d3c0d86d4ab5a466461e8bcd (commit) via be5ac8e3988e58318d77942d40003a0c1a84c86d (commit) from a33105078318232907b5ded460ef76d592d5b91e (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 a5c2c889acde7b0a12358829e5fb09faea05f8e1 Merge: a331050 e210007 Author: Darafei Praliaskouski Date: Sat Aug 1 14:50:56 2026 -0700 Merge pull request 'Retire Trac wiki links without losing raster history' (!27) from Komzpa/postgis.net:ai/trac-raster-artifacts-20260801 into website Reviewed-on: https://gitea.osgeo.org/postgis/postgis.net/pulls/27 commit e2100077fedbc828b71e6a3bf1fee236cc9eb976 Author: Darafei Praliaskouski Date: Sat Aug 1 22:59:53 2026 +0400 docs: point retired wiki content to maintained homes diff --git a/content/development/bug_reporting.md b/content/development/bug_reporting.md index 9d888a5..90cf8bc 100644 --- a/content/development/bug_reporting.md +++ b/content/development/bug_reporting.md @@ -1,6 +1,7 @@ --- title: Bug Reporting date: 2022-02-01 +lastmod: 2026-08-01 weight: 60 description: "The right way to report a bug so that it can be fixed." geekdocHidden: false @@ -35,6 +36,9 @@ geekdocHidden: false * If the issue is a crash, include a backtrace when possible. The [testing and debugging guide](/development/docs/testing/#backtraces) describes how to attach `gdb` to a PostgreSQL backend and capture one. + * For raster issues, select the `raster` component and include `gdalinfo` + output for the source raster when possible. For `raster2pgsql` problems, + include the complete loader command line.
## Security Issues diff --git a/content/news/2018/04-06_postgis-patches.md b/content/news/2018/04-06_postgis-patches.md index d809f72..f06fc1a 100644 --- a/content/news/2018/04-06_postgis-patches.md +++ b/content/news/2018/04-06_postgis-patches.md @@ -65,4 +65,4 @@ make sure to rerun the version packaged with these releases. * [Changelog](https://svn.osgeo.org/postgis/tags/2.4.4/ChangeLog) [1]: https://trac.osgeo.org/postgis/query?status=closed&resolution=fixed&milestone=PostGIS+2.4.4&milestone=PostGIS+2.3.7&milestone=PostGIS+2.2.7&col=id&col=summary&col=milestone&col=status&col=type&col=priority&col=component&order=priority -[2]: https://web.archive.org/web/20180427043448/https://trac.osgeo.org/postgis/wiki/UsersWikiPostgreSQLPostGIS +[2]: /development/compatibility/ commit cc6b0486f8f40ad2d3c0d86d4ab5a466461e8bcd Author: Darafei Praliaskouski Date: Sat Aug 1 21:35:46 2026 +0400 docs: restore historical raster training links diff --git a/content/documentation/training.md b/content/documentation/training.md index 36ec259..d400f46 100644 --- a/content/documentation/training.md +++ b/content/documentation/training.md @@ -1,7 +1,7 @@ --- title: Training Materials date: 2022-02-01 -lastmod: 2026-07-31 +lastmod: 2026-08-01 description: "In depth learning tools like workshops and books." weight: 100 geekdocHidden: false @@ -128,16 +128,25 @@ new projects. * [PostGIS 2.0 the new stuff, FOSS4G 2011](http://www.postgis.us/downloads/FOSS4G2011PostGIS20NewStuff.pdf) * [Store, manipulate and analyze raster data within PostgreSQL/PostGIS](https://web.archive.org/web/20260714021210id_/https://trac.osgeo.org/postgis/raw-attachment/wiki/WKTRaster/PierreRacine_FOSS4G-2011.pdf), Pierre Racine, FOSS4G Denver +* [PostGIS 2.0 3D and Raster support enhancements](https://www.postgis.us/downloads/ncgis2011/NCGISSDBPostGIS20_2011.pdf), + Regina Obe and Leo Hsu, North Carolina GIS Conference +* [PostGIS Raster Plugin for Quantum GIS](https://web.archive.org/web/20140423185737id_/http://mtc-m18.sid.inpe.br/col/sid.inpe.br/mtc-m18/2011/12.14.11.29/doc/mauricio2.pdf), + Maur?cio Carvalho Mathias de Paulo and Lubia Vinhas +* [Accessing PostGIS Raster from gvSIG Desktop](https://www.slideshare.net/nbrodin/postgisrastergvsig), + Jorge Sanz and Ignacio Brodin, with the [extension manual](https://web.archive.org/web/20110816142446id_/http://forge.osor.eu/docman/view.php/313/560/PostGISRaster-0.1-man-en.pdf) + and [video demonstration](https://web.archive.org/web/20120604184811id_/http://trac.osgeo.org/postgis/raw-attachment/wiki/WKTRaster/postgisraster_on_gvsig.zip) ### 2010 * [PostGIS - das Wo? in der Datenbank](https://wiki.postgresql.org/images/3/31/Postgis_das_wo_in_der_datenbank_pgday_eu_2010.pdf) * [PostGIS, a PostgreSQL module for spatial data](https://wiki.postgresql.org/images/2/2e/Postgis_vincent_picavet_pgdayEU2010.pdf) * [Integrating PostGIS in Web Applications](http://www.postgis.us/downloads/pgconeast2010/pgconeast2010_postgiswebapps.pdf) +* [Historical raster/vector overlay tutorial](/development/docs/history/raster-vector-tutorial/), + Pierre Racine's caribou and SRTM walkthrough updated to current PostGIS names * [Introducing PostGIS WKT Raster: Seamless Raster/Vector Operations in a Spatial Database](https://web.archive.org/web/20260714021207id_/https://trac.osgeo.org/postgis/raw-attachment/wiki/WKTRaster/FOSS4G2010_Pierre.pdf), Pierre Racine, FOSS4G Barcelona * [PostGIS WKT Raster: An Open Source Alternative to Oracle GeoRaster](https://web.archive.org/web/20260714021203id_/https://trac.osgeo.org/postgis/raw-attachment/wiki/WKTRaster/FOSS4G2010_Jorge.pdf), - Jorge Arevalo, FOSS4G Barcelona + Jorge Ar?valo, FOSS4G Barcelona ### 2009 @@ -145,6 +154,14 @@ new projects. and [movie](https://media.postgresql.org/pgcon2009/sessions/0521/pgcon2009-sessions-spatial.mov) * [Introduction to PostGIS WKT Raster and Raster Objects](https://web.archive.org/web/20260714022804id_/https://trac.osgeo.org/postgis/raw-attachment/wiki/WKTRaster/WKTRasterIntro-Geomatique2009.pdf), Pierre Racine, Geomatique 2009 +* [A Data System for Visualizing 4-D Atmospheric CO2 Models and Data](https://download.osgeo.org/osgeo/foss4g/2009/SPREP/2Thu/Parkside%20GO4/1030/Thu%20G04%201130%20Erickson/Erickson_foss4g.ppt), + Tyler Erickson, FOSS4G Sydney + +### 2008 + +* [PostGIS WKT Raster Specifications Version 1.0](https://www.cef-cfr.ca/uploads/Membres/WKTRasterSpecifications1.0.pdf), + Pierre Racine, Universit? Laval +* [PostGIS raster integration discussion bibliography, 2002-2008](https://web.archive.org/web/20250824144943/https://trac.osgeo.org/postgis/wiki/UsersWikiRasterNotes) ### 2007 commit be5ac8e3988e58318d77942d40003a0c1a84c86d Author: Darafei Praliaskouski Date: Sat Aug 1 09:35:39 2026 +0400 docs: retire historical Trac compatibility links diff --git a/content/news/2018/04-06_postgis-patches.md b/content/news/2018/04-06_postgis-patches.md index 00cf1ef..d809f72 100644 --- a/content/news/2018/04-06_postgis-patches.md +++ b/content/news/2018/04-06_postgis-patches.md @@ -65,4 +65,4 @@ make sure to rerun the version packaged with these releases. * [Changelog](https://svn.osgeo.org/postgis/tags/2.4.4/ChangeLog) [1]: https://trac.osgeo.org/postgis/query?status=closed&resolution=fixed&milestone=PostGIS+2.4.4&milestone=PostGIS+2.3.7&milestone=PostGIS+2.2.7&col=id&col=summary&col=milestone&col=status&col=type&col=priority&col=component&order=priority -[2]: https://trac.osgeo.org/postgis/wiki/UsersWikiPostgreSQLPostGIS +[2]: https://web.archive.org/web/20180427043448/https://trac.osgeo.org/postgis/wiki/UsersWikiPostgreSQLPostGIS diff --git a/content/news/2018/09-12_postgis-2.4.5.md b/content/news/2018/09-12_postgis-2.4.5.md index 7d8110e..cbfd6f5 100644 --- a/content/news/2018/09-12_postgis-2.4.5.md +++ b/content/news/2018/09-12_postgis-2.4.5.md @@ -41,4 +41,3 @@ make sure to rerun the version packaged with these releases. * [Changelog](https://svn.osgeo.org/postgis/tags/2.4.5/ChangeLog) [1]: https://trac.osgeo.org/postgis/query?status=closed&resolution=fixed&milestone=PostGIS+2.4.5&col=id&col=summary&col=milestone&col=status&col=type&col=priority&col=component&order=priority -[2]: https://trac.osgeo.org/postgis/wiki/UsersWikiPostgreSQLPostGIS ----------------------------------------------------------------------- Summary of changes: content/development/bug_reporting.md | 4 ++++ content/documentation/training.md | 21 +++++++++++++++++++-- content/news/2018/04-06_postgis-patches.md | 2 +- content/news/2018/09-12_postgis-2.4.5.md | 1 - 4 files changed, 24 insertions(+), 4 deletions(-) hooks/post-receive -- postgis.net From git at osgeo.org Sat Aug 1 14:56:53 2026 From: git at osgeo.org (git at osgeo.org) Date: Sat, 1 Aug 2026 14:56:53 -0700 (PDT) Subject: [SCM] PostGIS branch stable-3.5 updated. 3.5.7-99-g7e92bf7ad3 Message-ID: <20260801215653.882171B7B96@trac.osgeo.org> 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, stable-3.5 has been updated via 7e92bf7ad3db42ac7af27aab5f490bba757bd935 (commit) via a44c47502020c355e1f54fbee27c9e4e4fab5606 (commit) from f3995d28ecd4c23e8bc66ebe8d502a4850bb1104 (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 7e92bf7ad3db42ac7af27aab5f490bba757bd935 Merge: f3995d28ec a44c475020 Author: Darafei Praliaskouski Date: Sat Aug 1 14:56:51 2026 -0700 Merge pull request 'ci: split stable-3.5 regress workflow' (!633) from Komzpa/postgis:ci/split-regress-stable-3.5-20260731 into stable-3.5 Split the stable-3.5 Woodpecker regress workflow into independent matrix workflows so each branch-local coverage unit gets its own five-hour deadline. The PostgreSQL versions and install or upgrade commands are preserved; the change only moves the existing units from one serial workflow into separate scheduled workflows. No NEWS entry: this is CI infrastructure only and does not change user-visible PostGIS behavior. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/633 commit a44c47502020c355e1f54fbee27c9e4e4fab5606 Author: Darafei Praliaskouski Date: Fri Jul 31 16:46:08 2026 +0400 ci: split stable regress workflow Run each stable regress coverage unit as an independent Woodpecker matrix workflow so the long install and upgrade checks no longer share one five-hour pipeline deadline. This preserves the branch-local PostgreSQL versions and upgrade checks while letting the fleet schedule them in parallel. diff --git a/.woodpecker/regress.yml b/.woodpecker/regress.yml index 34420d4aed..244db82896 100644 --- a/.woodpecker/regress.yml +++ b/.woodpecker/regress.yml @@ -31,7 +31,9 @@ variables: --enable-lto --enable-lto CFLAGS="-O2 -Wall -fno-omit-frame-pointer -Werror" - - make -j + # Matrix jobs provide the parallelism. Keep each build serial: the PostGIS + # make graph can otherwise race generated protobuf headers. + - make -j1 steps-pg-test-preinstall: &steps-pg-test-preinstall - cd build/pg$${PGVER} - make check @@ -57,91 +59,70 @@ clone: depth: 50 steps: - autogen: image: *test-image pull: true commands: - ./autogen.sh - build-pg12: + build: image: *test-image depends_on: autogen - environment: - PGVER: 12 commands: - <<: *steps-env - <<: *steps-pg-build - build-pg17: + test-preinstall: image: *test-image - depends_on: autogen - environment: - PGVER: 17 - commands: - - <<: *steps-env - - <<: *steps-pg-build - - check-pg12: - image: *test-image - depends_on: build-pg12 - environment: - PGVER: 12 + depends_on: build + when: + - matrix: + REGRESS_SUITE: preinstall commands: - <<: *steps-env - <<: *steps-start-postgresql - <<: *steps-pg-test-preinstall - check-pg17: + test-install: image: *test-image - depends_on: build-pg17 - environment: - PGVER: 17 - commands: - - <<: *steps-env - - <<: *steps-start-postgresql - - <<: *steps-pg-test-preinstall - - installcheck-pg12: - image: *test-image - depends_on: check-pg12 - environment: - PGVER: 12 + depends_on: build + when: + - matrix: + REGRESS_SUITE: install commands: - <<: *steps-env - <<: *steps-start-postgresql - <<: *steps-pg-install - <<: *steps-pg-test-install - installcheck-pg17: + test-upgrades: image: *test-image - depends_on: check-pg17 - environment: - PGVER: 17 - commands: - - <<: *steps-env - - <<: *steps-start-postgresql - - <<: *steps-pg-install - - <<: *steps-pg-test-install - - upgradecheck-pg12: - image: *test-image - depends_on: installcheck-pg12 - environment: - PGVER: 12 + depends_on: build + when: + - matrix: + REGRESS_SUITE: extension-upgrade commands: - <<: *steps-env - <<: *steps-start-postgresql + - make -C "$${BUILDDIR}" staged-install - <<: *steps-pg-install - <<: *steps-pg-test-all-upgrades - upgradecheck-pg17: - image: *test-image - depends_on: installcheck-pg17 - environment: - PGVER: 17 - commands: - - <<: *steps-env - - <<: *steps-start-postgresql - - <<: *steps-pg-install - - <<: *steps-pg-test-all-upgrades +# Each matrix entry is an independent Woodpecker workflow with its own clone, +# build tree, PostgreSQL instance, and five-hour runner deadline. The entries +# below preserve the previous stable-3.5 coverage units while removing the +# single serial regress workflow that could not finish inside the deadline. +matrix: + include: + - PGVER: "12" + REGRESS_SUITE: preinstall + - PGVER: "17" + REGRESS_SUITE: preinstall + - PGVER: "12" + REGRESS_SUITE: install + - PGVER: "17" + REGRESS_SUITE: install + - PGVER: "12" + REGRESS_SUITE: extension-upgrade + - PGVER: "17" + REGRESS_SUITE: extension-upgrade ----------------------------------------------------------------------- Summary of changes: .woodpecker/regress.yml | 95 ++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 57 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Sat Aug 1 14:57:05 2026 From: git at osgeo.org (git at osgeo.org) Date: Sat, 1 Aug 2026 14:57:05 -0700 (PDT) Subject: [SCM] PostGIS branch stable-3.4 updated. 3.4.6-110-gec446a2cb3 Message-ID: <20260801215705.EA47B1B929E@trac.osgeo.org> 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, stable-3.4 has been updated via ec446a2cb34ffcf2e2ee0fa9237f6f4b47097b2f (commit) via 94ec0cc61c8fbfe2140b61abd7b8cd479d0cb3aa (commit) from 9a1766d29af52e467c9f3eab5239d7fd04111175 (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 ec446a2cb34ffcf2e2ee0fa9237f6f4b47097b2f Merge: 9a1766d29a 94ec0cc61c Author: Darafei Praliaskouski Date: Sat Aug 1 14:57:04 2026 -0700 Merge pull request 'ci: split stable-3.4 regress workflow' (!634) from Komzpa/postgis:ci/split-regress-stable-3.4-20260731 into stable-3.4 Split the stable-3.4 Woodpecker regress workflow into independent matrix workflows so each branch-local coverage unit gets its own five-hour deadline. The PostgreSQL versions and install or upgrade commands are preserved; the change only moves the existing units from one serial workflow into separate scheduled workflows. No NEWS entry: this is CI infrastructure only and does not change user-visible PostGIS behavior. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/634 commit 94ec0cc61c8fbfe2140b61abd7b8cd479d0cb3aa Author: Darafei Praliaskouski Date: Fri Jul 31 16:46:08 2026 +0400 ci: split stable regress workflow Run each stable regress coverage unit as an independent Woodpecker matrix workflow so the long install and upgrade checks no longer share one five-hour pipeline deadline. This preserves the branch-local PostgreSQL versions and upgrade checks while letting the fleet schedule them in parallel. diff --git a/.woodpecker/regress.yml b/.woodpecker/regress.yml index 0761dfb28c..2d644cd5fc 100644 --- a/.woodpecker/regress.yml +++ b/.woodpecker/regress.yml @@ -27,7 +27,9 @@ variables: --enable-lto --enable-lto CFLAGS="-O2 -Wall -fno-omit-frame-pointer -Werror" - - make -j + # Matrix jobs provide the parallelism. Keep each build serial: the PostGIS + # make graph can otherwise race generated protobuf headers. + - make -j1 steps-pg-test-preinstall: &steps-pg-test-preinstall - cd build/pg$${PGVER} - make check @@ -51,91 +53,70 @@ clone: depth: 50 steps: - autogen: image: *test-image pull: true commands: - ./autogen.sh - build-pg12: + build: image: *test-image depends_on: autogen - environment: - PGVER: 12 commands: - <<: *steps-env - <<: *steps-pg-build - build-pg15: + test-preinstall: image: *test-image - depends_on: autogen - environment: - PGVER: 15 - commands: - - <<: *steps-env - - <<: *steps-pg-build - - check-pg12: - image: *test-image - depends_on: build-pg12 - environment: - PGVER: 12 + depends_on: build + when: + - matrix: + REGRESS_SUITE: preinstall commands: - <<: *steps-env - <<: *steps-start-postgresql - <<: *steps-pg-test-preinstall - check-pg15: + test-install: image: *test-image - depends_on: build-pg15 - environment: - PGVER: 15 - commands: - - <<: *steps-env - - <<: *steps-start-postgresql - - <<: *steps-pg-test-preinstall - - installcheck-pg12: - image: *test-image - depends_on: build-pg12 - environment: - PGVER: 12 + depends_on: build + when: + - matrix: + REGRESS_SUITE: install commands: - <<: *steps-env - <<: *steps-start-postgresql - <<: *steps-pg-install - <<: *steps-pg-test-install - installcheck-pg15: + test-upgrades: image: *test-image - depends_on: build-pg15 - environment: - PGVER: 15 - commands: - - <<: *steps-env - - <<: *steps-start-postgresql - - <<: *steps-pg-install - - <<: *steps-pg-test-install - - upgradecheck-pg12: - image: *test-image - depends_on: build-pg12 - environment: - PGVER: 12 + depends_on: build + when: + - matrix: + REGRESS_SUITE: extension-upgrade commands: - <<: *steps-env - <<: *steps-start-postgresql + - make -C "$${BUILDDIR}" staged-install - <<: *steps-pg-install - <<: *steps-pg-test-all-upgrades - upgradecheck-pg15: - image: *test-image - depends_on: build-pg15 - environment: - PGVER: 15 - commands: - - <<: *steps-env - - <<: *steps-start-postgresql - - <<: *steps-pg-install - - <<: *steps-pg-test-all-upgrades +# Each matrix entry is an independent Woodpecker workflow with its own clone, +# build tree, PostgreSQL instance, and five-hour runner deadline. The entries +# below preserve the previous stable-3.4 coverage units while removing the +# single serial regress workflow that could not finish inside the deadline. +matrix: + include: + - PGVER: "12" + REGRESS_SUITE: preinstall + - PGVER: "15" + REGRESS_SUITE: preinstall + - PGVER: "12" + REGRESS_SUITE: install + - PGVER: "15" + REGRESS_SUITE: install + - PGVER: "12" + REGRESS_SUITE: extension-upgrade + - PGVER: "15" + REGRESS_SUITE: extension-upgrade ----------------------------------------------------------------------- Summary of changes: .woodpecker/regress.yml | 95 ++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 57 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Sat Aug 1 14:58:39 2026 From: git at osgeo.org (git at osgeo.org) Date: Sat, 1 Aug 2026 14:58:39 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-165-g263a3dbf96 Message-ID: <20260801215840.276611B8BD4@trac.osgeo.org> 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 263a3dbf965755f09b4f0a3aecc367b131641240 (commit) via b476d614c78f4579387cb62f5e3079ac04e8cdd2 (commit) via 8d662dd225659c5eee6ac932219cbe2ee7670624 (commit) from b53607dc54ae72020767e27c09c7ca800921f7f1 (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 263a3dbf965755f09b4f0a3aecc367b131641240 Merge: b53607dc54 b476d614c7 Author: Darafei Praliaskouski Date: Sat Aug 1 14:58:38 2026 -0700 Merge pull request 'regress: compare interrupt timing to local baseline' (!619) from Komzpa/postgis:fix/interrupt-relative-timing-20260729 into master The interrupt regression tests for GEOS relate predicates currently compare elapsed wall-clock time against fixed millisecond tolerances. Slow or loaded workers can fail that check even when PostGIS does propagate PostgreSQL cancellation into GEOS promptly. This changes the relate interrupt checks to measure each predicate's uninterrupted runtime on the same input and same worker, then require the timeout run to finish before it reaches 90 percent of that local baseline. The assertion still fails if PostGIS stops requesting GEOS interruption, because the timed run then approaches the full uninterrupted runtime instead of stopping promptly after `statement_timeout`. The `ST_Segmentize` and `ST_Buffer` interrupt smoke tests keep their existing absolute helper path because their uninterrupted forms are not a cheap, valid calibration target. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/619 commit b476d614c78f4579387cb62f5e3079ac04e8cdd2 Author: Darafei Praliaskouski Date: Wed Jul 29 19:19:26 2026 +0400 regress: keep interrupt relate input bounded diff --git a/regress/core/interrupt_relate.sql b/regress/core/interrupt_relate.sql index 52ead29c39..65271e5d66 100644 --- a/regress/core/interrupt_relate.sql +++ b/regress/core/interrupt_relate.sql @@ -6,7 +6,7 @@ SELECT 1::int as id, ST_Collect(g) g FROM ( ST_Point(cos(radians(x)),sin(radians(270-x))), ST_Point(sin(radians(x)),cos(radians(60-x))) ) g - FROM generate_series(1,1440) x + FROM generate_series(1,720) x ) foo ; commit 8d662dd225659c5eee6ac932219cbe2ee7670624 Author: Darafei Praliaskouski Date: Wed Jul 29 02:19:22 2026 +0400 regress: compare interrupt timing to local baseline diff --git a/NEWS b/NEWS index 1443dee89a..2269a09052 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,9 @@ These are only changes since 3.7.0beta1. - [liblwgeom] Reject malformed GSERIALIZED NURBS before curve evaluation (Darafei Praliaskouski) + - GT-619, Make interrupt regression tests compare timeout latency to + same-machine uninterrupted runtime, avoiding false failures under + slow CI load (Darafei Praliaskouski) - Make the computed-columns regression test assert the query plan instead of racing two stopwatches, so it no longer fails at random under CI load (Darafei Praliaskouski) diff --git a/regress/core/interrupt.sql b/regress/core/interrupt.sql index 78f30166e4..c9fc993b6a 100644 --- a/regress/core/interrupt.sql +++ b/regress/core/interrupt.sql @@ -17,4 +17,7 @@ SELECT _timecheck('segmentize', '300ms'); -- Not affected by old timeout SELECT '1',ST_AsText(ST_Segmentize('LINESTRING(0 0,4 0)'::geometry, 2)); +DROP FUNCTION _timecheck(text); DROP FUNCTION _timecheck(text, interval); +DROP FUNCTION _timecheck_baseline(text); +DROP FUNCTION _timecheck_start(); diff --git a/regress/core/interrupt_buffer.sql b/regress/core/interrupt_buffer.sql index fd942e1e6d..204ecae936 100644 --- a/regress/core/interrupt_buffer.sql +++ b/regress/core/interrupt_buffer.sql @@ -29,3 +29,6 @@ SELECT _timecheck('buffer', '350ms'); SELECT '1', ST_NPoints(ST_Buffer('POINT(4 0)'::geometry, 2, 1)); DROP FUNCTION _timecheck(text, interval); +DROP FUNCTION _timecheck(text); +DROP FUNCTION _timecheck_baseline(text); +DROP FUNCTION _timecheck_start(); diff --git a/regress/core/interrupt_relate.sql b/regress/core/interrupt_relate.sql index 11ffb5294e..52ead29c39 100644 --- a/regress/core/interrupt_relate.sql +++ b/regress/core/interrupt_relate.sql @@ -6,7 +6,7 @@ SELECT 1::int as id, ST_Collect(g) g FROM ( ST_Point(cos(radians(x)),sin(radians(270-x))), ST_Point(sin(radians(x)),cos(radians(60-x))) ) g - FROM generate_series(1,720) x + FROM generate_series(1,1440) x ) foo ; @@ -16,29 +16,69 @@ SELECT 1::int as id, ST_Collect(g) g FROM ( -- IM9 based predicates ----------------------------- +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Contains(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('contains'); +END; +$$; + BEGIN; SET LOCAL statement_timeout TO 100; select ST_Contains(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('contains', '220ms'); +SELECT _timecheck('contains'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Covers(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('covers'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Covers(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('covers', '220ms'); +SELECT _timecheck('covers'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_CoveredBy(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('coveredby'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_CoveredBy(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('coveredby', '250ms'); +SELECT _timecheck('coveredby'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Crosses(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('crosses'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Crosses(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('crosses', '220ms'); +SELECT _timecheck('crosses'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Equals(g,st_reverse(g)) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('equals'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; @@ -46,7 +86,15 @@ SET LOCAL statement_timeout TO 100; -- short-circuit described in #3226 select ST_Equals(g,st_reverse(g)) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('equals', '220ms'); +SELECT _timecheck('equals'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Intersects(g,ST_Segmentize(g,1e-4)) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('intersects'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; @@ -54,19 +102,38 @@ SET LOCAL statement_timeout TO 100; -- input to make it slower select ST_Intersects(g,ST_Segmentize(g,1e-4)) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('intersects', '210ms'); +SELECT _timecheck('intersects'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Overlaps(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('overlaps'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Overlaps(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('overlaps', '220ms'); +SELECT _timecheck('overlaps'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Relate(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('relate'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Relate(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('relate', '220ms'); +SELECT _timecheck('relate'); +DROP FUNCTION _timecheck(text); DROP FUNCTION _timecheck(text, interval); +DROP FUNCTION _timecheck_baseline(text); +DROP FUNCTION _timecheck_start(); DROP TABLE _inputs; diff --git a/regress/utils/timecheck.sql b/regress/utils/timecheck.sql index 75f3bbbbd0..c28fe265e3 100644 --- a/regress/utils/timecheck.sql +++ b/regress/utils/timecheck.sql @@ -1,3 +1,21 @@ +CREATE FUNCTION _timecheck_start() RETURNS void +AS $$ +BEGIN + UPDATE _time SET t = clock_timestamp(); +END; +$$ LANGUAGE 'plpgsql' VOLATILE; + +CREATE FUNCTION _timecheck_baseline(label text) RETURNS void +AS $$ +BEGIN + INSERT INTO _time_baseline + SELECT label, clock_timestamp() - t + FROM _time; + + UPDATE _time SET t = clock_timestamp(); +END; +$$ LANGUAGE 'plpgsql' VOLATILE; + CREATE FUNCTION _timecheck(label text, tolerated interval) RETURNS text AS $$ DECLARE @@ -37,6 +55,43 @@ BEGIN END; $$ LANGUAGE 'plpgsql' VOLATILE; +CREATE FUNCTION _timecheck(label text) RETURNS text +AS $$ +DECLARE + ret TEXT; + lap INTERVAL; + rec RECORD; +BEGIN + -- We use now() here to get the time at the + -- start of the transaction, which started when + -- this function was called, so the earliest + -- possible time + SELECT now() - t lap, b.baseline, b.baseline * 0.9 tolerated + FROM _time t + JOIN _time_baseline b ON b.label = _timecheck.label + INTO rec; + + RAISE DEBUG 'Uninterrupted baseline: %', rec.baseline; + RAISE DEBUG 'Resulting tolerance: %', rec.tolerated; + + IF rec.lap < rec.tolerated THEN + ret := format( + '%s interrupted on time', + label + ); + ELSE + ret := format( + '%s interrupted late: %s (%s tolerated)', + label, rec.lap, rec.tolerated + ); + END IF; + + UPDATE _time SET t = clock_timestamp(); + + RETURN ret; +END; +$$ LANGUAGE 'plpgsql' VOLATILE; + CREATE TEMPORARY TABLE _time AS SELECT now() t, @@ -45,3 +100,7 @@ SELECT '1' )::float8 sf; +CREATE TEMPORARY TABLE _time_baseline ( + label text PRIMARY KEY, + baseline interval NOT NULL +); ----------------------------------------------------------------------- Summary of changes: NEWS | 3 ++ regress/core/interrupt.sql | 3 ++ regress/core/interrupt_buffer.sql | 3 ++ regress/core/interrupt_relate.sql | 83 +++++++++++++++++++++++++++++++++++---- regress/utils/timecheck.sql | 59 ++++++++++++++++++++++++++++ 5 files changed, 143 insertions(+), 8 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Sat Aug 1 15:56:45 2026 From: git at osgeo.org (git at osgeo.org) Date: Sat, 1 Aug 2026 15:56:45 -0700 (PDT) Subject: [SCM] postgis.net branch website updated. clarity-final-243-g3af133b Message-ID: <20260801225645.33E181BD8C1@trac.osgeo.org> 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.net". The branch, website has been updated via 3af133b8867bf9ae9c8f7a3a10ae69fc058f494e (commit) via 8a97b22827d8248d790b4bd442d449d4099fb5ab (commit) from a5c2c889acde7b0a12358829e5fb09faea05f8e1 (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 3af133b8867bf9ae9c8f7a3a10ae69fc058f494e Merge: a5c2c88 8a97b22 Author: Darafei Praliaskouski Date: Sat Aug 1 15:56:43 2026 -0700 Merge pull request 'Fix the archived raster tutorial link' (!29) from Komzpa/postgis.net:fix/raster-tutorial-wayback-20260802 into website Reviewed-on: https://gitea.osgeo.org/postgis/postgis.net/pulls/29 commit 8a97b22827d8248d790b4bd442d449d4099fb5ab Author: Darafei Praliaskouski Date: Sun Aug 2 02:53:05 2026 +0400 fix: link the archived raster tutorial diff --git a/content/documentation/training.md b/content/documentation/training.md index d400f46..88931de 100644 --- a/content/documentation/training.md +++ b/content/documentation/training.md @@ -141,8 +141,8 @@ new projects. * [PostGIS - das Wo? in der Datenbank](https://wiki.postgresql.org/images/3/31/Postgis_das_wo_in_der_datenbank_pgday_eu_2010.pdf) * [PostGIS, a PostgreSQL module for spatial data](https://wiki.postgresql.org/images/2/2e/Postgis_vincent_picavet_pgdayEU2010.pdf) * [Integrating PostGIS in Web Applications](http://www.postgis.us/downloads/pgconeast2010/pgconeast2010_postgiswebapps.pdf) -* [Historical raster/vector overlay tutorial](/development/docs/history/raster-vector-tutorial/), - Pierre Racine's caribou and SRTM walkthrough updated to current PostGIS names +* [Historical raster/vector overlay tutorial](https://web.archive.org/web/20251112142920/https://trac.osgeo.org/postgis/wiki/WKTRasterTutorial01), + Pierre Racine's original caribou and SRTM walkthrough * [Introducing PostGIS WKT Raster: Seamless Raster/Vector Operations in a Spatial Database](https://web.archive.org/web/20260714021207id_/https://trac.osgeo.org/postgis/raw-attachment/wiki/WKTRaster/FOSS4G2010_Pierre.pdf), Pierre Racine, FOSS4G Barcelona * [PostGIS WKT Raster: An Open Source Alternative to Oracle GeoRaster](https://web.archive.org/web/20260714021203id_/https://trac.osgeo.org/postgis/raw-attachment/wiki/WKTRaster/FOSS4G2010_Jorge.pdf), ----------------------------------------------------------------------- Summary of changes: content/documentation/training.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- postgis.net From trac at osgeo.org Sat Aug 1 17:25:47 2026 From: trac at osgeo.org (PostGIS) Date: Sun, 02 Aug 2026 00:25:47 -0000 Subject: [PostGIS] #2563: Clarify support of standards In-Reply-To: <049.4fb98f84f9df877393c31daf946a9ec7@osgeo.org> References: <049.4fb98f84f9df877393c31daf946a9ec7@osgeo.org> Message-ID: <064.412f3f629eb8d47aa335f5145243194e@osgeo.org> #2563: Clarify support of standards ----------------------------+--------------------------- Reporter: mloskot | Owner: robe Type: defect | Status: closed Priority: medium | Milestone: PostGIS 3.7.0 Component: documentation | Version: 2.0.x Resolution: fixed | Keywords: ogc,sqlmm ----------------------------+--------------------------- Changes (by komzpa): * milestone: PostGIS Fund Me => PostGIS 3.7.0 * resolution: => fixed * status: new => closed -- Ticket URL: PostGIS The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project. From trac at osgeo.org Sat Aug 1 17:26:21 2026 From: trac at osgeo.org (PostGIS) Date: Sun, 02 Aug 2026 00:26:21 -0000 Subject: [PostGIS] #6103: debbie can't build docs In-Reply-To: <046.14db9b84888d45954eeb8442851e145a@osgeo.org> References: <046.14db9b84888d45954eeb8442851e145a@osgeo.org> Message-ID: <061.d7df7867dccbcd64e36eb038074637a8@osgeo.org> #6103: debbie can't build docs ---------------------------+--------------------------- Reporter: robe | Owner: robe Type: defect | Status: closed Priority: blocker | Milestone: PostGIS 3.7.0 Component: QA/buildbots | Version: master Resolution: fixed | Keywords: ---------------------------+--------------------------- Changes (by komzpa): * resolution: => fixed * status: new => closed Comment: should be working now -- Ticket URL: PostGIS The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project. From git at osgeo.org Sat Aug 1 22:33:28 2026 From: git at osgeo.org (git at osgeo.org) Date: Sat, 1 Aug 2026 22:33:28 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-166-g28528f2b7a Message-ID: <20260802053328.731E11CB1DA@trac.osgeo.org> 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 28528f2b7a1cbb6e9b06be3c6422b00db0722b46 (commit) from 263a3dbf965755f09b4f0a3aecc367b131641240 (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 28528f2b7a1cbb6e9b06be3c6422b00db0722b46 Author: Regina Obe Date: Sun Aug 2 01:31:59 2026 -0400 Add regress tests and news for geometry_columns speed issue References #6110 for PostGIS 3.7.0 diff --git a/NEWS b/NEWS index 2269a09052..08d1623765 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,7 @@ These are only changes since 3.7.0beta1. geometry data (Darafei Praliaskouski) - GT-564, Avoid ST_MakePolygon failures with NULL hole array entries (Darafei Praliaskouski) + - #6110, regression in speed with geometry_columns * Enhancements * diff --git a/regress/core/tickets.sql b/regress/core/tickets.sql index fd03131cee..84525a6f9e 100644 --- a/regress/core/tickets.sql +++ b/regress/core/tickets.sql @@ -1813,3 +1813,56 @@ SELECT '#5357', ST_AsText(ST_LineFromEncodedPolyline('__nphBgcoeiA?@', 6), 6); SELECT 'makepolygon-null-holes', ST_NPoints(ST_MakePolygon( 'LINESTRING ZM (0 0 0 0,0 1 0 0,1 1 0 0,0 0 0 0)'::geometry, ARRAY[NULL::geometry])); + +-- ------------------------------------------------------------------------------------- +-- #6110, geometry_columns view should be fast even with many spatial tables +CREATE SCHEMA test6110; + +CREATE FUNCTION test6110_check() RETURNS text AS $$ +DECLARE + t0 timestamptz; + t1 timestamptz; + elapsed interval; + n bigint; + tolerance interval; +BEGIN + tolerance := interval '2 seconds' * COALESCE( + NULLIF(current_setting('test.executor_slow_factor', true), ''), '1' + )::double precision; + + SELECT count(*) INTO n FROM geometry_columns + WHERE f_table_schema = 'test6110'; + IF n <> 1000 THEN + RETURN 'FAIL: count=' || n || ' (expected 1000)'; + END IF; + + t0 := clock_timestamp(); + SELECT count(*) INTO n FROM geometry_columns + WHERE f_table_schema = 'test6110'; + t1 := clock_timestamp(); + elapsed := t1 - t0; + + RAISE LOG 'geometry_columns count of test6110 took % (rows=%)', elapsed, n; + IF elapsed > tolerance THEN + RETURN 'FAIL: count took ' || elapsed || ' > ' || tolerance; + END IF; + RETURN 'PASS'; +END; +$$ LANGUAGE plpgsql; + +DO $$ +DECLARE i integer; +BEGIN + FOR i IN 1..500 LOOP + EXECUTE format('CREATE TABLE test6110.typmod_%s (geom geometry(Point, 4326))', i); + EXECUTE format('CREATE TABLE test6110.constraint_%s (id integer)', i); + EXECUTE format('SELECT AddGeometryColumn(%L, %L, %L, 4326, %L, 2, false)', + 'test6110', 'constraint_' || i, 'geom', 'POINT'); + END LOOP; +END +$$; + +SELECT '#6110', test6110_check(); + +DROP FUNCTION test6110_check(); +DROP SCHEMA test6110 CASCADE; diff --git a/regress/core/tickets_expected b/regress/core/tickets_expected index f6b6ec305c..9cc8aefd9a 100644 --- a/regress/core/tickets_expected +++ b/regress/core/tickets_expected @@ -526,3 +526,4 @@ public|test5978|shape|2|4326|POINT 1|01030000209713000000000000 #5357|LINESTRING(38.903876 55.336448,38.903875 55.336448) makepolygon-null-holes|4 +#6110|PASS ----------------------------------------------------------------------- Summary of changes: NEWS | 1 + regress/core/tickets.sql | 53 +++++++++++++++++++++++++++++++++++++++++++ regress/core/tickets_expected | 1 + 3 files changed, 55 insertions(+) hooks/post-receive -- PostGIS From trac at osgeo.org Sat Aug 1 22:33:30 2026 From: trac at osgeo.org (PostGIS) Date: Sun, 02 Aug 2026 05:33:30 -0000 Subject: [PostGIS] #6110: regressing in speed with geometry_columns In-Reply-To: <046.53d69bab4d7a72af1ecc34e593bfe044@osgeo.org> References: <046.53d69bab4d7a72af1ecc34e593bfe044@osgeo.org> Message-ID: <061.29db453a3ee72ce40a7b5b6836d1f876@osgeo.org> #6110: regressing in speed with geometry_columns ----------------------+--------------------------- Reporter: robe | Owner: pramsey Type: defect | Status: closed Priority: blocker | Milestone: PostGIS 3.7.0 Component: postgis | Version: master Resolution: fixed | Keywords: ----------------------+--------------------------- Comment (by Regina Obe ): In [changeset:"28528f2b7a1cbb6e9b06be3c6422b00db0722b46/git" 28528f2/git]: {{{#!CommitTicketReference repository="git" revision="28528f2b7a1cbb6e9b06be3c6422b00db0722b46" Add regress tests and news for geometry_columns speed issue References #6110 for PostGIS 3.7.0 }}} -- Ticket URL: PostGIS The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project. From git at osgeo.org Sat Aug 1 22:52:27 2026 From: git at osgeo.org (git at osgeo.org) Date: Sat, 1 Aug 2026 22:52:27 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-167-g3d6793d6ad Message-ID: <20260802055228.3FFD81CDCBD@trac.osgeo.org> 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 3d6793d6adbf37144c5024137604b30e04cdc96b (commit) from 28528f2b7a1cbb6e9b06be3c6422b00db0722b46 (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 3d6793d6adbf37144c5024137604b30e04cdc96b Author: Regina Obe Date: Sun Aug 2 01:51:58 2026 -0400 Quite NOTICE in #6110 test References #6110 for PostGIS 3.7.0 diff --git a/regress/core/tickets.sql b/regress/core/tickets.sql index 84525a6f9e..643d921ea6 100644 --- a/regress/core/tickets.sql +++ b/regress/core/tickets.sql @@ -1864,5 +1864,7 @@ $$; SELECT '#6110', test6110_check(); +SET client_min_messages TO WARNING; DROP FUNCTION test6110_check(); DROP SCHEMA test6110 CASCADE; +RESET client_min_messages; ----------------------------------------------------------------------- Summary of changes: regress/core/tickets.sql | 2 ++ 1 file changed, 2 insertions(+) hooks/post-receive -- PostGIS From trac at osgeo.org Sat Aug 1 22:52:30 2026 From: trac at osgeo.org (PostGIS) Date: Sun, 02 Aug 2026 05:52:30 -0000 Subject: [PostGIS] #6110: regressing in speed with geometry_columns In-Reply-To: <046.53d69bab4d7a72af1ecc34e593bfe044@osgeo.org> References: <046.53d69bab4d7a72af1ecc34e593bfe044@osgeo.org> Message-ID: <061.fcce2ec3a2825c11c103d2a89ab3d372@osgeo.org> #6110: regressing in speed with geometry_columns ----------------------+--------------------------- Reporter: robe | Owner: pramsey Type: defect | Status: closed Priority: blocker | Milestone: PostGIS 3.7.0 Component: postgis | Version: master Resolution: fixed | Keywords: ----------------------+--------------------------- Comment (by Regina Obe ): In [changeset:"3d6793d6adbf37144c5024137604b30e04cdc96b/git" 3d6793d/git]: {{{#!CommitTicketReference repository="git" revision="3d6793d6adbf37144c5024137604b30e04cdc96b" Quite NOTICE in #6110 test References #6110 for PostGIS 3.7.0 }}} -- Ticket URL: PostGIS The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project. From trac at osgeo.org Sat Aug 1 23:31:45 2026 From: trac at osgeo.org (PostGIS) Date: Sun, 02 Aug 2026 06:31:45 -0000 Subject: [PostGIS] #2362: Support building with CMake In-Reply-To: <046.26616307945f5a6f3ce87c5787c210c4@osgeo.org> References: <046.26616307945f5a6f3ce87c5787c210c4@osgeo.org> Message-ID: <061.18e4bbed3635a7f9de1da7bb08fc978c@osgeo.org> #2362: Support building with CMake --------------------------+----------------------------- Reporter: robe | Owner: strk Type: enhancement | Status: closed Priority: medium | Milestone: PostGIS Fund Me Component: build | Version: master Resolution: wontfix | Keywords: --------------------------+----------------------------- Changes (by robe): * resolution: => wontfix * status: new => closed -- Ticket URL: PostGIS The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project. From git at osgeo.org Sun Aug 2 00:16:29 2026 From: git at osgeo.org (git at osgeo.org) Date: Sun, 2 Aug 2026 00:16:29 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-171-g7684171f72 Message-ID: <20260802071630.297C91D2E04@trac.osgeo.org> 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 7684171f72b40191e6c7eea82a72a7aa0d83cbc2 (commit) via c01ccdc82f1dde302aea7218587629dd3347c7b6 (commit) from ad95178cf35dd18826561eb64a95a46b3b7ff5d7 (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 7684171f72b40191e6c7eea82a72a7aa0d83cbc2 Merge: ad95178cf3 c01ccdc82f Author: Darafei Praliaskouski Date: Sun Aug 2 00:16:28 2026 -0700 Merge pull request 'Stop -Werror=stringop-overflow rejecting the malformed-NURBS unit test' (!642) from Komzpa/postgis:ci/fix-stringop-overflow-cunit-20260802 into master The `pg14-geos310-gdal33-proj71` matrix cell on GitHub Actions fails on **every** open pull request, and on none of their accounts ? it fails on master: cu_gserialized2.c: In function 'test_gserialized2_malformed_nurbs_degree': cu_gserialized2.c:564:13: error: writing 4 bytes into a region of size 0 [-Werror=stringop-overflow=] 564 | payload[2] = 3; /* Three control points cannot support a degree-3 curve. */ make: *** [GNUmakefile:37: check-unit] Error 1 `test_gserialized2_malformed_nurbs_degree` deliberately corrupts a serialized NURBSCURVE's degree field to prove the parser rejects it, writing through the pointer `gserialized2_get_geometry_p` returns. GCC 10 sizes that region as zero, so an intentional, in-bounds write reads as an overflow and `-Werror` makes it fatal. Routing the pointer through a `noinline` helper leaves the object-size analysis nothing to conclude. This deliberately does **not** suppress the diagnostic for the file ? the rest of `cu_gserialized2.c` keeps being checked ? and does not change what the test asserts. Verified inside the failing image itself (`postgis/postgis-build-env:pg14-geos310-gdal33-proj71`, gcc 10.2.1): the error reproduces before the change, the compile exits 0 after it, and `make -C liblwgeom check-unit` runs 50 suites and 5775 assertions with none failing, the malformed-degree test among them. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/642 commit c01ccdc82f1dde302aea7218587629dd3347c7b6 Author: Darafei Praliaskouski Date: Sun Aug 2 03:11:58 2026 +0400 Stop -Werror=stringop-overflow rejecting the malformed-NURBS test The pg14-geos310-gdal33-proj71 CI cell fails on every pull request, and has nothing to do with any of them. test_gserialized2_malformed_nurbs_degree deliberately corrupts a serialized NURBSCURVE's degree field to prove the parser rejects it, writing through the pointer gserialized2_get_geometry_p returns. GCC 10 sizes that region as zero and reports the write as an overflow: cu_gserialized2.c:564:13: error: writing 4 bytes into a region of size 0 make: *** [GNUmakefile:37: check-unit] Error 1 The write is in bounds; the diagnostic is a false positive from the declared shape of the trailing data member. Route the pointer through a noinline helper so the object-size analysis has nothing to conclude, rather than silencing the warning for the file ? the rest of it should keep checking. Reproduced and fixed inside the failing image itself (postgis/postgis-build-env:pg14-geos310-gdal33-proj71, gcc 10.2.1): the compile now exits 0, and check-unit runs 50 suites and 5775 assertions with none failing, the malformed-degree test among them. diff --git a/liblwgeom/cunit/cu_gserialized2.c b/liblwgeom/cunit/cu_gserialized2.c index c02c5b2f83..c60b0f56b8 100644 --- a/liblwgeom/cunit/cu_gserialized2.c +++ b/liblwgeom/cunit/cu_gserialized2.c @@ -529,6 +529,20 @@ gserialized2_from_hexbytes(const char *hex) static void assert_gserialized2_malformed_rejected(GSERIALIZED *g); +#if defined(__GNUC__) || defined(__clang__) +#define CUNIT_NOINLINE __attribute__((noinline)) +#else +#define CUNIT_NOINLINE +#endif + +static CUNIT_NOINLINE uint8_t * +gserialized2_test_payload_p(GSERIALIZED *g) +{ + return (uint8_t *)(void *)gserialized2_get_geometry_p(g); +} + +#undef CUNIT_NOINLINE + static void test_gserialized2_malformed_collection_count(void) { @@ -552,16 +566,22 @@ test_gserialized2_malformed_nurbs_degree(void) { LWGEOM *lwgeom = lwgeom_from_wkt("NURBSCURVE(2, (0 0, 1 1, 2 0))", LW_PARSER_CHECK_NONE); GSERIALIZED *g; - uint32_t *payload; + uint8_t *payload; + uint32_t type; + uint32_t npoints; + uint32_t degree = 3; CU_ASSERT_PTR_NOT_NULL_FATAL(lwgeom); g = gserialized2_from_lwgeom(lwgeom, NULL); CU_ASSERT_PTR_NOT_NULL_FATAL(g); - payload = (uint32_t *)gserialized2_get_geometry_p(g); - CU_ASSERT_EQUAL(payload[0], NURBSCURVETYPE); - CU_ASSERT_EQUAL(payload[1], 3); - payload[2] = 3; /* Three control points cannot support a degree-3 curve. */ + payload = gserialized2_test_payload_p(g); + memcpy(&type, payload, sizeof(type)); + memcpy(&npoints, payload + sizeof(uint32_t), sizeof(npoints)); + CU_ASSERT_EQUAL(type, NURBSCURVETYPE); + CU_ASSERT_EQUAL(npoints, 3); + /* Three control points cannot support a degree-3 curve. */ + memcpy(payload + 2 * sizeof(uint32_t), °ree, sizeof(degree)); assert_gserialized2_malformed_rejected(g); ----------------------------------------------------------------------- Summary of changes: liblwgeom/cunit/cu_gserialized2.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Sun Aug 2 00:51:18 2026 From: git at osgeo.org (git at osgeo.org) Date: Sun, 2 Aug 2026 00:51:18 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-173-g7bc10724ea Message-ID: <20260802075119.2D3261D6AE4@trac.osgeo.org> 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 7bc10724ea488d17b005ef88d7135c9ce34d0558 (commit) via ef9b2e37ec65d84844d9cc8d6e4ee62cb9d056ac (commit) from 7684171f72b40191e6c7eea82a72a7aa0d83cbc2 (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 7bc10724ea488d17b005ef88d7135c9ce34d0558 Merge: 7684171f72 ef9b2e37ec Author: Darafei Praliaskouski Date: Sun Aug 2 00:51:16 2026 -0700 Merge pull request 'ci: stop ignoring failures in the s390x big-endian step' (!649) from Komzpa/postgis:ci/s390x-stop-ignoring-failures-20260801 into master The s390x step carries `failure: ignore`, so big-endian failures cannot fail a pipeline. The mute's stated reason was to keep it non-blocking "while the first big-endian findings are still being triaged". Over the 200 most recent pipelines this step completed four times and passed all four. There are no findings under triage, so the justification has expired and the mute now only hides whatever comes next. This removes it, and replaces the stale comment with what the measurement actually says. The `when:` gating is untouched: s390x still runs on push, tag and cron rather than on every pull request, because QEMU plus the geospatial dependency closure is expensive. What changes is only that a failure there now fails the workflow, like every other step. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/649 commit ef9b2e37ec65d84844d9cc8d6e4ee62cb9d056ac Author: Darafei Praliaskouski Date: Sat Aug 1 14:13:28 2026 +0400 ci: stop ignoring failures in the s390x big-endian step The mute was conditional from the start -- keep it non-blocking "while the first big-endian findings are still being triaged" -- and the condition has expired without anyone noticing. Over the 200 most recent pipelines the step completed four times and passed all four. Zero failures, so nothing is under triage. A mute whose stated reason has no instances left is not protecting anyone; it just means the project's only big-endian coverage cannot report a regression. The gating is untouched: this still runs on master pushes, tags and cron rather than on every pull request, because QEMU plus the geospatial dependency closure is expensive and that trade-off is still right. Worth knowing when judging this: four completions in 2.8 days is the whole of our big-endian signal, because the step is gated to master pushes and merge bursts cancel those. Unmuting makes each of those four count; it does not make them more frequent. diff --git a/.woodpecker/portability.yml b/.woodpecker/portability.yml index 19e14eb401..6b0eced045 100644 --- a/.woodpecker/portability.yml +++ b/.woodpecker/portability.yml @@ -167,15 +167,18 @@ steps: s390x-big-endian-qemu: image: s390x/debian at sha256:4b236f9aafe8a6201c6dca29ce78c28e1eb1e314ecedc2cd2c545f9e49d060e3 pull: true - failure: ignore # s390x is the only realistic big-endian coverage. It is intentionally not # run on every pull request: QEMU plus the geospatial dependency closure is # expensive, so master pushes, tags, and scheduled runs keep the signal # without making every contributor wait for full emulation. Pull requests # that change this workflow also run it so image and startup changes prove - # themselves before merge. Keep it non-blocking while the first big-endian - # findings are still being triaged; Woodpecker will show the failed step - # without failing the whole workflow. + # themselves before merge. + # + # It used to carry `failure: ignore`, kept "while the first big-endian + # findings are still being triaged". Over the 200 most recent pipelines this + # step completed four times and passed all four; there were no findings under + # triage, so the mute had nothing left to justify it and a failure here now + # fails the workflow like any other. when: - event: [push, tag, cron] branch: master ----------------------------------------------------------------------- Summary of changes: .woodpecker/portability.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Sun Aug 2 01:00:37 2026 From: git at osgeo.org (git at osgeo.org) Date: Sun, 2 Aug 2026 01:00:37 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-175-g08f9832fb3 Message-ID: <20260802080037.CA9751E2E28@trac.osgeo.org> 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 08f9832fb36e066a57e53f285cf33914e9061aaf (commit) via 9067ee7ba05ea014c12f40582715339bd11043f2 (commit) from 7bc10724ea488d17b005ef88d7135c9ce34d0558 (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 08f9832fb36e066a57e53f285cf33914e9061aaf Merge: 7bc10724ea 9067ee7ba0 Author: Darafei Praliaskouski Date: Sun Aug 2 01:00:36 2026 -0700 Merge pull request 'ci: stop ignoring failures in the usan-clang tier' (!645) from Komzpa/postgis:ci/usan-clang-cu-misc-20260801 into master `qa/usan-clang` is muted, so its result cannot fail a pipeline. A check that cannot fail is not a check; this removes the mute so the tier speaks for itself. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/645 commit 9067ee7ba05ea014c12f40582715339bd11043f2 Author: Darafei Praliaskouski Date: Sat Aug 1 04:21:27 2026 +0400 ci: stop ignoring failures in the usan-clang QA step The step was muted with this reason: # Current master trips this sanitizer in liblwgeom/cunit/cu_misc.c; # keep the signal visible without blocking unrelated pull requests. Both halves have stopped being true. The cu_misc.c finding was fixed by a73d06ef7 and the recipe exits 0 on fresh master, so there is nothing left to shield anyone from. And the mute is not protecting unrelated pull requests: it hides failures in the pull requests that cause them. Across the 200 most recent pipelines the step ran 140 times to completion -- 133 success, 7 failure -- and every one of those seven was ignored, leaving its pull request green. They are not sanitizer diagnostics; not one log contains a runtime error: line. The step runs the QA suite inside a sanitizer build, so what it swallowed were ordinary test failures: pipeline 6232, PR 434 topogeo_addlinestring, totopogeom Failed: 2 pipeline 6336, PR 429 topogeo_addlinestring_robust Failed: 1 pipeline 6331, PR 595 raster overview extents Failed: 1 Each was reproduced locally and each is branch-caused: master at f0c84f8c6 passes all three. So the step was reporting correctly and only the mute was discarding the report. Worth stating plainly, because anyone checking today will find those pull requests green: all three branches have since moved on and their current heads pass. The mute did not cause permanent damage. What it cost was time -- the authors were never shown a failure they had introduced, and each was found again later by someone else. That is the argument for removing it, not a claim that defects are sitting there now. Expect this to turn red any pull request that introduces a QA failure, which is the point. diff --git a/.woodpecker/qa.yml b/.woodpecker/qa.yml index 24fdf4e4da..1ebab3437d 100644 --- a/.woodpecker/qa.yml +++ b/.woodpecker/qa.yml @@ -33,9 +33,6 @@ steps: usan-clang: image: *test-image depends_on: autogen - # Current master trips this sanitizer in liblwgeom/cunit/cu_misc.c; - # keep the signal visible without blocking unrelated pull requests. - failure: ignore when: - matrix: QA_MODE: usan_clang ----------------------------------------------------------------------- Summary of changes: .woodpecker/qa.yml | 3 --- 1 file changed, 3 deletions(-) hooks/post-receive -- PostGIS From trac at osgeo.org Sun Aug 2 09:49:52 2026 From: trac at osgeo.org (PostGIS) Date: Sun, 02 Aug 2026 16:49:52 -0000 Subject: [PostGIS] #5967: berrie 32-bit seems to crash often on topology addnode In-Reply-To: <046.a81459a88d4826e5d251096f33bd036e@osgeo.org> References: <046.a81459a88d4826e5d251096f33bd036e@osgeo.org> Message-ID: <061.3ba1c0b6fca48301422e899b2ce6aca8@osgeo.org> #5967: berrie 32-bit seems to crash often on topology addnode -----------------------+--------------------------- Reporter: robe | Owner: strk Type: defect | Status: closed Priority: medium | Milestone: PostGIS 3.7.0 Component: topology | Version: master Resolution: fixed | Keywords: -----------------------+--------------------------- Changes (by komzpa): * resolution: => fixed * status: new => closed -- Ticket URL: PostGIS The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project. From git at osgeo.org Sun Aug 2 12:20:25 2026 From: git at osgeo.org (git at osgeo.org) Date: Sun, 2 Aug 2026 12:20:25 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-177-g07bdf384af Message-ID: <20260802192025.7F02C1C8733@trac.osgeo.org> 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 07bdf384af94565ac3e2ed5774afddea0f5ca548 (commit) via 248b014b9805911792e2fcc097ce7c0cde422308 (commit) from 08f9832fb36e066a57e53f285cf33914e9061aaf (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 07bdf384af94565ac3e2ed5774afddea0f5ca548 Merge: 08f9832fb3 248b014b98 Author: Darafei Praliaskouski Date: Sun Aug 2 12:20:13 2026 -0700 Merge pull request 'Do not ANALYZE inside the extension upgrade transaction' (!650) from Komzpa/postgis:ci/no-analyze-in-extension-script-20260802 into master `spatial_ref_sys.sql` ends with ON CONFLICT (srid) DO NOTHING; COMMIT; ANALYZE "spatial_ref_sys"; The `ANALYZE` follows `COMMIT` on purpose: run standalone, it refreshes the statistics of a table that has just gained thousands of rows, outside any transaction. `extensions/postgis/Makefile.in` strips `BEGIN` and `COMMIT` ? its own comment says why, "these are not allowed in extensions" ? and leaves the `ANALYZE`. So the statement written to run *after* the transaction ends up *inside* the extension upgrade's transaction, takes `ShareUpdateExclusiveLock` on `spatial_ref_sys`, and can deadlock against autovacuum analysing the same table: ERROR: deadlock detected DETAIL: Process 8802 waits for ShareUpdateExclusiveLock on relation 52329 ...; blocked by process 8803. Process 8803 waits for ShareLock on transaction 9332; blocked by process 8802. CONTEXT: SQL statement "ANALYZE "spatial_ref_sys"" extension script file "postgis--ANY--3.7.0dev.sql", near line 45810 **This is not only a CI problem.** `ALTER EXTENSION postgis UPDATE` runs this script on real databases, where autovacuum is running by definition, so an upgrade on a busy installation can simply abort. It also explains real CI noise: three of the eleven most recent failed Woodpecker pipelines died this way, in `regress/test-install` and `regress/test-upgrades`, on ordinary amd64 rows rather than emulated ones. Pull request 626 addressed the same class on armhf by disabling autovacuum in that workflow ? a CI workaround that protects the fleet and leaves users exposed. This strips the `ANALYZE` along with the transaction control it was written to follow. The standalone `spatial_ref_sys.sql` keeps it; autovacuum analyses the table on its own schedule, so the extension script does not need to. Verified by generating the file both ways: the standalone script still ends with `COMMIT;` and `ANALYZE "spatial_ref_sys";`, and the extension copy now ends at `ON CONFLICT (srid) DO NOTHING;`. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/650 commit 248b014b9805911792e2fcc097ce7c0cde422308 Author: Darafei Praliaskouski Date: Sun Aug 2 20:03:01 2026 +0400 Do not ANALYZE inside the extension upgrade transaction spatial_ref_sys.sql ends with ON CONFLICT (srid) DO NOTHING; COMMIT; ANALYZE "spatial_ref_sys"; The ANALYZE sits after COMMIT on purpose: run standalone it refreshes the statistics of a table that just gained thousands of rows, outside any transaction. The extension build strips BEGIN and COMMIT because those are not allowed in extension scripts, and left the ANALYZE behind ? so it ends up *inside* the upgrade's transaction, takes ShareUpdateExclusiveLock on spatial_ref_sys, and can deadlock against autovacuum analysing the same table: ERROR: deadlock detected DETAIL: Process A waits for ShareUpdateExclusiveLock on relation ...; blocked by process B. Process B waits for ShareLock on transaction ...; blocked by process A. CONTEXT: SQL statement "ANALYZE "spatial_ref_sys"" extension script file "postgis--ANY--3.7.0dev.sql" That aborts ALTER EXTENSION postgis UPDATE, so a user upgrading a busy database can simply lose the upgrade. It also accounts for three of the eleven most recent Woodpecker pipeline failures, in regress/test-install and regress/test-upgrades, on ordinary amd64 rows rather than emulated ones. Strip the ANALYZE along with the transaction control it was written to follow. The standalone spatial_ref_sys.sql keeps it; autovacuum analyses the table on its own schedule, so the extension script does not need to. diff --git a/NEWS b/NEWS index 08d1623765..d663d01851 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ These are only changes since 3.7.0beta1. * Bug Fixes * + - Stop the extension upgrade script running ANALYZE inside its transaction, + where it could deadlock with autovacuum (Darafei Praliaskouski) - [liblwgeom] Reject malformed GSERIALIZED NURBS before curve evaluation (Darafei Praliaskouski) - GT-619, Make interrupt regression tests compare timeout latency to diff --git a/extensions/postgis/Makefile.in b/extensions/postgis/Makefile.in index 88ef35afdf..fbf3bd09aa 100644 --- a/extensions/postgis/Makefile.in +++ b/extensions/postgis/Makefile.in @@ -104,9 +104,21 @@ sql/$(EXTENSION)--unpackaged.sql: Makefile | sql sql: mkdir -p $@ -#strip BEGIN/COMMIT since these are not allowed in extensions +# Strip BEGIN/COMMIT since these are not allowed in extensions, and the trailing +# ANALYZE with them. In spatial_ref_sys.sql that ANALYZE deliberately sits *after* +# COMMIT, so run standalone it refreshes statistics outside any transaction. Removing +# only the COMMIT moves it inside the extension's transaction, where it takes +# ShareUpdateExclusiveLock on spatial_ref_sys and can deadlock against autovacuum +# doing the same work: +# +# ERROR: deadlock detected +# CONTEXT: SQL statement "ANALYZE "spatial_ref_sys"" +# extension script file "postgis--ANY--.sql" +# +# That aborts ALTER EXTENSION postgis UPDATE on any busy database. Autovacuum will +# analyse the table on its own schedule, so the extension script does not need to. sql/spatial_ref_sys.sql: ../../spatial_ref_sys.sql | sql - $(PERL) -pe 's/BEGIN\;//g ; s/COMMIT\;//g' $< > $@ + $(PERL) -pe 's/BEGIN\;//g ; s/COMMIT\;//g ; s/^ANALYZE "spatial_ref_sys";\s*$$//g' $< > $@ sql/spatial_ref_sys_config_dump.sql: ../../spatial_ref_sys.sql ../../utils/create_spatial_ref_sys_config_dump.pl | sql $(PERL) @top_srcdir@/utils/create_spatial_ref_sys_config_dump.pl $< > $@ ----------------------------------------------------------------------- Summary of changes: NEWS | 2 ++ extensions/postgis/Makefile.in | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Sun Aug 2 12:24:21 2026 From: git at osgeo.org (git at osgeo.org) Date: Sun, 2 Aug 2026 12:24:21 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-183-g4852079f40 Message-ID: <20260802192422.8E7F11CBFD7@trac.osgeo.org> 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 4852079f40ba8e51f03997aeb6dceac331826694 (commit) via bdc18950063dd6c16947bc8ef5ea4c14decf67de (commit) via 1d92c46f6e7383e26cb369e81436f13dc030449f (commit) via bd815c84cb1a28d49386020f67495da085dcf998 (commit) via 582281454178074d92fc9e7c6db08e940810461f (commit) via 06f1e55ec0e15e47eb4ba812e16a797a99e548be (commit) from 07bdf384af94565ac3e2ed5774afddea0f5ca548 (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 4852079f40ba8e51f03997aeb6dceac331826694 Merge: 07bdf384af bdc1895006 Author: Darafei Praliaskouski Date: Sun Aug 2 12:24:20 2026 -0700 Merge pull request 'ci: add Woodpecker MinGW Wine coverage' (!520) from Komzpa/postgis:codex/woodie-mingw-wine into master This adds a Woodpecker Linux amd64 workflow that gives woodie Windows-target PostGIS coverage without needing a native Windows worker. The job cross-compiles the MinGW-w64 dependency stack and PostGIS, runs the Windows client-side binaries under Wine, starts a real PostgreSQL for Windows server under Wine, installs PostGIS into that server, and drives the normal Linux shell/Perl regression harness over TCP to `127.0.0.1`. The dependency stack includes SQLite, zlib, libjpeg-turbo, libpng, libiconv, GMP, CUnit, GEOS, PROJ, libtiff, libgeotiff, GDAL, json-c, protobuf-c, libxml2, and libpq. PostGIS is configured for `x86_64-w64-mingw32` with raster, topology, JSON-C, protobuf-c, PROJ, GEOS, GDAL, and libxml2 enabled. SFCGAL remains disabled for a concrete dependency reason rather than as a hidden coverage gap: Debian bookworm does not provide MinGW-targeted SFCGAL or CGAL packages. Enabling SFCGAL in this job requires cross-building at least SFCGAL, CGAL, Boost thread/serialization, GMP, MPFR, and nlohmann-json before configuring PostGIS with `--with-sfcgal`. The workflow lives in `.woodpecker/mingw-wine.yml` and its helper is `ci/woodie/postgis_mingw_wine.sh`. The broader legacy helper-directory rename from `ci/dronie` to `ci/woodie` is handled separately in https://gitea.osgeo.org/postgis/postgis/pulls/573 so this pull request can stay focused on the MinGW Wine coverage. The Wine setup keeps scratch state in the workspace `.tmp` tree, including the Wine prefix, Wine temp directory, downloaded PostgreSQL zip, staged PostgreSQL tree, and PostgreSQL data directory. The job uses WineHQ stable rather than Debian bookworm Wine because bookworm's Wine 8 did not run the official PostgreSQL 17 Windows binaries reliably. PostgreSQL runs with TCP on `127.0.0.1`, `unix_socket_directories = ''`, `dynamic_shared_memory_type = windows`, small shared buffers, trust auth, and `fsync = off` for CI. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/520 commit bdc18950063dd6c16947bc8ef5ea4c14decf67de Author: Darafei Praliaskouski Date: Tue Jul 28 21:08:46 2026 +0400 ci: keep MinGW Wine on EDB-reachable runner diff --git a/.woodpecker/mingw-wine.yml b/.woodpecker/mingw-wine.yml index ed79a30953..719d0826a4 100644 --- a/.woodpecker/mingw-wine.yml +++ b/.woodpecker/mingw-wine.yml @@ -1,5 +1,6 @@ labels: platform: linux/amd64 + hostname: smallcat when: event: [push, pull_request, tag] diff --git a/ci/woodie/postgis_mingw_wine.sh b/ci/woodie/postgis_mingw_wine.sh index 8b0fc5a844..b0ea9a4bac 100755 --- a/ci/woodie/postgis_mingw_wine.sh +++ b/ci/woodie/postgis_mingw_wine.sh @@ -10,7 +10,7 @@ PREFIX=${PREFIX:-${TMP_ROOT}/prefix} WORKDIR=${WORKDIR:-${TMP_ROOT}/work} LOG_DIR=${LOG_DIR:-${TMP_ROOT}/logs} DOWNLOAD_DIR=${DOWNLOAD_DIR:-${TMP_ROOT}/downloads} -PGWIN_URL=${PGWIN_URL:-https://get.enterprisedb.com/postgresql/postgresql-17.10-1-windows-x64-binaries.zip} +PGWIN_URL=${PGWIN_URL:-https://get.enterprisedb.com/postgresql/postgresql-17.10-2-windows-x64-binaries.zip} VCREDIST_URL=${VCREDIST_URL:-https://aka.ms/vs/17/release/vc_redist.x64.exe} INSTALL_VC_RUNTIME=${INSTALL_VC_RUNTIME:-0} PGWIN_ROOT=${PGWIN_ROOT:-${TMP_ROOT}/postgresql-windows/pgsql} commit 1d92c46f6e7383e26cb369e81436f13dc030449f Author: Darafei Praliaskouski Date: Tue Jul 28 03:45:05 2026 +0400 ci: update MinGW Wine review follow-ups diff --git a/.woodpecker/mingw-wine.yml b/.woodpecker/mingw-wine.yml index 77bb48e8ed..ed79a30953 100644 --- a/.woodpecker/mingw-wine.yml +++ b/.woodpecker/mingw-wine.yml @@ -15,4 +15,4 @@ steps: image: debian:bookworm pull: true commands: - - bash ci/dronie/postgis_mingw_wine.sh + - bash ci/woodie/postgis_mingw_wine.sh diff --git a/ci/woodie/postgis_mingw_wine.sh b/ci/woodie/postgis_mingw_wine.sh index 481712dc0c..8b0fc5a844 100755 --- a/ci/woodie/postgis_mingw_wine.sh +++ b/ci/woodie/postgis_mingw_wine.sh @@ -592,6 +592,9 @@ configure_postgis() export PROTOBUFC_CFLAGS="-I${PREFIX}/include" export PROTOBUFC_LIBS="-L${PREFIX}/lib -lprotobuf-c" + # Debian does not package a MinGW SFCGAL/CGAL stack. Enabling SFCGAL here + # requires cross-building SFCGAL, CGAL, Boost thread/serialization, GMP, + # MPFR, and nlohmann-json before running PostGIS configure. run_logged "${LOG_DIR}/postgis.configure.log" "${REPO_ROOT}/configure" \ --host="${TARGET}" \ --prefix="${PREFIX}" \ diff --git a/doc/development/testing/ci.md b/doc/development/testing/ci.md index 38360f08ad..1181e7945a 100644 --- a/doc/development/testing/ci.md +++ b/doc/development/testing/ci.md @@ -30,7 +30,7 @@ service that owns the behavior: | Winnie Windows jobs | `ci/winnie/` and the Winnie Jenkins jobs | | Bessie and Berrie/Berrie64 jobs | `ci/bessie/`, `ci/berrie*`, and the corresponding Jenkins worker labels | | Docker build images used by GitHub Actions | `postgis/postgis-build-env` image tags referenced from `.github/workflows/ci.yml` | -| Woodpecker MinGW Wine job | `.woodpecker/mingw-wine.yml` and `ci/dronie/postgis_mingw_wine.sh` | +| Woodpecker MinGW Wine job | `.woodpecker/mingw-wine.yml` and `ci/woodie/postgis_mingw_wine.sh` | When a dashboard row describes dependency versions, operating systems, branch coverage, or test modes, the row should be regenerated from those sources or @@ -199,9 +199,7 @@ Keep the remaining gaps explicit when changing this job: * Native Windows runtime behavior is only partially covered: Wine can expose Windows CRT, locale, codepage, threading, file-locking, and DLL-search issues, but it is not a substitute for running the same binaries on Windows. -* SFCGAL is not built in this job unless the script also provides a MinGW - SFCGAL dependency stack. The job must not report SFCGAL coverage merely - because the rest of PostGIS was configured. -* `address_standardizer` and the tiger geocoder are not part of this repository. - They need their own repository-owned Windows or Wine coverage if that scope is - required. +* SFCGAL is not built in this job because Debian does not provide MinGW-targeted + SFCGAL or CGAL packages. Enabling it requires cross-building at least the + SFCGAL, CGAL, Boost thread/serialization, GMP, MPFR, and nlohmann-json stack + before PostGIS is configured with `--with-sfcgal`. commit bd815c84cb1a28d49386020f67495da085dcf998 Author: Darafei Praliaskouski Date: Tue Jul 28 02:40:36 2026 +0400 ci: maximize MinGW Wine coverage diff --git a/ci/woodie/postgis_mingw_wine.sh b/ci/woodie/postgis_mingw_wine.sh index 8153352646..481712dc0c 100755 --- a/ci/woodie/postgis_mingw_wine.sh +++ b/ci/woodie/postgis_mingw_wine.sh @@ -40,7 +40,7 @@ export WINEPREFIX=${DEFAULT_WINEPREFIX} export WINEARCH=${WINEARCH:-win64} WINE_TMPDIR=${WINE_TMPDIR:-${TMP_ROOT}/wine-tmp} WINE=${WINE:-wine} -XVFB_WINE=(env -u XDG_RUNTIME_DIR TMPDIR="${WINE_TMPDIR}" xvfb-run -a "${WINE}") +XVFB_WINE=(env -u XDG_RUNTIME_DIR -u DISPLAY -u WAYLAND_DISPLAY TMPDIR="${WINE_TMPDIR}" xvfb-run -a "${WINE}") CURL=(curl --retry 5 --retry-delay 5 --retry-all-errors --connect-timeout 30 -fL) phase_log() @@ -615,13 +615,21 @@ build_postgis_targets() { cd "${REPO_ROOT}/${BUILD_DIR}" run_logged "${LOG_DIR}/postgis.make.log" make -j1 - run_logged "${LOG_DIR}/postgis.cunit.make.log" make -C liblwgeom/cunit -j1 + run_logged "${LOG_DIR}/postgis.cunit.make.log" make -C liblwgeom/cunit all -j1 + run_logged "${LOG_DIR}/postgis.backend-cunit.make.log" make -C postgis/cunit all -j1 + run_logged "${LOG_DIR}/postgis.loader-cunit.make.log" make -C loader/cunit all -j1 + run_logged "${LOG_DIR}/postgis.raster-cunit.make.log" make -C raster/test/cunit all -j1 run_logged "${LOG_DIR}/postgis.install.log" make install + run_logged "${LOG_DIR}/postgis.install-upgrades.log" make install-extension-upgrades-from-known-versions echo "BUILD_TAIL_BEGIN" tail -120 "${LOG_DIR}/postgis.make.log" tail -80 "${LOG_DIR}/postgis.cunit.make.log" + tail -80 "${LOG_DIR}/postgis.backend-cunit.make.log" + tail -80 "${LOG_DIR}/postgis.loader-cunit.make.log" + tail -80 "${LOG_DIR}/postgis.raster-cunit.make.log" tail -120 "${LOG_DIR}/postgis.install.log" + tail -80 "${LOG_DIR}/postgis.install-upgrades.log" echo "BUILD_TAIL_END" } @@ -633,15 +641,47 @@ copy_mingw_runtime_dlls() path=$(find "/usr/lib/gcc/${TARGET}" "/usr/${TARGET}" "${PREFIX}" -name "${dll}" -print -quit 2>/dev/null || true) if test -n "${path}"; then cp "${path}" liblwgeom/cunit/ + cp "${path}" postgis/cunit/ + cp "${path}" loader/cunit/ cp "${path}" loader/ if test -d raster/loader; then cp "${path}" raster/loader/ fi + if test -d raster/test/cunit; then + cp "${path}" raster/test/cunit/ + fi cp "${path}" "${PGWIN_ROOT}/bin/" || true fi done } +cunit_runner() +{ + local dir=$1 + local runner + for runner in "${dir}/cu_tester.exe" "${dir}/.libs/cu_tester.exe" "${dir}/cu_tester"; do + if test -f "${runner}"; then + printf '%s\n' "${runner}" + return 0 + fi + done + echo "CUnit runner not found under ${dir}" >&2 + exit 1 +} + +run_cunit_wine_suite() +{ + local name=$1 + local dir=$2 + local runner + runner=$(cunit_runner "${dir}") + "${XVFB_WINE[@]}" "${runner}" > "${LOG_DIR}/${name}.cunit.wine.log" 2>&1 \ + || log_tail "$?" "${LOG_DIR}/${name}.cunit.wine.log" + echo "CUNIT_WINE_${name}_BEGIN" + tail -80 "${LOG_DIR}/${name}.cunit.wine.log" + echo "CUNIT_WINE_${name}_END" +} + prepare_wine_prefix() { local status @@ -659,23 +699,17 @@ prepare_wine_prefix() run_wine_checks() { - local cunit_runner cd "${REPO_ROOT}/${BUILD_DIR}" - cunit_runner=liblwgeom/cunit/cu_tester.exe - if test ! -f "${cunit_runner}"; then - cunit_runner=liblwgeom/cunit/cu_tester - fi case "${WINEPREFIX}" in "${TMP_ROOT}"/*) rm -rf "${WINEPREFIX}" ;; esac prepare_wine_prefix copy_mingw_runtime_dlls - "${XVFB_WINE[@]}" "${cunit_runner}" > "${LOG_DIR}/postgis.cunit.wine.log" 2>&1 \ - || log_tail "$?" "${LOG_DIR}/postgis.cunit.wine.log" - echo "CUNIT_WINE_BEGIN" - tail -80 "${LOG_DIR}/postgis.cunit.wine.log" - echo "CUNIT_WINE_END" + run_cunit_wine_suite liblwgeom liblwgeom/cunit + run_cunit_wine_suite postgis postgis/cunit + run_cunit_wine_suite loader loader/cunit + run_cunit_wine_suite raster raster/test/cunit "${XVFB_WINE[@]}" loader/shp2pgsql.exe -s 4326 "${REPO_ROOT}/regress/loader/Point" public.point \ > "${LOG_DIR}/point.sql" 2>"${LOG_DIR}/shp2pgsql.stderr" \ @@ -813,19 +847,48 @@ install_regression_wrappers() fi cat >"${wrapdir}/${exe}" <"${wrapdir}/${exe}" < Date: Sun Jul 26 15:25:52 2026 +0400 ci: run full MinGW Wine PostGIS regressions diff --git a/ci/woodie/postgis_mingw_wine.sh b/ci/woodie/postgis_mingw_wine.sh index 42df01ab0f..8153352646 100755 --- a/ci/woodie/postgis_mingw_wine.sh +++ b/ci/woodie/postgis_mingw_wine.sh @@ -3,12 +3,26 @@ set -Eeuo pipefail TARGET=${TARGET:-x86_64-w64-mingw32} -PREFIX=${PREFIX:-/opt/postgis-mingw} -BUILD_DIR=${BUILD_DIR:-build-mingw-wine} +BUILD_DIR=${BUILD_DIR:-.tmp/build-mingw-wine} REPO_ROOT=$(pwd) TMP_ROOT=${TMP_ROOT:-${REPO_ROOT}/.tmp/mingw-wine} +PREFIX=${PREFIX:-${TMP_ROOT}/prefix} WORKDIR=${WORKDIR:-${TMP_ROOT}/work} LOG_DIR=${LOG_DIR:-${TMP_ROOT}/logs} +DOWNLOAD_DIR=${DOWNLOAD_DIR:-${TMP_ROOT}/downloads} +PGWIN_URL=${PGWIN_URL:-https://get.enterprisedb.com/postgresql/postgresql-17.10-1-windows-x64-binaries.zip} +VCREDIST_URL=${VCREDIST_URL:-https://aka.ms/vs/17/release/vc_redist.x64.exe} +INSTALL_VC_RUNTIME=${INSTALL_VC_RUNTIME:-0} +PGWIN_ROOT=${PGWIN_ROOT:-${TMP_ROOT}/postgresql-windows/pgsql} +PGDATA=${PGDATA:-${TMP_ROOT}/pgdata} +DEFAULT_WINEPREFIX=${WINEPREFIX:-${TMP_ROOT}/wine-prefix} +PGWIN_RUN_ROOT=${PGWIN_RUN_ROOT:-${DEFAULT_WINEPREFIX}/drive_c/pgsql} +PGDATA_RUN=${PGDATA_RUN:-${DEFAULT_WINEPREFIX}/drive_c/pgdata} +PGHOST=${PGHOST:-127.0.0.1} +PGPORT=${PGPORT:-55432} +PGUSER=${PGUSER:-postgres} +RUN_FROM=${RUN_FROM:-} +RUN_FROM_ACTIVE= export DEBIAN_FRONTEND=noninteractive export PATH="${PREFIX}/bin:/usr/${TARGET}/bin:${PATH}" @@ -21,10 +35,50 @@ export WINDRES=${WINDRES:-${TARGET}-windres} export PKG_CONFIG_LIBDIR="${PREFIX}/lib/pkgconfig" export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig" export WINEDEBUG=${WINEDEBUG:--all} -export WINEPREFIX=${WINEPREFIX:-/tmp/postgis-wine} +export WINEDLLOVERRIDES=${WINEDLLOVERRIDES:-mscoree,mshtml=} +export WINEPREFIX=${DEFAULT_WINEPREFIX} export WINEARCH=${WINEARCH:-win64} -WINE_TMPDIR=${WINE_TMPDIR:-/tmp} +WINE_TMPDIR=${WINE_TMPDIR:-${TMP_ROOT}/wine-tmp} WINE=${WINE:-wine} +XVFB_WINE=(env -u XDG_RUNTIME_DIR TMPDIR="${WINE_TMPDIR}" xvfb-run -a "${WINE}") +CURL=(curl --retry 5 --retry-delay 5 --retry-all-errors --connect-timeout 30 -fL) + +phase_log() +{ + local message=$1 + echo "${message}" | tee -a "${LOG_DIR}/phase-times.log" +} + +phase() +{ + local name=$1 + local started + shift + if test -n "${RUN_FROM}" && test -z "${RUN_FROM_ACTIVE}"; then + if test "${name}" = "${RUN_FROM}"; then + RUN_FROM_ACTIVE=1 + else + phase_log "PHASE_SKIP ${name}" + return 0 + fi + fi + started=$(date +%s) + phase_log "PHASE_BEGIN ${name}" + "$@" + phase_log "PHASE_SECONDS ${name} $(( $(date +%s) - started ))" +} + +src_dir() +{ + local pattern=$1 + local found + found=$(find "${WORKDIR}/src" -maxdepth 1 -type d -name "${pattern}" -print | sort | head -1) + if test -z "${found}"; then + echo "source directory matching ${pattern} not found under ${WORKDIR}/src" >&2 + exit 1 + fi + printf '%s\n' "${found}" +} log_tail() { @@ -42,12 +96,20 @@ run_logged() "$@" >"${log}" 2>&1 || log_tail "$?" "${log}" } +run_autogen() +{ + cd "${REPO_ROOT}" + ./autogen.sh >"${LOG_DIR}/postgis.autogen.log" 2>&1 || log_tail "$?" "${LOG_DIR}/postgis.autogen.log" +} + install_packages() { + dpkg --add-architecture i386 apt-get update >/dev/null apt-get install -y --no-install-recommends \ ca-certificates \ curl \ + gpg \ dpkg-dev \ build-essential \ autoconf \ @@ -61,32 +123,42 @@ install_packages() gettext \ perl \ sqlite3 \ + postgresql-client \ + unzip \ mingw-w64 \ gcc-mingw-w64-x86-64-posix \ g++-mingw-w64-x86-64-posix \ - wine \ - wine64 \ + protobuf-c-compiler \ + protobuf-compiler \ xauth \ xvfb \ diffutils >/dev/null + install -d -m 755 /etc/apt/keyrings + rm -f /etc/apt/keyrings/winehq-archive.key + "${CURL[@]}" https://dl.winehq.org/wine-builds/winehq.key \ + | gpg --dearmor -o /etc/apt/keyrings/winehq-archive.key + cat >/etc/apt/sources.list.d/winehq.list <<'EOF' +deb [signed-by=/etc/apt/keyrings/winehq-archive.key] https://dl.winehq.org/wine-builds/debian/ bookworm main +EOF cat >/etc/apt/sources.list.d/postgis-mingw-wine-src.list <<'EOF' deb-src http://deb.debian.org/debian trixie main deb-src http://deb.debian.org/debian-security trixie-security main deb-src http://deb.debian.org/debian trixie-updates main EOF apt-get update >/dev/null + apt-get install -y --install-recommends winehq-stable >/dev/null } fetch_sources() { rm -rf "${WORKDIR}" - mkdir -p "${WORKDIR}/src" "${PREFIX}/include" "${PREFIX}/lib/pkgconfig" + mkdir -p "${WORKDIR}/src" "${PREFIX}/include" "${PREFIX}/lib/pkgconfig" "${DOWNLOAD_DIR}" cd "${WORKDIR}/src" - apt-get source cunit geos proj libxml2 postgresql-17 >/dev/null - curl -fsSLO https://www.sqlite.org/2024/sqlite-autoconf-3460100.tar.gz - curl -fsSLO https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.18.tar.gz - curl -fsSLO https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz + apt-get source cunit geos proj libxml2 postgresql-17 zlib libjpeg-turbo libpng1.6 tiff libgeotiff gdal json-c protobuf-c >/dev/null + "${CURL[@]}" -O https://www.sqlite.org/2024/sqlite-autoconf-3460100.tar.gz + "${CURL[@]}" -O https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.18.tar.gz + "${CURL[@]}" -O https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz tar xf sqlite-autoconf-3460100.tar.gz tar xf libiconv-1.18.tar.gz tar xf gmp-6.3.0.tar.xz @@ -95,7 +167,7 @@ fetch_sources() build_sqlite() { cd "${WORKDIR}/src/sqlite-autoconf-3460100" - ${CC} -O2 -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -c sqlite3.c -o sqlite3.o + ${CC} -O2 -DSQLITE_THREADSAFE=1 -DSQLITE_OMIT_LOAD_EXTENSION -c sqlite3.c -o sqlite3.o cp sqlite3.h sqlite3ext.h "${PREFIX}/include/" ${AR} rcs "${PREFIX}/lib/libsqlite3.a" sqlite3.o cat >"${PREFIX}/lib/pkgconfig/sqlite3.pc" <"${PREFIX}/bin/${TARGET}-pg_config" <&2; exit 1 ;; esac EOF chmod +x "${PREFIX}/bin/${TARGET}-pg_config" + cp "${PREFIX}/bin/${TARGET}-pg_config" "${PREFIX}/bin/pg_config" } build_proj() { + rm -rf "${WORKDIR}/build-proj" run_logged "${LOG_DIR}/proj.configure.log" cmake \ -S "${WORKDIR}/src/proj-9.6.0" \ -B "${WORKDIR}/build-proj" \ -G Ninja \ -DCMAKE_SYSTEM_NAME=Windows \ + -DCMAKE_SYSTEM_PROCESSOR=x86_64 \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_C_COMPILER="${CC}" \ -DCMAKE_CXX_COMPILER="${CXX}" \ -DCMAKE_INSTALL_PREFIX="${PREFIX}" \ @@ -255,6 +492,91 @@ build_proj() run_logged "${LOG_DIR}/proj.install.log" cmake --install "${WORKDIR}/build-proj" } +build_gdal() +{ + local libstdcxx + libstdcxx=$("${CXX}" -print-file-name=libstdc++.a) + + rm -rf "${WORKDIR}/build-gdal" + run_logged "${LOG_DIR}/gdal.configure.log" cmake \ + -S "$(src_dir 'gdal-*')" \ + -B "${WORKDIR}/build-gdal" \ + -G Ninja \ + -DCMAKE_SYSTEM_NAME=Windows \ + -DCMAKE_SYSTEM_PROCESSOR=x86_64 \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ + -DCMAKE_C_COMPILER="${CC}" \ + -DCMAKE_CXX_COMPILER="${CXX}" \ + -DCMAKE_RC_COMPILER="${WINDRES}" \ + -DCMAKE_INSTALL_PREFIX="${PREFIX}" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH="${PREFIX}" \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_APPS=OFF \ + -DBUILD_TESTING=OFF \ + -DGDAL_USE_EXTERNAL_LIBS=OFF \ + -DGDAL_USE_ZLIB=ON \ + -DGDAL_USE_TIFF=ON \ + -DGDAL_USE_GEOTIFF=ON \ + -DGDAL_USE_PNG=ON \ + -DGDAL_USE_JPEG=ON \ + -DGDAL_USE_SQLITE3=ON \ + -DGDAL_USE_PROJ=ON \ + -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \ + -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_ENABLE_DRIVER_GTIFF=ON \ + -DGDAL_ENABLE_DRIVER_MEM=ON \ + -DGDAL_ENABLE_DRIVER_VRT=ON \ + -DGDAL_ENABLE_DRIVER_PNG=ON \ + -DGDAL_ENABLE_DRIVER_JPEG=ON \ + -DOGR_ENABLE_DRIVER_MEM=ON \ + -DZLIB_INCLUDE_DIR="${PREFIX}/include" \ + -DZLIB_LIBRARY="${PREFIX}/lib/libz.a" \ + -DTIFF_INCLUDE_DIR="${PREFIX}/include" \ + -DTIFF_LIBRARY="${PREFIX}/lib/libtiff.a" \ + -DGEOTIFF_INCLUDE_DIR="${PREFIX}/include" \ + -DGEOTIFF_LIBRARY="${PREFIX}/lib/libgeotiff.a" \ + -DPNG_PNG_INCLUDE_DIR="${PREFIX}/include" \ + -DPNG_LIBRARY="${PREFIX}/lib/libpng16.a" \ + -DJPEG_INCLUDE_DIR="${PREFIX}/include" \ + -DJPEG_LIBRARY="${PREFIX}/lib/libjpeg.a" \ + -DSQLite3_INCLUDE_DIR="${PREFIX}/include" \ + -DSQLite3_LIBRARY="${PREFIX}/lib/libsqlite3.a" \ + -DPROJ_INCLUDE_DIR="${PREFIX}/include" \ + -DPROJ_LIBRARY="${PREFIX}/lib/libproj.a" + run_logged "${LOG_DIR}/gdal.make.log" cmake --build "${WORKDIR}/build-gdal" -j"$(nproc)" + run_logged "${LOG_DIR}/gdal.install.log" cmake --install "${WORKDIR}/build-gdal" + cat >"${PREFIX}/bin/${TARGET}-gdal-config" </dev/null || echo "3.10.3" ;; + --ogr-enabled) echo "yes" ;; + --cflags) echo "-I${PREFIX}/include" ;; + --libs) echo "-L${PREFIX}/lib -lgdal -lgeotiff -ltiff -lpng -ljpeg -lz -lproj -lsqlite3 ${libstdcxx} -lwinpthread -lws2_32 -lbcrypt -lole32 -lshell32 -lcrypt32 -lversion -lshlwapi" ;; + *) echo "unsupported gdal-config option: \$1" >&2; exit 1 ;; +esac +EOF + chmod +x "${PREFIX}/bin/${TARGET}-gdal-config" + echo "GDAL_CONFIG_SUMMARY_BEGIN" + sed -n '/-- The following features have been enabled/,/-- The following features have been disabled/p' "${LOG_DIR}/gdal.configure.log" | sed -n '1,160p' + echo "GDAL_CONFIG_SUMMARY_END" +} + +setup_postgresql_windows() +{ + local zip + zip="${DOWNLOAD_DIR}/$(basename "${PGWIN_URL}")" + if test ! -f "${zip}"; then + "${CURL[@]}" "${PGWIN_URL}" -o "${zip}" + fi + rm -rf "${TMP_ROOT}/postgresql-windows" + mkdir -p "${TMP_ROOT}/postgresql-windows" + unzip -q "${zip}" -d "${TMP_ROOT}/postgresql-windows" + find "${PGWIN_ROOT}/bin" -maxdepth 1 -type f \( -iname '*.exe' -o -iname '*.dll' \) -exec chmod +x {} + + test -f "${PGWIN_ROOT}/bin/postgres.exe" + test -f "${PGWIN_ROOT}/bin/initdb.exe" +} + configure_postgis() { rm -rf "${BUILD_DIR}" @@ -264,16 +586,22 @@ configure_postgis() export GEOS_CFLAGS="-I${PREFIX}/include" export GEOS_LIBS="-L${PREFIX}/lib -lgeos_c -lgeos -lstdc++" export PROJ_CFLAGS="-I${PREFIX}/include" - export PROJ_LIBS="-L${PREFIX}/lib -lproj -lsqlite3 -lstdc++ -lws2_32 -lbcrypt -lole32 -lshell32" + export PROJ_LIBS="-L${PREFIX}/lib -lproj -lsqlite3 -lstdc++ -lwinpthread -lws2_32 -lbcrypt -lole32 -lshell32" + export JSONC_CFLAGS="-I${PREFIX}/include/json-c" + export JSONC_LIBS="-L${PREFIX}/lib -ljson-c" + export PROTOBUFC_CFLAGS="-I${PREFIX}/include" + export PROTOBUFC_LIBS="-L${PREFIX}/lib -lprotobuf-c" - run_logged "${LOG_DIR}/postgis.configure.log" ../configure \ + run_logged "${LOG_DIR}/postgis.configure.log" "${REPO_ROOT}/configure" \ --host="${TARGET}" \ + --prefix="${PREFIX}" \ + --mandir="${PREFIX}/share/man" \ --with-pgconfig="${PREFIX}/bin/${TARGET}-pg_config" \ --with-geosconfig="${PREFIX}/bin/${TARGET}-geos-config" \ + --with-gdalconfig="${PREFIX}/bin/${TARGET}-gdal-config" \ --with-xml2config="${PREFIX}/bin/xml2-config" \ --with-libiconv="${PREFIX}" \ - --without-protobuf \ - --without-raster \ + --without-sfcgal \ --disable-spellcheck-tests \ CFLAGS="-O2 -Wall" \ LDFLAGS="-L${PREFIX}/lib -static -static-libgcc -static-libstdc++" @@ -285,14 +613,15 @@ configure_postgis() build_postgis_targets() { - run_logged "${LOG_DIR}/postgis.liblwgeom.make.log" make -j"$(nproc)" -C liblwgeom - run_logged "${LOG_DIR}/postgis.cunit.make.log" make -j"$(nproc)" -C liblwgeom/cunit cu_tester - run_logged "${LOG_DIR}/postgis.loader.make.log" make -j"$(nproc)" -C loader shp2pgsql.exe pgsql2shp.exe + cd "${REPO_ROOT}/${BUILD_DIR}" + run_logged "${LOG_DIR}/postgis.make.log" make -j1 + run_logged "${LOG_DIR}/postgis.cunit.make.log" make -C liblwgeom/cunit -j1 + run_logged "${LOG_DIR}/postgis.install.log" make install echo "BUILD_TAIL_BEGIN" - tail -40 "${LOG_DIR}/postgis.liblwgeom.make.log" - tail -40 "${LOG_DIR}/postgis.cunit.make.log" - tail -60 "${LOG_DIR}/postgis.loader.make.log" + tail -120 "${LOG_DIR}/postgis.make.log" + tail -80 "${LOG_DIR}/postgis.cunit.make.log" + tail -120 "${LOG_DIR}/postgis.install.log" echo "BUILD_TAIL_END" } @@ -305,29 +634,50 @@ copy_mingw_runtime_dlls() if test -n "${path}"; then cp "${path}" liblwgeom/cunit/ cp "${path}" loader/ + if test -d raster/loader; then + cp "${path}" raster/loader/ + fi + cp "${path}" "${PGWIN_ROOT}/bin/" || true fi done } +prepare_wine_prefix() +{ + local status + mkdir -p "${WINE_TMPDIR}" + # Debian bookworm's Wine 8 misreports PostgreSQL Windows binaries as invalid. + # WineHQ stable carries the fix, but disable GUI bootstrap extras for headless CI. + timeout 240 "${XVFB_WINE[@]}" reg add 'HKEY_CURRENT_USER\Software\Wine\WineDbg' \ + /v ShowCrashDialog /t REG_DWORD /d 0 /f \ + > "${LOG_DIR}/wine.reg.log" 2>&1 || { + status=$? + "${WINE}" wineserver -k >/dev/null 2>&1 || true + log_tail "${status}" "${LOG_DIR}/wine.reg.log" + } +} + run_wine_checks() { local cunit_runner + cd "${REPO_ROOT}/${BUILD_DIR}" cunit_runner=liblwgeom/cunit/cu_tester.exe if test ! -f "${cunit_runner}"; then cunit_runner=liblwgeom/cunit/cu_tester fi case "${WINEPREFIX}" in - "${TMP_ROOT}"/*|/tmp/postgis-wine) rm -rf "${WINEPREFIX}" ;; + "${TMP_ROOT}"/*) rm -rf "${WINEPREFIX}" ;; esac + prepare_wine_prefix copy_mingw_runtime_dlls - env -u XDG_RUNTIME_DIR TMPDIR="${WINE_TMPDIR}" xvfb-run -a "${WINE}" "${cunit_runner}" > "${LOG_DIR}/postgis.cunit.wine.log" 2>&1 \ + "${XVFB_WINE[@]}" "${cunit_runner}" > "${LOG_DIR}/postgis.cunit.wine.log" 2>&1 \ || log_tail "$?" "${LOG_DIR}/postgis.cunit.wine.log" echo "CUNIT_WINE_BEGIN" tail -80 "${LOG_DIR}/postgis.cunit.wine.log" echo "CUNIT_WINE_END" - env -u XDG_RUNTIME_DIR TMPDIR="${WINE_TMPDIR}" xvfb-run -a "${WINE}" loader/shp2pgsql.exe -s 4326 ../regress/loader/Point public.point \ + "${XVFB_WINE[@]}" loader/shp2pgsql.exe -s 4326 "${REPO_ROOT}/regress/loader/Point" public.point \ > "${LOG_DIR}/point.sql" 2>"${LOG_DIR}/shp2pgsql.stderr" \ || log_tail "$?" "${LOG_DIR}/shp2pgsql.stderr" grep '^INSERT INTO "public"."point"' "${LOG_DIR}/point.sql" | tr -d '\r' > "${LOG_DIR}/point.inserts" @@ -338,40 +688,200 @@ INSERT INTO "public"."point" (geom) VALUES ('0101000020E610000000000000000022400 EOF diff -u "${LOG_DIR}/point.inserts.expected" "${LOG_DIR}/point.inserts" - env -u XDG_RUNTIME_DIR TMPDIR="${WINE_TMPDIR}" xvfb-run -a "${WINE}" loader/pgsql2shp.exe -? > "${LOG_DIR}/pgsql2shp.usage" 2>&1 || true + "${XVFB_WINE[@]}" loader/pgsql2shp.exe -? > "${LOG_DIR}/pgsql2shp.usage" 2>&1 || true grep -F "USAGE: pgsql2shp" "${LOG_DIR}/pgsql2shp.usage" >/dev/null + "${XVFB_WINE[@]}" raster/loader/raster2pgsql.exe -s 4326 "${REPO_ROOT}/raster/test/regress/loader/testraster.tif" public.testraster \ + > "${LOG_DIR}/testraster.sql" 2>"${LOG_DIR}/raster2pgsql.stderr" \ + || log_tail "$?" "${LOG_DIR}/raster2pgsql.stderr" + grep -F 'CREATE TABLE "public"."testraster"' "${LOG_DIR}/testraster.sql" >/dev/null + echo "LOADER_CHECK_BEGIN" sed -n '1,16p' "${LOG_DIR}/point.sql" diff -u "${LOG_DIR}/point.inserts.expected" "${LOG_DIR}/point.inserts" sed -n '1,8p' "${LOG_DIR}/pgsql2shp.usage" + sed -n '1,12p' "${LOG_DIR}/testraster.sql" echo "LOADER_CHECK_END" } +wine_path() +{ + "${WINE}" winepath -w "$1" 2>/dev/null | tr -d '\r' +} + +prepare_postgresql_wine_tree() +{ + rm -rf "${PGWIN_RUN_ROOT}" + mkdir -p "${PGWIN_RUN_ROOT}" + cp -a "${PGWIN_ROOT}/." "${PGWIN_RUN_ROOT}/" + find "${PGWIN_RUN_ROOT}/bin" -maxdepth 1 -type f \( -iname '*.exe' -o -iname '*.dll' \) -exec chmod +x {} + +} + +install_vc_runtime() +{ + local redist + if test "${INSTALL_VC_RUNTIME}" = "1"; then + redist="${DOWNLOAD_DIR}/vc_redist.x64.exe" + if test ! -f "${redist}"; then + "${CURL[@]}" -o "${redist}" "${VCREDIST_URL}" + fi + "${XVFB_WINE[@]}" "${redist}" /install /quiet /norestart \ + > "${LOG_DIR}/vcredist.install.log" 2>&1 || true + fi + ( + cd "${PGWIN_RUN_ROOT}/bin" + "${XVFB_WINE[@]}" ./postgres.exe --version + ) > "${LOG_DIR}/postgresql.postgres-version.log" 2>&1 \ + || log_tail "$?" "${LOG_DIR}/postgresql.postgres-version.log" + echo "POSTGRES_WINE_VERSION_BEGIN" + cat "${LOG_DIR}/postgresql.postgres-version.log" + echo "POSTGRES_WINE_VERSION_END" +} + +start_postgresql_wine() +{ + local pgdata_win + local log_win + local pid + prepare_wine_prefix + prepare_postgresql_wine_tree + install_vc_runtime + rm -rf "${PGDATA}" "${PGDATA_RUN}" + mkdir -p "${PGDATA_RUN}" + pgdata_win=$(wine_path "${PGDATA_RUN}") + log_win=$(wine_path "${LOG_DIR}/postgresql-wine.log") + ( + cd "${PGWIN_RUN_ROOT}/bin" + "${XVFB_WINE[@]}" ./initdb.exe -D "${pgdata_win}" -U "${PGUSER}" -A trust --encoding=UTF8 --locale=C --no-sync + ) > "${LOG_DIR}/postgresql.initdb.log" 2>&1 || log_tail "$?" "${LOG_DIR}/postgresql.initdb.log" + cat >>"${PGDATA_RUN}/postgresql.conf" <>"${PGDATA_RUN}/pg_hba.conf" <<'EOF' +host all all 127.0.0.1/32 trust +host all all ::1/128 trust +EOF + ( + cd "${PGWIN_RUN_ROOT}/bin" + "${XVFB_WINE[@]}" ./pg_ctl.exe -D "${pgdata_win}" -l "${log_win}" -w start + ) > "${LOG_DIR}/postgresql.start.log" 2>&1 || log_tail "$?" "${LOG_DIR}/postgresql.start.log" + pid=$( + cd "${PGWIN_RUN_ROOT}/bin" + "${XVFB_WINE[@]}" ./pg_ctl.exe -D "${pgdata_win}" status 2>/dev/null \ + | sed -n 's/.*PID: *\([0-9][0-9]*\).*/\1/p' | head -1 || true + ) + echo "${pid}" > "${TMP_ROOT}/postgresql-wine.pid" + PGHOST="${PGHOST}" PGPORT="${PGPORT}" PGUSER="${PGUSER}" psql -d postgres -c 'select version()' \ + > "${LOG_DIR}/postgresql.psql-version.log" 2>&1 || log_tail "$?" "${LOG_DIR}/postgresql.psql-version.log" + echo "POSTGRESQL_WINE_BEGIN" + tail -60 "${LOG_DIR}/postgresql.start.log" + cat "${LOG_DIR}/postgresql.psql-version.log" + echo "POSTGRESQL_WINE_END" +} + +stop_postgresql_wine() +{ + local pgdata_win + if test -d "${PGDATA_RUN}"; then + pgdata_win=$(wine_path "${PGDATA_RUN}" || true) + if test -n "${pgdata_win}"; then + ( + cd "${PGWIN_RUN_ROOT}/bin" + "${XVFB_WINE[@]}" ./pg_ctl.exe -D "${pgdata_win}" -m fast -w stop + ) > "${LOG_DIR}/postgresql.stop.log" 2>&1 || true + fi + fi +} + +install_regression_wrappers() +{ + local wrapdir + wrapdir="${TMP_ROOT}/wine-wrappers" + mkdir -p "${wrapdir}" + for exe in shp2pgsql pgsql2shp raster2pgsql; do + local exe_path + if test "${exe}" = raster2pgsql; then + exe_path="${REPO_ROOT}/${BUILD_DIR}/raster/loader/${exe}.exe" + else + exe_path="${REPO_ROOT}/${BUILD_DIR}/loader/${exe}.exe" + fi + cat >"${wrapdir}/${exe}" < "${LOG_DIR}/postgis.full-version.log" 2>&1 || log_tail "$?" "${LOG_DIR}/postgis.full-version.log" + echo "POSTGIS_FULL_VERSION_BEGIN" + cat "${LOG_DIR}/postgis.full-version.log" + echo "POSTGIS_FULL_VERSION_END" + run_logged "${LOG_DIR}/postgis.installcheck.log" make installcheck RUNTESTFLAGS="${RUNTESTFLAGS}" REGRESS_INSTALLDIR="${regress_installdir}" + echo "REGRESSION_SUMMARY_BEGIN" + grep -E '^(Run tests|Running|PASS|FAIL|SKIP|ERROR|Failed|Summary|Suite)' "${LOG_DIR}/postgis.installcheck.log" | tail -200 || tail -200 "${LOG_DIR}/postgis.installcheck.log" + echo "REGRESSION_SUMMARY_END" +} + main() { local started started=$(date +%s) - mkdir -p "${TMPDIR}" "${LOG_DIR}" - install_packages - fetch_sources - build_sqlite - build_libiconv - build_gmp - build_cunit - build_geos - build_libxml2 - build_libpq - build_proj + mkdir -p "${TMPDIR}" "${LOG_DIR}" "${WINE_TMPDIR}" + if test -n "${RUN_FROM}"; then + phase_log "RUN_FROM ${RUN_FROM}" + else + : >"${LOG_DIR}/phase-times.log" + fi + phase install_packages install_packages + phase fetch_sources fetch_sources + phase build_sqlite build_sqlite + phase build_zlib build_zlib + phase build_libjpeg build_libjpeg + phase build_libpng build_libpng + phase build_libiconv build_libiconv + phase build_gmp build_gmp + phase build_cunit build_cunit + phase build_geos build_geos + phase build_libtiff build_libtiff + phase build_proj build_proj + phase build_libgeotiff build_libgeotiff + phase build_gdal build_gdal + phase build_json_c build_json_c + phase build_protobuf_c build_protobuf_c + phase setup_postgresql_windows setup_postgresql_windows + phase build_libxml2 build_libxml2 + phase build_libpq build_libpq - cd "${REPO_ROOT}" - ./autogen.sh >"${LOG_DIR}/postgis.autogen.log" 2>&1 || log_tail "$?" "${LOG_DIR}/postgis.autogen.log" - configure_postgis - build_postgis_targets - run_wine_checks + phase run_autogen run_autogen + phase configure_postgis configure_postgis + phase build_postgis_targets build_postgis_targets + phase run_wine_checks run_wine_checks + trap stop_postgresql_wine EXIT + phase start_postgresql_wine start_postgresql_wine + phase run_regressions run_regressions - echo "WALL_CLOCK_SECONDS=$(( $(date +%s) - started ))" + phase_log "WALL_CLOCK_SECONDS=$(( $(date +%s) - started ))" } main "$@" commit 06f1e55ec0e15e47eb4ba812e16a797a99e548be Author: Darafei Praliaskouski Date: Sun Jul 26 06:03:36 2026 +0400 ci: add Woodpecker MinGW Wine coverage diff --git a/.gitignore b/.gitignore index e29ac79054..ad40a43b37 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ *~ +.tmp/ +build-mingw-wine/ *.a *.la .libs diff --git a/.woodpecker/mingw-wine.yml b/.woodpecker/mingw-wine.yml new file mode 100644 index 0000000000..77bb48e8ed --- /dev/null +++ b/.woodpecker/mingw-wine.yml @@ -0,0 +1,18 @@ +labels: + platform: linux/amd64 +when: + event: [push, pull_request, tag] + +clone: + git: + image: woodpeckerci/plugin-git + settings: + depth: 50 + partial: false + +steps: + mingw-wine: + image: debian:bookworm + pull: true + commands: + - bash ci/dronie/postgis_mingw_wine.sh diff --git a/ci/woodie/postgis_mingw_wine.sh b/ci/woodie/postgis_mingw_wine.sh new file mode 100755 index 0000000000..42df01ab0f --- /dev/null +++ b/ci/woodie/postgis_mingw_wine.sh @@ -0,0 +1,377 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail + +TARGET=${TARGET:-x86_64-w64-mingw32} +PREFIX=${PREFIX:-/opt/postgis-mingw} +BUILD_DIR=${BUILD_DIR:-build-mingw-wine} +REPO_ROOT=$(pwd) +TMP_ROOT=${TMP_ROOT:-${REPO_ROOT}/.tmp/mingw-wine} +WORKDIR=${WORKDIR:-${TMP_ROOT}/work} +LOG_DIR=${LOG_DIR:-${TMP_ROOT}/logs} + +export DEBIAN_FRONTEND=noninteractive +export PATH="${PREFIX}/bin:/usr/${TARGET}/bin:${PATH}" +export TMPDIR="${TMP_ROOT}/tmp" +export CC=${CC:-${TARGET}-gcc-posix} +export CXX=${CXX:-${TARGET}-g++-posix} +export AR=${AR:-${TARGET}-ar} +export RANLIB=${RANLIB:-${TARGET}-ranlib} +export WINDRES=${WINDRES:-${TARGET}-windres} +export PKG_CONFIG_LIBDIR="${PREFIX}/lib/pkgconfig" +export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig" +export WINEDEBUG=${WINEDEBUG:--all} +export WINEPREFIX=${WINEPREFIX:-/tmp/postgis-wine} +export WINEARCH=${WINEARCH:-win64} +WINE_TMPDIR=${WINE_TMPDIR:-/tmp} +WINE=${WINE:-wine} + +log_tail() +{ + local status=$1 + local file=$2 + echo "----- ${file} tail -----" >&2 + tail -160 "${file}" >&2 || true + exit "${status}" +} + +run_logged() +{ + local log=$1 + shift + "$@" >"${log}" 2>&1 || log_tail "$?" "${log}" +} + +install_packages() +{ + apt-get update >/dev/null + apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + dpkg-dev \ + build-essential \ + autoconf \ + automake \ + libtool \ + pkg-config \ + cmake \ + ninja-build \ + bison \ + flex \ + gettext \ + perl \ + sqlite3 \ + mingw-w64 \ + gcc-mingw-w64-x86-64-posix \ + g++-mingw-w64-x86-64-posix \ + wine \ + wine64 \ + xauth \ + xvfb \ + diffutils >/dev/null + + cat >/etc/apt/sources.list.d/postgis-mingw-wine-src.list <<'EOF' +deb-src http://deb.debian.org/debian trixie main +deb-src http://deb.debian.org/debian-security trixie-security main +deb-src http://deb.debian.org/debian trixie-updates main +EOF + apt-get update >/dev/null +} + +fetch_sources() +{ + rm -rf "${WORKDIR}" + mkdir -p "${WORKDIR}/src" "${PREFIX}/include" "${PREFIX}/lib/pkgconfig" + cd "${WORKDIR}/src" + apt-get source cunit geos proj libxml2 postgresql-17 >/dev/null + curl -fsSLO https://www.sqlite.org/2024/sqlite-autoconf-3460100.tar.gz + curl -fsSLO https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.18.tar.gz + curl -fsSLO https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz + tar xf sqlite-autoconf-3460100.tar.gz + tar xf libiconv-1.18.tar.gz + tar xf gmp-6.3.0.tar.xz +} + +build_sqlite() +{ + cd "${WORKDIR}/src/sqlite-autoconf-3460100" + ${CC} -O2 -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -c sqlite3.c -o sqlite3.o + cp sqlite3.h sqlite3ext.h "${PREFIX}/include/" + ${AR} rcs "${PREFIX}/lib/libsqlite3.a" sqlite3.o + cat >"${PREFIX}/lib/pkgconfig/sqlite3.pc" <"${LOG_DIR}/cunit.autoreconf.log" 2>&1 || true + run_logged "${LOG_DIR}/cunit.configure.log" ./configure \ + --host="${TARGET}" \ + --prefix="${PREFIX}" \ + --disable-shared \ + --enable-static + run_logged "${LOG_DIR}/cunit.make.log" make -j"$(nproc)" + run_logged "${LOG_DIR}/cunit.install.log" make install +} + +build_libiconv() +{ + cd "${WORKDIR}/src/libiconv-1.18" + run_logged "${LOG_DIR}/libiconv.configure.log" ./configure \ + --host="${TARGET}" \ + --prefix="${PREFIX}" \ + --disable-shared \ + --enable-static + run_logged "${LOG_DIR}/libiconv.make.log" make -j"$(nproc)" + run_logged "${LOG_DIR}/libiconv.install.log" make install +} + +build_gmp() +{ + cd "${WORKDIR}/src/gmp-6.3.0" + run_logged "${LOG_DIR}/gmp.configure.log" env CC_FOR_BUILD="/usr/bin/gcc -B/usr/bin/" CPP_FOR_BUILD="/usr/bin/gcc -E" ./configure \ + --host="${TARGET}" \ + --prefix="${PREFIX}" \ + --disable-shared \ + --enable-static + run_logged "${LOG_DIR}/gmp.make.log" make -j"$(nproc)" + run_logged "${LOG_DIR}/gmp.install.log" make install +} + +build_geos() +{ + run_logged "${LOG_DIR}/geos.configure.log" cmake \ + -S "${WORKDIR}/src/geos-3.13.1" \ + -B "${WORKDIR}/build-geos" \ + -G Ninja \ + -DCMAKE_SYSTEM_NAME=Windows \ + -DCMAKE_C_COMPILER="${CC}" \ + -DCMAKE_CXX_COMPILER="${CXX}" \ + -DCMAKE_INSTALL_PREFIX="${PREFIX}" \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTING=OFF \ + -DGEOS_BUILD_DEVELOPER=OFF + run_logged "${LOG_DIR}/geos.make.log" cmake --build "${WORKDIR}/build-geos" -j"$(nproc)" + run_logged "${LOG_DIR}/geos.install.log" cmake --install "${WORKDIR}/build-geos" + cat >"${PREFIX}/bin/${TARGET}-geos-config" <&2; exit 1 ;; +esac +EOF + chmod +x "${PREFIX}/bin/${TARGET}-geos-config" +} + +build_libxml2() +{ + cd "${WORKDIR}/src/libxml2-2.12.7+dfsg+really2.9.14" + run_logged "${LOG_DIR}/libxml2.autoreconf.log" autoreconf -fi + run_logged "${LOG_DIR}/libxml2.configure.log" ./configure \ + --host="${TARGET}" \ + --prefix="${PREFIX}" \ + --disable-shared \ + --enable-static \ + --without-python \ + --without-threads \ + --without-zlib \ + --without-lzma \ + --without-iconv \ + --without-modules \ + --without-ftp \ + --without-http + run_logged "${LOG_DIR}/libxml2.make.log" make -j"$(nproc)" + run_logged "${LOG_DIR}/libxml2.install.log" make install +} + +build_libpq() +{ + cd "${WORKDIR}/src/postgresql-17-17.10" + run_logged "${LOG_DIR}/postgresql.configure.log" ./configure \ + --host="${TARGET}" \ + --prefix="${PREFIX}" \ + --without-readline \ + --without-zlib \ + --without-icu + run_logged "${LOG_DIR}/postgresql.libpq.make.log" make -C src/interfaces/libpq -j"$(nproc)" + run_logged "${LOG_DIR}/postgresql.include.install.log" make -C src/include install + run_logged "${LOG_DIR}/postgresql.libpq.install.log" make -C src/interfaces/libpq install + + mkdir -p "${PREFIX}/lib/pgxs/src/makefiles" "${PREFIX}/bin" + touch "${PREFIX}/lib/pgxs/src/makefiles/pgxs.mk" + cat >"${PREFIX}/bin/${TARGET}-pg_config" <&2; exit 1 ;; +esac +EOF + chmod +x "${PREFIX}/bin/${TARGET}-pg_config" +} + +build_proj() +{ + run_logged "${LOG_DIR}/proj.configure.log" cmake \ + -S "${WORKDIR}/src/proj-9.6.0" \ + -B "${WORKDIR}/build-proj" \ + -G Ninja \ + -DCMAKE_SYSTEM_NAME=Windows \ + -DCMAKE_C_COMPILER="${CC}" \ + -DCMAKE_CXX_COMPILER="${CXX}" \ + -DCMAKE_INSTALL_PREFIX="${PREFIX}" \ + -DCMAKE_PREFIX_PATH="${PREFIX}" \ + -DSQLite3_INCLUDE_DIR="${PREFIX}/include" \ + -DSQLite3_LIBRARY="${PREFIX}/lib/libsqlite3.a" \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTING=OFF \ + -DBUILD_APPS=OFF \ + -DENABLE_CURL=OFF \ + -DENABLE_TIFF=OFF \ + -DENABLE_IPO=OFF + run_logged "${LOG_DIR}/proj.make.log" cmake --build "${WORKDIR}/build-proj" -j"$(nproc)" + run_logged "${LOG_DIR}/proj.install.log" cmake --install "${WORKDIR}/build-proj" +} + +configure_postgis() +{ + rm -rf "${BUILD_DIR}" + mkdir "${BUILD_DIR}" + cd "${BUILD_DIR}" + + export GEOS_CFLAGS="-I${PREFIX}/include" + export GEOS_LIBS="-L${PREFIX}/lib -lgeos_c -lgeos -lstdc++" + export PROJ_CFLAGS="-I${PREFIX}/include" + export PROJ_LIBS="-L${PREFIX}/lib -lproj -lsqlite3 -lstdc++ -lws2_32 -lbcrypt -lole32 -lshell32" + + run_logged "${LOG_DIR}/postgis.configure.log" ../configure \ + --host="${TARGET}" \ + --with-pgconfig="${PREFIX}/bin/${TARGET}-pg_config" \ + --with-geosconfig="${PREFIX}/bin/${TARGET}-geos-config" \ + --with-xml2config="${PREFIX}/bin/xml2-config" \ + --with-libiconv="${PREFIX}" \ + --without-protobuf \ + --without-raster \ + --disable-spellcheck-tests \ + CFLAGS="-O2 -Wall" \ + LDFLAGS="-L${PREFIX}/lib -static -static-libgcc -static-libstdc++" + + echo "CONFIGURE_SUMMARY_BEGIN" + sed -n '/^ PostGIS is now configured/,/^$/p' "${LOG_DIR}/postgis.configure.log" + echo "CONFIGURE_SUMMARY_END" +} + +build_postgis_targets() +{ + run_logged "${LOG_DIR}/postgis.liblwgeom.make.log" make -j"$(nproc)" -C liblwgeom + run_logged "${LOG_DIR}/postgis.cunit.make.log" make -j"$(nproc)" -C liblwgeom/cunit cu_tester + run_logged "${LOG_DIR}/postgis.loader.make.log" make -j"$(nproc)" -C loader shp2pgsql.exe pgsql2shp.exe + + echo "BUILD_TAIL_BEGIN" + tail -40 "${LOG_DIR}/postgis.liblwgeom.make.log" + tail -40 "${LOG_DIR}/postgis.cunit.make.log" + tail -60 "${LOG_DIR}/postgis.loader.make.log" + echo "BUILD_TAIL_END" +} + +copy_mingw_runtime_dlls() +{ + local dll + local path + for dll in libstdc++-6.dll libgcc_s_seh-1.dll libwinpthread-1.dll LIBPQ.dll libpq.dll; do + path=$(find "/usr/lib/gcc/${TARGET}" "/usr/${TARGET}" "${PREFIX}" -name "${dll}" -print -quit 2>/dev/null || true) + if test -n "${path}"; then + cp "${path}" liblwgeom/cunit/ + cp "${path}" loader/ + fi + done +} + +run_wine_checks() +{ + local cunit_runner + cunit_runner=liblwgeom/cunit/cu_tester.exe + if test ! -f "${cunit_runner}"; then + cunit_runner=liblwgeom/cunit/cu_tester + fi + + case "${WINEPREFIX}" in + "${TMP_ROOT}"/*|/tmp/postgis-wine) rm -rf "${WINEPREFIX}" ;; + esac + copy_mingw_runtime_dlls + env -u XDG_RUNTIME_DIR TMPDIR="${WINE_TMPDIR}" xvfb-run -a "${WINE}" "${cunit_runner}" > "${LOG_DIR}/postgis.cunit.wine.log" 2>&1 \ + || log_tail "$?" "${LOG_DIR}/postgis.cunit.wine.log" + echo "CUNIT_WINE_BEGIN" + tail -80 "${LOG_DIR}/postgis.cunit.wine.log" + echo "CUNIT_WINE_END" + + env -u XDG_RUNTIME_DIR TMPDIR="${WINE_TMPDIR}" xvfb-run -a "${WINE}" loader/shp2pgsql.exe -s 4326 ../regress/loader/Point public.point \ + > "${LOG_DIR}/point.sql" 2>"${LOG_DIR}/shp2pgsql.stderr" \ + || log_tail "$?" "${LOG_DIR}/shp2pgsql.stderr" + grep '^INSERT INTO "public"."point"' "${LOG_DIR}/point.sql" | tr -d '\r' > "${LOG_DIR}/point.inserts" + cat > "${LOG_DIR}/point.inserts.expected" <<'EOF' +INSERT INTO "public"."point" (geom) VALUES ('0101000020E61000000000000000000000000000000000F03F'); +INSERT INTO "public"."point" (geom) VALUES ('0101000020E61000000000000000002240000000000000F0BF'); +INSERT INTO "public"."point" (geom) VALUES ('0101000020E61000000000000000002240000000000000F0BF'); +EOF + diff -u "${LOG_DIR}/point.inserts.expected" "${LOG_DIR}/point.inserts" + + env -u XDG_RUNTIME_DIR TMPDIR="${WINE_TMPDIR}" xvfb-run -a "${WINE}" loader/pgsql2shp.exe -? > "${LOG_DIR}/pgsql2shp.usage" 2>&1 || true + grep -F "USAGE: pgsql2shp" "${LOG_DIR}/pgsql2shp.usage" >/dev/null + + echo "LOADER_CHECK_BEGIN" + sed -n '1,16p' "${LOG_DIR}/point.sql" + diff -u "${LOG_DIR}/point.inserts.expected" "${LOG_DIR}/point.inserts" + sed -n '1,8p' "${LOG_DIR}/pgsql2shp.usage" + echo "LOADER_CHECK_END" +} + +main() +{ + local started + started=$(date +%s) + + mkdir -p "${TMPDIR}" "${LOG_DIR}" + install_packages + fetch_sources + build_sqlite + build_libiconv + build_gmp + build_cunit + build_geos + build_libxml2 + build_libpq + build_proj + + cd "${REPO_ROOT}" + ./autogen.sh >"${LOG_DIR}/postgis.autogen.log" 2>&1 || log_tail "$?" "${LOG_DIR}/postgis.autogen.log" + configure_postgis + build_postgis_targets + run_wine_checks + + echo "WALL_CLOCK_SECONDS=$(( $(date +%s) - started ))" +} + +main "$@" ----------------------------------------------------------------------- Summary of changes: .gitignore | 2 + .../{contributor-credits.yml => mingw-wine.yml} | 11 +- ci/woodie/postgis_mingw_wine.sh | 965 +++++++++++++++++++++ doc/development/testing/ci.md | 23 + 4 files changed, 996 insertions(+), 5 deletions(-) copy .woodpecker/{contributor-credits.yml => mingw-wine.yml} (58%) create mode 100755 ci/woodie/postgis_mingw_wine.sh hooks/post-receive -- PostGIS From git at osgeo.org Sun Aug 2 18:39:15 2026 From: git at osgeo.org (git at osgeo.org) Date: Sun, 2 Aug 2026 18:39:15 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-184-gc69b4727c0 Message-ID: <20260803013915.A22E61D7044@trac.osgeo.org> 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 c69b4727c0a1eff664138d2538eba7e8201743da (commit) from 4852079f40ba8e51f03997aeb6dceac331826694 (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 c69b4727c0a1eff664138d2538eba7e8201743da Author: Teramoto Ikuhiro Date: Mon Aug 3 01:36:31 2026 +0000 Translated PostGIS Manual using Weblate (Japanese) Currently translated at 88.3% (5285 of 5981 strings) Translation: postgis/PostGIS Manual Translate-URL: https://weblate.osgeo.org/projects/postgis/postgis-manual/ja/ diff --git a/doc/po/ja/postgis-manual.po b/doc/po/ja/postgis-manual.po index c7ac8ccb9a..8fc5563472 100644 --- a/doc/po/ja/postgis-manual.po +++ b/doc/po/ja/postgis-manual.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: postgis 3.5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2026-07-20 08:06+0000\n" -"PO-Revision-Date: 2026-07-29 03:39+0000\n" +"PO-Revision-Date: 2026-08-03 01:39+0000\n" "Last-Translator: Teramoto Ikuhiro \n" "Language-Team: Japanese \n" @@ -7320,11 +7320,15 @@ msgid "" "PostGIS behavior. " "summarizes SQL/MM compliance and geometry-type support across functions." msgstr "" +"??????????????????????????????????????" +"??????????????PostGIS ??????????? ??????? SQL/MM ????" +"???????????????????" #. Tag: title #, no-c-format msgid "Project and Community" -msgstr "" +msgstr "??????????????" #. Tag: para #, no-c-format @@ -7337,6 +7341,12 @@ msgid "" "contributor and sponsor record is in at " "the end of this manual." msgstr "" +"PostGIS ?2001?? Refractions Research ??????????????????" +"???????????????????????????????? OSGeo project " +"??????????????????????????????????????" +"????????????????????????????????? ??????" #. Tag: para #, no-c-format @@ -7344,6 +7354,8 @@ msgid "" "The manual is the authoritative reference for the released SQL interface. " "The project website and source tree provide the surrounding material:" msgstr "" +"??????????????? SQL ????????????????" +"???????????????????????????????????:" #. Tag: para #, no-c-format @@ -7352,6 +7364,9 @@ msgid "" "routes readers to getting-started instructions, versioned manuals, tips, " "training material, and the FAQ." msgstr "" +"Documentation " +"??????????????????????????????????????" +"??????????" #. Tag: para #, no-c-format @@ -7359,6 +7374,9 @@ msgid "" "Community lists " "mailing lists, chat, events, videos, and other support channels." msgstr "" +"Community ??" +"??????????????????????????????????????" +"?" #. Tag: para #, no-c-format @@ -7368,6 +7386,10 @@ msgid "" "environments, testing, coding style, internals, maintenance, governance, " "releases, and website work." msgstr "" +"Developer documentation ????????????" +"??????????????????????????????????????" +"??????" #. Tag: title #, no-c-format @@ -7545,6 +7567,9 @@ msgid "" "an index. For a mostly read-only table whose queries frequently use the same " "spatial index, this can reduce I/O and improve cache locality." msgstr "" +"PostgreSQL CLUSTER ?????????????????????????????" +"????????????????????????????????????" +"?????????????????????????????????????" #. Tag: para #, no-c-format @@ -7552,6 +7577,9 @@ msgid "" "PostgreSQL supports clustering on GiST indices, including indices on " "nullable geometry columns. To cluster a table using a geometry index:" msgstr "" +"PostgreSQL ?GiST ??????????????????????????NULL ?" +"??????????????????????????????????????" +"???????????????????:" #. Tag: title #, no-c-format @@ -8220,12 +8248,12 @@ msgstr "" #. Tag: para #, no-c-format msgid "LineString with boundary points overlaid." -msgstr "" +msgstr "???????????????????????" #. Tag: para #, no-c-format msgid "Polygon holes with the boundary MultiLineString overlaid." -msgstr "" +msgstr "??????????????????????????" #. Tag: para #, no-c-format @@ -8309,7 +8337,7 @@ msgstr "&M_support;" #, no-c-format msgid "" "This example shows a polygon together with the diagonal of its bounding box." -msgstr "" +msgstr "?????????????????????????????????????" #. Tag: para #, no-c-format @@ -8385,6 +8413,11 @@ msgid "" "Solid geometry semantics, such as volume, are handled separately by the SQL/" "MM 3D solid functions (SQL-MM IEC 13249-3: 9.1)." msgstr "" +"TIN (TIN ????????) ???????????????" +"?? 2 ???????????????? ??" +"??????????????????????????????????????" +"????? SQL/MM 3?????? (SQL-MM IEC 13249-3: 9.1) ?????????" +"?" #. Tag: para #, no-c-format @@ -8405,7 +8438,7 @@ msgstr "2.0.0?????????????????????? #. Tag: para #, no-c-format msgid ", , " -msgstr "" +msgstr ", , " #. Tag: refpurpose #, no-c-format @@ -8471,13 +8504,13 @@ msgstr "" #. Tag: para #, no-c-format msgid "Dump the components of geometries stored in a table." -msgstr "" +msgstr "?????????????????????????????" #. Tag: para #, no-c-format msgid "" "Break a CompoundCurve into its constituent LineStrings and CircularStrings." -msgstr "" +msgstr "???????????????????????????????" #. Tag: para #, no-c-format @@ -8568,7 +8601,7 @@ msgstr "Enhanced: 2.1.0 ?????????C????????? #. Tag: para #, no-c-format msgid "Explode a table of LineStrings into their vertices." -msgstr "" +msgstr "??????????????????????" #. Tag: para #, no-c-format ----------------------------------------------------------------------- Summary of changes: doc/po/ja/postgis-manual.po | 51 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 9 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Sun Aug 2 20:39:18 2026 From: git at osgeo.org (git at osgeo.org) Date: Sun, 2 Aug 2026 20:39:18 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-185-g66a5f3d56d Message-ID: <20260803033918.56BE11DBDF1@trac.osgeo.org> 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 66a5f3d56d091911ff502d207082c0792d3a6931 (commit) from c69b4727c0a1eff664138d2538eba7e8201743da (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 66a5f3d56d091911ff502d207082c0792d3a6931 Author: Teramoto Ikuhiro Date: Mon Aug 3 02:59:43 2026 +0000 Translated PostGIS Manual using Weblate (Japanese) Currently translated at 89.0% (5326 of 5981 strings) Translation: postgis/PostGIS Manual Translate-URL: https://weblate.osgeo.org/projects/postgis/postgis-manual/ja/ diff --git a/doc/po/ja/postgis-manual.po b/doc/po/ja/postgis-manual.po index 8fc5563472..fc25b0b514 100644 --- a/doc/po/ja/postgis-manual.po +++ b/doc/po/ja/postgis-manual.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: postgis 3.5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2026-07-20 08:06+0000\n" -"PO-Revision-Date: 2026-08-03 01:39+0000\n" +"PO-Revision-Date: 2026-08-03 03:39+0000\n" "Last-Translator: Teramoto Ikuhiro \n" "Language-Team: Japanese \n" @@ -8253,7 +8253,7 @@ msgstr "???????????????????????" #. Tag: para #, no-c-format msgid "Polygon holes with the boundary MultiLineString overlaid." -msgstr "??????????????????????????" +msgstr "????????????????????????????" #. Tag: para #, no-c-format @@ -8606,12 +8606,12 @@ msgstr "??????????????????????" #. Tag: para #, no-c-format msgid "Dump every vertex from a mixed GeometryCollection." -msgstr "" +msgstr "???????????????????????????" #. Tag: para #, no-c-format msgid "Collect the dumped vertices to visualize them over the source geometry." -msgstr "" +msgstr "??????????????????????????????" #. Tag: para #, no-c-format @@ -8771,7 +8771,7 @@ msgstr "??????????????" #. Tag: para #, no-c-format msgid "Finding interior rings which lie close to the exterior ring." -msgstr "" +msgstr "???????????????????" #. Tag: para #, no-c-format @@ -8782,6 +8782,11 @@ msgid "" "linkend=\"ST_ExteriorRing\"/>, , " msgstr "" +", , , , , , , , " #. Tag: refpurpose #, no-c-format @@ -8918,7 +8923,7 @@ msgstr "&sqlmm_compliant; SQL-MM 3: 5.1.19" #. Tag: para #, no-c-format msgid "Envelope of a point and LineString." -msgstr "" +msgstr "?????????????????????" #. Tag: para #, no-c-format @@ -8962,7 +8967,7 @@ msgstr "&sqlmm_compliant; SQL-MM 3: 8.2.3, 8.3.3" #. Tag: para #, no-c-format msgid "Extract the exterior ring from a Polygon with a hole." -msgstr "" +msgstr "?????????????????????" #. Tag: para #, no-c-format @@ -8970,11 +8975,13 @@ msgid "" "For a MultiPolygon, dump the component Polygons before extracting their " "exterior rings. Both component Polygons in this example have holes." msgstr "" +"??????????????????????????????????????" +"?????????????????????????" #. Tag: para #, no-c-format msgid "Extract exterior rings from a table of Polygons." -msgstr "" +msgstr "???????????????????????" #. Tag: para #, no-c-format @@ -8982,11 +8989,13 @@ msgid "" "For a table of MultiPolygons, dump the component Polygons and collect their " "exterior rings into a MultiLineString." msgstr "" +"??????????????????????????????????????" +"?????????????????" #. Tag: para #, no-c-format msgid "This example returns the 3D exterior ring of a Polygon." -msgstr "" +msgstr "????? 3???????????????????" #. Tag: para #, no-c-format @@ -9010,6 +9019,12 @@ msgid "" "and to access and count the faces of a TIN " "or PolyhedralSurface." msgstr "" +"GEOMETRYCOLLECTION, MULTIPOINT, MULTILINESTRING, MULTICURVE, MULTIPOLYGON ? " +"1????N?????????????????????TIN ? POLYHEDRALSURFACE " +"?????1 ?????????????????????????????? " +"NULL ??????TIN ? POLYHEDRALSURFACE ?????????????????" +"?????????? ? ??????????" #. Tag: para #, no-c-format @@ -9044,6 +9059,9 @@ msgid "" "Changed: 3.6.0 TIN and PolyhedralSurface are treated as unitary geometries " "and are not decomposed into patches; use ST_PatchN to access faces." msgstr "" +"Changed: 3.6.0 TIN ? POLYHEDRALSURFACE ??????????????????" +"??????????????????????????????????? " +"ST_PatchN ??????" #. Tag: para #, no-c-format @@ -9063,7 +9081,7 @@ msgstr "3??MULTIPOINT???????????????" #. Tag: para #, no-c-format msgid "Extracting all geometries (useful when you want to assign an id)." -msgstr "" +msgstr "??????????????? (ID????????????)?" #. Tag: title #, no-c-format @@ -9079,16 +9097,22 @@ msgid "" "varname>. Use and to access individual faces." msgstr "" +"POLYHEDRALSURFACE ??? TIN ?????????????????????" +"?????????????????ST_GeometryN ?" +"???????????????????1 ?????????????????" +"?NULL ??????????????????????" +"? ? ????" +"??" #. Tag: para #, no-c-format msgid "This example requests the third element of a PolyhedralSurface." -msgstr "" +msgstr "????? POLYHEDRALSURFACE ?3?????????????" #. Tag: para #, no-c-format msgid "This example requests the second element of a TIN." -msgstr "" +msgstr "????? TIN ? 2?????????????" #. Tag: para #, no-c-format @@ -9096,6 +9120,8 @@ msgid "" ", , , " msgstr "" +", , , " #. Tag: refpurpose #, no-c-format @@ -9196,12 +9222,12 @@ msgstr "" #. Tag: para #, no-c-format msgid "This CompoundCurve contains three component curves." -msgstr "" +msgstr "???????? 3??????????????" #. Tag: para #, no-c-format msgid "An empty CompoundCurve has no component curves." -msgstr "" +msgstr "???????????????????" #. Tag: para #, no-c-format @@ -9232,7 +9258,7 @@ msgstr "" msgid "" "This example extracts the second component curve, a CircularString, from a " "CompoundCurve." -msgstr "" +msgstr "??????????? 2?????? CIRCULARSTRING ?????????" #. Tag: refpurpose #, no-c-format @@ -9618,16 +9644,20 @@ msgid "" "Compare the memory used by all geometries in a Massachusetts town dataset " "with the subset for Boston." msgstr "" +"??????????????????????????????????????" +"?????" #. Tag: para #, no-c-format msgid "Return the memory size of a CircularString in bytes." -msgstr "" +msgstr "CIRCULARSTRING????????????????????" #. Tag: para #, no-c-format msgid "Calculate the percentage of a table's total size used by geometry data." msgstr "" +"??????????????????????????????????????" +"?????????" #. Tag: refpurpose #, no-c-format @@ -9664,12 +9694,12 @@ msgstr "" #. Tag: para #, no-c-format msgid "Count the points in a 2D LineString." -msgstr "" +msgstr "2?????????????????????" #. Tag: para #, no-c-format msgid "Count the points in a 3D LineString." -msgstr "" +msgstr "3????????????????????" #. Tag: refpurpose #, no-c-format @@ -9718,6 +9748,8 @@ msgid "" "Changed: 3.6.0 TIN and PolyhedralSurface are treated as unitary geometries " "and return 1; use ST_NumPatches to count faces." msgstr "" +"Changed: 3.6.0 TIN ? POLYHEDRALSURFACE ???????????????? 1?" +"?????????????????? ST_NumPatches ??????" #. Tag: para #, no-c-format @@ -9732,7 +9764,7 @@ msgstr "?????1???????????????NULL?? #. Tag: para #, no-c-format msgid "A MultiPoint counts as one geometry within a GeometryCollection." -msgstr "" +msgstr "GEOMETRYCOLLECTION ???????????? MULTIPOINT ??????" #. Tag: para #, no-c-format @@ -9770,14 +9802,14 @@ msgstr "" #. Tag: para #, no-c-format msgid "Count the interior rings of a Polygon." -msgstr "" +msgstr "??????????????????" #. Tag: para #, no-c-format msgid "" "For a MultiPolygon, dump its component Polygons and sum their interior ring " "counts." -msgstr "" +msgstr "MULTIPOLYGON??POLYGON??????????????????????" #. Tag: para #, no-c-format @@ -9789,12 +9821,12 @@ msgstr ", " msgid "" "Returns the number of interior rings (holes) of a Polygon. Alias for " "ST_NumInteriorRings." -msgstr "" +msgstr "POLYGON ?????? (?) ????????ST_NumInteriorRings ??????" #. Tag: para #, no-c-format msgid "This function is an alias for ." -msgstr "" +msgstr "????? ??????" #. Tag: para #, no-c-format @@ -9804,7 +9836,7 @@ msgstr "Availability: 1.2.2" #. Tag: refpurpose #, no-c-format msgid "Returns the number of faces in a PolyhedralSurface or TIN." -msgstr "" +msgstr "POLYHEDRALSURFACE ??? TIN ?????????????" #. Tag: para #, no-c-format @@ -9813,6 +9845,9 @@ msgid "" "other geometries. Unlike , this function " "counts individual faces." msgstr "" +"POLYHEDRALSURFACE ??? TIN ????????????????????????" +"? NULL ?????? ??????????" +"????????????" #. Tag: para #, no-c-format @@ -9822,7 +9857,7 @@ msgstr "&sqlmm_compliant; SQL-MM ISO/IEC 13249-3: 8.5" #. Tag: para #, no-c-format msgid ", , " -msgstr "" +msgstr ", , " #. Tag: refpurpose #, no-c-format @@ -9851,7 +9886,7 @@ msgstr "&sqlmm_compliant; SQL-MM 3: 7.2.4" #. Tag: refpurpose #, no-c-format msgid "Returns the Nth face of a PolyhedralSurface or TIN." -msgstr "" +msgstr "POLYHEDRALSURFACE ??? TIN ? N?????????????" #. Tag: para #, no-c-format @@ -9861,6 +9896,11 @@ msgid "" "faces, because treats PolyhedralSurface and " "TIN as unitary geometries." msgstr "" +"POLYHEDRALSURFACE ??? TIN ? 1???? N???????????????" +"????????????????????????????? NULL ??????" +"????????????????????????? ? POLYHEDRALSURFACE ? TIN ???????????" +"????????" #. Tag: para #, no-c-format @@ -9888,6 +9928,9 @@ msgid "" "linkend=\"ST_GeometryN\"/>, , " msgstr "" +", , , , , " #. Tag: refpurpose #, no-c-format @@ -9969,6 +10012,8 @@ msgid "" "The index is 1-based. A negative index counts backward from the end of the " "LineString." msgstr "" +"??????? 1??????????????? LINESTRING ?????????" +"????" #. Tag: refpurpose #, no-c-format @@ -10088,6 +10133,9 @@ msgid "" "table. The example uses exact endpoint equality, so linework with nearly " "coincident endpoints should be snapped or otherwise cleaned first." msgstr "" +"LINESTRING ?????????????????????????????????" +"??????????????????????????????????????" +"??????????????" #. Tag: para #, no-c-format @@ -11171,7 +11219,7 @@ msgstr "" #. Tag: para #, no-c-format msgid "10-meter expanded box around bbox of a linestring." -msgstr "" +msgstr "??????????????????????? 10m ?????????" #. Tag: para #, no-c-format @@ -11248,7 +11296,7 @@ msgstr "" #. Tag: para #, no-c-format msgid "Return extent of each geometry category." -msgstr "" +msgstr "?????????????????????????????" #. Tag: para #, no-c-format ----------------------------------------------------------------------- Summary of changes: doc/po/ja/postgis-manual.po | 104 ++++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 28 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Sun Aug 2 22:40:14 2026 From: git at osgeo.org (git at osgeo.org) Date: Sun, 2 Aug 2026 22:40:14 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-188-gc726cfb93c Message-ID: <20260803054015.190481DEBF2@trac.osgeo.org> 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 c726cfb93c31609f076ebc33bed2cd976922de51 (commit) via 8c7a156de49610d39bb7cde310e2ea998f8f7913 (commit) via 31aec6787f974c94ff5fa0180969d73dd1817e14 (commit) from 66a5f3d56d091911ff502d207082c0792d3a6931 (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 c726cfb93c31609f076ebc33bed2cd976922de51 Author: Regina Obe Date: Mon Aug 3 01:39:57 2026 -0400 Change to beta2 since too many changes for an RC diff --git a/NEWS b/NEWS index 1b3a9e87da..65e6328bc5 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -PostGIS 3.7.0rc1 +PostGIS 3.7.0beta2 2026/xx/xx This version requires GEOS 3.10+, PostgreSQL 14-19beta2, Proj 6.1+, libgmp. To take advantage of all features postgis extension features, GEOS 3.15+ is needed. commit 8c7a156de49610d39bb7cde310e2ea998f8f7913 Author: Regina Obe Date: Mon Aug 3 01:38:13 2026 -0400 Add Dennis Tighe to credits for https://trac.osgeo.org/postgis/ticket/6109 For PostGIS 3.7.0 diff --git a/.mailmap b/.mailmap index d72621b923..4508bcf05b 100644 --- a/.mailmap +++ b/.mailmap @@ -33,7 +33,7 @@ Darafei Praliaskouski Darafei Praliaskouski Darafei Dave Blasby David Blasby - +Dennis Tighe Devrim G?nd?z Devrim G?ND?Z Edouard Choini?re Edouard Choiniere diff --git a/NEWS b/NEWS index d663d01851..1b3a9e87da 100644 --- a/NEWS +++ b/NEWS @@ -37,7 +37,9 @@ These are only changes since 3.7.0beta1. geometry data (Darafei Praliaskouski) - GT-564, Avoid ST_MakePolygon failures with NULL hole array entries (Darafei Praliaskouski) - - #6110, regression in speed with geometry_columns + - #6109, Out-of-bounds heap read in BOX2D_out and BOX2D_expand + on 65-byte box2d under ASAN (Dennis Tighe, Google) + - #6110, regression in speed with geometry_columns (Regina Obe) * Enhancements * diff --git a/doc/credits.xml b/doc/credits.xml index 8f3517223d..cdb0e7be25 100644 --- a/doc/credits.xml +++ b/doc/credits.xml @@ -305,6 +305,7 @@ David Garnier David Skea David Techer + Dennis Tighe Denys Kovshun Devrim G?nd?z Dian M Fay commit 31aec6787f974c94ff5fa0180969d73dd1817e14 Author: Dennis Tighe Date: Wed Jul 29 17:49:01 2026 -0700 Fix out-of-bounds read in BOX2D_out and BOX2D_expand box2d is declared with internallength=65 (postgis.sql.in), which is 7 bytes short of sizeof(GBOX) (72). Copying the full GBOX struct (72 bytes) via memcpy in BOX2D_out and BOX2D_expand causes a 7-byte out-of-bounds heap read under ASAN. Reference: #6109 This change fixes this by copying only up to offsetof(GBOX, zmin), which contains all 2D box fields (xmin, xmax, ymin, ymax, flags, SRID) within the 65-byte payload. This also memzeros the target buffer out as a defensive measure where it wasn't done previously. Add regression test regress/core/box2d.sql (these fail under ASAN today). References #6109 for PostGIS 3.7.0 Closes https://gitea.osgeo.org/postgis/postgis/pulls/628 for PostGIS 3.7.0 diff --git a/postgis/lwgeom_box.c b/postgis/lwgeom_box.c index 98b39ed955..f53424507a 100644 --- a/postgis/lwgeom_box.c +++ b/postgis/lwgeom_box.c @@ -100,9 +100,15 @@ Datum BOX2D_out(PG_FUNCTION_ARGS) int size = 0; GBOX *box = (GBOX *)PG_GETARG_POINTER(0); - /* Avoid unaligned access to the gbox struct */ + /* Avoid unaligned access to the gbox struct. + * + * box2d can be 65 bytes, which is 7 bytes short of sizeof(GBOX) (72) + * so just copy the required part (xy/min, xy/max) and zero the rest + * (matches BOX2d_expand). + */ GBOX box_aligned; - memcpy(&box_aligned, box, sizeof(GBOX)); + memset(&box_aligned, 0, sizeof(box_aligned)); + memcpy(&box_aligned, box, offsetof(GBOX, zmin)); size = 4; size += lwprint_double(box_aligned.xmin, precision, &tmp[size]); @@ -387,8 +393,10 @@ PG_FUNCTION_INFO_V1(BOX2D_expand); Datum BOX2D_expand(PG_FUNCTION_ARGS) { GBOX *box = (GBOX *)PG_GETARG_POINTER(0); - GBOX *result = (GBOX *)palloc(sizeof(GBOX)); - memcpy(result, box, sizeof(GBOX)); + /* box2d is 65 bytes (7 bytes short of sizeof(GBOX)) and is a purely + * 2D box; copy only the 2D header */ + GBOX *result = (GBOX *)palloc0(sizeof(GBOX)); + memcpy(result, box, offsetof(GBOX, zmin)); if (PG_NARGS() == 2) { diff --git a/regress/core/box2d.sql b/regress/core/box2d.sql new file mode 100644 index 0000000000..746f778603 --- /dev/null +++ b/regress/core/box2d.sql @@ -0,0 +1,8 @@ +-- box2d output / expand must not read past a materialised box2d value. +-- see #6109 +SELECT 'out', ('LINESTRING(0 0,1 1)'::geometry::box2d)::text; +SELECT 'out_3d', ('LINESTRING Z (0 0 9,2 3 9)'::geometry::box2d)::text; +SELECT 'roundtrip', 'BOX(1.5 2.5,3.5 4.5)'::box2d::text; +SELECT 'extent', ST_Extent(g)::text FROM (VALUES ('POINT(0 0)'::geometry),('POINT(5 7)'::geometry)) v(g); +SELECT 'expand_d', ST_Expand('LINESTRING(0 0,10 10)'::geometry::box2d, 1)::text; +SELECT 'expand_dxdy',ST_Expand('LINESTRING(0 0,10 10)'::geometry::box2d, 2, 3)::text; diff --git a/regress/core/box2d_expected b/regress/core/box2d_expected new file mode 100644 index 0000000000..e6ce8e0b6d --- /dev/null +++ b/regress/core/box2d_expected @@ -0,0 +1,6 @@ +out|BOX(0 0,1 1) +out_3d|BOX(0 0,2 3) +roundtrip|BOX(1.5 2.5,3.5 4.5) +extent|BOX(0 0,5 7) +expand_d|BOX(-1 -1,11 11) +expand_dxdy|BOX(-2 -3,12 13) diff --git a/regress/core/tests.mk.in b/regress/core/tests.mk.in index 1b14fbeebc..784c507130 100644 --- a/regress/core/tests.mk.in +++ b/regress/core/tests.mk.in @@ -33,6 +33,7 @@ TESTS += \ $(top_srcdir)/regress/core/bestsrid \ $(top_srcdir)/regress/core/binary \ $(top_srcdir)/regress/core/boundary \ + $(top_srcdir)/regress/core/box2d \ $(top_srcdir)/regress/core/catmullrom \ $(top_srcdir)/regress/core/chaikin \ $(top_srcdir)/regress/core/clean \ ----------------------------------------------------------------------- Summary of changes: .mailmap | 2 +- NEWS | 6 ++++-- doc/credits.xml | 1 + postgis/lwgeom_box.c | 16 ++++++++++++---- regress/core/box2d.sql | 8 ++++++++ regress/core/box2d_expected | 6 ++++++ regress/core/tests.mk.in | 1 + 7 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 regress/core/box2d.sql create mode 100644 regress/core/box2d_expected hooks/post-receive -- PostGIS From trac at osgeo.org Sun Aug 2 22:40:16 2026 From: trac at osgeo.org (PostGIS) Date: Mon, 03 Aug 2026 05:40:16 -0000 Subject: [PostGIS] #6109: Out-of-bounds heap read in BOX2D_out and BOX2D_expand on 65-byte box2d under ASAN In-Reply-To: <048.9fdb58191af370fb0c5962c74366793e@osgeo.org> References: <048.9fdb58191af370fb0c5962c74366793e@osgeo.org> Message-ID: <063.bf374b29e1e3766b616091f8e4ff652c@osgeo.org> #6109: Out-of-bounds heap read in BOX2D_out and BOX2D_expand on 65-byte box2d under ASAN ----------------------+--------------------------- Reporter: dtighe | Owner: pramsey Type: defect | Status: new Priority: medium | Milestone: PostGIS 3.6.5 Component: postgis | Version: 3.6.x Resolution: | Keywords: ----------------------+--------------------------- Comment (by Regina Obe ): In [changeset:"31aec6787f974c94ff5fa0180969d73dd1817e14/git" 31aec67/git]: {{{#!CommitTicketReference repository="git" revision="31aec6787f974c94ff5fa0180969d73dd1817e14" Fix out-of-bounds read in BOX2D_out and BOX2D_expand box2d is declared with internallength=65 (postgis.sql.in), which is 7 bytes short of sizeof(GBOX) (72). Copying the full GBOX struct (72 bytes) via memcpy in BOX2D_out and BOX2D_expand causes a 7-byte out-of-bounds heap read under ASAN. Reference: #6109 This change fixes this by copying only up to offsetof(GBOX, zmin), which contains all 2D box fields (xmin, xmax, ymin, ymax, flags, SRID) within the 65-byte payload. This also memzeros the target buffer out as a defensive measure where it wasn't done previously. Add regression test regress/core/box2d.sql (these fail under ASAN today). References #6109 for PostGIS 3.7.0 Closes https://gitea.osgeo.org/postgis/postgis/pulls/628 for PostGIS 3.7.0 }}} -- Ticket URL: PostGIS The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project. From git at osgeo.org Sun Aug 2 23:21:37 2026 From: git at osgeo.org (git at osgeo.org) Date: Sun, 2 Aug 2026 23:21:37 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-189-ge1f0a0baa6 Message-ID: <20260803062137.6B85C1B9C0C@trac.osgeo.org> 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 e1f0a0baa66f59f2e99dcf56c962d654b478a649 (commit) from c726cfb93c31609f076ebc33bed2cd976922de51 (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 e1f0a0baa66f59f2e99dcf56c962d654b478a649 Author: Regina Obe Date: Sun Aug 2 23:21:35 2026 -0700 Update .mailmap Try to fix contributor thingy to make the contributor checker happy diff --git a/.mailmap b/.mailmap index 4508bcf05b..a9aa9e31f3 100644 --- a/.mailmap +++ b/.mailmap @@ -33,7 +33,7 @@ Darafei Praliaskouski Darafei Praliaskouski Darafei Dave Blasby David Blasby -Dennis Tighe +Dennis Tighe, Google Devrim G?nd?z Devrim G?ND?Z Edouard Choini?re Edouard Choiniere ----------------------------------------------------------------------- Summary of changes: .mailmap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- PostGIS From git at osgeo.org Sun Aug 2 23:39:15 2026 From: git at osgeo.org (git at osgeo.org) Date: Sun, 2 Aug 2026 23:39:15 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-190-g393c276ab5 Message-ID: <20260803063916.59F011BB2F7@trac.osgeo.org> 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 393c276ab57fdebe12d8bc753346e219d4fa228a (commit) from e1f0a0baa66f59f2e99dcf56c962d654b478a649 (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 393c276ab57fdebe12d8bc753346e219d4fa228a Author: Teramoto Ikuhiro Date: Mon Aug 3 05:03:57 2026 +0000 Translated PostGIS Manual using Weblate (Japanese) Currently translated at 89.1% (5332 of 5981 strings) Translation: postgis/PostGIS Manual Translate-URL: https://weblate.osgeo.org/projects/postgis/postgis-manual/ja/ diff --git a/doc/po/ja/postgis-manual.po b/doc/po/ja/postgis-manual.po index fc25b0b514..9c1b03a14a 100644 --- a/doc/po/ja/postgis-manual.po +++ b/doc/po/ja/postgis-manual.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: postgis 3.5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2026-07-20 08:06+0000\n" -"PO-Revision-Date: 2026-08-03 03:39+0000\n" +"PO-Revision-Date: 2026-08-03 06:39+0000\n" "Last-Translator: Teramoto Ikuhiro \n" "Language-Team: Japanese \n" @@ -14865,7 +14865,7 @@ msgstr "" msgid "" "A Polygon is converted to a single-element MultiPolygon. The coordinates are " "unchanged." -msgstr "" +msgstr "???????? 1???????????????????????????" #. Tag: refpurpose #, no-c-format @@ -15289,17 +15289,19 @@ msgid "" "The input polygon has 55 points. The result retains 15 points, while " "rendering the same shape inside the view envelope." msgstr "" +"??????? 55??????????? 15 ?????????????????" +"????????????????" #. Tag: para #, no-c-format msgid "" "Only linework affecting the view is retained; existing vertices are reused." -msgstr "" +msgstr "??????????????????????????????????" #. Tag: para #, no-c-format msgid "A line with no segment relevant to the view becomes empty." -msgstr "" +msgstr "?????????????????????????" #. Tag: para #, no-c-format @@ -15307,6 +15309,8 @@ msgid "" "Removing vertices without computing intersections can introduce self-" "intersections in the result." msgstr "" +"???????????????????????????????????" +"????????????????????????" #. Tag: para #, no-c-format @@ -15314,6 +15318,8 @@ msgid "" "With the default cartesian_hint, the function removes " "only points known to be irrelevant to the view." msgstr "" +"?????? cartesian_hint ?????????????" +"????????????????????????" #. Tag: para #, no-c-format ----------------------------------------------------------------------- Summary of changes: doc/po/ja/postgis-manual.po | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 00:29:42 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 00:29:42 -0700 (PDT) Subject: [SCM] PostGIS branch stable-3.6 updated. 3.6.4-106-g36241ae180 Message-ID: <20260803072942.63FE91BE6BD@trac.osgeo.org> 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, stable-3.6 has been updated via 36241ae1809fd6335c22fbff12785720d05f3997 (commit) via 8227f9b542e6c3fcd8c05b80e1126df6ae621daa (commit) from 6fd44ca600201cf916447c8586346e7d05d94335 (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 36241ae1809fd6335c22fbff12785720d05f3997 Author: Regina Obe Date: Mon Aug 3 03:29:27 2026 -0400 Add NEWS and credits. Reference #6109 for PostGIS 3.6.5 diff --git a/NEWS b/NEWS index 26417e01b4..63e6a05a2d 100644 --- a/NEWS +++ b/NEWS @@ -57,7 +57,8 @@ PostGIS 3.6.5 (Darafei Praliaskouski) - GT-564, Avoid ST_MakePolygon failures with NULL hole array entries (Darafei Praliaskouski) - +- #6109, Out-of-bounds heap read in BOX2D_out and BOX2D_expand + on 65-byte box2d under ASAN (Dennis Tighe, Google) PostGIS 3.6.4 2026/06/08 diff --git a/doc/introduction.xml b/doc/introduction.xml index 983f01f64f..8e2e9f30ef 100644 --- a/doc/introduction.xml +++ b/doc/introduction.xml @@ -247,6 +247,7 @@ Christoph Berg Christoph Moench-Tegeder Dane Springmeyer + Dennis Tighe Daniel Nylander Dapeng Wang Daryl Herzmann commit 8227f9b542e6c3fcd8c05b80e1126df6ae621daa Author: Dennis Tighe, Google Date: Wed Jul 29 17:49:01 2026 -0700 Fix out-of-bounds read in BOX2D_out and BOX2D_expand box2d is declared with internallength=65 (postgis.sql.in), which is 7 bytes short of sizeof(GBOX) (72). Copying the full GBOX struct (72 bytes) via memcpy in BOX2D_out and BOX2D_expand causes a 7-byte out-of-bounds heap read under ASAN. Reference: #6109 This change fixes this by copying only up to offsetof(GBOX, zmin), which contains all 2D box fields (xmin, xmax, ymin, ymax, flags, SRID) within the 65-byte payload. This also memzeros the target buffer out as a defensive measure where it wasn't done previously. Add regression test regress/core/box2d.sql (these fail under ASAN today). References #6109 for PostGIS 3.6.5 Closes https://gitea.osgeo.org/postgis/postgis/pulls/628 for PostGIS 3.6.5 diff --git a/postgis/lwgeom_box.c b/postgis/lwgeom_box.c index 98b39ed955..f53424507a 100644 --- a/postgis/lwgeom_box.c +++ b/postgis/lwgeom_box.c @@ -100,9 +100,15 @@ Datum BOX2D_out(PG_FUNCTION_ARGS) int size = 0; GBOX *box = (GBOX *)PG_GETARG_POINTER(0); - /* Avoid unaligned access to the gbox struct */ + /* Avoid unaligned access to the gbox struct. + * + * box2d can be 65 bytes, which is 7 bytes short of sizeof(GBOX) (72) + * so just copy the required part (xy/min, xy/max) and zero the rest + * (matches BOX2d_expand). + */ GBOX box_aligned; - memcpy(&box_aligned, box, sizeof(GBOX)); + memset(&box_aligned, 0, sizeof(box_aligned)); + memcpy(&box_aligned, box, offsetof(GBOX, zmin)); size = 4; size += lwprint_double(box_aligned.xmin, precision, &tmp[size]); @@ -387,8 +393,10 @@ PG_FUNCTION_INFO_V1(BOX2D_expand); Datum BOX2D_expand(PG_FUNCTION_ARGS) { GBOX *box = (GBOX *)PG_GETARG_POINTER(0); - GBOX *result = (GBOX *)palloc(sizeof(GBOX)); - memcpy(result, box, sizeof(GBOX)); + /* box2d is 65 bytes (7 bytes short of sizeof(GBOX)) and is a purely + * 2D box; copy only the 2D header */ + GBOX *result = (GBOX *)palloc0(sizeof(GBOX)); + memcpy(result, box, offsetof(GBOX, zmin)); if (PG_NARGS() == 2) { diff --git a/regress/core/box2d.sql b/regress/core/box2d.sql new file mode 100644 index 0000000000..746f778603 --- /dev/null +++ b/regress/core/box2d.sql @@ -0,0 +1,8 @@ +-- box2d output / expand must not read past a materialised box2d value. +-- see #6109 +SELECT 'out', ('LINESTRING(0 0,1 1)'::geometry::box2d)::text; +SELECT 'out_3d', ('LINESTRING Z (0 0 9,2 3 9)'::geometry::box2d)::text; +SELECT 'roundtrip', 'BOX(1.5 2.5,3.5 4.5)'::box2d::text; +SELECT 'extent', ST_Extent(g)::text FROM (VALUES ('POINT(0 0)'::geometry),('POINT(5 7)'::geometry)) v(g); +SELECT 'expand_d', ST_Expand('LINESTRING(0 0,10 10)'::geometry::box2d, 1)::text; +SELECT 'expand_dxdy',ST_Expand('LINESTRING(0 0,10 10)'::geometry::box2d, 2, 3)::text; diff --git a/regress/core/box2d_expected b/regress/core/box2d_expected new file mode 100644 index 0000000000..e6ce8e0b6d --- /dev/null +++ b/regress/core/box2d_expected @@ -0,0 +1,6 @@ +out|BOX(0 0,1 1) +out_3d|BOX(0 0,2 3) +roundtrip|BOX(1.5 2.5,3.5 4.5) +extent|BOX(0 0,5 7) +expand_d|BOX(-1 -1,11 11) +expand_dxdy|BOX(-2 -3,12 13) diff --git a/regress/core/tests.mk.in b/regress/core/tests.mk.in index a959ad92f3..734209cd5d 100644 --- a/regress/core/tests.mk.in +++ b/regress/core/tests.mk.in @@ -32,6 +32,7 @@ TESTS += \ $(top_srcdir)/regress/core/bestsrid \ $(top_srcdir)/regress/core/binary \ $(top_srcdir)/regress/core/boundary \ + $(top_srcdir)/regress/core/box2d \ $(top_srcdir)/regress/core/chaikin \ $(top_srcdir)/regress/core/filterm \ $(top_srcdir)/regress/core/cluster \ ----------------------------------------------------------------------- Summary of changes: NEWS | 3 ++- doc/introduction.xml | 1 + postgis/lwgeom_box.c | 16 ++++++++++++---- regress/core/box2d.sql | 8 ++++++++ regress/core/box2d_expected | 6 ++++++ regress/core/tests.mk.in | 1 + 6 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 regress/core/box2d.sql create mode 100644 regress/core/box2d_expected hooks/post-receive -- PostGIS From trac at osgeo.org Mon Aug 3 00:29:44 2026 From: trac at osgeo.org (PostGIS) Date: Mon, 03 Aug 2026 07:29:44 -0000 Subject: [PostGIS] #6109: Out-of-bounds heap read in BOX2D_out and BOX2D_expand on 65-byte box2d under ASAN In-Reply-To: <048.9fdb58191af370fb0c5962c74366793e@osgeo.org> References: <048.9fdb58191af370fb0c5962c74366793e@osgeo.org> Message-ID: <063.fdfce7c338c737aac8b476c25958a093@osgeo.org> #6109: Out-of-bounds heap read in BOX2D_out and BOX2D_expand on 65-byte box2d under ASAN ----------------------+--------------------------- Reporter: dtighe | Owner: pramsey Type: defect | Status: new Priority: medium | Milestone: PostGIS 3.6.5 Component: postgis | Version: 3.6.x Resolution: | Keywords: ----------------------+--------------------------- Comment (by Regina Obe ): In [changeset:"8227f9b542e6c3fcd8c05b80e1126df6ae621daa/git" 8227f9b5/git]: {{{#!CommitTicketReference repository="git" revision="8227f9b542e6c3fcd8c05b80e1126df6ae621daa" Fix out-of-bounds read in BOX2D_out and BOX2D_expand box2d is declared with internallength=65 (postgis.sql.in), which is 7 bytes short of sizeof(GBOX) (72). Copying the full GBOX struct (72 bytes) via memcpy in BOX2D_out and BOX2D_expand causes a 7-byte out-of-bounds heap read under ASAN. Reference: #6109 This change fixes this by copying only up to offsetof(GBOX, zmin), which contains all 2D box fields (xmin, xmax, ymin, ymax, flags, SRID) within the 65-byte payload. This also memzeros the target buffer out as a defensive measure where it wasn't done previously. Add regression test regress/core/box2d.sql (these fail under ASAN today). References #6109 for PostGIS 3.6.5 Closes https://gitea.osgeo.org/postgis/postgis/pulls/628 for PostGIS 3.6.5 }}} -- Ticket URL: PostGIS The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project. From git at osgeo.org Mon Aug 3 01:39:15 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 01:39:15 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-193-g2631fe89f3 Message-ID: <20260803083915.C97191C9284@trac.osgeo.org> 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 2631fe89f3c7918d2a5e25e4d8dd74aef4b0dec8 (commit) from c6cb9713472c36d4e5e72e9465a1928c2089c754 (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 2631fe89f3c7918d2a5e25e4d8dd74aef4b0dec8 Author: Teramoto Ikuhiro Date: Mon Aug 3 07:30:48 2026 +0000 Translated PostGIS Manual using Weblate (Japanese) Currently translated at 89.2% (5338 of 5981 strings) Translation: postgis/PostGIS Manual Translate-URL: https://weblate.osgeo.org/projects/postgis/postgis-manual/ja/ diff --git a/doc/po/ja/postgis-manual.po b/doc/po/ja/postgis-manual.po index 9c1b03a14a..5e5cfcc0d7 100644 --- a/doc/po/ja/postgis-manual.po +++ b/doc/po/ja/postgis-manual.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: postgis 3.5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2026-07-20 08:06+0000\n" -"PO-Revision-Date: 2026-08-03 06:39+0000\n" +"PO-Revision-Date: 2026-08-03 08:39+0000\n" "Last-Translator: Teramoto Ikuhiro \n" "Language-Team: Japanese \n" @@ -11360,6 +11360,9 @@ msgid "" "coordinate bounding box. It is assumed here that the geometries are stored " "with SRID=2163 (US National Atlas equal area)." msgstr "" +"??????????????????????????????????????" +"????????????????????????????? SRID=2163 (??" +"?????????????) ???????" #. Tag: para #, no-c-format @@ -11834,6 +11837,8 @@ msgid "" "Cluster polygons within 50 units of each other, requiring at least two " "polygons per cluster. The isolated polygon is reported as noise." msgstr "" +"????? 50????????????????????????????????" +"??????????????????????????????????" #. Tag: para #, no-c-format @@ -12010,6 +12015,8 @@ msgid "" "These six edges describe a square with both diagonals. The minimum spanning " "tree keeps three edges and excludes the rest." msgstr "" +"??6??????????????????????3?????????????" +"??????" #. Tag: para #, no-c-format @@ -12073,12 +12080,12 @@ msgstr "Enhanced: 3.1.0 3?????????????????? msgid "" "Define the parcel geometries once in a CTE and reuse them across the " "executable examples." -msgstr "" +msgstr "??CTE??????????????????????????????" #. Tag: para #, no-c-format msgid "Parcels color-coded by cluster number (cid)." -msgstr "" +msgstr "??????? (cid) ???????????????" #. Tag: para #, no-c-format @@ -12094,6 +12101,11 @@ msgid "" "dataset\">Kontur Population Data that do not span more than 3000 km " "from their center:" msgstr "" +"?: 3????????????????????????????????????" +"?????????????????????Kontur Population Data ?????????? 3000 km ????????????????? 20??" +"???????" #. Tag: para #, no-c-format ----------------------------------------------------------------------- Summary of changes: doc/po/ja/postgis-manual.po | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 02:31:35 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 02:31:35 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-195-g1dea1ba1ad Message-ID: <20260803093135.512FA1CBD6F@trac.osgeo.org> 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 1dea1ba1ade42f25d8d28b981eddd857a6710dae (commit) via 43d35acf56cb1a93aaa10bc7d127532f34c3ca64 (commit) from 2631fe89f3c7918d2a5e25e4d8dd74aef4b0dec8 (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 1dea1ba1ade42f25d8d28b981eddd857a6710dae Merge: 2631fe89f3 43d35acf56 Author: Darafei Praliaskouski Date: Mon Aug 3 02:31:26 2026 -0700 Merge pull request 'ci: give every localized docs step the same path filter' (!659) from Komzpa/postgis:ci/docs-locale-filter-20260803 into master Pipeline **6570 on master died before running a single step**: ``` step 'check-cheatsheets-ja' depends on step 'check-cheatsheets-de' which is filtered out by its conditions ``` Woodpecker refuses a whole pipeline when an included step depends on a step its own conditions leave out. The localized steps are chained to each other to cap memory (14bec3c66, 74ac1ee1c), but each one was filtered to its own language's `.po` files, so the chain only held together when a commit touched every language at once. Every single-language translation commit ? which is exactly what Weblate produces ? breaks it. The commit 6570 built, `c69b4727c`, touches Japanese only. The chain is worth keeping, so the filters have to agree instead. All localized steps now share one `when_localized` anchor: the languages are included or excluded together, a translation commit runs the localized targets for every language serialized as before, and no step can depend on a step that is not there. Checked before pushing: * `woodpecker-cli lint .woodpecker/docs.yml` ? `Config is valid` * cross-language dependencies whose filters disagree: **60 on master, 0 here** (same 72 steps) * the memory-control chain is unchanged ? `depends_on: [ prepare, check-xml-it_IT ]` and friends are all still there * `update-docs-localized.sh` is idempotent: running it twice produces a byte-identical file One thing found on the way: the comment explaining why the chain exists sat *past* the `DO NOT EDIT PAST THIS LINE` marker, so `update-docs-localized.sh` deleted it on every run. It is now printed by the generator, and says what the filter has to do with the chain. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/659 commit 43d35acf56cb1a93aaa10bc7d127532f34c3ca64 Author: Darafei Praliaskouski Date: Mon Aug 3 05:53:02 2026 +0400 ci: give every localized docs step the same path filter A pipeline for master died before it ran a single step: step 'check-cheatsheets-ja' depends on step 'check-cheatsheets-de' which is filtered out by its conditions Woodpecker refuses the whole pipeline when an included step depends on a step that its own conditions leave out. The localized steps are chained to each other to cap memory, but each one was filtered to its own language's .po files, so the chain only held together when a commit touched every language at once. Every single-language translation commit -- which is what Weblate produces -- broke it. Pipeline 6570 on master is one; the commit it built touched Japanese only. Keeping the chain matters, so the filters have to agree instead: all localized steps now share when_localized, and the languages are included or excluded together. A translation commit runs the localized targets for every language, serialized as before, rather than erroring the pipeline. The comment explaining why the chain exists lived past the DO NOT EDIT line, so update-docs-localized.sh deleted it every time it ran. It is now printed by the generator and says what the filter has to do with the chain. diff --git a/.woodpecker/docs-localized.yml.in b/.woodpecker/docs-localized.yml.in index 26b9b5c1b2..137d24911a 100644 --- a/.woodpecker/docs-localized.yml.in +++ b/.woodpecker/docs-localized.yml.in @@ -5,7 +5,5 @@ - make -C build-docs/doc/po/@LANG@ local- at TARGET@ depends_on: @DEP@ when: - - path: - include: - - "doc/po/@LANG@/*.po" + - path: *when_localized diff --git a/.woodpecker/docs.yml b/.woodpecker/docs.yml index 86f9a75db0..51ee6147cc 100644 --- a/.woodpecker/docs.yml +++ b/.woodpecker/docs.yml @@ -32,6 +32,16 @@ variables: # Any localized assets - "doc/po/*/Makefile.in" - "doc/po/*/*.po" + # Every localized step shares this one filter on purpose. The localized steps are + # chained to each other to cap memory (see the generated section below), and + # Woodpecker rejects a whole pipeline when an included step depends on a step that + # its conditions filtered out. Per-language filters made that happen on every + # single-language translation commit, so the languages must be included or + # excluded together. + - &when_localized + include: + - "doc/po/*/Makefile.in" + - "doc/po/*/*.po" steps: prepare: @@ -123,6 +133,9 @@ steps: ### TARGET check-xml # Localized check-xml steps are intentionally chained to cap memory per step; this is a memory-control # measure, not a dependency between languages. Breaking the chain restores the fan-out that caused the kills. + # The chain is why every localized step carries the same when_localized filter: Woodpecker refuses a whole + # pipeline when an included step depends on one its conditions filtered out, so the languages are included + # or excluded together. Per-language filters broke every single-language translation commit. check-xml-it_IT: image: *test_image pull: true @@ -130,9 +143,7 @@ steps: - make -C build-docs/doc/po/it_IT local-check-xml depends_on: prepare when: - - path: - include: - - "doc/po/it_IT/*.po" + - path: *when_localized check-xml-pt_BR: image: *test_image @@ -141,9 +152,7 @@ steps: - make -C build-docs/doc/po/pt_BR local-check-xml depends_on: [ prepare, check-xml-it_IT ] when: - - path: - include: - - "doc/po/pt_BR/*.po" + - path: *when_localized check-xml-fr: image: *test_image @@ -152,9 +161,7 @@ steps: - make -C build-docs/doc/po/fr local-check-xml depends_on: [ prepare, check-xml-pt_BR ] when: - - path: - include: - - "doc/po/fr/*.po" + - path: *when_localized check-xml-es: image: *test_image @@ -163,9 +170,7 @@ steps: - make -C build-docs/doc/po/es local-check-xml depends_on: [ prepare, check-xml-fr ] when: - - path: - include: - - "doc/po/es/*.po" + - path: *when_localized check-xml-pl: image: *test_image @@ -174,9 +179,7 @@ steps: - make -C build-docs/doc/po/pl local-check-xml depends_on: [ prepare, check-xml-es ] when: - - path: - include: - - "doc/po/pl/*.po" + - path: *when_localized check-xml-ka: image: *test_image @@ -185,9 +188,7 @@ steps: - make -C build-docs/doc/po/ka local-check-xml depends_on: [ prepare, check-xml-pl ] when: - - path: - include: - - "doc/po/ka/*.po" + - path: *when_localized check-xml-ko_KR: image: *test_image @@ -196,9 +197,7 @@ steps: - make -C build-docs/doc/po/ko_KR local-check-xml depends_on: [ prepare, check-xml-ka ] when: - - path: - include: - - "doc/po/ko_KR/*.po" + - path: *when_localized check-xml-da: image: *test_image @@ -207,9 +206,7 @@ steps: - make -C build-docs/doc/po/da local-check-xml depends_on: [ prepare, check-xml-ko_KR ] when: - - path: - include: - - "doc/po/da/*.po" + - path: *when_localized check-xml-de: image: *test_image @@ -218,9 +215,7 @@ steps: - make -C build-docs/doc/po/de local-check-xml depends_on: [ prepare, check-xml-da ] when: - - path: - include: - - "doc/po/de/*.po" + - path: *when_localized check-xml-ja: image: *test_image @@ -229,9 +224,7 @@ steps: - make -C build-docs/doc/po/ja local-check-xml depends_on: [ prepare, check-xml-de ] when: - - path: - include: - - "doc/po/ja/*.po" + - path: *when_localized check-xml-ru: image: *test_image @@ -240,9 +233,7 @@ steps: - make -C build-docs/doc/po/ru local-check-xml depends_on: [ prepare, check-xml-ja ] when: - - path: - include: - - "doc/po/ru/*.po" + - path: *when_localized check-xml-zh_Hans: image: *test_image @@ -251,9 +242,7 @@ steps: - make -C build-docs/doc/po/zh_Hans local-check-xml depends_on: [ prepare, check-xml-ru ] when: - - path: - include: - - "doc/po/zh_Hans/*.po" + - path: *when_localized check-xml-ro: image: *test_image @@ -262,9 +251,7 @@ steps: - make -C build-docs/doc/po/ro local-check-xml depends_on: [ prepare, check-xml-zh_Hans ] when: - - path: - include: - - "doc/po/ro/*.po" + - path: *when_localized check-xml-sv: image: *test_image @@ -273,9 +260,7 @@ steps: - make -C build-docs/doc/po/sv local-check-xml depends_on: [ prepare, check-xml-ro ] when: - - path: - include: - - "doc/po/sv/*.po" + - path: *when_localized check-xml-uk: image: *test_image @@ -284,9 +269,7 @@ steps: - make -C build-docs/doc/po/uk local-check-xml depends_on: [ prepare, check-xml-sv ] when: - - path: - include: - - "doc/po/uk/*.po" + - path: *when_localized check-xml-be: image: *test_image @@ -295,11 +278,14 @@ steps: - make -C build-docs/doc/po/be local-check-xml depends_on: [ prepare, check-xml-uk ] when: - - path: - include: - - "doc/po/be/*.po" + - path: *when_localized ### TARGET html + # Localized html steps are intentionally chained to cap memory per step; this is a memory-control + # measure, not a dependency between languages. Breaking the chain restores the fan-out that caused the kills. + # The chain is why every localized step carries the same when_localized filter: Woodpecker refuses a whole + # pipeline when an included step depends on one its conditions filtered out, so the languages are included + # or excluded together. Per-language filters broke every single-language translation commit. html-it_IT: image: *test_image pull: true @@ -307,9 +293,7 @@ steps: - make -C build-docs/doc/po/it_IT local-html depends_on: check-xml-it_IT when: - - path: - include: - - "doc/po/it_IT/*.po" + - path: *when_localized html-pt_BR: image: *test_image @@ -318,9 +302,7 @@ steps: - make -C build-docs/doc/po/pt_BR local-html depends_on: [ check-xml-pt_BR, html-it_IT ] when: - - path: - include: - - "doc/po/pt_BR/*.po" + - path: *when_localized html-fr: image: *test_image @@ -329,9 +311,7 @@ steps: - make -C build-docs/doc/po/fr local-html depends_on: [ check-xml-fr, html-pt_BR ] when: - - path: - include: - - "doc/po/fr/*.po" + - path: *when_localized html-es: image: *test_image @@ -340,9 +320,7 @@ steps: - make -C build-docs/doc/po/es local-html depends_on: [ check-xml-es, html-fr ] when: - - path: - include: - - "doc/po/es/*.po" + - path: *when_localized html-pl: image: *test_image @@ -351,9 +329,7 @@ steps: - make -C build-docs/doc/po/pl local-html depends_on: [ check-xml-pl, html-es ] when: - - path: - include: - - "doc/po/pl/*.po" + - path: *when_localized html-ka: image: *test_image @@ -362,9 +338,7 @@ steps: - make -C build-docs/doc/po/ka local-html depends_on: [ check-xml-ka, html-pl ] when: - - path: - include: - - "doc/po/ka/*.po" + - path: *when_localized html-ko_KR: image: *test_image @@ -373,9 +347,7 @@ steps: - make -C build-docs/doc/po/ko_KR local-html depends_on: [ check-xml-ko_KR, html-ka ] when: - - path: - include: - - "doc/po/ko_KR/*.po" + - path: *when_localized html-da: image: *test_image @@ -384,9 +356,7 @@ steps: - make -C build-docs/doc/po/da local-html depends_on: [ check-xml-da, html-ko_KR ] when: - - path: - include: - - "doc/po/da/*.po" + - path: *when_localized html-de: image: *test_image @@ -395,9 +365,7 @@ steps: - make -C build-docs/doc/po/de local-html depends_on: [ check-xml-de, html-da ] when: - - path: - include: - - "doc/po/de/*.po" + - path: *when_localized html-ja: image: *test_image @@ -406,9 +374,7 @@ steps: - make -C build-docs/doc/po/ja local-html depends_on: [ check-xml-ja, html-de ] when: - - path: - include: - - "doc/po/ja/*.po" + - path: *when_localized html-ru: image: *test_image @@ -417,9 +383,7 @@ steps: - make -C build-docs/doc/po/ru local-html depends_on: [ check-xml-ru, html-ja ] when: - - path: - include: - - "doc/po/ru/*.po" + - path: *when_localized html-zh_Hans: image: *test_image @@ -428,9 +392,7 @@ steps: - make -C build-docs/doc/po/zh_Hans local-html depends_on: [ check-xml-zh_Hans, html-ru ] when: - - path: - include: - - "doc/po/zh_Hans/*.po" + - path: *when_localized html-ro: image: *test_image @@ -439,9 +401,7 @@ steps: - make -C build-docs/doc/po/ro local-html depends_on: [ check-xml-ro, html-zh_Hans ] when: - - path: - include: - - "doc/po/ro/*.po" + - path: *when_localized html-sv: image: *test_image @@ -450,9 +410,7 @@ steps: - make -C build-docs/doc/po/sv local-html depends_on: [ check-xml-sv, html-ro ] when: - - path: - include: - - "doc/po/sv/*.po" + - path: *when_localized html-uk: image: *test_image @@ -461,9 +419,7 @@ steps: - make -C build-docs/doc/po/uk local-html depends_on: [ check-xml-uk, html-sv ] when: - - path: - include: - - "doc/po/uk/*.po" + - path: *when_localized html-be: image: *test_image @@ -472,11 +428,14 @@ steps: - make -C build-docs/doc/po/be local-html depends_on: [ check-xml-be, html-uk ] when: - - path: - include: - - "doc/po/be/*.po" + - path: *when_localized ### TARGET cheatsheets + # Localized cheatsheets steps are intentionally chained to cap memory per step; this is a memory-control + # measure, not a dependency between languages. Breaking the chain restores the fan-out that caused the kills. + # The chain is why every localized step carries the same when_localized filter: Woodpecker refuses a whole + # pipeline when an included step depends on one its conditions filtered out, so the languages are included + # or excluded together. Per-language filters broke every single-language translation commit. cheatsheets-it_IT: image: *test_image pull: true @@ -484,9 +443,7 @@ steps: - make -C build-docs/doc/po/it_IT local-cheatsheets depends_on: check-xml-it_IT when: - - path: - include: - - "doc/po/it_IT/*.po" + - path: *when_localized cheatsheets-pt_BR: image: *test_image @@ -495,9 +452,7 @@ steps: - make -C build-docs/doc/po/pt_BR local-cheatsheets depends_on: [ check-xml-pt_BR, cheatsheets-it_IT ] when: - - path: - include: - - "doc/po/pt_BR/*.po" + - path: *when_localized cheatsheets-fr: image: *test_image @@ -506,9 +461,7 @@ steps: - make -C build-docs/doc/po/fr local-cheatsheets depends_on: [ check-xml-fr, cheatsheets-pt_BR ] when: - - path: - include: - - "doc/po/fr/*.po" + - path: *when_localized cheatsheets-es: image: *test_image @@ -517,9 +470,7 @@ steps: - make -C build-docs/doc/po/es local-cheatsheets depends_on: [ check-xml-es, cheatsheets-fr ] when: - - path: - include: - - "doc/po/es/*.po" + - path: *when_localized cheatsheets-pl: image: *test_image @@ -528,9 +479,7 @@ steps: - make -C build-docs/doc/po/pl local-cheatsheets depends_on: [ check-xml-pl, cheatsheets-es ] when: - - path: - include: - - "doc/po/pl/*.po" + - path: *when_localized cheatsheets-ka: image: *test_image @@ -539,9 +488,7 @@ steps: - make -C build-docs/doc/po/ka local-cheatsheets depends_on: [ check-xml-ka, cheatsheets-pl ] when: - - path: - include: - - "doc/po/ka/*.po" + - path: *when_localized cheatsheets-ko_KR: image: *test_image @@ -550,9 +497,7 @@ steps: - make -C build-docs/doc/po/ko_KR local-cheatsheets depends_on: [ check-xml-ko_KR, cheatsheets-ka ] when: - - path: - include: - - "doc/po/ko_KR/*.po" + - path: *when_localized cheatsheets-da: image: *test_image @@ -561,9 +506,7 @@ steps: - make -C build-docs/doc/po/da local-cheatsheets depends_on: [ check-xml-da, cheatsheets-ko_KR ] when: - - path: - include: - - "doc/po/da/*.po" + - path: *when_localized cheatsheets-de: image: *test_image @@ -572,9 +515,7 @@ steps: - make -C build-docs/doc/po/de local-cheatsheets depends_on: [ check-xml-de, cheatsheets-da ] when: - - path: - include: - - "doc/po/de/*.po" + - path: *when_localized cheatsheets-ja: image: *test_image @@ -583,9 +524,7 @@ steps: - make -C build-docs/doc/po/ja local-cheatsheets depends_on: [ check-xml-ja, cheatsheets-de ] when: - - path: - include: - - "doc/po/ja/*.po" + - path: *when_localized cheatsheets-ru: image: *test_image @@ -594,9 +533,7 @@ steps: - make -C build-docs/doc/po/ru local-cheatsheets depends_on: [ check-xml-ru, cheatsheets-ja ] when: - - path: - include: - - "doc/po/ru/*.po" + - path: *when_localized cheatsheets-zh_Hans: image: *test_image @@ -605,9 +542,7 @@ steps: - make -C build-docs/doc/po/zh_Hans local-cheatsheets depends_on: [ check-xml-zh_Hans, cheatsheets-ru ] when: - - path: - include: - - "doc/po/zh_Hans/*.po" + - path: *when_localized cheatsheets-ro: image: *test_image @@ -616,9 +551,7 @@ steps: - make -C build-docs/doc/po/ro local-cheatsheets depends_on: [ check-xml-ro, cheatsheets-zh_Hans ] when: - - path: - include: - - "doc/po/ro/*.po" + - path: *when_localized cheatsheets-sv: image: *test_image @@ -627,9 +560,7 @@ steps: - make -C build-docs/doc/po/sv local-cheatsheets depends_on: [ check-xml-sv, cheatsheets-ro ] when: - - path: - include: - - "doc/po/sv/*.po" + - path: *when_localized cheatsheets-uk: image: *test_image @@ -638,9 +569,7 @@ steps: - make -C build-docs/doc/po/uk local-cheatsheets depends_on: [ check-xml-uk, cheatsheets-sv ] when: - - path: - include: - - "doc/po/uk/*.po" + - path: *when_localized cheatsheets-be: image: *test_image @@ -649,11 +578,14 @@ steps: - make -C build-docs/doc/po/be local-cheatsheets depends_on: [ check-xml-be, cheatsheets-uk ] when: - - path: - include: - - "doc/po/be/*.po" + - path: *when_localized ### TARGET check-cheatsheets + # Localized check-cheatsheets steps are intentionally chained to cap memory per step; this is a memory-control + # measure, not a dependency between languages. Breaking the chain restores the fan-out that caused the kills. + # The chain is why every localized step carries the same when_localized filter: Woodpecker refuses a whole + # pipeline when an included step depends on one its conditions filtered out, so the languages are included + # or excluded together. Per-language filters broke every single-language translation commit. check-cheatsheets-it_IT: image: *test_image pull: true @@ -661,9 +593,7 @@ steps: - make -C build-docs/doc/po/it_IT local-check-cheatsheets depends_on: [ cheatsheets-it_IT, build-cheatsheets ] when: - - path: - include: - - "doc/po/it_IT/*.po" + - path: *when_localized check-cheatsheets-pt_BR: image: *test_image @@ -672,9 +602,7 @@ steps: - make -C build-docs/doc/po/pt_BR local-check-cheatsheets depends_on: [ cheatsheets-pt_BR, build-cheatsheets, check-cheatsheets-it_IT ] when: - - path: - include: - - "doc/po/pt_BR/*.po" + - path: *when_localized check-cheatsheets-fr: image: *test_image @@ -683,9 +611,7 @@ steps: - make -C build-docs/doc/po/fr local-check-cheatsheets depends_on: [ cheatsheets-fr, build-cheatsheets, check-cheatsheets-pt_BR ] when: - - path: - include: - - "doc/po/fr/*.po" + - path: *when_localized check-cheatsheets-es: image: *test_image @@ -694,9 +620,7 @@ steps: - make -C build-docs/doc/po/es local-check-cheatsheets depends_on: [ cheatsheets-es, build-cheatsheets, check-cheatsheets-fr ] when: - - path: - include: - - "doc/po/es/*.po" + - path: *when_localized check-cheatsheets-pl: image: *test_image @@ -705,9 +629,7 @@ steps: - make -C build-docs/doc/po/pl local-check-cheatsheets depends_on: [ cheatsheets-pl, build-cheatsheets, check-cheatsheets-es ] when: - - path: - include: - - "doc/po/pl/*.po" + - path: *when_localized check-cheatsheets-ka: image: *test_image @@ -716,9 +638,7 @@ steps: - make -C build-docs/doc/po/ka local-check-cheatsheets depends_on: [ cheatsheets-ka, build-cheatsheets, check-cheatsheets-pl ] when: - - path: - include: - - "doc/po/ka/*.po" + - path: *when_localized check-cheatsheets-ko_KR: image: *test_image @@ -727,9 +647,7 @@ steps: - make -C build-docs/doc/po/ko_KR local-check-cheatsheets depends_on: [ cheatsheets-ko_KR, build-cheatsheets, check-cheatsheets-ka ] when: - - path: - include: - - "doc/po/ko_KR/*.po" + - path: *when_localized check-cheatsheets-da: image: *test_image @@ -738,9 +656,7 @@ steps: - make -C build-docs/doc/po/da local-check-cheatsheets depends_on: [ cheatsheets-da, build-cheatsheets, check-cheatsheets-ko_KR ] when: - - path: - include: - - "doc/po/da/*.po" + - path: *when_localized check-cheatsheets-de: image: *test_image @@ -749,9 +665,7 @@ steps: - make -C build-docs/doc/po/de local-check-cheatsheets depends_on: [ cheatsheets-de, build-cheatsheets, check-cheatsheets-da ] when: - - path: - include: - - "doc/po/de/*.po" + - path: *when_localized check-cheatsheets-ja: image: *test_image @@ -760,9 +674,7 @@ steps: - make -C build-docs/doc/po/ja local-check-cheatsheets depends_on: [ cheatsheets-ja, build-cheatsheets, check-cheatsheets-de ] when: - - path: - include: - - "doc/po/ja/*.po" + - path: *when_localized check-cheatsheets-ru: image: *test_image @@ -771,9 +683,7 @@ steps: - make -C build-docs/doc/po/ru local-check-cheatsheets depends_on: [ cheatsheets-ru, build-cheatsheets, check-cheatsheets-ja ] when: - - path: - include: - - "doc/po/ru/*.po" + - path: *when_localized check-cheatsheets-zh_Hans: image: *test_image @@ -782,9 +692,7 @@ steps: - make -C build-docs/doc/po/zh_Hans local-check-cheatsheets depends_on: [ cheatsheets-zh_Hans, build-cheatsheets, check-cheatsheets-ru ] when: - - path: - include: - - "doc/po/zh_Hans/*.po" + - path: *when_localized check-cheatsheets-ro: image: *test_image @@ -793,9 +701,7 @@ steps: - make -C build-docs/doc/po/ro local-check-cheatsheets depends_on: [ cheatsheets-ro, build-cheatsheets, check-cheatsheets-zh_Hans ] when: - - path: - include: - - "doc/po/ro/*.po" + - path: *when_localized check-cheatsheets-sv: image: *test_image @@ -804,9 +710,7 @@ steps: - make -C build-docs/doc/po/sv local-check-cheatsheets depends_on: [ cheatsheets-sv, build-cheatsheets, check-cheatsheets-ro ] when: - - path: - include: - - "doc/po/sv/*.po" + - path: *when_localized check-cheatsheets-uk: image: *test_image @@ -815,9 +719,7 @@ steps: - make -C build-docs/doc/po/uk local-check-cheatsheets depends_on: [ cheatsheets-uk, build-cheatsheets, check-cheatsheets-sv ] when: - - path: - include: - - "doc/po/uk/*.po" + - path: *when_localized check-cheatsheets-be: image: *test_image @@ -826,6 +728,4 @@ steps: - make -C build-docs/doc/po/be local-check-cheatsheets depends_on: [ cheatsheets-be, build-cheatsheets, check-cheatsheets-uk ] when: - - path: - include: - - "doc/po/be/*.po" + - path: *when_localized diff --git a/.woodpecker/update-docs-localized.sh b/.woodpecker/update-docs-localized.sh index e2409df615..39d34a88a4 100755 --- a/.woodpecker/update-docs-localized.sh +++ b/.woodpecker/update-docs-localized.sh @@ -16,6 +16,14 @@ exec >> docs.yml.new for target in ${TARGETS} do echo "### TARGET ${target}" + # This comment has to be printed, not written into docs.yml by hand: everything + # past the DO NOT EDIT line is regenerated, so a warning left there is deleted by + # the next run of this script. + echo " # Localized ${target} steps are intentionally chained to cap memory per step; this is a memory-control" + echo " # measure, not a dependency between languages. Breaking the chain restores the fan-out that caused the kills." + echo " # The chain is why every localized step carries the same when_localized filter: Woodpecker refuses a whole" + echo " # pipeline when an included step depends on one its conditions filtered out, so the languages are included" + echo " # or excluded together. Per-language filters broke every single-language translation commit." previous_step= for lang in ${SUPPORTED_LANGUAGES}; do ----------------------------------------------------------------------- Summary of changes: .woodpecker/docs-localized.yml.in | 4 +- .woodpecker/docs.yml | 284 ++++++++++++----------------------- .woodpecker/update-docs-localized.sh | 8 + 3 files changed, 101 insertions(+), 195 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 02:44:59 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 02:44:59 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-206-g80a9286dba Message-ID: <20260803094500.992B51CFEFF@trac.osgeo.org> 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 80a9286dbacc32ce1538d67745a596b0dd93d52a (commit) via d8acbe05c92d928294cfde1dbb65fdb237924b47 (commit) via 621c293ed8f2c076c60d015574a33f8054c3b548 (commit) via 2dd6482998dbbcca61b2b2363a6361d05dae7a7d (commit) via c2c14b6b6cd6b077c1241d71c9e782de6f5b7bb5 (commit) via 21709044eb0dde1bfb1010e5ed0931a10d164470 (commit) via 2883c3b7e5ac6b3e3fd9fc409480fbe26d21e0c9 (commit) via a2fbed92cfdb7c9811c86b4c8d436b5655fb07cb (commit) via 4248b65e6b8f117116ebbee9bc13e62feacaf9be (commit) via 9451df186a4c519d4544babadc1bebab1fb6e2b9 (commit) via 1bcca9054b901f289be2c279a4220316fb04cab1 (commit) from 1dea1ba1ade42f25d8d28b981eddd857a6710dae (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 80a9286dbacc32ce1538d67745a596b0dd93d52a Merge: 1dea1ba1ad d8acbe05c9 Author: Darafei Praliaskouski Date: Mon Aug 3 02:44:58 2026 -0700 Merge pull request 'docs: consolidate CI reference and parity notes' (!558) from Komzpa/postgis:ci/docs-reference-parity-20260727 into master This consolidates the green CI documentation and parity-map pull requests into one review surface. It also closes the native Windows parity question in the CI map: Linux Woodpecker's MinGW+Wine job is documented as MinGW ABI/runtime coverage, while GitHub Actions MSYS2 and Jenkins Winnie remain authoritative until OSGeo has a licensed Windows Woodie agent with an owner. It adds 64-bit ARM emulation to the existing Woodpecker portability workflow as `portability` / `arm64-berrie64-qemu`. The step uses an arm64 Debian manifest digest and the QEMU scheduler label so the Docker backend does not accidentally pull or schedule an amd64-only run. This is useful emulated ARM regression coverage on amd64 hosts, but it is not native Berrie64 parity: native parity still needs a registered `linux/arm64` Woodie agent, a host owner, and a maintainer decision. It keeps the dashboard ownership notes from https://gitea.osgeo.org/postgis/postgis/pulls/526, the CI image and runner provenance page from https://gitea.osgeo.org/postgis/postgis/pulls/527, the native arm64 parity workflow and map from https://gitea.osgeo.org/postgis/postgis/pulls/553, and the macOS coverage decision page from https://gitea.osgeo.org/postgis/postgis/pulls/555. The branch preserves the existing commits and authorship, with only conflict resolution needed where the separate documentation changes touched the same CI inventory page. This intentionally does not include https://gitea.osgeo.org/postgis/postgis/pulls/528. That failure-debugging guide is related documentation work, but its current head is red, so folding it into this consolidation would discard green CI for a cosmetic reduction. Supersedes https://gitea.osgeo.org/postgis/postgis/pulls/526 Supersedes https://gitea.osgeo.org/postgis/postgis/pulls/527 Supersedes https://gitea.osgeo.org/postgis/postgis/pulls/553 Supersedes https://gitea.osgeo.org/postgis/postgis/pulls/555 Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/558 commit d8acbe05c92d928294cfde1dbb65fdb237924b47 Author: Darafei Praliaskouski Date: Tue Jul 28 05:37:04 2026 +0400 ci: run arm64 portability before armhf diff --git a/.woodpecker/portability.yml b/.woodpecker/portability.yml index 375afe7431..d6aa7accb1 100644 --- a/.woodpecker/portability.yml +++ b/.woodpecker/portability.yml @@ -190,19 +190,6 @@ steps: - ./autogen.sh - *build-and-test - arm64-berrie64-qemu: - image: arm64v8/debian:trixie-slim at sha256:8b5033c95ca60cdffb0e0f4c446e5f714e82d8960a9ef4153c0eaf13e988b0ea - pull: true - commands: - - uname -m | grep -E '^aarch64$' - - export PORTABILITY_TIER=arm64-berrie64-qemu - - export PORTABILITY_CFLAGS="-O2 -Wall -Werror -fno-omit-frame-pointer" - - *prepare-debian - - *abi-env - - *start-postgresql - - ./autogen.sh - - *build-and-test - s390x-big-endian-qemu: image: s390x/debian at sha256:4b236f9aafe8a6201c6dca29ce78c28e1eb1e314ecedc2cd2c545f9e49d060e3 pull: true commit 621c293ed8f2c076c60d015574a33f8054c3b548 Author: Darafei Praliaskouski Date: Tue Jul 28 05:25:19 2026 +0400 ci: run arm64 QEMU in portability workflow diff --git a/.woodpecker/arm64.yml b/.woodpecker/arm64.yml deleted file mode 100644 index 29a61ecb3d..0000000000 --- a/.woodpecker/arm64.yml +++ /dev/null @@ -1,172 +0,0 @@ -labels: - platform: linux/amd64 - qemu: "true" -when: - - event: [push, cron] - branch: [master, stable-*] - - event: tag - -# Emulated 64-bit ARM coverage for the current Woodpecker fleet. -# -# Native arm64 remains the right replacement for Jenkins Berrie64: QEMU does -# not cover native timing, atomic-operation, kernel, scheduler, or hardware -# behavior, and garden plus all-upgrades are too expensive under emulation. -# The current alternative in Woodpecker is no arm64 lane at all, so this job -# takes the smaller but real signal from the core extension: 64-bit ARM ABI -# shape, pointer width, alignment-sensitive execution, char signedness, byte -# order, dependency detection, build correctness, liblwgeom CUnit, extension -# install, and a targeted SQL regression slice. -# -# The OSGeo build-test image is not used here yet. The postgis-docker image -# stack has proven linux/arm64 build-test images through a local registry round -# trip, but repo.osgeo.org/postgis/build-test:debian13 is still published as -# amd64-only. Switch this job to that image after the docker stack lands and a -# maintainer publishes the multi-architecture tag. -# -# Host requirement: the amd64 Woodie agent host must have persistent -# binfmt_misc handlers for qemu-aarch64 and advertise the qemu scheduler label. -# On Debian-family hosts this is provided by qemu-user, qemu-user-binfmt, and -# binfmt-support. -variables: - arm64-deps: &arm64-deps >- - autoconf - automake - bison - build-essential - ca-certificates - file - flex - git - libcurl4-openssl-dev - libcunit1-dev - libgeos-dev - libjson-c-dev - libpcre2-dev - libproj-dev - libprotobuf-c-dev - libtool - libxml2-dev - locales - perl - pkg-config - postgresql-17 - postgresql-server-dev-17 - protobuf-c-compiler - arm64-test-script: &arm64-test-script | - set -eux - export DEBIAN_FRONTEND=noninteractive - export SRCDIR="$${CI_WORKSPACE}" - mkdir -p "$${TMPDIR:-$${SRCDIR}/.tmp/arm64-qemu-tmp}" - setup_start="$$(date +%s)" - apt-get update - apt-get install -y --no-install-recommends $${ARM64_DEPS} - rm -rf /var/lib/apt/lists/* - setup_end="$$(date +%s)" - echo "MEASURE setup_seconds=$$((setup_end - setup_start))" - - cd "$${SRCDIR}" - git config --global --add safe.directory "$${SRCDIR}" - runuser -u postgres -- git config --global --add safe.directory "$${SRCDIR}" - uname -m | grep -E '^aarch64$' - cc --version | sed -n '1p' - /usr/lib/postgresql/17/bin/pg_config --version - - build_start="$$(date +%s)" - ./autogen.sh - rm -rf build/arm64-qemu-pg17 - mkdir -p build/arm64-qemu-pg17 - cd build/arm64-qemu-pg17 - ../../configure \ - --with-library-minor-version \ - --disable-spellcheck-tests \ - --without-interrupt-tests \ - --without-raster \ - --without-topology \ - --without-sfcgal \ - CFLAGS="-O2 -Wall -fno-omit-frame-pointer -Werror" - make -j1 - build_end="$$(date +%s)" - echo "MEASURE build_seconds=$$((build_end - build_start))" - - test_start="$$(date +%s)" - make -C liblwgeom/cunit check - make install - chmod -R a+rwX "$${SRCDIR}/build/arm64-qemu-pg17" - - export PATH=/usr/lib/postgresql/17/bin:$${PATH} - export PGROOT="$${SRCDIR}/build/arm64-qemu-pgroot" - export PGDATA="$${PGROOT}/data" - export PGHOST="$${PGROOT}/socket" - export PGUSER=postgres - export PGDATABASE=postgres - rm -rf "$${PGROOT}" - mkdir -p "$${PGROOT}" - chown postgres:postgres "$${PGROOT}" - runuser -u postgres -- mkdir "$${PGDATA}" "$${PGHOST}" - runuser -u postgres -- initdb -D "$${PGDATA}" -A trust --no-sync - runuser -u postgres -- pg_ctl -D "$${PGDATA}" \ - -l "$${PGROOT}/postgresql.log" \ - -o "-F -k $${PGHOST} -c synchronous_commit=off -c full_page_writes=off" \ - -w start - trap 'runuser -u postgres -- pg_ctl -D "$${PGDATA}" -m fast -w stop || true' EXIT - psql -c 'select version()' template1 - - export RUNTESTFLAGS="-v --extension" - runuser -u postgres -- make -C "$${SRCDIR}/build/arm64-qemu-pg17" check-regress \ - TESTS="$${SRCDIR}/regress/core/regress_index $${SRCDIR}/regress/core/regress_lrs" - runuser -u postgres -- make -C "$${SRCDIR}/build/arm64-qemu-pg17" installcheck-base \ - TESTS="$${SRCDIR}/regress/core/regress_index $${SRCDIR}/regress/core/regress_lrs" - test_end="$$(date +%s)" - echo "MEASURE test_seconds=$$((test_end - test_start))" - -clone: - git: - image: woodpeckerci/plugin-git - settings: - depth: 50 - partial: false - -steps: - preflight-arm64-binfmt: - image: debian:trixie-slim - pull: true - commands: - - | - export DEBIAN_FRONTEND=noninteractive - dpkg --add-architecture arm64 - apt-get update - mkdir -p "$${CI_WORKSPACE}/.tmp/arm64-binfmt-preflight" - cd "$${CI_WORKSPACE}/.tmp/arm64-binfmt-preflight" - apt-get download busybox-static:arm64 - deb="$$(ls -1 busybox-static_*_arm64.deb | tail -n 1)" - root="$${PWD}/arm64" - mkdir -p "$${root}" - dpkg-deb -x "$${deb}" "$${root}" - - if ! output="$$("$${root}/bin/busybox" uname -m 2>&1)"; then - echo "Woodie agent host cannot execute arm64 binaries through binfmt_misc/QEMU." - echo "Install qemu-user, qemu-user-binfmt, and binfmt-support on the amd64 agent host." - echo "Operator check: docker run --rm --platform=linux/arm64 debian:trixie-slim uname -m" - echo "Observed error: $${output}" - exit 1 - fi - - if ! printf '%s\n' "$${output}" | grep -Eq '^aarch64$'; then - echo "Woodie agent host executed arm64, but uname -m returned unexpected value: $${output}" - echo "Operator check: docker run --rm --platform=linux/arm64 debian:trixie-slim uname -m" - exit 1 - fi - - echo "arm64 foreign execution ok: uname -m -> $${output}" - - arm64-qemu-regress: - image: arm64v8/debian:trixie-slim at sha256:8b5033c95ca60cdffb0e0f4c446e5f714e82d8960a9ef4153c0eaf13e988b0ea - pull: true - depends_on: preflight-arm64-binfmt - commands: - - /bin/sh -ec "$${ARM64_TEST_SCRIPT}" - -matrix: - include: - - ARM64_DEPS: *arm64-deps - ARM64_TEST_SCRIPT: *arm64-test-script diff --git a/.woodpecker/portability.yml b/.woodpecker/portability.yml index 6b0eced045..375afe7431 100644 --- a/.woodpecker/portability.yml +++ b/.woodpecker/portability.yml @@ -15,10 +15,14 @@ when: # Tier 1: armhf via arm32v7/debian under QEMU. This mirrors berrie: 32-bit # pointers and long, unsigned char, and stricter alignment than amd64. # -# Tier 2: s390x via s390x/debian under QEMU. This is the practical big-endian +# Tier 2: arm64 via arm64v8/debian under QEMU. This is an emulated stopgap for +# the Berrie64 class, not native Berrie64 parity. It proves 64-bit ARM build and +# regression execution while the project has no native linux/arm64 Woodie agent. +# +# Tier 3: s390x via s390x/debian under QEMU. This is the practical big-endian # target for WKB/EWKB, TWKB, raster byte order, hashes, and integer memcpy paths. # -# Tier 3 was investigated as Debian Ports powerpc: 32-bit, big-endian, unsigned +# Tier 4 was investigated as Debian Ports powerpc: 32-bit, big-endian, unsigned # char. Docker Hub currently has no official linux/ppc Debian manifest, and the # only discovered powerpc Debian image is a removed schema-1 image. Keep this # tier out of the required pipeline until there is a maintained OCI image or an @@ -26,9 +30,9 @@ when: # the big-endian and unsigned-char parts of the bug class. # # QEMU depends on persistent binfmt_misc registrations on the amd64 Woodie agent -# host, so the scheduler label selects hosts where foreign images can start. -# Without that label, these jobs can silently land on amd64 hosts without -# emulation and fail before the step commands run. +# host and the qemu scheduler label. Woodpecker starts the foreign-architecture +# step image directly; steps do not need a Docker socket or a nested docker run +# probe. variables: native-image: &native-image repo.osgeo.org/postgis/build-test:debian13 prepare-debian: &prepare-debian | @@ -150,6 +154,28 @@ steps: - ./autogen.sh - *build-and-test + arm64-berrie64-qemu: + image: arm64v8/debian:trixie-slim at sha256:8b5033c95ca60cdffb0e0f4c446e5f714e82d8960a9ef4153c0eaf13e988b0ea + pull: true + # Keep this off broad pull-request runs. The emulated arm64 tier preserves + # the former standalone arm64 workflow's branch and cron coverage without + # making every contributor wait for expensive QEMU regression coverage. + when: + - event: push + branch: + - master + - stable-* + - event: cron + commands: + - uname -m | grep -E '^aarch64$' + - export PORTABILITY_TIER=arm64-berrie64-qemu + - export PORTABILITY_CFLAGS="-O2 -Wall -Werror -fno-omit-frame-pointer" + - *prepare-debian + - *abi-env + - *start-postgresql + - ./autogen.sh + - *build-and-test + armhf-berrie-qemu: image: arm32v7/debian at sha256:743aca1ad24c5e48132df88f561f8d1365bfb6da33e006eb44b44fe32a7a30eb pull: true @@ -164,6 +190,19 @@ steps: - ./autogen.sh - *build-and-test + arm64-berrie64-qemu: + image: arm64v8/debian:trixie-slim at sha256:8b5033c95ca60cdffb0e0f4c446e5f714e82d8960a9ef4153c0eaf13e988b0ea + pull: true + commands: + - uname -m | grep -E '^aarch64$' + - export PORTABILITY_TIER=arm64-berrie64-qemu + - export PORTABILITY_CFLAGS="-O2 -Wall -Werror -fno-omit-frame-pointer" + - *prepare-debian + - *abi-env + - *start-postgresql + - ./autogen.sh + - *build-and-test + s390x-big-endian-qemu: image: s390x/debian at sha256:4b236f9aafe8a6201c6dca29ce78c28e1eb1e314ecedc2cd2c545f9e49d060e3 pull: true diff --git a/doc/development/testing/ci.md b/doc/development/testing/ci.md index 339624d21a..3193025434 100644 --- a/doc/development/testing/ci.md +++ b/doc/development/testing/ci.md @@ -96,7 +96,7 @@ only overlap part of its defect class. | Make Dist | Jenkins Debbie | In flight in . Until that lands, Woodpecker does not check source distribution tarballs. | | FreeBSD and Bessie | GitHub Actions FreeBSD and Jenkins Bessie | In flight in . YAML running on a Linux container is not FreeBSD parity; this needs a FreeBSD VM or agent surface. | | 32-bit ARM and extra portability tiers | Jenkins Berrie | Covered by `.woodpecker/portability.yml` from , with hostile type-default coverage proposed in . Plain armhf emulation is useful for pointer-width and alignment assumptions, but the valuable tier is the hostile configuration with explicit type, signedness, alignment, and sanitizer probes. | -| 64-bit ARM | Jenkins Berrie64 | Partly covered by `.woodpecker/arm64.yml` on amd64 agents through QEMU arm64 emulation. This is core-extension build, ABI, CUnit, install, and targeted SQL smoke coverage, not Berrie64 parity. | +| 64-bit ARM | Jenkins Berrie64 | Partly covered by the `arm64-berrie64-qemu` child in `.woodpecker/portability.yml` on amd64 agents through QEMU arm64 emulation. This is build, ABI, CUnit, install, and focused regression coverage, not Berrie64 parity. | | CodeQL | GitHub Actions | In flight as Woodpecker configuration carried separately. Woodpecker can build a CodeQL database and produce SARIF, but GitHub remains authoritative for code-scanning upload, annotations, and alert management unless Woodie artifact retention and SARIF consumption are also configured. | | macOS | GitHub Actions macOS | Not coverable by Woodpecker YAML on Linux. See [macOS coverage options](macos-coverage-options.md) for the actual choices, costs, licensing boundary, and current recommendation. | | Native Windows MSYS2 and Winnie | GitHub Actions MSYS2 and Jenkins Winnie | Not covered natively by Linux Woodpecker. MinGW+Wine coverage is valuable ABI/runtime coverage but not native Windows parity. A Woodpecker replacement would need a licensed native Windows agent, registered with Woodie and owned like any other CI host. | @@ -170,15 +170,14 @@ garden and all-upgrades coverage. QEMU can compile and run a smaller smoke suite, but it makes the expensive suites too slow and can hide timing, atomic-operation, kernel, and native scheduling behavior. -The Woodpecker arm64 workflow is therefore an explicit stopgap, not parity. It -runs on amd64 agents through QEMU because the current fleet has no registered -`linux/arm64` agent. The covered signal is still useful for the core extension: +The `arm64-berrie64-qemu` Woodpecker portability child is therefore an explicit +stopgap, not parity. It runs on amd64 agents through QEMU because the current +fleet has no registered `linux/arm64` agent. The covered signal is still useful: 64-bit ARM ABI shape, pointer width, alignment-sensitive execution, char signedness, byte order, dependency detection, build correctness, liblwgeom -CUnit, extension install, and targeted SQL regressions. It does not cover -native CPU timing, atomic operations, kernel behavior, scheduler behavior, -raster, topology, SFCGAL, garden, all-upgrades, or release-grade Berrie64 -evidence. +CUnit, extension install, and focused regressions. It does not cover native CPU +timing, atomic operations, kernel behavior, scheduler behavior, garden, +all-upgrades, or release-grade Berrie64 evidence. ## Woodie API and Pipeline Approvals commit 2dd6482998dbbcca61b2b2363a6361d05dae7a7d Author: Darafei Praliaskouski Date: Tue Jul 28 05:23:21 2026 +0400 ci: pin arm64 Woodie QEMU runner diff --git a/.woodpecker/arm64.yml b/.woodpecker/arm64.yml index 88a7a867c6..29a61ecb3d 100644 --- a/.woodpecker/arm64.yml +++ b/.woodpecker/arm64.yml @@ -1,5 +1,6 @@ labels: platform: linux/amd64 + qemu: "true" when: - event: [push, cron] branch: [master, stable-*] @@ -23,8 +24,9 @@ when: # maintainer publishes the multi-architecture tag. # # Host requirement: the amd64 Woodie agent host must have persistent -# binfmt_misc handlers for qemu-aarch64. On Debian-family hosts this is provided -# by qemu-user, qemu-user-binfmt, and binfmt-support. +# binfmt_misc handlers for qemu-aarch64 and advertise the qemu scheduler label. +# On Debian-family hosts this is provided by qemu-user, qemu-user-binfmt, and +# binfmt-support. variables: arm64-deps: &arm64-deps >- autoconf @@ -158,7 +160,7 @@ steps: echo "arm64 foreign execution ok: uname -m -> $${output}" arm64-qemu-regress: - image: arm64v8/debian:trixie-slim + image: arm64v8/debian:trixie-slim at sha256:8b5033c95ca60cdffb0e0f4c446e5f714e82d8960a9ef4153c0eaf13e988b0ea pull: true depends_on: preflight-arm64-binfmt commands: commit c2c14b6b6cd6b077c1241d71c9e782de6f5b7bb5 Author: Darafei Praliaskouski Date: Mon Jul 27 20:07:33 2026 +0400 ci: add emulated arm64 smoke coverage diff --git a/.woodpecker/arm64.yml b/.woodpecker/arm64.yml index baefb26573..88a7a867c6 100644 --- a/.woodpecker/arm64.yml +++ b/.woodpecker/arm64.yml @@ -1,45 +1,104 @@ labels: - platform: linux/arm64 + platform: linux/amd64 when: - - event: [push, tag, cron] + - event: [push, cron] branch: [master, stable-*] - event: tag -# Native 64-bit ARM coverage for the Berrie64 defect class. This workflow is -# intentionally not a QEMU job: the garden and all-upgrades suites are expensive -# under emulation, and emulation is a poor proxy for native ARM64 timing, -# alignment, atomic, and kernel behavior. +# Emulated 64-bit ARM coverage for the current Woodpecker fleet. # -# Required infrastructure: a Woodpecker agent registered with -# platform=linux/arm64. The current OSGeo build-test image is amd64-only, so the -# workflow starts from Debian's multi-arch base image and installs build -# dependencies inside the job. +# Native arm64 remains the right replacement for Jenkins Berrie64: QEMU does +# not cover native timing, atomic-operation, kernel, scheduler, or hardware +# behavior, and garden plus all-upgrades are too expensive under emulation. +# The current alternative in Woodpecker is no arm64 lane at all, so this job +# takes the smaller but real signal from the core extension: 64-bit ARM ABI +# shape, pointer width, alignment-sensitive execution, char signedness, byte +# order, dependency detection, build correctness, liblwgeom CUnit, extension +# install, and a targeted SQL regression slice. +# +# The OSGeo build-test image is not used here yet. The postgis-docker image +# stack has proven linux/arm64 build-test images through a local registry round +# trip, but repo.osgeo.org/postgis/build-test:debian13 is still published as +# amd64-only. Switch this job to that image after the docker stack lands and a +# maintainer publishes the multi-architecture tag. +# +# Host requirement: the amd64 Woodie agent host must have persistent +# binfmt_misc handlers for qemu-aarch64. On Debian-family hosts this is provided +# by qemu-user, qemu-user-binfmt, and binfmt-support. variables: - test-image: &test-image debian:trixie-slim - prepare-debian: &prepare-debian | + arm64-deps: &arm64-deps >- + autoconf + automake + bison + build-essential + ca-certificates + file + flex + git + libcurl4-openssl-dev + libcunit1-dev + libgeos-dev + libjson-c-dev + libpcre2-dev + libproj-dev + libprotobuf-c-dev + libtool + libxml2-dev + locales + perl + pkg-config + postgresql-17 + postgresql-server-dev-17 + protobuf-c-compiler + arm64-test-script: &arm64-test-script | + set -eux export DEBIAN_FRONTEND=noninteractive + export SRCDIR="$${CI_WORKSPACE}" + mkdir -p "$${TMPDIR:-$${SRCDIR}/.tmp/arm64-qemu-tmp}" + setup_start="$$(date +%s)" apt-get update - apt-get install -y --no-install-recommends \ - autoconf automake libtool build-essential ca-certificates pkg-config \ - postgresql postgresql-server-dev-all \ - libcunit1-dev libgeos-dev libproj-dev proj-bin libgdal-dev libjson-c-dev \ - libprotobuf-c-dev protobuf-c-compiler libxml2-dev libxml2-utils \ - xsltproc docbook-xsl docbook-xml gettext zlib1g-dev + apt-get install -y --no-install-recommends $${ARM64_DEPS} rm -rf /var/lib/apt/lists/* - arm64-env: &arm64-env | - export SRCDIR=$${CI_WORKSPACE} - export BUILDDIR=$${SRCDIR}/build/arm64-berrie64 - export PG_MAJOR=$$(pg_config --version | awk '{print $$2}' | cut -d. -f1) - export PATH=/usr/lib/postgresql/$${PG_MAJOR}/bin:$${PATH} - export PGROOT=$$(mktemp -d) - export PGDATA=$${PGROOT}/data - export PGHOST=$${PGROOT}/socket + setup_end="$$(date +%s)" + echo "MEASURE setup_seconds=$$((setup_end - setup_start))" + + cd "$${SRCDIR}" + git config --global --add safe.directory "$${SRCDIR}" + runuser -u postgres -- git config --global --add safe.directory "$${SRCDIR}" + uname -m | grep -E '^aarch64$' + cc --version | sed -n '1p' + /usr/lib/postgresql/17/bin/pg_config --version + + build_start="$$(date +%s)" + ./autogen.sh + rm -rf build/arm64-qemu-pg17 + mkdir -p build/arm64-qemu-pg17 + cd build/arm64-qemu-pg17 + ../../configure \ + --with-library-minor-version \ + --disable-spellcheck-tests \ + --without-interrupt-tests \ + --without-raster \ + --without-topology \ + --without-sfcgal \ + CFLAGS="-O2 -Wall -fno-omit-frame-pointer -Werror" + make -j1 + build_end="$$(date +%s)" + echo "MEASURE build_seconds=$$((build_end - build_start))" + + test_start="$$(date +%s)" + make -C liblwgeom/cunit check + make install + chmod -R a+rwX "$${SRCDIR}/build/arm64-qemu-pg17" + + export PATH=/usr/lib/postgresql/17/bin:$${PATH} + export PGROOT="$${SRCDIR}/build/arm64-qemu-pgroot" + export PGDATA="$${PGROOT}/data" + export PGHOST="$${PGROOT}/socket" export PGUSER=postgres export PGDATABASE=postgres - uname -m | grep -E '^(aarch64|arm64)$' - dpkg-architecture -qDEB_HOST_GNU_TYPE - pg_config --version - start-postgresql: &start-postgresql | + rm -rf "$${PGROOT}" + mkdir -p "$${PGROOT}" chown postgres:postgres "$${PGROOT}" runuser -u postgres -- mkdir "$${PGDATA}" "$${PGHOST}" runuser -u postgres -- initdb -D "$${PGDATA}" -A trust --no-sync @@ -49,18 +108,14 @@ variables: -w start trap 'runuser -u postgres -- pg_ctl -D "$${PGDATA}" -m fast -w stop || true' EXIT psql -c 'select version()' template1 - build-install-and-check: &build-install-and-check | - mkdir -p "$${BUILDDIR}" - cd "$${BUILDDIR}" - "$${SRCDIR}/configure" \ - --with-raster \ - --with-library-minor-version \ - --without-interrupt-tests \ - CFLAGS="-O2 -Wall -Werror -fno-omit-frame-pointer" - make -j1 - make check RUNTESTFLAGS="-v" - make install - make check RUNTESTFLAGS="-v --extension" + + export RUNTESTFLAGS="-v --extension" + runuser -u postgres -- make -C "$${SRCDIR}/build/arm64-qemu-pg17" check-regress \ + TESTS="$${SRCDIR}/regress/core/regress_index $${SRCDIR}/regress/core/regress_lrs" + runuser -u postgres -- make -C "$${SRCDIR}/build/arm64-qemu-pg17" installcheck-base \ + TESTS="$${SRCDIR}/regress/core/regress_index $${SRCDIR}/regress/core/regress_lrs" + test_end="$$(date +%s)" + echo "MEASURE test_seconds=$$((test_end - test_start))" clone: git: @@ -70,28 +125,46 @@ clone: partial: false steps: - berrie64-native-regress: - image: *test-image + preflight-arm64-binfmt: + image: debian:trixie-slim pull: true commands: - - *prepare-debian - - *arm64-env - - *start-postgresql - - ./autogen.sh - - *build-install-and-check - - berrie64-native-garden-upgrades: - image: *test-image - pull: true - depends_on: berrie64-native-regress - commands: - - *prepare-debian - - *arm64-env - - *start-postgresql - - ./autogen.sh - - *build-install-and-check - - cd "$${BUILDDIR}" - - make garden EXAMPLETEST_CHECK_ENVIRONMENT=no - | - "$${SRCDIR}/utils/check_all_upgrades.sh" \ - "$$(grep '^POSTGIS_' "$${SRCDIR}/Version.config" | cut -d= -f2 | paste -sd '.')" + export DEBIAN_FRONTEND=noninteractive + dpkg --add-architecture arm64 + apt-get update + mkdir -p "$${CI_WORKSPACE}/.tmp/arm64-binfmt-preflight" + cd "$${CI_WORKSPACE}/.tmp/arm64-binfmt-preflight" + apt-get download busybox-static:arm64 + deb="$$(ls -1 busybox-static_*_arm64.deb | tail -n 1)" + root="$${PWD}/arm64" + mkdir -p "$${root}" + dpkg-deb -x "$${deb}" "$${root}" + + if ! output="$$("$${root}/bin/busybox" uname -m 2>&1)"; then + echo "Woodie agent host cannot execute arm64 binaries through binfmt_misc/QEMU." + echo "Install qemu-user, qemu-user-binfmt, and binfmt-support on the amd64 agent host." + echo "Operator check: docker run --rm --platform=linux/arm64 debian:trixie-slim uname -m" + echo "Observed error: $${output}" + exit 1 + fi + + if ! printf '%s\n' "$${output}" | grep -Eq '^aarch64$'; then + echo "Woodie agent host executed arm64, but uname -m returned unexpected value: $${output}" + echo "Operator check: docker run --rm --platform=linux/arm64 debian:trixie-slim uname -m" + exit 1 + fi + + echo "arm64 foreign execution ok: uname -m -> $${output}" + + arm64-qemu-regress: + image: arm64v8/debian:trixie-slim + pull: true + depends_on: preflight-arm64-binfmt + commands: + - /bin/sh -ec "$${ARM64_TEST_SCRIPT}" + +matrix: + include: + - ARM64_DEPS: *arm64-deps + ARM64_TEST_SCRIPT: *arm64-test-script diff --git a/doc/development/testing/ci.md b/doc/development/testing/ci.md index 54ce16d064..339624d21a 100644 --- a/doc/development/testing/ci.md +++ b/doc/development/testing/ci.md @@ -96,7 +96,7 @@ only overlap part of its defect class. | Make Dist | Jenkins Debbie | In flight in . Until that lands, Woodpecker does not check source distribution tarballs. | | FreeBSD and Bessie | GitHub Actions FreeBSD and Jenkins Bessie | In flight in . YAML running on a Linux container is not FreeBSD parity; this needs a FreeBSD VM or agent surface. | | 32-bit ARM and extra portability tiers | Jenkins Berrie | Covered by `.woodpecker/portability.yml` from , with hostile type-default coverage proposed in . Plain armhf emulation is useful for pointer-width and alignment assumptions, but the valuable tier is the hostile configuration with explicit type, signedness, alignment, and sanitizer probes. | -| 64-bit ARM | Jenkins Berrie64 | Covered by `.woodpecker/arm64.yml` only when the fleet has a native `linux/arm64` agent. The workflow intentionally has no QEMU fallback. | +| 64-bit ARM | Jenkins Berrie64 | Partly covered by `.woodpecker/arm64.yml` on amd64 agents through QEMU arm64 emulation. This is core-extension build, ABI, CUnit, install, and targeted SQL smoke coverage, not Berrie64 parity. | | CodeQL | GitHub Actions | In flight as Woodpecker configuration carried separately. Woodpecker can build a CodeQL database and produce SARIF, but GitHub remains authoritative for code-scanning upload, annotations, and alert management unless Woodie artifact retention and SARIF consumption are also configured. | | macOS | GitHub Actions macOS | Not coverable by Woodpecker YAML on Linux. See [macOS coverage options](macos-coverage-options.md) for the actual choices, costs, licensing boundary, and current recommendation. | | Native Windows MSYS2 and Winnie | GitHub Actions MSYS2 and Jenkins Winnie | Not covered natively by Linux Woodpecker. MinGW+Wine coverage is valuable ABI/runtime coverage but not native Windows parity. A Woodpecker replacement would need a licensed native Windows agent, registered with Woodie and owned like any other CI host. | @@ -166,11 +166,19 @@ and sanitizer settings catch assumptions that amd64 and a plain Berrie rerun do not falsify. The 64-bit lane should be native. Berrie64's value is 64-bit ARM execution plus -garden and all-upgrades coverage. QEMU can compile and run some smoke tests, but -it makes the expensive suites too slow and can hide timing, atomic-operation, -kernel, and native scheduling behavior. The Woodpecker arm64 workflow therefore -requires a registered `linux/arm64` agent and intentionally avoids an emulated -fallback. +garden and all-upgrades coverage. QEMU can compile and run a smaller smoke +suite, but it makes the expensive suites too slow and can hide timing, +atomic-operation, kernel, and native scheduling behavior. + +The Woodpecker arm64 workflow is therefore an explicit stopgap, not parity. It +runs on amd64 agents through QEMU because the current fleet has no registered +`linux/arm64` agent. The covered signal is still useful for the core extension: +64-bit ARM ABI shape, pointer width, alignment-sensitive execution, char +signedness, byte order, dependency detection, build correctness, liblwgeom +CUnit, extension install, and targeted SQL regressions. It does not cover +native CPU timing, atomic operations, kernel behavior, scheduler behavior, +raster, topology, SFCGAL, garden, all-upgrades, or release-grade Berrie64 +evidence. ## Woodie API and Pipeline Approvals commit 21709044eb0dde1bfb1010e5ed0931a10d164470 Author: Darafei Praliaskouski Date: Mon Jul 27 18:22:44 2026 +0400 Document native Windows CI parity verdict diff --git a/doc/development/testing/ci.md b/doc/development/testing/ci.md index 77a453a195..54ce16d064 100644 --- a/doc/development/testing/ci.md +++ b/doc/development/testing/ci.md @@ -99,7 +99,7 @@ only overlap part of its defect class. | 64-bit ARM | Jenkins Berrie64 | Covered by `.woodpecker/arm64.yml` only when the fleet has a native `linux/arm64` agent. The workflow intentionally has no QEMU fallback. | | CodeQL | GitHub Actions | In flight as Woodpecker configuration carried separately. Woodpecker can build a CodeQL database and produce SARIF, but GitHub remains authoritative for code-scanning upload, annotations, and alert management unless Woodie artifact retention and SARIF consumption are also configured. | | macOS | GitHub Actions macOS | Not coverable by Woodpecker YAML on Linux. See [macOS coverage options](macos-coverage-options.md) for the actual choices, costs, licensing boundary, and current recommendation. | -| Native Windows MSYS2 and Winnie | GitHub Actions MSYS2 and Jenkins Winnie | Not covered natively by Linux Woodpecker. MinGW+Wine coverage is valuable ABI/runtime coverage but not native Windows parity. | +| Native Windows MSYS2 and Winnie | GitHub Actions MSYS2 and Jenkins Winnie | Not covered natively by Linux Woodpecker. MinGW+Wine coverage is valuable ABI/runtime coverage but not native Windows parity. A Woodpecker replacement would need a licensed native Windows agent, registered with Woodie and owned like any other CI host. | The companion inventory and debugging documents are deliberately narrower than this parity map. Dashboard ownership, CI image provenance, and failure-debugging @@ -120,6 +120,34 @@ behavior, Windows CRT, locale and codepage behavior, native threading and file locking, DLL search order, and failures where Wine itself may be the broken component. +Do not treat a Linux-hosted cross build as closure of the native Windows gap. +The practical replacement shape is a Windows agent registered with Woodie, +running either the MSYS2 workflow or the Winnie script family on a licensed +Windows installation, with an owner who keeps the host patched and credentials +rotated. + +The project investigated Microsoft evaluation VM images as a possible +zero-cost route for such an agent in July 2026. That investigation downloaded +the Windows 11 development environment Hyper-V VHDX, converted it for QEMU/KVM, +and reached the UEFI handoff to Windows Boot Manager. It did not reach a login +prompt, run PostGIS, or prove an unattended Windows CI path; the attempts ended +when the driving automation session lost its connection, not because Windows +refused to boot. + +Licensing is the durable blocker for making that experiment a standing CI +service. Microsoft documents Windows 11 Enterprise evaluation media as a +90-day evaluation and notes that an expired or unactivated evaluation shuts down +periodically. The Windows development VM is an evaluation image, not a stable +renewable CI entitlement. Windows Server evaluation media are similarly trial +media, with a 180-day duration, while the Windows Server license terms limit +evaluation software to evaluation, test, or demonstration use and prohibit +production-environment use after the evaluation period. A legitimate unattended +PostGIS Windows agent therefore needs OSGeo-provided Windows licensing, such as +proper Windows Server VM licensing or Windows Enterprise/VDA licensing for a +desktop VM, plus a named host owner. Until that exists, keep GitHub Actions +MSYS2 and Jenkins Winnie authoritative for native Windows behavior and describe +Linux Woodpecker's MinGW+Wine job as MinGW ABI/runtime coverage only. + ### macOS macOS cannot be covered by Linux containers, Wine, or cross-compilation. Darwin commit 2883c3b7e5ac6b3e3fd9fc409480fbe26d21e0c9 Author: Darafei Praliaskouski Date: Mon Jul 27 14:18:43 2026 +0400 ci: run arm64 Woodie coverage on stable branches diff --git a/.woodpecker/arm64.yml b/.woodpecker/arm64.yml index 68f8f1edf4..baefb26573 100644 --- a/.woodpecker/arm64.yml +++ b/.woodpecker/arm64.yml @@ -2,7 +2,7 @@ labels: platform: linux/arm64 when: - event: [push, tag, cron] - branch: master + branch: [master, stable-*] - event: tag # Native 64-bit ARM coverage for the Berrie64 defect class. This workflow is commit a2fbed92cfdb7c9811c86b4c8d436b5655fb07cb Author: Darafei Praliaskouski Date: Mon Jul 27 11:01:48 2026 +0400 docs: document macOS CI coverage options diff --git a/doc/development/environment/macos.md b/doc/development/environment/macos.md index ac5319fea2..628f54bec9 100644 --- a/doc/development/environment/macos.md +++ b/doc/development/environment/macos.md @@ -9,7 +9,10 @@ The current macOS pull-request build is defined in `.github/workflows/ci-macos.yml`. Use that workflow as the source of truth when checking platform-specific dependencies or flags. -At the time of this note, the job uses `macos-latest`, Homebrew, PostgreSQL 17, +For the decision about whether Woodpecker should grow native Darwin coverage, +see [macOS coverage options](../testing/macos-coverage-options.md). + +At the time of this note, the job uses `macos-latest`, Homebrew, PostgreSQL 18, and clang through ccache. It builds the topology, SFCGAL, and protobuf paths, but disables raster, GUI, and interrupt tests: @@ -21,7 +24,7 @@ brew install \ gdal geos icu4c json-c libpq libxml2 \ proj protobuf-c sfcgal cunit \ docbook docbook-xsl \ - postgresql at 17 gettext + postgresql at 18 gettext brew link --force gettext ``` @@ -29,10 +32,10 @@ The workflow exports Homebrew include and library paths before configuring: ```sh export HOMEBREW_PREFIX=/opt/homebrew -export PATH="${HOMEBREW_PREFIX}/opt/postgresql at 17/bin:${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin:${HOMEBREW_PREFIX}/opt/ccache/libexec:${PATH}" -export PGCONFIG="${HOMEBREW_PREFIX}/opt/postgresql at 17/bin/pg_config" -export CFLAGS="-I${HOMEBREW_PREFIX}/opt/gettext/include -I${HOMEBREW_PREFIX}/opt/postgresql at 17/include -I${HOMEBREW_PREFIX}/include -Wno-nullability-completeness" -export LDFLAGS="-L${HOMEBREW_PREFIX}/opt/gettext/lib -L${HOMEBREW_PREFIX}/opt/postgresql at 17/lib" +export PATH="${HOMEBREW_PREFIX}/opt/postgresql at 18/bin:${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin:${HOMEBREW_PREFIX}/opt/ccache/libexec:${PATH}" +export PGCONFIG="${HOMEBREW_PREFIX}/opt/postgresql at 18/bin/pg_config" +export CFLAGS="-I${HOMEBREW_PREFIX}/opt/gettext/include -I${HOMEBREW_PREFIX}/opt/postgresql at 18/include -I${HOMEBREW_PREFIX}/include -Wno-nullability-completeness" +export LDFLAGS="-L${HOMEBREW_PREFIX}/opt/gettext/lib -L${HOMEBREW_PREFIX}/opt/postgresql at 18/lib" export CXXFLAGS="-std=c++17" export CC="ccache clang" export CXX="ccache clang++" @@ -51,11 +54,11 @@ Then it runs: --with-protobuf \ --with-pgconfig="${PGCONFIG}" -brew services start postgresql at 17 +brew services start postgresql at 18 make -j"$(sysctl -n hw.logicalcpu)" sudo make install make -j"$(sysctl -n hw.logicalcpu)" check RUNTESTFLAGS="-v --extension --dumprestore" -brew services stop postgresql at 17 +brew services stop postgresql at 18 ``` If local behavior differs from CI, first compare the local Homebrew package diff --git a/doc/development/testing/_index.md b/doc/development/testing/_index.md index 8d6f12876e..105e89e37a 100644 --- a/doc/development/testing/_index.md +++ b/doc/development/testing/_index.md @@ -168,6 +168,9 @@ Other useful targets: full run when the gate is wrong. * [CI images and runners](ci-images-runners.md) maps the container image families, Woodie agents, and Jenkins worker setup repositories used by CI. +* [macOS coverage options](macos-coverage-options.md) records why Woodpecker + cannot cover Darwin by Linux configuration alone, the real Apple-runner + options, and the current recommendation. ## Garden Checks diff --git a/doc/development/testing/ci.md b/doc/development/testing/ci.md index 15dfe8294e..77a453a195 100644 --- a/doc/development/testing/ci.md +++ b/doc/development/testing/ci.md @@ -98,7 +98,7 @@ only overlap part of its defect class. | 32-bit ARM and extra portability tiers | Jenkins Berrie | Covered by `.woodpecker/portability.yml` from , with hostile type-default coverage proposed in . Plain armhf emulation is useful for pointer-width and alignment assumptions, but the valuable tier is the hostile configuration with explicit type, signedness, alignment, and sanitizer probes. | | 64-bit ARM | Jenkins Berrie64 | Covered by `.woodpecker/arm64.yml` only when the fleet has a native `linux/arm64` agent. The workflow intentionally has no QEMU fallback. | | CodeQL | GitHub Actions | In flight as Woodpecker configuration carried separately. Woodpecker can build a CodeQL database and produce SARIF, but GitHub remains authoritative for code-scanning upload, annotations, and alert management unless Woodie artifact retention and SARIF consumption are also configured. | -| macOS | GitHub Actions macOS | Not coverable by Woodpecker YAML on Linux. Keep GitHub Actions as the Darwin lane, operate an Apple Woodpecker agent, or accept no Darwin coverage. | +| macOS | GitHub Actions macOS | Not coverable by Woodpecker YAML on Linux. See [macOS coverage options](macos-coverage-options.md) for the actual choices, costs, licensing boundary, and current recommendation. | | Native Windows MSYS2 and Winnie | GitHub Actions MSYS2 and Jenkins Winnie | Not covered natively by Linux Woodpecker. MinGW+Wine coverage is valuable ABI/runtime coverage but not native Windows parity. | The companion inventory and debugging documents are deliberately narrower than @@ -125,8 +125,10 @@ component. macOS cannot be covered by Linux containers, Wine, or cross-compilation. Darwin libc, the Mach-O dynamic loader, Homebrew's dependency graph, Apple clang, the filesystem, and codesign or SIP-adjacent behavior have to run on macOS to be -meaningful. The realistic choices are an Apple Woodpecker agent, GitHub Actions -as the Darwin lane, or no Darwin parity. +meaningful. The realistic choices are documented in +[macOS coverage options](macos-coverage-options.md): keep GitHub Actions as the +Darwin lane, run a hosted or project-owned Apple Woodpecker agent, or accept no +Darwin coverage. ### ARM diff --git a/doc/development/testing/macos-coverage-options.md b/doc/development/testing/macos-coverage-options.md new file mode 100644 index 0000000000..aa4426a755 --- /dev/null +++ b/doc/development/testing/macos-coverage-options.md @@ -0,0 +1,118 @@ +--- +title: "macOS Coverage Options" +date: 2026-07-27 +weight: 11 +geekdocHidden: false +--- + +The macOS CI job is not a Woodpecker configuration gap. The current Darwin +coverage is the GitHub Actions workflow in `.github/workflows/ci-macos.yml`, +which runs on `macos-latest`, installs dependencies with Homebrew, builds with +Apple clang and Darwin `make`, installs PostGIS, and runs regression tests with +extension and dump/restore coverage. + +Woodpecker jobs running on Linux cannot substitute for that lane. Containers, +Wine, and cross-compilation do not exercise Darwin libc, the Mach-O dynamic +loader, Homebrew's dependency graph, Apple clang, Darwin filesystem behavior, or +codesign and SIP-adjacent behavior. Real macOS coverage needs macOS on Apple +hardware. + +## Option 1: Keep GitHub Actions Authoritative + +This is the recommended default. + +PostGIS keeps the current GitHub Actions macOS job as the authoritative Darwin +signal and does not try to make Woodpecker claim full parity. The project loses +one property: Woodpecker cannot independently prove every release and pull +request platform from the OSGeo CI surface alone. + +If GitHub Actions is unavailable, if `macos-latest` changes underneath the +workflow, or if GitHub changes access to macOS runners, the project loses the +Darwin signal until the workflow is updated or another Apple runner is +available. That does not by itself block source tarball creation, Debbie release +jobs, Winnie jobs, or Linux/FreeBSD/ARM Woodpecker coverage, but the release +greenlight checklist's "all bots are green" check should treat the Darwin row as +unknown rather than green. + +The cost is the existing GitHub Actions dependency. As of 2026-07-27, GitHub's +published hosted-runner rates list standard macOS at `$0.062` per minute, +larger macOS at `$0.077` per minute, and M2 Pro larger macOS at `$0.102` per +minute. Public-repository billing and organization quotas are GitHub account +policy, not a PostGIS repository setting, so the operational risk is runner +availability and image churn more than direct per-minute cost in this repo. + +## Option 2: Register A Hosted Apple Runner As A Woodpecker Agent + +This gives Woodpecker real Darwin coverage, but it creates a standing hosted +machine to administer. + +Representative hosted Apple hardware prices found on 2026-07-27: + +| Provider | Representative published price | Third-party agent feasibility | +| -------- | ------------------------------ | ----------------------------- | +| MacStadium | M2 Mac mini from `$109` per month; M4 Mac mini from `$149` per month | Suitable in principle. The product is dedicated Apple hardware with root access, a dedicated IP address, and current macOS, so a Woodpecker agent can be installed by the project. | +| Macly | M4 Mac mini `$99.99` per month or `$14.99` per day | Suitable in principle. The product advertises full SSH/admin access and explicitly says users can install any CI/CD agent. | +| Scaleway Apple Mac mini | M4 advertised at `EUR 0.22` per hour in Scaleway's product announcement, about `EUR 160.60` for a 730-hour month before tax; the product page describes dedicated Mac minis reachable over remote desktop or SSH | Suitable in principle. The product exposes a dedicated Mac mini and documents runner setup; the project would administer the Woodpecker agent. | +| AWS EC2 Mac Dedicated Host | `mac2-m2` listed at `$0.878` per host-hour and `mac-m4` listed on the dedicated-host price table; EC2 Mac hosts have a 24-hour minimum allocation | Technically suitable but usually too expensive for always-on open-source CI. It is dedicated Apple hardware presented as EC2 infrastructure, so installing an agent is possible, but the host-hour model makes it a poor fit for a mostly idle PostGIS Darwin lane. | +| MacinCloud Dedicated Server | Dedicated server advertised from `$49` per month | Possibly suitable only for tiers with full administrator/root access. Shared or managed remote-desktop plans are not enough for an unattended Woodpecker agent. | + +The real total is provider cost plus OS patching, Homebrew cache and package +maintenance, Woodpecker secret handling, runner upgrades, monitoring, and a +named administrator. If nobody owns those tasks, the hosted runner will become a +stale red CI row rather than useful parity. + +## Option 3: Project-Owned Apple Hardware + +A project-owned Mac mini is the usual physical answer. As of 2026-07-27, +Apple's US shop structured product data listed the Mac mini aggregate low price +as `$799`, with M4 and M4 Pro configurations available. The CI total is not only +the purchase price: + +* a Mac mini with enough RAM and storage for Homebrew, PostgreSQL, build trees, + and ccache; +* hosting on an OSGeo-administered buildbot network or on a trusted + maintainer's desk; +* outbound network access to `woodie.osgeo.org`, plus a policy for inbound SSH + or VPN administration if needed; +* power, storage replacement, OS upgrades, reboots, and physical recovery; +* a named administrator who keeps the Woodpecker agent, Homebrew dependencies, + and macOS updates current. + +OSGeo already hosts buildbots, so this is not a new infrastructure category. +The decision is whether the incremental Apple-hardware ownership and +administration cost is worth moving the Darwin signal from GitHub Actions into +Woodpecker. + +## Option 4: Virtualized macOS + +Virtualized macOS is only a compliant CI option when it runs on Apple hardware. +Apple's current macOS license permits up to two additional macOS instances in +virtual operating system environments on each Apple-branded computer the +licensee owns or controls and that is already running macOS, for software +development and testing. The same license language does not permit using those +virtualized copies for service-bureau, time-sharing, terminal-sharing, relay, or +similar services. + +That permits a project-owned or hosted Apple machine to run macOS VMs for +isolation and reproducibility, subject to the license and the provider's terms. +It does not permit a Linux KVM host, ordinary cloud VM, or non-Apple bare-metal +host to run macOS as a Woodpecker substitute. + +## Recommendation + +Keep GitHub Actions authoritative for Darwin and record the Woodpecker row as +not coverable by configuration alone. + +The maintainer-disagreeable version of the reasoning is simple: Darwin coverage +matters, but PostGIS does not currently have enough macOS-specific failure rate +or release dependency to justify adding a permanent Apple machine and a named +administrator. The cheapest credible hosted option is about `$100` to `$150` per +month before maintenance time. A project-owned Mac mini lowers recurring rental +cost but replaces it with physical hosting and administration. AWS is too +expensive for an always-on lane. Virtualized macOS is useful only after the +project already has Apple hardware, so it is not a way around the ownership +decision. + +Revisit this decision if GitHub Actions macOS becomes unavailable for the +project, if a recurring Darwin-only defect starts escaping releases, or if OSGeo +accepts a named owner and budget for an Apple Woodpecker agent. commit 4248b65e6b8f117116ebbee9bc13e62feacaf9be Author: Darafei Praliaskouski Date: Mon Jul 27 09:46:05 2026 +0400 ci: document parity map and add native arm64 workflow diff --git a/.woodpecker/arm64.yml b/.woodpecker/arm64.yml index a37119ad97..68f8f1edf4 100644 --- a/.woodpecker/arm64.yml +++ b/.woodpecker/arm64.yml @@ -1,36 +1,34 @@ labels: - platform: linux/amd64 - qemu: "true" + platform: linux/arm64 when: - - event: push - branch: - - master - - stable-* - - event: cron + - event: [push, tag, cron] + branch: master + - event: tag -# This workflow gives Woodpecker a 64-bit ARM row matching Jenkins Berrie64. -# It catches little beyond that platform parity: unlike armhf it exercises the -# aarch64 64-bit ABI, and unlike s390x it stays little-endian. Keep it off pull -# requests because arm64 emulation is expensive. +# Native 64-bit ARM coverage for the Berrie64 defect class. This workflow is +# intentionally not a QEMU job: the garden and all-upgrades suites are expensive +# under emulation, and emulation is a poor proxy for native ARM64 timing, +# alignment, atomic, and kernel behavior. # -# The image is pinned to the linux/arm64/v8 manifest digest. A tag-only pull -# from an amd64 Docker backend can resolve an amd64 variant and fail before QEMU -# is involved, so do not replace this with arm64v8/debian:trixie-slim alone. +# Required infrastructure: a Woodpecker agent registered with +# platform=linux/arm64. The current OSGeo build-test image is amd64-only, so the +# workflow starts from Debian's multi-arch base image and installs build +# dependencies inside the job. variables: - arm64-image: &arm64-image arm64v8/debian:trixie-slim at sha256:8b5033c95ca60cdffb0e0f4c446e5f714e82d8960a9ef4153c0eaf13e988b0ea + test-image: &test-image debian:trixie-slim prepare-debian: &prepare-debian | export DEBIAN_FRONTEND=noninteractive apt-get update apt-get install -y --no-install-recommends \ autoconf automake libtool build-essential ca-certificates pkg-config \ - bison flex \ postgresql postgresql-server-dev-all \ - libcunit1-dev libgeos-dev libproj-dev libgdal-dev libjson-c-dev \ - libprotobuf-c-dev protobuf-c-compiler libxml2-dev gettext zlib1g-dev + libcunit1-dev libgeos-dev libproj-dev proj-bin libgdal-dev libjson-c-dev \ + libprotobuf-c-dev protobuf-c-compiler libxml2-dev libxml2-utils \ + xsltproc docbook-xsl docbook-xml gettext zlib1g-dev rm -rf /var/lib/apt/lists/* arm64-env: &arm64-env | export SRCDIR=$${CI_WORKSPACE} - export BUILDDIR=$${SRCDIR}/build/arm64-qemu + export BUILDDIR=$${SRCDIR}/build/arm64-berrie64 export PG_MAJOR=$$(pg_config --version | awk '{print $$2}' | cut -d. -f1) export PATH=/usr/lib/postgresql/$${PG_MAJOR}/bin:$${PATH} export PGROOT=$$(mktemp -d) @@ -38,7 +36,7 @@ variables: export PGHOST=$${PGROOT}/socket export PGUSER=postgres export PGDATABASE=postgres - uname -m + uname -m | grep -E '^(aarch64|arm64)$' dpkg-architecture -qDEB_HOST_GNU_TYPE pg_config --version start-postgresql: &start-postgresql | @@ -51,6 +49,18 @@ variables: -w start trap 'runuser -u postgres -- pg_ctl -D "$${PGDATA}" -m fast -w stop || true' EXIT psql -c 'select version()' template1 + build-install-and-check: &build-install-and-check | + mkdir -p "$${BUILDDIR}" + cd "$${BUILDDIR}" + "$${SRCDIR}/configure" \ + --with-raster \ + --with-library-minor-version \ + --without-interrupt-tests \ + CFLAGS="-O2 -Wall -Werror -fno-omit-frame-pointer" + make -j1 + make check RUNTESTFLAGS="-v" + make install + make check RUNTESTFLAGS="-v --extension" clone: git: @@ -60,24 +70,28 @@ clone: partial: false steps: - build-regress: - image: *arm64-image + berrie64-native-regress: + image: *test-image pull: true commands: - - uname -m | grep -E '^aarch64$' - *prepare-debian - *arm64-env - *start-postgresql - ./autogen.sh - - mkdir -p "$${BUILDDIR}" + - *build-install-and-check + + berrie64-native-garden-upgrades: + image: *test-image + pull: true + depends_on: berrie64-native-regress + commands: + - *prepare-debian + - *arm64-env + - *start-postgresql + - ./autogen.sh + - *build-install-and-check - cd "$${BUILDDIR}" - - >- - "$${SRCDIR}/configure" - --with-raster - --without-topology - --without-sfcgal - --without-interrupt-tests - - make -j1 - - make -C liblwgeom check-unit - - make install - - make -C regress check RUNTESTFLAGS="-v --extension" + - make garden EXAMPLETEST_CHECK_ENVIRONMENT=no + - | + "$${SRCDIR}/utils/check_all_upgrades.sh" \ + "$$(grep '^POSTGIS_' "$${SRCDIR}/Version.config" | cut -d= -f2 | paste -sd '.')" diff --git a/doc/development/testing/ci.md b/doc/development/testing/ci.md index c8cc3fb93c..15dfe8294e 100644 --- a/doc/development/testing/ci.md +++ b/doc/development/testing/ci.md @@ -80,6 +80,68 @@ the expensive QA workflow is branch-limited and owns coverage and garden checks. Read `.woodpecker/qa.yml` and `.woodpecker/qa-expensive.yml` before changing that split. +## CI Parity Map + +The repository now keeps CI ownership split across several services. Use this +map to decide which service is authoritative for a platform-specific failure, +and whether a Woodpecker workflow is intended to replace another service or +only overlap part of its defect class. + +| Surface | Current authoritative provider | Woodpecker coverage | +| ------- | ------------------------------ | ------------------- | +| Linux build and regression checks | Woodpecker and GitHub Actions | Covered on amd64 by `.woodpecker/regress.yml`, `.woodpecker/qa.yml`, and `.woodpecker/qa-expensive.yml`. The Woodpecker matrix is not byte-for-byte identical to GitHub's Docker matrix, but it covers the standard Linux build, CUnit, install, extension-upgrade, cluster-upgrade, sanitizer, standard-conforming-strings-off, coverage, and garden classes. | +| Codespell | Woodpecker and GitHub Actions | Covered by `.woodpecker/codespell.yml`. GitHub pins a specific `codespell` package version; Woodpecker follows the OSGeo build image unless that workflow is pinned separately. | +| Contributor credits | Woodpecker and GitHub Actions | Covered by `.woodpecker/contributor-credits.yml`. | +| Debbie Linux regression classes | Jenkins Debbie and Woodpecker | Mostly covered by Woodpecker's Linux regression and expensive QA workflows. Debbie still remains useful for its exact Jenkins host, dependency, and release-job environment. | +| Make Dist | Jenkins Debbie | In flight in . Until that lands, Woodpecker does not check source distribution tarballs. | +| FreeBSD and Bessie | GitHub Actions FreeBSD and Jenkins Bessie | In flight in . YAML running on a Linux container is not FreeBSD parity; this needs a FreeBSD VM or agent surface. | +| 32-bit ARM and extra portability tiers | Jenkins Berrie | Covered by `.woodpecker/portability.yml` from , with hostile type-default coverage proposed in . Plain armhf emulation is useful for pointer-width and alignment assumptions, but the valuable tier is the hostile configuration with explicit type, signedness, alignment, and sanitizer probes. | +| 64-bit ARM | Jenkins Berrie64 | Covered by `.woodpecker/arm64.yml` only when the fleet has a native `linux/arm64` agent. The workflow intentionally has no QEMU fallback. | +| CodeQL | GitHub Actions | In flight as Woodpecker configuration carried separately. Woodpecker can build a CodeQL database and produce SARIF, but GitHub remains authoritative for code-scanning upload, annotations, and alert management unless Woodie artifact retention and SARIF consumption are also configured. | +| macOS | GitHub Actions macOS | Not coverable by Woodpecker YAML on Linux. Keep GitHub Actions as the Darwin lane, operate an Apple Woodpecker agent, or accept no Darwin coverage. | +| Native Windows MSYS2 and Winnie | GitHub Actions MSYS2 and Jenkins Winnie | Not covered natively by Linux Woodpecker. MinGW+Wine coverage is valuable ABI/runtime coverage but not native Windows parity. | + +The companion inventory and debugging documents are deliberately narrower than +this parity map. Dashboard ownership, CI image provenance, and failure-debugging +procedures should stay in their own sections rather than being repeated here; +use this section to answer the parity question. + +### MinGW And Native Windows + +MinGW+Wine coverage is not native Windows coverage. The Woodpecker MinGW+Wine +workflow cross-compiles PostGIS and dependencies, links Windows binaries and +DLLs, starts Windows PostgreSQL binaries under Wine, and runs loaders, CUnit, +and SQL regressions in that environment. That is strong MinGW ABI coverage. + +It does not replace GitHub MSYS2 or Winnie. Native Windows remains authoritative +for NT path handling and path-length behavior, drive-letter and UNC semantics, +MSYS2 path translation, service registration and Service Control Manager +behavior, Windows CRT, locale and codepage behavior, native threading and file +locking, DLL search order, and failures where Wine itself may be the broken +component. + +### macOS + +macOS cannot be covered by Linux containers, Wine, or cross-compilation. Darwin +libc, the Mach-O dynamic loader, Homebrew's dependency graph, Apple clang, the +filesystem, and codesign or SIP-adjacent behavior have to run on macOS to be +meaningful. The realistic choices are an Apple Woodpecker agent, GitHub Actions +as the Darwin lane, or no Darwin parity. + +### ARM + +Treat 32-bit and 64-bit ARM as separate defect classes. The 32-bit lane is most +useful when it is hostile: explicit `char` signedness, enum-width, alignment, +and sanitizer settings catch assumptions that amd64 and a plain Berrie rerun do +not falsify. + +The 64-bit lane should be native. Berrie64's value is 64-bit ARM execution plus +garden and all-upgrades coverage. QEMU can compile and run some smoke tests, but +it makes the expensive suites too slow and can hide timing, atomic-operation, +kernel, and native scheduling behavior. The Woodpecker arm64 workflow therefore +requires a registered `linux/arm64` agent and intentionally avoids an emulated +fallback. + ## Woodie API and Pipeline Approvals Use a Woodie personal access token for the Woodie API and commit 9451df186a4c519d4544babadc1bebab1fb6e2b9 Author: Darafei Praliaskouski Date: Sun Jul 26 18:30:07 2026 +0400 Document CI image and runner provenance diff --git a/doc/development/testing/_index.md b/doc/development/testing/_index.md index c4377cdce8..8d6f12876e 100644 --- a/doc/development/testing/_index.md +++ b/doc/development/testing/_index.md @@ -166,6 +166,8 @@ Other useful targets: * [Pull request CI gating](ci-gating.md) explains why expensive pull-request suites may be skipped, how upgrade ABI decisions are made, and how to force a full run when the gate is wrong. +* [CI images and runners](ci-images-runners.md) maps the container image + families, Woodie agents, and Jenkins worker setup repositories used by CI. ## Garden Checks diff --git a/doc/development/testing/ci-images-runners.md b/doc/development/testing/ci-images-runners.md new file mode 100644 index 0000000000..1dc0a577f9 --- /dev/null +++ b/doc/development/testing/ci-images-runners.md @@ -0,0 +1,75 @@ +--- +title: "CI Images and Runners" +date: 2026-07-26 +weight: 12 +geekdocHidden: false +--- + +PostGIS CI uses two container image families and several runner fleets. Keep +the dependency details in the image repositories and host setup repositories; +this page is the navigation map. + +## Container Image Families + +| Image family | Published at | Owner | Consumers | +| ------------ | ------------ | ----- | --------- | +| `postgis/postgis-build-env:*` | Docker Hub | | GitHub Actions Linux matrix in `.github/workflows/ci.yml` | +| `repo.osgeo.org/postgis/build-test:*` | OSGeo container registry | | Woodpecker workflows under `.woodpecker/` | + +`postgis/postgis-build-env` has one `Dockerfile` and `build.py`. The script +builds and pushes the tag matrix used by the GitHub Actions Linux workflow. Its +README points at the Debbie Jenkins job that runs the regular image build. + +`postgis/postgis-docker` owns the Woodpecker build-test images. The +`build-test/Containerfile.*` files and `build-test/Makefile` define the image +set, and the repository README documents logging in and pushing to the OSGeo +registry. At the time this page was written, this repository had build +instructions and a Debbie helper script, but no checked-in GitHub Actions, +Woodpecker, GitLab CI, or Jenkinsfile workflow of its own. + +An image pull can fail before any PostGIS test starts. Treat registry timeouts, +manifest failures, and authentication failures as infrastructure failures until +the failing step has successfully entered a PostGIS build or test command. A +Docker Hub registry timeout has made the GitHub Actions Linux matrix red before +without identifying a source defect. + +## Runner And Host Repositories + +| Runner surface | Owner | What it covers | +| -------------- | ----- | -------------- | +| Woodie agents | , branch `woodie-3` | OSGeo Woodpecker agent startup scripts and deployment notes | +| Jenkins buildbot hosts | | Linux, Debian, FreeBSD, Raspberry Pi, and Windows worker setup notes | +| In-tree Jenkins scripts | `ci/debbie/`, `ci/winnie/`, `ci/bessie/`, `ci/berrie*` | Commands run by PostGIS Jenkins jobs and worker labels | + +Woodpecker pull-request jobs run on Woodie agents. Agent capacity, Docker +socket access, `binfmt_misc` handlers, DNS, and registry access are runner +properties, not PostGIS source properties. If a workflow adds an emulated or +cross-architecture job, verify the runner preflight in the Woodie agent fleet +before treating the failure as a test failure. + +Jenkins worker setup lives outside this repository in +`postgis/postgis-buildbots`. That repository still contains historical setup +notes as well as active worker notes, so use the maintained inventory in +`utils/docs/ci_status/config.json` and the live Jenkins job labels before +reviving an old platform. Current 32-bit coverage is the Berrie Raspberry Pi +worker, which is 32-bit ARM. The old `bessie32` FreeBSD worker is not part of +the maintained CI inventory; do not rebuild 32-bit FreeBSD coverage from the old badge table +without fresh maintainer approval and a live worker readback. + +## Architecture Coverage + +Use the owning workflow or worker label for architecture claims: + +* GitHub Actions Linux runs in Docker on GitHub-hosted Linux. +* GitHub Actions FreeBSD and macOS are owned by their workflow files and only + cover the branches where those files exist. +* Woodpecker jobs currently declare `platform: linux/amd64` unless the + workflow says otherwise. +* Jenkins `berrie` is the maintained 32-bit ARM surface, and `berrie64` is the + Raspberry Pi 64-bit surface. +* Jenkins `bessie` is the maintained FreeBSD surface; `bessie32` is retired + from the maintained inventory. + +When changing architecture coverage, update the owning workflow or worker job, +then update [CI inventory standards](ci.md) and +`utils/docs/ci_status/config.json`. commit 1bcca9054b901f289be2c279a4220316fb04cab1 Author: Darafei Praliaskouski Date: Sun Jul 26 18:29:05 2026 +0400 Document CI inventory dashboard ownership diff --git a/doc/development/testing/ci.md b/doc/development/testing/ci.md index 1181e7945a..c8cc3fb93c 100644 --- a/doc/development/testing/ci.md +++ b/doc/development/testing/ci.md @@ -26,10 +26,12 @@ service that owns the behavior: | macOS GitHub Actions job | `.github/workflows/ci-macos.yml`; see [macOS development environment](../environment/macos.md) | | MSYS2/MinGW GitHub Actions job | `.github/workflows/msys.yml` | | GitHub CodeQL, codespell, and contributor-credit jobs | `.github/workflows/codeql.yml`, `.github/workflows/codespell.yml`, and `.github/workflows/contributor-credits.yml` | +| Woodpecker pull-request and branch pipelines | `.woodpecker/*.yml`, with pipeline status published by Woodie at | | Debbie build, docs, and release jobs | `ci/debbie/`, the Debbie Jenkins jobs, and release-process notes | | Winnie Windows jobs | `ci/winnie/` and the Winnie Jenkins jobs | | Bessie and Berrie/Berrie64 jobs | `ci/bessie/`, `ci/berrie*`, and the corresponding Jenkins worker labels | | Docker build images used by GitHub Actions | `postgis/postgis-build-env` image tags referenced from `.github/workflows/ci.yml` | +| Docker build images used by Woodpecker | `repo.osgeo.org/postgis/build-test:*` image tags referenced from `.woodpecker/*.yml` | | Woodpecker MinGW Wine job | `.woodpecker/mingw-wine.yml` and `ci/woodie/postgis_mingw_wine.sh` | When a dashboard row describes dependency versions, operating systems, branch @@ -64,6 +66,20 @@ following overrides: The result is clamped to at least `1`, and if memory detection fails the function falls back to the CPU-based maximum. +Woodpecker is the CI surface attached to canonical Gitea pull requests. Its +status contexts are produced from the checked-in `.woodpecker/` workflows, so a +new Woodpecker job belongs there first, then in the generated dashboard +inventory described below. Do not document the current split count by hand: +parallel matrix expansion and retries change the number of published +`ci/woodpecker/...` contexts for a commit. + +On `master`, the maintained Woodpecker workflows include regression, docs, +tools, codespell, contributor-credit, and QA coverage. The QA workflow runs +sanitizer and `standard_conforming_strings=off` checks for pull requests, while +the expensive QA workflow is branch-limited and owns coverage and garden +checks. Read `.woodpecker/qa.yml` and `.woodpecker/qa-expensive.yml` before +changing that split. + ## Woodie API and Pipeline Approvals Use a Woodie personal access token for the Woodie API and @@ -127,8 +143,10 @@ same check path as the badge URL. Update the inventory when any of these change: * a workflow file under `.github/workflows/`; +* a workflow file under `.woodpecker/`; * a script under `ci/`; * a `postgis/postgis-build-env` tag used by the GitHub Actions matrix; +* a `repo.osgeo.org/postgis/build-test` tag used by a Woodpecker workflow; * a Jenkins job, worker label, or badge URL referenced from Trac or website dashboards; * a supported release branch or support-window row that affects which branches ----------------------------------------------------------------------- Summary of changes: .woodpecker/arm64.yml | 83 --------------- .woodpecker/portability.yml | 36 ++++++- doc/development/environment/macos.md | 19 ++-- doc/development/testing/_index.md | 5 + doc/development/testing/ci-images-runners.md | 75 ++++++++++++++ doc/development/testing/ci.md | 117 +++++++++++++++++++++ doc/development/testing/macos-coverage-options.md | 118 ++++++++++++++++++++++ 7 files changed, 357 insertions(+), 96 deletions(-) delete mode 100644 .woodpecker/arm64.yml create mode 100644 doc/development/testing/ci-images-runners.md create mode 100644 doc/development/testing/macos-coverage-options.md hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 02:45:44 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 02:45:44 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-208-gc244b1110d Message-ID: <20260803094544.CBE511D3A7B@trac.osgeo.org> 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 c244b1110db72edbe5073a3ee04cab0da232a8e7 (commit) via a10a9fd696417400ab20b39245676596dec715d3 (commit) from 80a9286dbacc32ce1538d67745a596b0dd93d52a (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 c244b1110db72edbe5073a3ee04cab0da232a8e7 Merge: 80a9286dba a10a9fd696 Author: Darafei Praliaskouski Date: Mon Aug 3 02:45:42 2026 -0700 Merge pull request 'ci: name the failed step on the CI status dashboard' (!653) from Komzpa/postgis:ci-status-failed-step-name-20260801 into master A red cell on https://postgis.net/ci/ said only which *workflow* failed. On this repository a workflow is a matrix cell with a dozen steps, so `regress/29` told a reader nothing about whether the build broke, a suite failed, or the agent died ? every diagnosis began by opening Woodpecker and hunting for the step. The step states are already inside the pipeline records the report reads, so naming them costs no extra API call. A failed workflow now renders as `regress/29 (test-upgrades)`. Only failed children are listed, and only for workflows that failed, so successful and in-progress cells are unchanged. Verified both directions: the new regression passes against this change and **fails** against the previous `report.py`. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/653 commit a10a9fd696417400ab20b39245676596dec715d3 Author: Darafei Praliaskouski Date: Sat Aug 1 03:13:54 2026 +0400 ci: name the failed step on the CI status dashboard A red cell on https://postgis.net/ci/ said only which workflow failed. On this repository a workflow is a matrix cell with a dozen steps, so 'regress/29' told a reader nothing about whether the build broke, a suite failed, or the agent died ? every diagnosis started by opening Woodpecker and hunting for the step. The step states are already present in the pipeline records the report reads, so naming them costs no extra API call: a failed workflow now renders as 'regress/29 (test-upgrades)'. Only failed children are listed, and only for workflows that failed, so successful and in-progress cells are unchanged. The regression asserts the rendered label contains the failing step name; it fails against the previous report.py. diff --git a/utils/docs/ci_status/report.py b/utils/docs/ci_status/report.py index 7c61baa8bb..172adbd89d 100644 --- a/utils/docs/ci_status/report.py +++ b/utils/docs/ci_status/report.py @@ -421,7 +421,8 @@ def woodpecker_build_sort_key(build): ) -def woodpecker_workflow_label(workflow, duplicate_names): +def woodpecker_workflow_base_label(workflow, duplicate_names): + """Return the human workflow label, disambiguating duplicate names by pid.""" name = workflow.get("name") or f"workflow {workflow.get('pid') or workflow.get('id')}" pid = workflow.get("pid") if pid is not None and name in duplicate_names: @@ -429,6 +430,27 @@ def woodpecker_workflow_label(workflow, duplicate_names): return name +def woodpecker_failed_step_labels(workflow): + """Return failed child step labels already included in a workflow record.""" + return [ + str(step.get("name") or f"step {step.get('pid') or step.get('id')}") + for step in workflow.get("children") or [] + if normalize_woodpecker_status(step.get("state") or step.get("status")) == FAILURE + ] + + +def woodpecker_workflow_label(workflow, duplicate_names, status): + base_label = woodpecker_workflow_base_label(workflow, duplicate_names) + if status != FAILURE: + return base_label + + failed_children = woodpecker_failed_step_labels(workflow) + if not failed_children: + return base_label + + return f"{base_label} ({', '.join(failed_children)})" + + def woodpecker_workflow_url(web_url, pipeline, workflow): if not web_url or not pipeline.get("number") or workflow.get("pid") is None: return None @@ -469,7 +491,7 @@ def woodpecker_workflow_details(pipeline, web_url): status = normalize_woodpecker_status(workflow.get("state") or workflow.get("status")) if status == SUCCESS: continue - label = woodpecker_workflow_label(workflow, duplicate_names) + label = woodpecker_workflow_label(workflow, duplicate_names, status) if status == FAILURE: by_bucket["failed"].append((label, workflow)) elif status == IN_PROGRESS: diff --git a/utils/docs/tests/test_ci_status.py b/utils/docs/tests/test_ci_status.py index 852c190bdc..4249b539ca 100644 --- a/utils/docs/tests/test_ci_status.py +++ b/utils/docs/tests/test_ci_status.py @@ -519,6 +519,52 @@ class CIStatusTest(unittest.TestCase): http_json.call_args_list[1].args[0], ) + def test_woodpecker_failure_names_single_failed_workflow_child_step(self): + check_config = { + "name": "Woodpecker", + "provider": "woodpecker", + "required": True, + "api_url": "https://woodie.example.test/api/repos/30/pipelines", + "web_url": "https://woodie.example.test/repos/30", + } + branch = {"name": "stable-3.6", "label": "3.6"} + pipeline = { + "number": 5431, + "event": "push", + "branch": "stable-3.6", + "ref": "refs/heads/stable-3.6", + "status": "failure", + "commit": "b" * 40, + "message": "opaque commit message", + } + pipeline_detail = { + **pipeline, + "workflows": [ + {"pid": 9, "id": 24470, "name": "regress", "state": "success"}, + { + "pid": 29, + "id": 24477, + "name": "regress", + "state": "failure", + "children": [ + {"pid": 100, "name": "test-upgrades", "state": "failure"}, + ], + }, + ], + } + + with mock.patch.object(CI_STATUS, "http_json", side_effect=([pipeline], pipeline_detail)) as http_json: + result = CI_STATUS.woodpecker_check(check_config, branch, timeout=5) + + self.assertEqual(CI_STATUS.FAILURE, result["status"]) + self.assertEqual("failed: regress/29 (test-upgrades)", result["message"]) + self.assertEqual("https://woodie.example.test/repos/30/pipeline/5431/29", result["url"]) + self.assertEqual("b" * 40, result["revision"]) + self.assertEqual( + "https://woodie.example.test/api/repos/30/pipelines/5431", + http_json.call_args_list[1].args[0], + ) + def test_woodpecker_error_without_workflows_shows_error_message(self): check_config = { "name": "Woodpecker", ----------------------------------------------------------------------- Summary of changes: utils/docs/ci_status/report.py | 26 +++++++++++++++++++-- utils/docs/tests/test_ci_status.py | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 02:46:25 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 02:46:25 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-210-g91d090f292 Message-ID: <20260803094626.0F3091D82A0@trac.osgeo.org> 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 91d090f2927552be91c44e02e3a17f4d94099fa6 (commit) via 56c65e755590a79a9272bc72e67ea901549fc3bb (commit) from c244b1110db72edbe5073a3ee04cab0da232a8e7 (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 91d090f2927552be91c44e02e3a17f4d94099fa6 Merge: c244b1110d 56c65e7555 Author: Darafei Praliaskouski Date: Mon Aug 3 02:46:24 2026 -0700 Merge pull request 'ci: stop superseded GitHub Actions runs from stacking up' (!658) from Komzpa/postgis:ci/github-actions-concurrency-20260803 into master Only `codeql.yml` declared a concurrency group. Every other workflow started a full matrix for each push and kept it, so a branch pushed several times, or a run of Weblate translation commits on master, left every earlier run queued behind the newest one. Measured on 2026-08-03, `postgis/postgis` on GitHub had **41 runs queued, the oldest created 15 hours earlier** ? 12 push runs on master and 29 `pull_request` runs across 12 branches. None of that work could still be useful: for a pull request only the newest head matters, and for master only the newest commit is what the CI dashboard reads. The group expression is copied verbatim from `codeql.yml`, so the six workflows now behave the same way as the one that already got this right. Cancelled runs are safe for the dashboard: `utils/docs/ci_status/report.py` maps `cancelled` to UNKNOWN, and only the newest run of a workflow/branch pair is read ? which is exactly the run `cancel-in-progress` keeps. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/658 commit 56c65e755590a79a9272bc72e67ea901549fc3bb Author: Darafei Praliaskouski Date: Mon Aug 3 05:45:53 2026 +0400 ci: stop superseded GitHub Actions runs from stacking up Only codeql.yml declared a concurrency group. Every other workflow started a full matrix for each push and kept it, so a branch pushed several times, or a run of Weblate translation commits on master, left every earlier run queued behind the newest one. Measured on 2026-08-03 05:5x +04: postgis/postgis had 41 GitHub Actions runs queued, the oldest created 15 hours earlier, 12 of them push runs on master and 29 pull_request runs across 12 branches. None of that work could still be useful -- for a pull request only the newest head matters, and for master only the newest commit is what the CI dashboard reads. The group expression is copied verbatim from codeql.yml, which has carried it since it was added, so the six workflows now behave the same way as the one that already got this right. diff --git a/.github/workflows/ci-freebsd.yml b/.github/workflows/ci-freebsd.yml index ea88bbcbc3..6906e059ce 100644 --- a/.github/workflows/ci-freebsd.yml +++ b/.github/workflows/ci-freebsd.yml @@ -7,6 +7,10 @@ on: push: ~ pull_request: ~ +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + jobs: freebsd: diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 2241c337c2..954468fe12 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -7,6 +7,10 @@ on: push: ~ pull_request: ~ +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + jobs: macos: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22fb1e5bdf..dd2686ead6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,10 @@ on: - 'main' pull_request: ~ +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + jobs: linux: name: "CI" diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 6292eeb96c..164cc8ae1c 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -6,6 +6,10 @@ on: - 'main' pull_request: ~ +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + jobs: linux: diff --git a/.github/workflows/contributor-credits.yml b/.github/workflows/contributor-credits.yml index eaeb5fb92b..c5237153f5 100644 --- a/.github/workflows/contributor-credits.yml +++ b/.github/workflows/contributor-credits.yml @@ -9,6 +9,10 @@ on: permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + jobs: contributor-credits: runs-on: ubuntu-latest diff --git a/.github/workflows/msys.yml b/.github/workflows/msys.yml index 34c3dbc46e..8e9e204df2 100644 --- a/.github/workflows/msys.yml +++ b/.github/workflows/msys.yml @@ -3,6 +3,10 @@ on: push: pull_request: ~ +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + jobs: mingw: name: mingw ----------------------------------------------------------------------- Summary of changes: .github/workflows/ci-freebsd.yml | 4 ++++ .github/workflows/ci-macos.yml | 4 ++++ .github/workflows/ci.yml | 4 ++++ .github/workflows/codespell.yml | 4 ++++ .github/workflows/contributor-credits.yml | 4 ++++ .github/workflows/msys.yml | 4 ++++ 6 files changed, 24 insertions(+) hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 02:47:02 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 02:47:02 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-212-gaab8128078 Message-ID: <20260803094703.12D9E1DC288@trac.osgeo.org> 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 aab812807800cf2f3e89e23fcaba50673c763860 (commit) via bbe24efeec92554ba9e17af1a109eb149529f3ec (commit) from 91d090f2927552be91c44e02e3a17f4d94099fa6 (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 aab812807800cf2f3e89e23fcaba50673c763860 Merge: 91d090f292 bbe24efeec Author: Darafei Praliaskouski Date: Mon Aug 3 02:47:01 2026 -0700 Merge pull request 'ci: let the MinGW/Wine workflow run on any amd64 agent' (!657) from Komzpa/postgis:ci/mingw-wine-unpin-host-20260803 into master The MinGW/Wine workflow pins itself to `hostname: smallcat`. That agent is out of the fleet ? it carries `no_schedule=true` because the CI load interfered with interactive work on that machine ? so no agent can accept the workflow and it waits indefinitely. **The damage is not limited to Wine coverage.** A workflow that is never scheduled never reaches a terminal state, so its whole pipeline stays `running`. Measured just now: **5 of 18 live pipelines** were held open this way, including master's own pipeline, and the oldest had been waiting **7 h 14 min** ? far past the five-hour pipeline deadline, because that deadline never starts for a workflow that never starts. Nothing in the job needs that host. `ci/woodie/postgis_mingw_wine.sh` runs inside `debian:bookworm`, derives every path from the workspace, and downloads its own toolchain; it contains no reference to smallcat or to any host-specific path. Dropping the pin lets any `linux/amd64` agent take it. Pinning to one interactive machine is what made this fragile in the first place, so this deliberately does not repin to another single host. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/657 commit bbe24efeec92554ba9e17af1a109eb149529f3ec Author: Darafei Praliaskouski Date: Mon Aug 3 01:18:42 2026 +0400 ci: let the MinGW/Wine workflow run on any amd64 agent The workflow pinned itself to `hostname: smallcat`. That agent is out of the fleet: it carries no_schedule=true because the CI load interfered with interactive work on that machine, and it is not to be brought back for CI capacity. So the workflow has no agent that can accept it and waits forever. The effect is not confined to Wine coverage. A workflow that never gets scheduled never reaches a terminal state, so the whole pipeline stays running: at the time of writing, 5 of 18 live pipelines were held open this way, including master's own, and the oldest had been waiting 7 hours 14 minutes - well past the five-hour pipeline deadline, because the deadline never starts for a workflow that never starts. Nothing in the job needs that host. ci/woodie/postgis_mingw_wine.sh runs inside debian:bookworm, derives every path from the workspace, and downloads its own toolchain; it contains no reference to smallcat or to any host-specific path. Dropping the pin lets any linux/amd64 agent take it. diff --git a/.woodpecker/mingw-wine.yml b/.woodpecker/mingw-wine.yml index 719d0826a4..ed79a30953 100644 --- a/.woodpecker/mingw-wine.yml +++ b/.woodpecker/mingw-wine.yml @@ -1,6 +1,5 @@ labels: platform: linux/amd64 - hostname: smallcat when: event: [push, pull_request, tag] ----------------------------------------------------------------------- Summary of changes: .woodpecker/mingw-wine.yml | 1 - 1 file changed, 1 deletion(-) hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 03:39:16 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 03:39:16 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-213-gbeac83bc71 Message-ID: <20260803103917.4DCD61E01DE@trac.osgeo.org> 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 beac83bc71bd7442b69da1053f6b1aab98fffa0f (commit) from aab812807800cf2f3e89e23fcaba50673c763860 (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 beac83bc71bd7442b69da1053f6b1aab98fffa0f Author: Teramoto Ikuhiro Date: Mon Aug 3 09:43:40 2026 +0000 Translated PostGIS Manual using Weblate (Japanese) Currently translated at 89.3% (5343 of 5981 strings) Translation: postgis/PostGIS Manual Translate-URL: https://weblate.osgeo.org/projects/postgis/postgis-manual/ja/ diff --git a/doc/po/ja/postgis-manual.po b/doc/po/ja/postgis-manual.po index 5e5cfcc0d7..142d9aa1b0 100644 --- a/doc/po/ja/postgis-manual.po +++ b/doc/po/ja/postgis-manual.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: postgis 3.5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2026-07-20 08:06+0000\n" -"PO-Revision-Date: 2026-08-03 08:39+0000\n" +"PO-Revision-Date: 2026-08-03 10:39+0000\n" "Last-Translator: Teramoto Ikuhiro \n" "Language-Team: Japanese \n" @@ -11916,6 +11916,9 @@ msgid "" "conventional cid alias keeps the geometry column ready " "for color-by-cluster rendering." msgstr "" +"???????????????????? ID ?????????? " +"cid ???????????????????????????????" +"???????????" #. Tag: refpurpose #, no-c-format @@ -12115,11 +12118,15 @@ msgid "" "island clusters span the antimeridian, and cluster edges follow the Earth's " "curvature." msgstr "" +"???????? 46?????????????????????????????" +"??????????????????????????????????????" +"???????????????180??????????????????????" +"????????" #. Tag: para #, no-c-format msgid "Kontur population clustered with 3000 km maximum radius." -msgstr "" +msgstr "???? 3000km ????????? Kontur ???" #. Tag: para #, no-c-format @@ -12128,6 +12135,9 @@ msgid "" "The maximum radius is specified in meters, while the returned geometries " "stay in WGS 84 for display." msgstr "" +"??????????????????????????????????????" +"???????????????????? WGS 84 ??????????????" +"???" #. Tag: para #, no-c-format @@ -12298,6 +12308,13 @@ msgid "" "ST_Union also splits linestrings at intersections and " "may return a single geometry after dissolving boundaries." msgstr "" +"ST_Collect ??????????????????" +"?????????????????????????????????? " +"MultiPolygon ???????????????????????" +"??????????????????????????????????????" +"?????????? ??????" +"ST_Union ????????????????????????????" +"????????????????????????" #. Tag: para #, no-c-format ----------------------------------------------------------------------- Summary of changes: doc/po/ja/postgis-manual.po | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 09:31:56 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 09:31:56 -0700 (PDT) Subject: [SCM] PostGIS branch stable-3.4 updated. 3.4.6-112-g95e296e07c Message-ID: <20260803163157.329631B9DDC@trac.osgeo.org> 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, stable-3.4 has been updated via 95e296e07caee9db09979d124e5766fd7e186dba (commit) via 9544c1a06417d49d300c2f9ddc368b47d1f0db8b (commit) from ec446a2cb34ffcf2e2ee0fa9237f6f4b47097b2f (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 95e296e07caee9db09979d124e5766fd7e186dba Merge: ec446a2cb3 9544c1a064 Author: Darafei Praliaskouski Date: Mon Aug 3 09:31:51 2026 -0700 Merge pull request 'Do not ANALYZE inside the extension upgrade transaction (stable-3.4)' (!660) from Komzpa/postgis:fix/no-analyze-in-extension-script-3.4-20260803 into stable-3.4 `stable-3.4` is red on the CI dashboard, and has been for 26 hours. The failure is pipeline 6460, workflow `regress`, step `test-upgrades`: ``` FAIL: postgis_sfcgal extension upgrade 3.4.2--3.4.7dev! ... DETAIL: Process 135651 waits for ShareUpdateExclusiveLock on relation 685754 ...; blocked by process 135652. Process 135652 waits for ShareLock on transaction 239369; blocked by process 135651. CONTEXT: SQL statement "ALTER EXTENSION postgis UPDATE TO "ANY"; ALTER EXTENSION postgis UPDATE TO "3.4.7dev"" ``` That is the deadlock already fixed on master by !650. This is that commit, cherry-picked (`248b014b9`), with the NEWS entry rewritten for the 3.4.7 section and this branch's style. `spatial_ref_sys.sql` on this branch ends with the same three lines master had ? `ON CONFLICT (srid) DO NOTHING;` / `COMMIT;` / `ANALYZE "spatial_ref_sys";` ? so the bug and the fix are identical here. Checked by running the substitution against this branch's file: with the current rule the generated extension script still ends in `ANALYZE "spatial_ref_sys";`, and with the new rule it contains no `ANALYZE` line at all. No CI configuration is added or changed on this branch; this only fixes the script generation that makes an existing check red. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/660 commit 9544c1a06417d49d300c2f9ddc368b47d1f0db8b Author: Darafei Praliaskouski Date: Sun Aug 2 20:03:01 2026 +0400 Do not ANALYZE inside the extension upgrade transaction spatial_ref_sys.sql ends with ON CONFLICT (srid) DO NOTHING; COMMIT; ANALYZE "spatial_ref_sys"; The ANALYZE sits after COMMIT on purpose: run standalone it refreshes the statistics of a table that just gained thousands of rows, outside any transaction. The extension build strips BEGIN and COMMIT because those are not allowed in extension scripts, and left the ANALYZE behind ? so it ends up *inside* the upgrade's transaction, takes ShareUpdateExclusiveLock on spatial_ref_sys, and can deadlock against autovacuum analysing the same table: ERROR: deadlock detected DETAIL: Process A waits for ShareUpdateExclusiveLock on relation ...; blocked by process B. Process B waits for ShareLock on transaction ...; blocked by process A. CONTEXT: SQL statement "ANALYZE "spatial_ref_sys"" extension script file "postgis--ANY--3.7.0dev.sql" That aborts ALTER EXTENSION postgis UPDATE, so a user upgrading a busy database can simply lose the upgrade. It also accounts for three of the eleven most recent Woodpecker pipeline failures, in regress/test-install and regress/test-upgrades, on ordinary amd64 rows rather than emulated ones. Strip the ANALYZE along with the transaction control it was written to follow. The standalone spatial_ref_sys.sql keeps it; autovacuum analyses the table on its own schedule, so the extension script does not need to. (cherry picked from commit 248b014b9805911792e2fcc097ce7c0cde422308) diff --git a/NEWS b/NEWS index 86a12e5f66..361f4b074e 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,9 @@ PostGIS 3.4.7 * Bug Fixes * + - Stop the extension upgrade script running ANALYZE inside its + transaction, where it could deadlock with autovacuum analysing + spatial_ref_sys (Darafei Praliaskouski) - GT-569, Initialize GSERIALIZED peek test fixtures so check-unit stays clean under Valgrind (Darafei Praliaskouski) - GT-575, Scope interrupt regression timeouts to the statements being diff --git a/extensions/postgis/Makefile.in b/extensions/postgis/Makefile.in index 4814afe368..2436c5725c 100644 --- a/extensions/postgis/Makefile.in +++ b/extensions/postgis/Makefile.in @@ -106,9 +106,21 @@ sql/$(EXTENSION)--unpackaged.sql: Makefile | sql sql: mkdir -p $@ -#strip BEGIN/COMMIT since these are not allowed in extensions +# Strip BEGIN/COMMIT since these are not allowed in extensions, and the trailing +# ANALYZE with them. In spatial_ref_sys.sql that ANALYZE deliberately sits *after* +# COMMIT, so run standalone it refreshes statistics outside any transaction. Removing +# only the COMMIT moves it inside the extension's transaction, where it takes +# ShareUpdateExclusiveLock on spatial_ref_sys and can deadlock against autovacuum +# doing the same work: +# +# ERROR: deadlock detected +# CONTEXT: SQL statement "ANALYZE "spatial_ref_sys"" +# extension script file "postgis--ANY--.sql" +# +# That aborts ALTER EXTENSION postgis UPDATE on any busy database. Autovacuum will +# analyse the table on its own schedule, so the extension script does not need to. sql/spatial_ref_sys.sql: ../../spatial_ref_sys.sql | sql - $(PERL) -pe 's/BEGIN\;//g ; s/COMMIT\;//g' $< > $@ + $(PERL) -pe 's/BEGIN\;//g ; s/COMMIT\;//g ; s/^ANALYZE "spatial_ref_sys";\s*$$//g' $< > $@ ../../doc/postgis_comments.sql: $(MAKE) -C ../../doc comments ----------------------------------------------------------------------- Summary of changes: NEWS | 3 +++ extensions/postgis/Makefile.in | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 09:46:54 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 09:46:54 -0700 (PDT) Subject: [SCM] PostGIS branch stable-3.6 updated. 3.6.4-108-ga740a246ac Message-ID: <20260803164655.3E0E71BAA88@trac.osgeo.org> 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, stable-3.6 has been updated via a740a246aca10d8ab5d07e56889e3b4c8b2833b0 (commit) via 355aa8ae85f88c2048ae26b1558d9d31f145c98b (commit) from 36241ae1809fd6335c22fbff12785720d05f3997 (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 a740a246aca10d8ab5d07e56889e3b4c8b2833b0 Merge: 36241ae180 355aa8ae85 Author: Darafei Praliaskouski Date: Mon Aug 3 09:46:52 2026 -0700 Merge pull request 'regress: compare interrupt timing to local baseline (stable-3.6)' (!664) from Komzpa/postgis:fix/interrupt-baseline-3.6-20260803 into stable-3.6 `stable-3.5` went red today on `regress/core/interrupt_relate`: ``` -relate interrupted on time +relate interrupted late: 00:00:00.75175 (00:00:00.22 tolerated) ``` Nothing was slow to cancel ? the interrupt arrived in **752 ms** against a hard-coded tolerance, on a machine that was also running the rest of the suite. Master fixed this in !619 by measuring an uninterrupted baseline on the same machine first and comparing against that instead of a constant. This branch has the same harness, and is not immune: it asserts `500ms` where 3.5 asserts `220ms`, and the run that broke 3.5 measured 752 ms ? past 500 ms as well. It is green only because it did not run at that moment. This is `8d662dd22` cherry-picked. The one conflict is in `regress/core/interrupt_relate.sql` and only over those literal tolerances, which the master commit rewrites wholesale, so master's file is the resolution. The NEWS entry is placed in this branch's current section and indentation. One extra file here that 3.4 did not need: `regress/core/interrupt_buffer_expected` on this branch still says `buffer interrupted`, while the new `_timecheck` prints `buffer interrupted on time`. Without that line the backport would fail the test it is meant to stabilise. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/664 commit 355aa8ae85f88c2048ae26b1558d9d31f145c98b Author: Darafei Praliaskouski Date: Wed Jul 29 02:19:22 2026 +0400 regress: compare interrupt timing to local baseline (cherry picked from commit 8d662dd225659c5eee6ac932219cbe2ee7670624) diff --git a/NEWS b/NEWS index 26417e01b4..5cc20f5741 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,9 @@ PostGIS 3.6.5 * Fixes * +- GT-619, Make interrupt regression tests compare timeout latency to + same-machine uninterrupted runtime, avoiding false failures under + slow CI load (Darafei Praliaskouski) - GT-582, Make the computed-columns regression test assert the query plan instead of racing two stopwatches, so it no longer fails at random under CI load (Darafei Praliaskouski) diff --git a/regress/core/interrupt.sql b/regress/core/interrupt.sql index 78f30166e4..c9fc993b6a 100644 --- a/regress/core/interrupt.sql +++ b/regress/core/interrupt.sql @@ -17,4 +17,7 @@ SELECT _timecheck('segmentize', '300ms'); -- Not affected by old timeout SELECT '1',ST_AsText(ST_Segmentize('LINESTRING(0 0,4 0)'::geometry, 2)); +DROP FUNCTION _timecheck(text); DROP FUNCTION _timecheck(text, interval); +DROP FUNCTION _timecheck_baseline(text); +DROP FUNCTION _timecheck_start(); diff --git a/regress/core/interrupt_buffer.sql b/regress/core/interrupt_buffer.sql index fd942e1e6d..204ecae936 100644 --- a/regress/core/interrupt_buffer.sql +++ b/regress/core/interrupt_buffer.sql @@ -29,3 +29,6 @@ SELECT _timecheck('buffer', '350ms'); SELECT '1', ST_NPoints(ST_Buffer('POINT(4 0)'::geometry, 2, 1)); DROP FUNCTION _timecheck(text, interval); +DROP FUNCTION _timecheck(text); +DROP FUNCTION _timecheck_baseline(text); +DROP FUNCTION _timecheck_start(); diff --git a/regress/core/interrupt_buffer_expected b/regress/core/interrupt_buffer_expected index 2e5b6dae29..f7004e0f77 100644 --- a/regress/core/interrupt_buffer_expected +++ b/regress/core/interrupt_buffer_expected @@ -1,3 +1,3 @@ ERROR: canceling statement due to statement timeout -buffer interrupted +buffer interrupted on time 1|5 diff --git a/regress/core/interrupt_relate.sql b/regress/core/interrupt_relate.sql index 74703296b8..52ead29c39 100644 --- a/regress/core/interrupt_relate.sql +++ b/regress/core/interrupt_relate.sql @@ -6,7 +6,7 @@ SELECT 1::int as id, ST_Collect(g) g FROM ( ST_Point(cos(radians(x)),sin(radians(270-x))), ST_Point(sin(radians(x)),cos(radians(60-x))) ) g - FROM generate_series(1,720) x + FROM generate_series(1,1440) x ) foo ; @@ -16,57 +16,124 @@ SELECT 1::int as id, ST_Collect(g) g FROM ( -- IM9 based predicates ----------------------------- +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Contains(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('contains'); +END; +$$; + BEGIN; SET LOCAL statement_timeout TO 100; select ST_Contains(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('contains', '500ms'); +SELECT _timecheck('contains'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Covers(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('covers'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Covers(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('covers', '500ms'); +SELECT _timecheck('covers'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_CoveredBy(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('coveredby'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_CoveredBy(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('coveredby', '500ms'); +SELECT _timecheck('coveredby'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Crosses(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('crosses'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Crosses(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('crosses', '500ms'); +SELECT _timecheck('crosses'); +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Equals(g,st_reverse(g)) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('equals'); +END; +$$; + +BEGIN; +SET LOCAL statement_timeout TO 100; -- NOTE: we're reversing one of the operands to avoid the -- short-circuit described in #3226 -BEGIN; -SET LOCAL statement_timeout TO 100; select ST_Equals(g,st_reverse(g)) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('equals', '500ms'); +SELECT _timecheck('equals'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Intersects(g,ST_Segmentize(g,1e-4)) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('intersects'); +END; +$$; --- NOTE: intersects became very fast, so we segmentize --- input to make it slower BEGIN; SET LOCAL statement_timeout TO 100; +-- NOTE: intersects became very fast, so we segmentize +-- input to make it slower select ST_Intersects(g,ST_Segmentize(g,1e-4)) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('intersects', '500ms'); +SELECT _timecheck('intersects'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Overlaps(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('overlaps'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Overlaps(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('overlaps', '500ms'); +SELECT _timecheck('overlaps'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Relate(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('relate'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Relate(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('relate', '500ms'); +SELECT _timecheck('relate'); +DROP FUNCTION _timecheck(text); DROP FUNCTION _timecheck(text, interval); +DROP FUNCTION _timecheck_baseline(text); +DROP FUNCTION _timecheck_start(); DROP TABLE _inputs; diff --git a/regress/utils/timecheck.sql b/regress/utils/timecheck.sql index 08f2af7df8..e8b324603e 100644 --- a/regress/utils/timecheck.sql +++ b/regress/utils/timecheck.sql @@ -1,3 +1,21 @@ +CREATE FUNCTION _timecheck_start() RETURNS void +AS $$ +BEGIN + UPDATE _time SET t = clock_timestamp(); +END; +$$ LANGUAGE 'plpgsql' VOLATILE; + +CREATE FUNCTION _timecheck_baseline(label text) RETURNS void +AS $$ +BEGIN + INSERT INTO _time_baseline + SELECT label, clock_timestamp() - t + FROM _time; + + UPDATE _time SET t = clock_timestamp(); +END; +$$ LANGUAGE 'plpgsql' VOLATILE; + CREATE FUNCTION _timecheck(label text, tolerated interval) RETURNS text AS $$ DECLARE @@ -33,6 +51,43 @@ BEGIN END; $$ LANGUAGE 'plpgsql' VOLATILE; +CREATE FUNCTION _timecheck(label text) RETURNS text +AS $$ +DECLARE + ret TEXT; + lap INTERVAL; + rec RECORD; +BEGIN + -- We use now() here to get the time at the + -- start of the transaction, which started when + -- this function was called, so the earliest + -- possible time + SELECT now() - t lap, b.baseline, b.baseline * 0.9 tolerated + FROM _time t + JOIN _time_baseline b ON b.label = _timecheck.label + INTO rec; + + RAISE DEBUG 'Uninterrupted baseline: %', rec.baseline; + RAISE DEBUG 'Resulting tolerance: %', rec.tolerated; + + IF rec.lap < rec.tolerated THEN + ret := format( + '%s interrupted on time', + label + ); + ELSE + ret := format( + '%s interrupted late: %s (%s tolerated)', + label, rec.lap, rec.tolerated + ); + END IF; + + UPDATE _time SET t = clock_timestamp(); + + RETURN ret; +END; +$$ LANGUAGE 'plpgsql' VOLATILE; + CREATE TEMPORARY TABLE _time AS SELECT now() t, @@ -41,3 +96,7 @@ SELECT '1' )::float8 sf; +CREATE TEMPORARY TABLE _time_baseline ( + label text PRIMARY KEY, + baseline interval NOT NULL +); ----------------------------------------------------------------------- Summary of changes: NEWS | 3 ++ regress/core/interrupt.sql | 3 ++ regress/core/interrupt_buffer.sql | 3 ++ regress/core/interrupt_buffer_expected | 2 +- regress/core/interrupt_relate.sql | 93 +++++++++++++++++++++++++++++----- regress/utils/timecheck.sql | 59 +++++++++++++++++++++ 6 files changed, 149 insertions(+), 14 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 09:47:19 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 09:47:19 -0700 (PDT) Subject: [SCM] PostGIS branch stable-3.5 updated. 3.5.7-101-ga3192f3232 Message-ID: <20260803164719.3EB4D1BA8AB@trac.osgeo.org> 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, stable-3.5 has been updated via a3192f3232f67d539bfcfc373c5b31d8c2175475 (commit) via 7d75222c239c04dffac365881bd46aa1aa6bf8a1 (commit) from 7e92bf7ad3db42ac7af27aab5f490bba757bd935 (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 a3192f3232f67d539bfcfc373c5b31d8c2175475 Merge: 7e92bf7ad3 7d75222c23 Author: Darafei Praliaskouski Date: Mon Aug 3 09:47:17 2026 -0700 Merge pull request 'regress: compare interrupt timing to local baseline (stable-3.5)' (!661) from Komzpa/postgis:fix/interrupt-baseline-3.5-20260803 into stable-3.5 `stable-3.5` is red on the CI dashboard. Pipeline 6459, workflow `regress`, step `test-upgrades`, fails on one test out of 170: ``` regress/core/interrupt_relate .. failed (diff expected obtained: /tmp/pgis_reg/test_125_diff) @@ -13,4 +13,4 @@ ERROR: canceling statement due to statement timeout -relate interrupted on time +relate interrupted late: 00:00:00.75175 (00:00:00.22 tolerated) ``` Nothing was slow to cancel: the interrupt arrived in 752 ms against a **hard-coded** 220 ms tolerance, on a machine that was also running the rest of the suite. This is the false failure master fixed in !619 ? `_timecheck` there measures an uninterrupted baseline on the same machine first and compares against that instead of a constant. This is `8d662dd22` cherry-picked, with the NEWS entry moved into the 3.5.8 section and reindented to this branch's style. The three `*_expected` files are byte-identical between master and this branch, so the assertion text does not change ? only how the tolerance is derived. No CI configuration is added or changed on this branch; this only stops an existing check failing for a reason that is not PostGIS. Reviewed-on: https://gitea.osgeo.org/postgis/postgis/pulls/661 commit 7d75222c239c04dffac365881bd46aa1aa6bf8a1 Author: Darafei Praliaskouski Date: Wed Jul 29 02:19:22 2026 +0400 regress: compare interrupt timing to local baseline (cherry picked from commit 8d662dd225659c5eee6ac932219cbe2ee7670624) diff --git a/NEWS b/NEWS index 4319b581d9..fe80d32b15 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,9 @@ PostGIS 3.5.8 cancellation state (Darafei Praliaskouski) - GH-1160, [topology] Preserve overlay intersection boundaries when noding lines with GEOS main (Darafei Praliaskouski) + - GT-619, Make interrupt regression tests compare timeout latency to + same-machine uninterrupted runtime, avoiding false failures under + slow CI load (Darafei Praliaskouski) - GT-564, Avoid ST_MakePolygon crashes with NULL hole array entries (Darafei Praliaskouski) diff --git a/regress/core/interrupt.sql b/regress/core/interrupt.sql index 78f30166e4..c9fc993b6a 100644 --- a/regress/core/interrupt.sql +++ b/regress/core/interrupt.sql @@ -17,4 +17,7 @@ SELECT _timecheck('segmentize', '300ms'); -- Not affected by old timeout SELECT '1',ST_AsText(ST_Segmentize('LINESTRING(0 0,4 0)'::geometry, 2)); +DROP FUNCTION _timecheck(text); DROP FUNCTION _timecheck(text, interval); +DROP FUNCTION _timecheck_baseline(text); +DROP FUNCTION _timecheck_start(); diff --git a/regress/core/interrupt_buffer.sql b/regress/core/interrupt_buffer.sql index fd942e1e6d..204ecae936 100644 --- a/regress/core/interrupt_buffer.sql +++ b/regress/core/interrupt_buffer.sql @@ -29,3 +29,6 @@ SELECT _timecheck('buffer', '350ms'); SELECT '1', ST_NPoints(ST_Buffer('POINT(4 0)'::geometry, 2, 1)); DROP FUNCTION _timecheck(text, interval); +DROP FUNCTION _timecheck(text); +DROP FUNCTION _timecheck_baseline(text); +DROP FUNCTION _timecheck_start(); diff --git a/regress/core/interrupt_relate.sql b/regress/core/interrupt_relate.sql index 9df2262d71..fb29babd73 100644 --- a/regress/core/interrupt_relate.sql +++ b/regress/core/interrupt_relate.sql @@ -6,7 +6,7 @@ SELECT 1::int as id, ST_Collect(g) g FROM ( ST_Point(cos(radians(x)),sin(radians(270-x))), ST_Point(sin(radians(x)),cos(radians(60-x))) ) g - FROM generate_series(1,720) x + FROM generate_series(1,1440) x ) foo ; @@ -16,29 +16,69 @@ SELECT 1::int as id, ST_Collect(g) g FROM ( -- IM9 based predicates ----------------------------- +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Contains(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('contains'); +END; +$$; + BEGIN; SET LOCAL statement_timeout TO 100; select ST_Contains(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('contains', '220ms'); +SELECT _timecheck('contains'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Covers(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('covers'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Covers(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('covers', '220ms'); +SELECT _timecheck('covers'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_CoveredBy(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('coveredby'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_CoveredBy(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('coveredby', '250ms'); +SELECT _timecheck('coveredby'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Crosses(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('crosses'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Crosses(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('crosses', '220ms'); +SELECT _timecheck('crosses'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Equals(g,st_reverse(g)) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('equals'); +END; +$$; -- NOTE: we're reversing one of the operands to avoid the -- short-circuit described in #3226 @@ -46,7 +86,15 @@ BEGIN; SET LOCAL statement_timeout TO 100; select ST_Equals(g,st_reverse(g)) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('equals', '220ms'); +SELECT _timecheck('equals'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Intersects(g,ST_Segmentize(g,1e-4)) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('intersects'); +END; +$$; -- NOTE: intersects became very fast, so we segmentize -- input to make it slower @@ -54,19 +102,38 @@ BEGIN; SET LOCAL statement_timeout TO 100; select ST_Intersects(g,ST_Segmentize(g,1e-4)) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('intersects', '210ms'); +SELECT _timecheck('intersects'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Overlaps(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('overlaps'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Overlaps(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('overlaps', '220ms'); +SELECT _timecheck('overlaps'); + +DO $$ +BEGIN + PERFORM _timecheck_start(); + PERFORM ST_Relate(g,g) FROM _inputs WHERE id = 1; + PERFORM _timecheck_baseline('relate'); +END; +$$; BEGIN; SET LOCAL statement_timeout TO 100; select ST_Relate(g,g) from _inputs WHERE id = 1; -- 6+ seconds ROLLBACK; -SELECT _timecheck('relate', '220ms'); +SELECT _timecheck('relate'); +DROP FUNCTION _timecheck(text); DROP FUNCTION _timecheck(text, interval); +DROP FUNCTION _timecheck_baseline(text); +DROP FUNCTION _timecheck_start(); DROP TABLE _inputs; diff --git a/regress/utils/timecheck.sql b/regress/utils/timecheck.sql index 75f3bbbbd0..c28fe265e3 100644 --- a/regress/utils/timecheck.sql +++ b/regress/utils/timecheck.sql @@ -1,3 +1,21 @@ +CREATE FUNCTION _timecheck_start() RETURNS void +AS $$ +BEGIN + UPDATE _time SET t = clock_timestamp(); +END; +$$ LANGUAGE 'plpgsql' VOLATILE; + +CREATE FUNCTION _timecheck_baseline(label text) RETURNS void +AS $$ +BEGIN + INSERT INTO _time_baseline + SELECT label, clock_timestamp() - t + FROM _time; + + UPDATE _time SET t = clock_timestamp(); +END; +$$ LANGUAGE 'plpgsql' VOLATILE; + CREATE FUNCTION _timecheck(label text, tolerated interval) RETURNS text AS $$ DECLARE @@ -37,6 +55,43 @@ BEGIN END; $$ LANGUAGE 'plpgsql' VOLATILE; +CREATE FUNCTION _timecheck(label text) RETURNS text +AS $$ +DECLARE + ret TEXT; + lap INTERVAL; + rec RECORD; +BEGIN + -- We use now() here to get the time at the + -- start of the transaction, which started when + -- this function was called, so the earliest + -- possible time + SELECT now() - t lap, b.baseline, b.baseline * 0.9 tolerated + FROM _time t + JOIN _time_baseline b ON b.label = _timecheck.label + INTO rec; + + RAISE DEBUG 'Uninterrupted baseline: %', rec.baseline; + RAISE DEBUG 'Resulting tolerance: %', rec.tolerated; + + IF rec.lap < rec.tolerated THEN + ret := format( + '%s interrupted on time', + label + ); + ELSE + ret := format( + '%s interrupted late: %s (%s tolerated)', + label, rec.lap, rec.tolerated + ); + END IF; + + UPDATE _time SET t = clock_timestamp(); + + RETURN ret; +END; +$$ LANGUAGE 'plpgsql' VOLATILE; + CREATE TEMPORARY TABLE _time AS SELECT now() t, @@ -45,3 +100,7 @@ SELECT '1' )::float8 sf; +CREATE TEMPORARY TABLE _time_baseline ( + label text PRIMARY KEY, + baseline interval NOT NULL +); ----------------------------------------------------------------------- Summary of changes: NEWS | 3 ++ regress/core/interrupt.sql | 3 ++ regress/core/interrupt_buffer.sql | 3 ++ regress/core/interrupt_relate.sql | 85 ++++++++++++++++++++++++++++++++++----- regress/utils/timecheck.sql | 59 +++++++++++++++++++++++++++ 5 files changed, 144 insertions(+), 9 deletions(-) hooks/post-receive -- PostGIS From git at osgeo.org Mon Aug 3 14:45:35 2026 From: git at osgeo.org (git at osgeo.org) Date: Mon, 3 Aug 2026 14:45:35 -0700 (PDT) Subject: [SCM] PostGIS branch master updated. 3.7.0beta1-215-g59dce1353c Message-ID: <20260803214535.C0DB71BE46B@trac.osgeo.org> 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 59dce1353cc498bb657b19336ed4e6622fcfb873 (commit) via 2dd8052b88e9aed59dfa9e2f72bfa09ec75830d7 (commit) from beac83bc71bd7442b69da1053f6b1aab98fffa0f (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 59dce1353cc498bb657b19336ed4e6622fcfb873 Author: Regina Obe Date: Mon Aug 3 17:45:27 2026 -0400 Only run mingw-wine,portability during tag, cron events diff --git a/.woodpecker/mingw-wine.yml b/.woodpecker/mingw-wine.yml index ed79a30953..94b427d5c4 100644 --- a/.woodpecker/mingw-wine.yml +++ b/.woodpecker/mingw-wine.yml @@ -1,7 +1,7 @@ labels: platform: linux/amd64 when: - event: [push, pull_request, tag] + event: [tag] clone: git: diff --git a/.woodpecker/portability.yml b/.woodpecker/portability.yml index d6aa7accb1..5e9b3bf867 100644 --- a/.woodpecker/portability.yml +++ b/.woodpecker/portability.yml @@ -2,7 +2,7 @@ labels: platform: linux/amd64 qemu: "true" when: - event: [push, pull_request, tag, cron] + event: [tag, cron] # This workflow keeps the existing amd64 CI honest by attacking ABI properties # that normal amd64 builds cannot falsify. commit 2dd8052b88e9aed59dfa9e2f72bfa09ec75830d7 Author: Regina Obe Date: Mon Aug 3 16:32:12 2026 -0400 Schema qualify all references to pg_catalog and postgis - geometry_columns view - geography_columns view diff --git a/NEWS b/NEWS index 65e6328bc5..11dd7c99e9 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,8 @@ These are only changes since 3.7.0beta1. - #6109, Out-of-bounds heap read in BOX2D_out and BOX2D_expand on 65-byte box2d under ASAN (Dennis Tighe, Google) - #6110, regression in speed with geometry_columns (Regina Obe) + - Schema qualify references to pg_catalog and postgis + in geometry_columns and geography_columns views (Regina Obe) * Enhancements * diff --git a/postgis/geography.sql.in b/postgis/geography.sql.in index edfd09d424..e7c1f5d32b 100644 --- a/postgis/geography.sql.in +++ b/postgis/geography.sql.in @@ -166,22 +166,22 @@ CREATE OR REPLACE VIEW geography_columns AS n.nspname AS f_table_schema, c.relname AS f_table_name, a.attname AS f_geography_column, - postgis_typmod_dims(a.atttypmod) AS coord_dimension, - postgis_typmod_srid(a.atttypmod) AS srid, - postgis_typmod_type(a.atttypmod) AS type + @extschema at .postgis_typmod_dims(a.atttypmod) AS coord_dimension, + @extschema at .postgis_typmod_srid(a.atttypmod) AS srid, + @extschema at .postgis_typmod_type(a.atttypmod) AS type FROM - pg_class c, - pg_attribute a, - pg_type t, - pg_namespace n - WHERE t.typname = 'geography' - AND a.attisdropped = false - AND a.atttypid = t.oid - AND a.attrelid = c.oid - AND c.relnamespace = n.oid - AND c.relkind = ANY (ARRAY['r'::"char", 'v'::"char", 'm'::"char", 'f'::"char", 'p'::"char"] ) + pg_catalog.pg_class c, + pg_catalog.pg_attribute a, + pg_catalog.pg_type t, + pg_catalog.pg_namespace n + WHERE t.typname OPERATOR(pg_catalog.=) 'geography'::pg_catalog.name + AND a.attisdropped OPERATOR(pg_catalog.=) false + AND a.atttypid OPERATOR(pg_catalog.=) t.oid + AND a.attrelid OPERATOR(pg_catalog.=) c.oid + AND c.relnamespace OPERATOR(pg_catalog.=) n.oid + AND c.relkind OPERATOR(pg_catalog.=) ANY (ARRAY['r'::pg_catalog."char", 'v'::pg_catalog."char", 'm'::pg_catalog."char", 'f'::pg_catalog."char", 'p'::pg_catalog."char"] ) AND NOT pg_catalog.pg_is_other_temp_schema(c.relnamespace) - AND pg_catalog.has_column_privilege(c.oid, a.attname,'SELECT'::text); + AND pg_catalog.has_column_privilege(c.oid, a.attname, 'SELECT'::pg_catalog.text); -- Availability: 1.5.0 CREATE OR REPLACE FUNCTION geography(geometry) diff --git a/postgis/postgis.sql.in b/postgis/postgis.sql.in index 57088ad4d7..1df0e2b0bf 100644 --- a/postgis/postgis.sql.in +++ b/postgis/postgis.sql.in @@ -6709,95 +6709,95 @@ WITH constraint_defs AS NOT MATERIALIZED ( SELECT connamespace, conrelid, conkey, - regexp_replace(pg_get_constraintdef(oid), $$\s+NOT\s+VALID$$, '', 'i') AS consrc - FROM pg_constraint + pg_catalog.regexp_replace(pg_catalog.pg_get_constraintdef(oid), $$\s+NOT\s+VALID$$, '', 'i') AS consrc + FROM pg_catalog.pg_constraint ) -SELECT current_database()::character varying(256) AS f_table_catalog, +SELECT pg_catalog.current_database()::pg_catalog.varchar(256) AS f_table_catalog, n.nspname AS f_table_schema, c.relname AS f_table_name, a.attname AS f_geometry_column, - COALESCE(postgis_typmod_dims(a.atttypmod), sn.ndims, 2) AS coord_dimension, - COALESCE(NULLIF(postgis_typmod_srid(a.atttypmod), 0), sr.srid, 0) AS srid, - replace(replace(COALESCE(NULLIF(upper(postgis_typmod_type(a.atttypmod)), 'GEOMETRY'::text), st.type, 'GEOMETRY'::text), 'ZM'::text, ''::text), 'Z'::text, ''::text)::character varying(30) AS type - FROM pg_class c - JOIN pg_attribute a ON a.attrelid = c.oid AND NOT a.attisdropped - JOIN pg_namespace n ON c.relnamespace = n.oid - JOIN pg_type t ON a.atttypid = t.oid + COALESCE(@extschema at .postgis_typmod_dims(a.atttypmod), sn.ndims, 2) AS coord_dimension, + COALESCE(NULLIF(@extschema at .postgis_typmod_srid(a.atttypmod), 0), sr.srid, 0) AS srid, + pg_catalog.replace(pg_catalog.replace(COALESCE(NULLIF(pg_catalog.upper(@extschema at .postgis_typmod_type(a.atttypmod)), 'GEOMETRY'::pg_catalog.text), st.type, 'GEOMETRY'::pg_catalog.text), 'ZM'::pg_catalog.text, ''::pg_catalog.text), 'Z'::pg_catalog.text, ''::pg_catalog.text)::pg_catalog.varchar(30) AS type + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_attribute a ON a.attrelid OPERATOR(pg_catalog.=) c.oid AND NOT a.attisdropped + JOIN pg_catalog.pg_namespace n ON c.relnamespace OPERATOR(pg_catalog.=) n.oid + JOIN pg_catalog.pg_type t ON a.atttypid OPERATOR(pg_catalog.=) t.oid -- Direct view columns have rewrite-rule target entries with origin metadata. -- Use only top-level bare VAR target entries, so expressions keep needing explicit casts. LEFT JOIN LATERAL ( SELECT origin.base_relid, origin.base_attnum - FROM pg_rewrite AS r - CROSS JOIN LATERAL _postgis_geometry_columns_view_column_origin(r.ev_action, a.attnum) AS origin - WHERE c.relkind = ANY (ARRAY['v'::"char", 'm'::"char"]) - AND r.ev_class = c.oid - AND r.rulename = '_RETURN' + FROM pg_catalog.pg_rewrite AS r + CROSS JOIN LATERAL @extschema at ._postgis_geometry_columns_view_column_origin(r.ev_action, a.attnum) AS origin + WHERE c.relkind OPERATOR(pg_catalog.=) ANY (ARRAY['v'::pg_catalog."char", 'm'::pg_catalog."char"]) + AND r.ev_class OPERATOR(pg_catalog.=) c.oid + AND r.rulename OPERATOR(pg_catalog.=) '_RETURN' ) AS vco ON true LEFT JOIN ( SELECT s.connamespace, s.conrelid, s.conkey, - (regexp_match(s.consrc, $$geometrytype\(\w+\)\s*=\s*'(\w+)'$$, 'i'))[1]::text AS type + (pg_catalog.regexp_match(s.consrc, $$geometrytype\(\w+\)\s*=\s*'(\w+)'$$, 'i'))[1]::pg_catalog.text AS type FROM constraint_defs AS s - WHERE s.consrc ~* $$geometrytype\(\w+\)\s*=\s*'\w+'$$::text - ) st ON st.conrelid = COALESCE(vco.base_relid, c.oid) AND (COALESCE(vco.base_attnum, a.attnum) = ANY (st.conkey)) + WHERE s.consrc OPERATOR(pg_catalog.~*) $$geometrytype\(\w+\)\s*=\s*'\w+'$$::pg_catalog.text + ) st ON st.conrelid OPERATOR(pg_catalog.=) COALESCE(vco.base_relid, c.oid) AND (COALESCE(vco.base_attnum, a.attnum) OPERATOR(pg_catalog.=) ANY (st.conkey)) LEFT JOIN ( SELECT s.connamespace, s.conrelid, s.conkey, - (regexp_match(s.consrc, $$ndims\(\w+\)\s*=\s*(\d+)$$, 'i'))[1]::integer AS ndims + (pg_catalog.regexp_match(s.consrc, $$ndims\(\w+\)\s*=\s*(\d+)$$, 'i'))[1]::integer AS ndims FROM constraint_defs AS s - WHERE s.consrc ~* $$ndims\(\w+\)\s*=\s*\d+$$::text - ) sn ON sn.conrelid = COALESCE(vco.base_relid, c.oid) AND (COALESCE(vco.base_attnum, a.attnum) = ANY (sn.conkey)) + WHERE s.consrc OPERATOR(pg_catalog.~*) $$ndims\(\w+\)\s*=\s*\d+$$::pg_catalog.text + ) sn ON sn.conrelid OPERATOR(pg_catalog.=) COALESCE(vco.base_relid, c.oid) AND (COALESCE(vco.base_attnum, a.attnum) OPERATOR(pg_catalog.=) ANY (sn.conkey)) LEFT JOIN ( SELECT s.connamespace, s.conrelid, s.conkey, - (regexp_match(s.consrc, $$srid\(\w+\)\s*=\s*(\d+)$$, 'i'))[1]::integer As srid + (pg_catalog.regexp_match(s.consrc, $$srid\(\w+\)\s*=\s*(\d+)$$, 'i'))[1]::integer As srid FROM constraint_defs AS s - WHERE s.consrc ~* $$srid\(\w+\)\s*=\s*\d+$$::text - ) sr ON sr.conrelid = COALESCE(vco.base_relid, c.oid) AND (COALESCE(vco.base_attnum, a.attnum) = ANY (sr.conkey)) - WHERE (c.relkind = ANY (ARRAY['r'::"char", 'v'::"char", 'm'::"char", 'f'::"char", 'p'::"char"])) - AND NOT c.relname = 'raster_columns'::name AND t.typname = 'geometry'::name - AND NOT pg_is_other_temp_schema(c.relnamespace) + WHERE s.consrc OPERATOR(pg_catalog.~*) $$srid\(\w+\)\s*=\s*\d+$$::pg_catalog.text + ) sr ON sr.conrelid OPERATOR(pg_catalog.=) COALESCE(vco.base_relid, c.oid) AND (COALESCE(vco.base_attnum, a.attnum) OPERATOR(pg_catalog.=) ANY (sr.conkey)) + WHERE (c.relkind OPERATOR(pg_catalog.=) ANY (ARRAY['r'::pg_catalog."char", 'v'::pg_catalog."char", 'm'::pg_catalog."char", 'f'::pg_catalog."char", 'p'::pg_catalog."char"])) + AND NOT c.relname OPERATOR(pg_catalog.=) 'raster_columns'::pg_catalog.name AND t.typname OPERATOR(pg_catalog.=) 'geometry'::pg_catalog.name + AND NOT pg_catalog.pg_is_other_temp_schema(c.relnamespace) -- A stale MVCC snapshot can still see a dropped pg_class row (#6038). -- Re-resolve the qualified relation name only when the schema is visible, -- because to_regclass reports permission errors for inaccessible schemas. -- Without schema visibility, keep the old OID-based privilege semantics. -- Keep the visible-schema SELECT check in the same CASE branch as the -- re-resolution guard so PostgreSQL cannot evaluate it for a stale OID. - AND CASE WHEN has_schema_privilege(c.relnamespace, 'USAGE'::text) - THEN CASE WHEN pg_catalog.to_regclass(pg_catalog.format('%I.%I', n.nspname, c.relname)) = c.oid - THEN pg_catalog.has_column_privilege(c.oid, a.attname, 'SELECT'::text) + AND CASE WHEN pg_catalog.has_schema_privilege(c.relnamespace, 'USAGE'::pg_catalog.text) + THEN CASE WHEN pg_catalog.to_regclass(pg_catalog.format('%I.%I', n.nspname, c.relname)) OPERATOR(pg_catalog.=) c.oid + THEN pg_catalog.has_column_privilege(c.oid, a.attname, 'SELECT'::pg_catalog.text) ELSE false END - ELSE pg_catalog.has_column_privilege(c.oid, a.attname, 'SELECT'::text) + ELSE pg_catalog.has_column_privilege(c.oid, a.attname, 'SELECT'::pg_catalog.text) END AND ( EXISTS ( SELECT 1 - FROM pg_roles - WHERE rolname = current_user + FROM pg_catalog.pg_roles + WHERE rolname OPERATOR(pg_catalog.=) current_user AND rolsuper ) OR EXISTS ( SELECT 1 - FROM pg_roles - WHERE rolname = 'pg_read_all_data' - AND pg_has_role(current_user, oid, 'USAGE') + FROM pg_catalog.pg_roles + WHERE rolname OPERATOR(pg_catalog.=) 'pg_read_all_data' + AND pg_catalog.pg_has_role(current_user, oid, 'USAGE') ) OR EXISTS ( SELECT 1 - FROM aclexplode(COALESCE(c.relacl, acldefault('r', c.relowner))) AS acl - WHERE acl.privilege_type = 'SELECT' - AND (acl.grantee = 0 OR pg_has_role(acl.grantee, 'USAGE')) + FROM pg_catalog.aclexplode(COALESCE(c.relacl, pg_catalog.acldefault('r', c.relowner))) AS acl + WHERE acl.privilege_type OPERATOR(pg_catalog.=) 'SELECT' + AND (acl.grantee OPERATOR(pg_catalog.=) 0 OR pg_catalog.pg_has_role(acl.grantee, 'USAGE')) ) OR EXISTS ( SELECT 1 - FROM aclexplode(a.attacl) AS acl - WHERE acl.privilege_type = 'SELECT' - AND (acl.grantee = 0 OR pg_has_role(acl.grantee, 'USAGE')) + FROM pg_catalog.aclexplode(a.attacl) AS acl + WHERE acl.privilege_type OPERATOR(pg_catalog.=) 'SELECT' + AND (acl.grantee OPERATOR(pg_catalog.=) 0 OR pg_catalog.pg_has_role(acl.grantee, 'USAGE')) ) ); ----------------------------------------------------------------------- Summary of changes: .woodpecker/mingw-wine.yml | 2 +- .woodpecker/portability.yml | 2 +- NEWS | 2 ++ postgis/geography.sql.in | 28 +++++++-------- postgis/postgis.sql.in | 84 ++++++++++++++++++++++----------------------- 5 files changed, 60 insertions(+), 58 deletions(-) hooks/post-receive -- PostGIS