diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d4aaec9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,17 @@ +name: CI +on: [push, pull_request] +jobs: + test: + strategy: + matrix: + pg: [17, 16, 15, 14, 13, 12, 11, 10] + name: 🐘 PostgreSQL ${{ matrix.pg }} + runs-on: ubuntu-latest + container: pgxn/pgxn-tools + steps: + - name: Start PostgreSQL ${{ matrix.pg }} + run: pg-start ${{ matrix.pg }} + - name: Check out the repo + uses: actions/checkout@v4 + - name: Test on PostgreSQL ${{ matrix.pg }} + run: pg-build-test diff --git a/META.in.json b/META.in.json index 6bfa55c..c730255 100644 --- a/META.in.json +++ b/META.in.json @@ -16,7 +16,7 @@ "name": "count_nulls", "X_comment": "REQUIRED. Version of the distribution. http://pgxn.org/spec/#version", - "version": "0.9.7", + "version": "1.0.0", "X_comment": "REQUIRED. Short description of distribution.", "abstract": "Count the number of null arguments", @@ -43,7 +43,7 @@ "file": "sql/count_nulls.sql", "X_comment": "REQUIRED. Version the extension is at.", - "version": "0.9.6", + "version": "1.0.0", "X_comment": "Optional: \"abstract\": Description of the extension.", "abstract": "Count the number of null arguments", diff --git a/META.json b/META.json index 4bfc36b..19c84e1 100644 --- a/META.json +++ b/META.json @@ -16,7 +16,7 @@ "name": "count_nulls", "X_comment": "REQUIRED. Version of the distribution. http://pgxn.org/spec/#version", - "version": "0.9.7", + "version": "1.0.0", "X_comment": "REQUIRED. Short description of distribution.", "abstract": "Count the number of null arguments", @@ -43,7 +43,7 @@ "file": "sql/count_nulls.sql", "X_comment": "REQUIRED. Version the extension is at.", - "version": "0.9.6", + "version": "1.0.0", "X_comment": "Optional: \"abstract\": Description of the extension.", "abstract": "Count the number of null arguments", diff --git a/count_nulls.control b/count_nulls.control index 14eaa22..c5c5c28 100644 --- a/count_nulls.control +++ b/count_nulls.control @@ -1,4 +1,4 @@ # count_nulls extension comment = 'Count the number of null arguments' -default_version = '0.9.6' +default_version = '1.0.0' relocatable = false diff --git a/sql/count_nulls--0.9.6--1.0.0.sql b/sql/count_nulls--0.9.6--1.0.0.sql new file mode 100644 index 0000000..dc73d7b --- /dev/null +++ b/sql/count_nulls--0.9.6--1.0.0.sql @@ -0,0 +1 @@ +-- No actual SQL changes to this version bump diff --git a/sql/count_nulls--1.0.0.sql b/sql/count_nulls--1.0.0.sql new file mode 100644 index 0000000..b6dc949 --- /dev/null +++ b/sql/count_nulls--1.0.0.sql @@ -0,0 +1,89 @@ +/* DO NOT EDIT - AUTO-GENERATED FILE */ +SET client_min_messages = WARNING; + +CREATE OR REPLACE FUNCTION null_count( + VARIADIC argument anyarray +) RETURNS int LANGUAGE sql IMMUTABLE AS $body$ + SELECT sum( CASE WHEN a IS NULL THEN 1 ELSE 0 END )::int + FROM unnest( $1 ) a +$body$; + +CREATE OR REPLACE FUNCTION null_count( + argument jsonb +) RETURNS int LANGUAGE sql IMMUTABLE AS $body$ +SELECT count(*)::int + FROM jsonb_each_text( $1 ) a + WHERE value IS NULL +$body$; +CREATE OR REPLACE FUNCTION null_count( + argument json +) RETURNS int LANGUAGE sql IMMUTABLE AS 'SELECT @extschema@.null_count($1::jsonb)'; + +CREATE OR REPLACE FUNCTION null_count_trigger( +) RETURNS trigger LANGUAGE plpgsql IMMUTABLE AS $body$ +DECLARE + c_msg CONSTANT text := coalesce( + nullif( TG_ARGV[1], 'null' ) + , format( '%s must contain %s NULL fields', TG_RELID::regclass, TG_ARGV[0] ) + ); +BEGIN + IF TG_NARGS NOT BETWEEN 1 AND 2 THEN + RAISE '% usage: number of NULL columns[, error message]', TG_NAME; + END IF; + -- Casing intentional for cut/paste/replace/ + IF nullif(TG_ARGV[0], 'null') IS null THEN + RAISE '%: first argument must not be null', TG_NAME; + END IF; + + IF @extschema@.null_count( row_to_json(NEW) ) <> TG_ARGV[0]::int THEN + RAISE '%', c_msg; + END IF; + + RETURN NEW; +END +$body$; + + +CREATE OR REPLACE FUNCTION not_null_count( + VARIADIC argument anyarray +) RETURNS int LANGUAGE sql IMMUTABLE AS $body$ + SELECT sum( CASE WHEN a IS NOT NULL THEN 1 ELSE 0 END )::int + FROM unnest( $1 ) a +$body$; + +CREATE OR REPLACE FUNCTION not_null_count( + argument jsonb +) RETURNS int LANGUAGE sql IMMUTABLE AS $body$ +SELECT count(*)::int + FROM jsonb_each_text( $1 ) a + WHERE value IS NOT NULL +$body$; +CREATE OR REPLACE FUNCTION not_null_count( + argument json +) RETURNS int LANGUAGE sql IMMUTABLE AS 'SELECT @extschema@.not_null_count($1::jsonb)'; + +CREATE OR REPLACE FUNCTION not_null_count_trigger( +) RETURNS trigger LANGUAGE plpgsql IMMUTABLE AS $body$ +DECLARE + c_msg CONSTANT text := coalesce( + nullif( TG_ARGV[1], 'null' ) + , format( '%s must contain %s NOT NULL fields', TG_RELID::regclass, TG_ARGV[0] ) + ); +BEGIN + IF TG_NARGS NOT BETWEEN 1 AND 2 THEN + RAISE '% usage: number of NOT NULL columns[, error message]', TG_NAME; + END IF; + -- Casing intentional for cut/paste/replace/ + IF nullif(TG_ARGV[0], 'null') IS null THEN + RAISE '%: first argument must not be null', TG_NAME; + END IF; + + IF @extschema@.not_null_count( row_to_json(NEW) ) <> TG_ARGV[0]::int THEN + RAISE '%', c_msg; + END IF; + + RETURN NEW; +END +$body$; + +-- vi: expandtab sw=2 ts=2