\echo Use "CREATE EXTENSION pgpm-utils" to load this file. \quit
CREATE SCHEMA utils;

GRANT USAGE ON SCHEMA utils TO PUBLIC;

ALTER DEFAULT PRIVILEGES IN SCHEMA utils
  GRANT EXECUTE ON FUNCTIONS TO PUBLIC;

CREATE FUNCTION utils.mask_pad(bitstr text, bitlen int, pad text DEFAULT '0') RETURNS text AS $EOFCODE$
  SELECT
    (
      CASE WHEN length(bitstr) > bitlen THEN
        substring(bitstr FROM (length(bitstr) - (bitlen - 1))
          FOR bitlen)
      ELSE
        lpad(bitstr, bitlen, pad)
      END)
$EOFCODE$ LANGUAGE sql;

CREATE FUNCTION utils.bitmask_pad(bitstr pg_catalog.varbit, bitlen int, pad text DEFAULT '0') RETURNS pg_catalog.varbit AS $EOFCODE$
  SELECT
    (
      CASE WHEN length(bitstr) > bitlen THEN
        substring(bitstr::text FROM (length(bitstr) - (bitlen - 1))
          FOR bitlen)
      ELSE
        lpad(bitstr::text, bitlen, pad)
      END)::varbit;
$EOFCODE$ LANGUAGE sql;

CREATE FUNCTION utils.throw() RETURNS trigger AS $EOFCODE$
BEGIN

  IF (TG_NARGS = 1) THEN 
    RAISE EXCEPTION '% (%)', TG_ARGV[0], TG_TABLE_NAME;
  END IF;

  IF (TG_NARGS > 1) THEN 
    RAISE EXCEPTION '% (%, %)', TG_ARGV[0], TG_TABLE_NAME, TG_ARGV[1];
  END IF;

  RAISE EXCEPTION 'THROWN_ERROR (%)', TG_TABLE_NAME;

END;
$EOFCODE$ LANGUAGE plpgsql;

CREATE FUNCTION utils.ensure_singleton() RETURNS trigger AS $EOFCODE$
DECLARE
  sql text;
  num int;
BEGIN

  sql = format('SELECT count(1) FROM %1I.%2I;', TG_TABLE_SCHEMA, TG_TABLE_NAME);
  
  EXECUTE sql
    INTO num;

  IF (num > 0) THEN 
    RAISE EXCEPTION 'SINGLETON_TABLE';
  END IF;

  RETURN NEW;
END;
$EOFCODE$ LANGUAGE plpgsql;

CREATE FUNCTION utils.enforce_identity_providers_quota() RETURNS trigger AS $EOFCODE$
DECLARE
  v_settings_schema text;
  v_settings_table text;
  v_max int;
  v_count int;
BEGIN

  -- Built-in providers are exempt from the quota.
  IF NEW.is_built_in THEN
    RETURN NEW;
  END IF;

  v_settings_schema = TG_ARGV[0];
  v_settings_table = TG_ARGV[1];

  EXECUTE format(
    'SELECT identity_providers_max FROM %1$I.%2$I LIMIT 1',
    v_settings_schema,
    v_settings_table
  )
  INTO v_max;

  EXECUTE format(
    'SELECT count(1) FROM %1$I.%2$I WHERE NOT is_built_in',
    TG_TABLE_SCHEMA,
    TG_TABLE_NAME
  )
  INTO v_count;

  IF (v_count >= v_max) THEN
    RAISE EXCEPTION 'IDENTITY_PROVIDER_QUOTA_EXCEEDED';
  END IF;

  RETURN NEW;
END;
$EOFCODE$ LANGUAGE plpgsql;