CREATE FUNCTION @extschema@.check_name_length ( p_object_name text , p_suffix text DEFAULT NULL , p_table_partition boolean DEFAULT FALSE ) RETURNS text LANGUAGE plpgsql IMMUTABLE SET search_path TO pg_catalog, pg_temp AS $$ DECLARE v_new_name text; v_suffix text; BEGIN /* * Truncate the name of the given object if it is greater than the postgres default max (63 bytes). * Also appends given suffix and schema if given and truncates the name so that the entire suffix will fit. * Returns original name (with suffix if given) if it doesn't require truncation */ IF p_table_partition IS TRUE AND (NULLIF(p_suffix, '') IS NULL) THEN RAISE EXCEPTION 'Table partition name requires a suffix value'; END IF; v_suffix := format('%s%s', CASE WHEN p_table_partition THEN '_p' END, p_suffix); -- Use optimistic behavior: in almost all cases `v_new_name` will be less than allowed maximum. -- Do "heavy" work only in rare cases. v_new_name := p_object_name || v_suffix; -- Postgres' relation name limit is in bytes, not characters; also it can be compiled with bigger allowed length. -- Use its internals to detect where to cut new object name. IF v_new_name::name != v_new_name THEN -- Here we need to detect how many chars (not bytes) we need to get from the `p_object_name`. -- Use suffix as prefix and get the rest of `p_object_name`. v_new_name := (v_suffix || p_object_name)::name; -- `substr` starts from 1, that is why we need to add 1 below. -- Edge case: `v_suffix` is empty, length is 0, but need to start from 1. v_new_name := substr(v_new_name, length(v_suffix) + 1) || v_suffix; END IF; RETURN v_new_name; END $$;