Skip to content
Merged
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
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,14 @@ jobs:
steps:
- uses: actions/checkout@v4

# THE RELEASE TAGS, FOR native_upgrade_converge'S FIXTURE ARMS (#1341). Each
# released fixture must be byte-identical to what its tag shipped, compared by
# blob id against `v<version>:pgcolumnar--<version>.sql`. actions/checkout
# fetches no tags, so these arms used to skip on every CI run. Depth 1 is
# enough: only the file at each tagged commit is read.
- name: fetch the release tags, for the fixture-blob comparisons
run: git fetch --depth=1 origin '+refs/tags/v1.0-alpha*:refs/tags/v1.0-alpha*'

- name: Add the PGDG repository and install PostgreSQL ${{ matrix.pg }} with its headers
run: |
set -euo pipefail
Expand Down Expand Up @@ -557,6 +565,14 @@ jobs:
git fetch --depth=1 origin \
"+refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }}"

# THE RELEASE TAGS, FOR native_upgrade_converge'S FIXTURE ARMS (#1341). Each
# released fixture must be byte-identical to what its tag shipped, compared by
# blob id against `v<version>:pgcolumnar--<version>.sql`. actions/checkout
# fetches no tags, so these arms used to skip on every CI run. Depth 1 is
# enough: only the file at each tagged commit is read.
- name: fetch the release tags, for the fixture-blob comparisons
run: git fetch --depth=1 origin '+refs/tags/v1.0-alpha*:refs/tags/v1.0-alpha*'

# The repository and the package lists first, on their own, because the
# cache key below is derived from the versions apt resolves and cannot be
# computed before the lists exist.
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ jobs:
with:
fetch-depth: 2

# THE RELEASE TAGS, FOR native_upgrade_converge'S FIXTURE ARMS (#1341). Each
# released fixture must be byte-identical to what its tag shipped, compared by
# blob id against `v<version>:pgcolumnar--<version>.sql`. actions/checkout
# fetches no tags, so these arms used to skip on every CI run. Depth 1 is
# enough: only the file at each tagged commit is read, and it leaves the
# checkout's own history as it was (HEAD~1 still resolves at fetch-depth 2).
- name: fetch the release tags, for the fixture-blob comparisons
run: git fetch --depth=1 origin '+refs/tags/v1.0-alpha*:refs/tags/v1.0-alpha*'

# The packages are ~102 MB, of which ~91 MB is the LLVM toolchain that
# postgresql-server-dev-N depends on. That download is what stalls: every
# failure of this step sat at the 600s bound while every success finished
Expand Down Expand Up @@ -727,6 +736,15 @@ jobs:
steps:
- uses: actions/checkout@v4

# THE RELEASE TAGS, FOR native_upgrade_converge'S FIXTURE ARMS (#1341). Each
# released fixture must be byte-identical to what its tag shipped, compared by
# blob id against `v<version>:pgcolumnar--<version>.sql`. actions/checkout
# fetches no tags, so these arms used to skip on every CI run. Depth 1 is
# enough: only the file at each tagged commit is read, and it leaves the
# checkout's own history as it was (HEAD~1 still resolves at fetch-depth 2).
- name: fetch the release tags, for the fixture-blob comparisons
run: git fetch --depth=1 origin '+refs/tags/v1.0-alpha*:refs/tags/v1.0-alpha*'

- name: Add the PGDG repository and install PostgreSQL ${{ matrix.pg }} with its headers
run: |
set -euo pipefail
Expand Down
15 changes: 9 additions & 6 deletions test/native_upgrade_converge.sh
Original file line number Diff line number Diff line change
Expand Up @@ -219,23 +219,26 @@ _fx_git() { git -C "$HERE/.." "$@" 2>/dev/null; }
if ! _fx_git rev-parse --git-dir >/dev/null; then
_fx_why="no git repository in the tree under test"
elif [ -z "$(_fx_git tag -l 'v1.0-alpha*')" ]; then
# CI checks out at depth 1 with no tags, so this cannot run there. It runs
# locally and in the five-major release gate, which is where a fixture is
# captured and therefore where it can be captured wrongly.
# actions/checkout fetches no tags, so CI fetches the release tags in a step
# of its own for these arms (#1341). A local checkout without them still
# lands here, and the arms skip rather than compare against nothing.
_fx_why="no release tags in this checkout"
else
_fx_why=""
fi

