I'd like to generate codes for many tables in the database, and stopped to refactor my solution when I was ready to write my third implementation of "get code for table X".
My code is this:
-- Tenants receive a code that's composed of a portion of their subdomain and a unique number. -- This number comes from this sequence. CREATE SEQUENCE tenant_codes_seq MAXVALUE 9999 NO CYCLE; CREATE TABLE tenants ( subdomain varchar(36) NOT NULL UNIQUE , tenant_code char(8) NOT NULL UNIQUE , PRIMARY KEY (tenant_code) ); -- This function expects four parameters: -- 1. The column that's receiving the generated code (RECEIVING_COLUMN_NAME) -- 2. The column that's used to salt the code (SALT_COLUMN_NAME) -- 3. The number of characters to use from the salt column (SALT_LENGTH) -- 4. The sequence name, but defaults to RECEIVING_COLUMN_NAME || 's' CREATE OR REPLACE FUNCTION generate_table_code() RETURNS trigger AS $$ DECLARE receiving_column_name text; salt_column_name text; salt_length text; sequence_name text; BEGIN receiving_column_name := TG_ARGV[0]; salt_column_name := TG_ARGV[1]; salt_length := TG_ARGV[2]; CASE WHEN TG_NARGS = 3 THEN sequence_name := receiving_column_name || 's'; WHEN TG_NARGS = 4 THEN sequence_name := TG_ARGV[3]; ELSE RAISE EXCEPTION '3 or 4 arguments expected, received %', TG_NARGS; END CASE; -- The intent is to return ABC-0001 when salt_column contains 'ABC' EXECUTE 'rpad(substr(' || quote_ident(salt_column_name) || ', 1, 4), 4, ' || quote_literal('-') || ') || lpad(nextval(' || quote_literal(sequence_name) || ')::text, ' || quote_literal(salt_length) || ', ' || quote_literal('0') || ')' INTO STRICT NEW; RETURN NEW; END $$ LANGUAGE plpgsql; CREATE TRIGGER generate_tenant_code_trig BEFORE INSERT ON tenants FOR EACH ROW EXECUTE PROCEDURE generate_table_code('tenant_code', 'subdomain', 4);
How do I assign to NEW.tenant_code, NEW.user_code or NEW.table_whatever_code?
Running some tests yields the correct "statement", but I can't seem to assign correctly:
INSERT INTO tenants(subdomain) VALUES ('abc') CREATE TABLE ERROR: syntax error at or near "NEW" LINE 1: NEW.tenant_code := rpad(substr(subdomain, 1, 4), 4, '-') || ... ^ QUERY: NEW.tenant_code := rpad(substr(subdomain, 1, 4), 4, '-') || lpad(nextval('tenant_codes')::text, '4', '0'::text) CONTEXT: PL/pgSQL function "generate_table_code" line 20 at EXECUTE statement