diff --git a/.github/gcc-problem-matcher.json b/.github/gcc-problem-matcher.json new file mode 100644 index 0000000..337dda9 --- /dev/null +++ b/.github/gcc-problem-matcher.json @@ -0,0 +1,17 @@ +{ + "problemMatcher": [ + { + "owner": "gcc", + "pattern": [ + { + "regexp": "^(.+?):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.+)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + ] + } + ] +} diff --git a/.github/workflows/build-werror.yml b/.github/workflows/build-werror.yml new file mode 100644 index 0000000..87d98ad --- /dev/null +++ b/.github/workflows/build-werror.yml @@ -0,0 +1,167 @@ +# +# Build snowflake with -Werror +# +# Compiles snowflake against every supported PostgreSQL major with warnings +# promoted to errors. Only the build is checked here; the Docker regression +# workflow (snowflake_regression_tests.yml) builds snowflake without +# -Werror, so a new warning fails this one job with a clear cause instead +# of hiding the results of a test run. +# +# The matrix covers the build switches that reach snowflake's compile: +# +# pgver snowflake compiles against the server headers of each major and +# carries PG_VERSION_NUM conditionals, so every supported major +# is a separate build. The list matches the Docker test matrix +# in snowflake_regression_tests.yml. +# +# cc gcc and clang produce different warning sets. PostgreSQL is +# built with the same compiler, so the CFLAGS PGXS hands to +# snowflake were probed against the compiler that receives them. +# +# config stock: plain configure (-O2), the configuration packagers use. +# full: --enable-cassert, mirroring a developer build. A +# variable used only inside an Assert() reads as unused in +# "stock" but not in "full", and both configs use -O2, which +# enables the flow-sensitive warnings (maybe-uninitialized and +# friends) that an -O0 build never sees. +# +# snowflake is built with PGXS against the installation, so it needs no +# PostgreSQL rebuild of its own. Unlike lolor, snowflake has no +# compile-time switch of its own (no FSDB-style define), so each job +# compiles it once. +# +# snowflake is a plain PGXS extension and does not include Spock headers, +# so vanilla PostgreSQL is enough here -- Spock is not needed to compile it. +# +# A weekly run catches warnings that appear without a change to snowflake: +# a new PostgreSQL minor release, or a newer compiler on the runner image. +# +# The gcc problem matcher turns each diagnostic into an annotation, so it +# shows up on the offending line in the PR's "Files changed" tab. clang +# prints diagnostics in the same format. +# + +name: Build with -Werror +run-name: Compile snowflake with warnings as errors + +on: + workflow_dispatch: + pull_request: + types: [opened, synchronize, reopened] + push: + branches: [main] + schedule: + - cron: '0 22 * * 0' # Sunday, 22:00 (UTC) + +permissions: + contents: read + +concurrency: + group: build-werror-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + # Explicit shell: GitHub then runs with -eo pipefail. + shell: bash + +jobs: + build: + strategy: + fail-fast: false + matrix: + pgver: [15, 16, 17, 18, 19] + cc: [gcc, clang] + config: [stock, full] + + name: PG ${{ matrix.pgver }} ${{ matrix.cc }} ${{ matrix.config }} + + runs-on: ubuntu-latest + timeout-minutes: 45 + + env: + CC: ${{ matrix.cc }} + PG_PREFIX: ${{ github.workspace }}/../pg-install + PG_SRCDIR: ${{ github.workspace }}/../postgres + + steps: + # Checked out at the workspace root, so the relative paths the + # compiler prints (snowflake.c) match repository paths for the + # annotations. + - name: Checkout snowflake + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: Install build dependencies + run: | + sudo apt-get update -qq + sudo apt-get install -y --no-install-recommends \ + build-essential clang bison flex pkg-config \ + libicu-dev libreadline-dev zlib1g-dev + + # Same ladder as the Docker test workflow: the newest stable minor + # tag of the major, falling back to the newest RC and then BETA for + # a major that has not gone GA yet, and finally to the REL_x_STABLE + # branch for a major that has been branched but not yet tagged. + # + # --refs drops the peeled ^{} entries, so a failing git is the only + # thing that can fail the fetch. Each selection instead ends in + # "|| true": grep exits 1 when a major has no tag of that kind, + # which pipefail would otherwise turn into a failed step -- that is + # the normal case for every pre-GA major, and the ladder exists + # precisely to fall through it. + - name: Resolve PostgreSQL source ref + id: pgtag + run: | + PG_TAGS=$(git ls-remote --tags --refs \ + https://github.com/postgres/postgres.git "REL_${{ matrix.pgver }}_*" \ + | awk -F/ '{print $NF}') + pick() { printf '%s\n' "$PG_TAGS" | grep -E "$1" | sort -V | tail -n 1 || true; } + PG_REF=$(pick "^REL_${{ matrix.pgver }}_[0-9]+$") + [ -n "$PG_REF" ] || PG_REF=$(pick "^REL_${{ matrix.pgver }}_RC[0-9]+$") + [ -n "$PG_REF" ] || PG_REF=$(pick "^REL_${{ matrix.pgver }}_BETA[0-9]+$") + if [ -z "$PG_REF" ] \ + && git ls-remote --exit-code --heads \ + https://github.com/postgres/postgres.git \ + "REL_${{ matrix.pgver }}_STABLE" >/dev/null; then + PG_REF="REL_${{ matrix.pgver }}_STABLE" + fi + if [ -z "$PG_REF" ]; then + echo "::error::Failed to resolve a source ref for PostgreSQL ${{ matrix.pgver }}" + exit 1 + fi + echo "PG ${{ matrix.pgver }} resolved to $PG_REF" + echo "pg_ref=$PG_REF" >> "$GITHUB_OUTPUT" + + - name: Fetch PostgreSQL source + run: | + git init "$PG_SRCDIR" + git -C "$PG_SRCDIR" remote add origin \ + https://github.com/postgres/postgres.git + git -C "$PG_SRCDIR" fetch --depth 1 origin "${{ steps.pgtag.outputs.pg_ref }}" + git -C "$PG_SRCDIR" checkout --detach FETCH_HEAD + + - name: Configure, build, install PostgreSQL + id: pg + run: | + cd "$PG_SRCDIR" + CONFIGURE_OPTS=(--prefix="$PG_PREFIX") + if [ "${{ matrix.config }}" = "full" ]; then + CONFIGURE_OPTS+=(--enable-cassert) + fi + echo "configure ${CONFIGURE_OPTS[*]}" + ./configure "${CONFIGURE_OPTS[@]}" + make -j"$(nproc)" -s + make install -s + echo "$PG_PREFIX/bin" >> "$GITHUB_PATH" + + - name: Register problem matcher + run: echo "::add-matcher::.github/gcc-problem-matcher.json" + + # COPT is appended to CFLAGS by PGXS, so it reaches every object. + # -k keeps going after the first failing file, so a single run + # reports every warning. + - name: Build snowflake + if: ${{ !cancelled() && steps.pg.outcome == 'success' }} + run: | + make USE_PGXS=1 clean + make USE_PGXS=1 -k -j"$(nproc)" COPT=-Werror diff --git a/snowflake.c b/snowflake.c index 7402638..499682a 100644 --- a/snowflake.c +++ b/snowflake.c @@ -129,11 +129,13 @@ typedef struct Snowflake static HTAB *seqhashtab = NULL; /* hash table for SeqTable items */ +#if 0 /* * last_used_seq is updated by nextval() to point to the last used * sequence. */ static SeqTableData *last_used_seq = NULL; +#endif static int32 snowflake_node_id = 0; extern void _PG_init(void); @@ -237,9 +239,9 @@ snowflake_nextval(PG_FUNCTION_ARGS) elm->last = result; /* last returned number */ elm->cached = result; /* last fetched number */ elm->last_valid = true; - +#if 0 last_used_seq = elm; - +#endif snowflake_apply_and_log(seqrel, buf, seqdatatuple, page, seq, flake, result, logit);