# The name is written out in each call rather than held in a variable: the twin
# grader reads a check's name from the call, and `check "$_fx_name"` was invisible
# to it, so a port could drop this arm and still grade complete.
for v in $_FX_TAGGED; do
_fx_name="the $v fixture is byte-identical to what v$v shipped"
if [ -n "$_fx_why" ]; then
check_skip "$_fx_name" "SKIP $_fx_name ($_fx_why)" "$_fx_why"
check_skip "the $v fixture is byte-identical to what v$v shipped" \
"SKIP the $v fixture is byte-identical to what v$v shipped ($_fx_why)" "$_fx_why"
continue
fi
_fx_tag="$(_fx_git rev-parse "v$v:pgcolumnar--$v.sql" || echo "no such path at v$v")"
_fx_fix="$(_fx_git hash-object "$HERE/fixtures/pgcolumnar--$v.sql" || echo "fixture missing")"
check "$_fx_name" "$_fx_fix" "$_fx_tag"
check "the $v fixture is byte-identical to what v$v shipped" "$_fx_fix" "$_fx_tag"
done

# THE ARM THAT CATCHES THE QUIET HALF. Staging unconditionally fixes it; this
Expand Down
4 changes: 3 additions & 1 deletion test/pytest/TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7531,7 +7531,7 @@ Part of the pytest twin of `test/drop_cleanup.sh` (#1265, ported for #1341): its

## 143. test_native_upgrade_converge.py: every release upgrades to a fresh catalog, and the window before it

The pytest twin of `test/native_upgrade_converge.sh` (#1341), by the shell's names, except its release-tag checks, so the pair is declared INCOMPLETE. `ALTER EXTENSION pgcolumnar UPDATE` must bring a database on any released version to a catalog identical to a fresh install of the current `default_version`: every function's definition, ACL and comment, and every relation, column, type and foreign-data wrapper. The released starting points are the install scripts in `test/fixtures`. They are staged into the extension directory once for the module, under a lock that makes a second stager wait, and whatever was there is put back after. A backup already there means an earlier run died, so it holds the original and is kept.
The pytest twin of `test/native_upgrade_converge.sh` (#1341), every check by the shell's name, so the pair is declared COMPLETE. `ALTER EXTENSION pgcolumnar UPDATE` must bring a database on any released version to a catalog identical to a fresh install of the current `default_version`: every function's definition, ACL and comment, and every relation, column, type and foreign-data wrapper. The released starting points are the install scripts in `test/fixtures`. They are staged into the extension directory once for the module, under a lock that makes a second stager wait, and whatever was there is put back after. A backup already there means an earlier run died, so it holds the original and is kept.

Between installing a new library and running the update, a database runs the new library over its previous release's catalog (#1341 item 66). Reads and writes must work there. `DROP TABLE`, `TRUNCATE` and `pgcolumnar.vacuum()` need a catalog table the old one lacks, so they must be refused with 42P01, change nothing, and carry a hint naming the update. After the update all three succeed on the same rows.

Expand All @@ -7544,6 +7544,8 @@ Between installing a new library and running the update, a database runs the new
| `test_the_staged_fixtures_are_the_committed_ones` | the control's `default_version`; no backup was already staged; every fixture was staged, and each staged script is the committed fixture |
| `test_each_release_upgrades_to_a_fresh_catalog` | parametrized by the four fixtures: a fresh install of the target has more than 100 objects to compare, the upgrade applies, the extension is at the target, and its catalog equals the fresh install's |
| `test_the_upgrade_window` | at the previous catalog: rows written, deleted and read; the three operations refused with the hint and nothing changed; after the update the rows are intact and all three succeed |
| `test_the_fixture_sweep_found_fixtures` | the fixtures on disk, less the synthetic `1.0-alpha`, are not an empty list: an empty sweep would compare nothing and report clean |
| `test_each_fixture_is_what_its_tag_shipped` | parametrized by those fixtures: each one's blob id equals `v<version>:pgcolumnar--<version>.sql`'s; with no git repository or no release tags it cannot run (UNMET_PRECONDITION) rather than pass. CI fetches the tags for it |

## 144. test_fk_referencing.py: a foreign key referencing a columnar table is refused where it is chosen

Expand Down
4 changes: 3 additions & 1 deletion test/pytest/expected_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -858,4 +858,6 @@ guard_tests 442
# tests, one per check, by collection over the cluster files.
# cluster_tests 1018 -> 1025 for #1341, test_native_upgrade_converge.py ported by name except its
# release-tag arms (1 -> 8 tests), by collection over the cluster files.
cluster_tests 1025
# cluster_tests 1025 -> 1029 for #1341, test_native_upgrade_converge.py's release-tag arms (the
# fixture sweep premise and one test per tagged fixture: 1 + 3), by collection over the cluster files.
cluster_tests 1029
7 changes: 1 addition & 6 deletions test/pytest/test_compare_to_bash.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
"native_skip",
"native_toasted_write",
"native_truncate",
"native_upgrade_converge",
"native_vacuum_race",
"native_varlena_bound",
"native_vecskip",
Expand Down Expand Up @@ -226,12 +227,6 @@
# about the PORT rather than a licence: the standing arm does not grade it, so the
# reason is the only thing standing between a declared gap and a forgotten one.
INCOMPLETE = {
# #1341 ported every arm but the release-tag ones: each tagged fixture is
# byte-identical to what its tag shipped. CI checks out without tags, so the shell
# skips them there with check_skip, and this layer has no verdict for an arm that
# runs on one checkout and not another.
"native_upgrade_converge": "every arm is ported except the release-tag sweep and "
"the per-tag fixture-blob comparisons",
# #1341 item 29 ported the arms four fixes added with shell arms only. Each
# pair below holds that fix's arms and nothing else of its shell suite.
"inheritance": "the #1259 arms (a partitioned columnar parent is refused with "
Expand Down
40 changes: 40 additions & 0 deletions test/pytest/test_native_upgrade_converge.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,46 @@ def test_the_staged_fixtures_are_the_committed_ones(staging, expect):
"every staged install script is the committed fixture, not a leftover")


# The fixtures to compare against their tags, derived from the fixtures on disk as
# the shell derives them, so a fixture added at the next cycle-open is checked
# without anyone listing it. 1.0-alpha is synthetic: v1.0-alpha shipped
# pgcolumnar--1.0-dev.sql, so no tag holds a pgcolumnar--1.0-alpha.sql.
TAGGED = sorted(p.name[len("pgcolumnar--"):-len(".sql")] for p in FIXTURES.glob("pgcolumnar--*.sql")
if p.name != "pgcolumnar--1.0-alpha.sql")


def _git(*args):
"""-> git's stripped stdout in the repository under test, or None when it fails."""
r = subprocess.run(["git", "-C", str(REPO), *args], capture_output=True, text=True)
return r.stdout.strip() if r.returncode == 0 else None


def test_the_fixture_sweep_found_fixtures(expect):
# An empty sweep would leave nothing below to compare and report clean.
expect.text("yes" if TAGGED else "no", "yes",
"premise: the fixture sweep found fixtures to compare against their tags")


@pytest.mark.parametrize("v", TAGGED)
def test_each_fixture_is_what_its_tag_shipped(v, expect):
"""Blob ids, not a diff: a blob id is a lookup that no similarity heuristic can
distort. The local tag is trusted, as in the shell; if this fails and the fixture
looks right, check the tag with `git ls-remote origin refs/tags/v<version>`."""
if _git("rev-parse", "--git-dir") is None:
why = "no git repository in the tree under test"
elif not _git("tag", "-l", "v1.0-alpha*"):
why = "no release tags in this checkout"
else:
why = ""
if why:
expect.cannot_run("UNMET_PRECONDITION", why,
name=f"the {v} fixture is byte-identical to what v{v} shipped")
return
tag = _git("rev-parse", f"v{v}:pgcolumnar--{v}.sql") or query_error(f"no such path at v{v}")
fixture = _git("hash-object", str(FIXTURES / f"pgcolumnar--{v}.sql")) or query_error("fixture missing")
expect.text(fixture, tag, f"the {v} fixture is byte-identical to what v{v} shipped")


@pytest.mark.parametrize("from_", VERSIONS)
def test_each_release_upgrades_to_a_fresh_catalog(pgc_cluster, staging, reference, from_, expect):
extdir, _, _ = staging
Expand Down
Loading