-- This file was automatically created by Diesel to setup helper functions -- and other internal bookkeeping. This file is safe to edit, any future -- changes will be added to existing projects as new migrations. -- Sets up a trigger for the given table to automatically set a column called -- `updated_at` whenever the row is modified (unless `updated_at` was included -- in the modified columns) -- -- # Example -- -- ```sql -- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); -- -- SELECT diesel_manage_updated_at('users'); -- ``` CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ BEGIN EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ BEGIN IF ( NEW IS DISTINCT FROM OLD AND NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at ) THEN NEW.updated_at := current_timestamp; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; -- nanoid function CREATE EXTENSION IF NOT EXISTS pgcrypto; -- The `nanoid()` function generates a compact, URL-friendly unique identifier. -- Based on the given size and alphabet, it creates a randomized string that's ideal for -- use-cases requiring small, unpredictable IDs (e.g., URL shorteners, generated file names, etc.). -- While it comes with a default configuration, the function is designed to be flexible, -- allowing for customization to meet specific needs. DROP FUNCTION IF EXISTS nanoid(int, text, float); CREATE OR REPLACE FUNCTION nanoid( size int DEFAULT 21, -- The number of symbols in the NanoId String. Must be greater than 0. alphabet text DEFAULT '_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', -- The symbols used in the NanoId String. Must contain between 1 and 255 symbols. additionalBytesFactor float DEFAULT 1.6 -- The additional bytes factor used for calculating the step size. Must be equal or greater then 1. ) RETURNS text -- A randomly generated NanoId String LANGUAGE plpgsql VOLATILE LEAKPROOF PARALLEL SAFE AS $$ DECLARE alphabetArray text[]; alphabetLength int := 64; mask int := 63; step int := 34; BEGIN IF size IS NULL OR size < 1 THEN RAISE EXCEPTION 'The size must be defined and greater than 0!'; END IF; IF alphabet IS NULL OR length(alphabet) = 0 OR length(alphabet) > 255 THEN RAISE EXCEPTION 'The alphabet can''t be undefined, zero or bigger than 255 symbols!'; END IF; IF additionalBytesFactor IS NULL OR additionalBytesFactor < 1 THEN RAISE EXCEPTION 'The additional bytes factor can''t be less than 1!'; END IF; alphabetArray := regexp_split_to_array(alphabet, ''); alphabetLength := array_length(alphabetArray, 1); mask := (2 << cast(floor(log(alphabetLength - 1) / log(2)) as int)) - 1; step := cast(ceil(additionalBytesFactor * mask * size / alphabetLength) AS int); IF step > 1024 THEN step := 1024; -- The step size % can''t be bigger then 1024! END IF; RETURN nanoid_optimized(size, alphabet, mask, step); END $$; -- Generates an optimized random string of a specified size using the given alphabet, mask, and step. -- This optimized version is designed for higher performance and lower memory overhead. -- No checks are performed! Use it only if you really know what you are doing. DROP FUNCTION IF EXISTS nanoid_optimized(int, text, int, int); CREATE OR REPLACE FUNCTION nanoid_optimized( size int, -- The desired length of the generated string. alphabet text, -- The set of characters to choose from for generating the string. mask int, -- The mask used for mapping random bytes to alphabet indices. Should be `(2^n) - 1` where `n` is a power of 2 less than or equal to the alphabet size. step int -- The number of random bytes to generate in each iteration. A larger value may speed up the function but increase memory usage. ) RETURNS text -- A randomly generated NanoId String LANGUAGE plpgsql VOLATILE LEAKPROOF PARALLEL SAFE AS $$ DECLARE idBuilder text := ''; counter int := 0; bytes bytea; alphabetIndex int; alphabetArray text[]; alphabetLength int := 64; BEGIN alphabetArray := regexp_split_to_array(alphabet, ''); alphabetLength := array_length(alphabetArray, 1); LOOP bytes := gen_random_bytes(step); FOR counter IN 0..step - 1 LOOP alphabetIndex := (get_byte(bytes, counter) & mask) + 1; IF alphabetIndex <= alphabetLength THEN idBuilder := idBuilder || alphabetArray[alphabetIndex]; IF length(idBuilder) = size THEN RETURN idBuilder; END IF; END IF; END LOOP; END LOOP; END $$;