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: 8 additions & 8 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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";
};
};

Expand Down
40 changes: 40 additions & 0 deletions nix/plpgsql-check.nix
Original file line number Diff line number Diff line change
@@ -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 ];
};
}
37 changes: 28 additions & 9 deletions shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion test/test_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
36 changes: 36 additions & 0 deletions test/test_misc.py
Original file line number Diff line number Diff line change
@@ -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
Loading