Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions HISTORY.asc
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
STABLE
------
== Guarantee `test/install/*.sql` ordering
Install files ran in whatever order `$(wildcard)` happened to return --
alphabetical in practice, but undocumented and not actually guaranteed.
A consumer with an implicit dependency between two install files (one
provisioning roles the other's `CREATE EXTENSION ... CASCADE` requires)
was silently relying on that accident. `TEST_INSTALL_SQL_FILES` is now
wrapped in `$(sort ...)`, which GNU Make implements as a plain byte-value
comparison independent of locale -- so ordering is now a documented
guarantee, not an accident of the filesystem. If install files have an
inter-file dependency, encode it via filename (e.g. a numeric prefix).

Issues fixed in this release: #111

2.3.0
-----
== Rename `PGTLE_VERSION` to `PGXNTOOL_PGTLE_VERSION`
Expand Down
2 changes: 2 additions & 0 deletions README.asc
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ test/install/

The `schedule` file is generated automatically and listed in `.gitignore`. Do not edit it.

**Ordering:** Install files run in plain byte-value (ASCII) order of their filenames, guaranteed regardless of filesystem or locale. If one install file depends on another having already run, encode that dependency in the filenames themselves (e.g. `01_roles.sql` before `02_extension.sql`).

**Configuration:**

The feature auto-detects based on whether `test/install/*.sql` files exist:
Expand Down
19 changes: 17 additions & 2 deletions README.html
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,18 @@ <h3 id="_test"><a class="anchor" href="#_test"></a><a class="link" href="#_test"
<div class="title">Note</div>
</td>
<td class="content">
<code>test</code> exits non-zero (after printing <code>regression.diffs</code>) if any test fails. Previously it always exited 0 regardless of test results, silently masking failures from CI and other automation that relies on the exit code.
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
While you can still run <code>make installcheck</code> or any other valid PGXS make target directly, it&#8217;s recommended to use <code>make test</code> when using pgxntool. The <code>test</code> target ensures proper test isolation and correct dependency installation.
</td>
</tr>
Expand Down Expand Up @@ -790,6 +802,9 @@ <h3 id="_testinstall"><a class="anchor" href="#_testinstall"></a><a class="link"
<p>The <code>schedule</code> file is generated automatically and listed in <code>.gitignore</code>. Do not edit it.</p>
</div>
<div class="paragraph">
<p><strong>Ordering:</strong> Install files run in plain byte-value (ASCII) order of their filenames, guaranteed regardless of filesystem or locale. If one install file depends on another having already run, encode that dependency in the filenames themselves (e.g. <code>01_roles.sql</code> before <code>02_extension.sql</code>).</p>
</div>
<div class="paragraph">
<p><strong>Configuration:</strong></p>
</div>
<div class="paragraph">
Expand Down Expand Up @@ -1071,7 +1086,7 @@ <h3 id="_dist"><a class="anchor" href="#_dist"></a><a class="link" href="#_dist"
<div class="sect2">
<h3 id="_pgxntool_sync"><a class="anchor" href="#_pgxntool_sync"></a><a class="link" href="#_pgxntool_sync">4.9. pgxntool-sync</a></h3>
<div class="paragraph">
<p>This rule will pull down the latest released version of PGXNtool via <code>git subtree pull</code> and then reconcile the files <code>setup.sh</code> copied into your project (<code>.gitignore</code>, <code>test/deps.sql</code>) with a 3-way merge.</p>
<p>This rule will pull down the latest released version of PGXNtool via <code>git subtree pull</code> and then reconcile the files <code>setup.sh</code> copied into your project (<code>.gitignore</code>, <code>test/deps.sql</code>) with a 3-way merge (it also verifies the <code>test/pgxntool</code> symlink, recreating it if missing).</p>
</div>
<div class="admonitionblock note">
<table>
Expand Down Expand Up @@ -1983,7 +1998,7 @@ <h2 id="_copyright"><a class="anchor" href="#_copyright"></a><a class="link" hre
</div>
<div id="footer">
<div id="footer-text">
Last updated 2026-07-31 16:13:06 -0500
Last updated 2026-09-15 17:18:43 -0500
</div>
</div>
</body>
Expand Down
9 changes: 8 additions & 1 deletion base.mk
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,19 @@ endif
# The schedule files use relative paths (../install/testname) so pg_regress
# resolves install files from their original location without copying.
#
# Ordering guarantee: install files run in plain byte-value (ASCII) order of
# their filenames, via $(sort). This is GNU Make's own sort, not the shell's
# `sort` -- it's unaffected by locale (LC_COLLATE etc.), so it's the same on
# every machine regardless of environment. If one install file depends on
# another having already run, encode that dependency in the filenames
# themselves (e.g. a numeric prefix: 01_roles.sql before 02_extension.sql).
#
# NOTE: The variable normalization pattern below (ifdef/NORM/error/override) is
# identical to test-build and verify-results. Refactoring options:
# 1. A $(call normalize_bool_var,VAR,DEFAULT) Make function
# 2. A small include fragment (e.g. pgxntool/mk/bool-var.mk)
# Either approach would eliminate the ~10-line block repeated for each feature.
TEST_INSTALL_SQL_FILES = $(wildcard $(TESTDIR)/install/*.sql)
TEST_INSTALL_SQL_FILES = $(sort $(wildcard $(TESTDIR)/install/*.sql))
ifdef PGXNTOOL_ENABLE_TEST_INSTALL
# override needed so command-line values (make VAR=YES) are normalized, not silently ignored.
# := needed for immediate evaluation of the function call (avoids infinite recursion with =).
Expand Down