From 4ad94785f1d0d470ff92d27be73c98aafacbb5a5 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Wed, 14 Oct 2026 14:26:27 -0500 Subject: [PATCH] chore: add plpgsql_check to testing --- flake.lock | 16 ++++++++-------- flake.nix | 3 ++- nix/plpgsql-check.nix | 40 ++++++++++++++++++++++++++++++++++++++++ shell.nix | 37 ++++++++++++++++++++++++++++--------- test/test_engine.py | 2 +- test/test_misc.py | 36 ++++++++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+), 19 deletions(-) create mode 100644 nix/plpgsql-check.nix create mode 100644 test/test_misc.py diff --git a/flake.lock b/flake.lock index ca935bd..704715e 100644 --- a/flake.lock +++ b/flake.lock @@ -18,16 +18,16 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1764521362, - "narHash": "sha256-M101xMtWdF1eSD0xhiR8nG8CXRlHmv6V+VoY65Smwf4=", + "lastModified": 1780145889, + "narHash": "sha256-md0zn0RnwNvPyASas1yG5YUuwQ4ALA6ucL50l0DvqCo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "871b9fd269ff6246794583ce4ee1031e1da71895", + "rev": "8c50a710ddca43d7a530fb805ad55bde8d0141c5", "type": "github" }, "original": { "owner": "NixOS", - "ref": "25.11", + "ref": "26.05", "repo": "nixpkgs", "type": "github" } @@ -43,16 +43,16 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1785529904, - "narHash": "sha256-DDIeJCHRtmvB7yocWTo1MISIGf0DsUmyLw6ISuEV4e0=", + "lastModified": 1791394750, + "narHash": "sha256-SMv4EKUaGmfUyXyeGHW3AiX1vbef7El56RKTIxio8jQ=", "owner": "supabase", "repo": "xpg", - "rev": "e7d47eb58f19168b5facc6b78a64f6cc7f04bbcb", + "rev": "8f2a2005e8e020e0db5a7cbb94a87a9dd3227411", "type": "github" }, "original": { "owner": "supabase", - "ref": "v2.5.0", + "ref": "v2.6.0", "repo": "xpg", "type": "github" } diff --git a/flake.nix b/flake.nix index e66b190..f34b991 100644 --- a/flake.nix +++ b/flake.nix @@ -4,8 +4,9 @@ inputs = { # 2025-11-13 nixpkgs.url = "github:NixOS/nixpkgs/91c9a64ce2a84e648d0cf9671274bb9c2fb9ba60"; + xpg = { - url = "github:supabase/xpg/v2.5.0"; + url = "github:supabase/xpg/v2.6.0"; }; }; diff --git a/nix/plpgsql-check.nix b/nix/plpgsql-check.nix new file mode 100644 index 0000000..d3c9050 --- /dev/null +++ b/nix/plpgsql-check.nix @@ -0,0 +1,40 @@ +{ + lib, + stdenv, + fetchFromGitHub, + postgresql, +}: + +stdenv.mkDerivation rec { + pname = "plpgsql-check"; + version = "2.10.12"; + + src = fetchFromGitHub { + owner = "okbob"; + repo = "plpgsql_check"; + rev = "v${version}"; + hash = "sha256-99TemcnEgbhSY1YhSrIdAlclgIzak+X2PEaC/QUJwic="; + }; + + buildInputs = [ postgresql ]; + + installPhase = '' + install -D -t $out *${postgresql.dlSuffix} + install -D -t $out *.sql + install -D -t $out *.control + + # Needed for postgres 18+ native implementation of extension_search_path + mkdir $out/extension + install -D -t $out/extension *.sql + install -D -t $out/extension *.control + ''; + + meta = with lib; { + description = "Linter tool for language PL/pgSQL"; + homepage = "https://github.com/okbob/plpgsql_check"; + changelog = "https://github.com/okbob/plpgsql_check/releases/tag/v${version}"; + platforms = postgresql.meta.platforms; + license = licenses.mit; + maintainers = [ maintainers.marsam ]; + }; +} diff --git a/shell.nix b/shell.nix index 024abfd..0cfe3d9 100644 --- a/shell.nix +++ b/shell.nix @@ -37,18 +37,37 @@ let ${pkgs.ruff}/bin/ruff check ${pkgs.findutils}/bin/find . -name '*.nix' -exec ${pkgs.nixfmt}/bin/nixfmt --check {} \+ ''; + plpgsqlcheck14 = pkgs.callPackage ./nix/plpgsql-check.nix { + postgresql = xpgPkgs.postgresql_14; + }; + plpgsqlcheck15 = pkgs.callPackage ./nix/plpgsql-check.nix { + postgresql = xpgPkgs.postgresql_15; + }; + plpgsqlcheck16 = pkgs.callPackage ./nix/plpgsql-check.nix { + postgresql = xpgPkgs.postgresql_16; + }; + plpgsqlcheck17 = pkgs.callPackage ./nix/plpgsql-check.nix { + postgresql = xpgPkgs.postgresql_17; + }; + plpgsqlcheck18 = pkgs.callPackage ./nix/plpgsql-check.nix { + postgresql = xpgPkgs.postgresql_18; + }; + plpgsqlcheck19 = pkgs.callPackage ./nix/plpgsql-check.nix { + postgresql = xpgPkgs.postgresql_19; + }; in pkgs.mkShell { buildInputs = [ - ( - if pgVersion == null then - xpgPkgs.xpg - else - xpgPkgs.xpg.forVersions { - versions = [ pgVersion ]; - inherit cassert; - } - ) + (xpgPkgs.xpg.withExtensions { + extensions = { + "14" = [ plpgsqlcheck14 ]; + "15" = [ plpgsqlcheck15 ]; + "16" = [ plpgsqlcheck16 ]; + "17" = [ plpgsqlcheck17 ]; + "18" = [ plpgsqlcheck18 ]; + "19" = [ plpgsqlcheck19 ]; + }; + }) pythonDeps nginxCustom.nginxScript pkgs.curlWithGnuTls diff --git a/test/test_engine.py b/test/test_engine.py index af8f145..349e19d 100644 --- a/test/test_engine.py +++ b/test/test_engine.py @@ -2,4 +2,4 @@ def test_connect(conn): """Sanity test verifying connection to postgres works""" conn.execute("select 1") - assert [(1, )] == conn.execute("select 1").fetchall() + assert [(1,)] == conn.execute("select 1").fetchall() diff --git a/test/test_misc.py b/test/test_misc.py new file mode 100644 index 0000000..c523db2 --- /dev/null +++ b/test/test_misc.py @@ -0,0 +1,36 @@ +def test_plpgsql_check(conn): + """ + Test check all plpgsql functions (functions or trigger functions with defined + triggers) via plpgsql_check. Query sourced from below URL. + + https://github.com/okbob/plpgsql_check/blob/0ac96adc13b34d071c4be8ba0ec4f73e6e7520f5/README.md?plain=1#L310 + """ + sql = "create extension plpgsql_check;" + conn.execute(sql) + + + sql = """ + SELECT + (pcf).functionid::regprocedure, (pcf).lineno, (pcf).statement, + (pcf).sqlstate, (pcf).message, (pcf).detail, (pcf).hint, (pcf).level, + (pcf)."position", (pcf).query, (pcf).context + FROM + ( + SELECT + plpgsql_check_function_tb(pg_proc.oid, COALESCE(pg_trigger.tgrelid, 0), + oldtable=>pg_trigger.tgoldtable, + newtable=>pg_trigger.tgnewtable) AS pcf + FROM pg_proc + LEFT JOIN pg_trigger + ON (pg_trigger.tgfoid = pg_proc.oid) + WHERE + prolang = (SELECT lang.oid FROM pg_language lang WHERE lang.lanname = 'plpgsql') AND + pronamespace <> (SELECT nsp.oid FROM pg_namespace nsp WHERE nsp.nspname = 'pg_catalog') AND + -- ignore unused triggers + (pg_proc.prorettype <> (SELECT typ.oid FROM pg_type typ WHERE typ.typname = 'trigger') OR + pg_trigger.tgfoid IS NOT NULL) + OFFSET 0 + ) ss + ORDER BY (pcf).functionid::regprocedure::text, (pcf).lineno; + """ + assert len(conn.execute(sql).fetchall()) == 2