W tym poście chciałbym przedstawić dwie funkcje jakie zostały wprowadzone do PostgreSQL 16: pg_input_is_valid oraz pg_input_error_info Moim zdaniem ułatwiają pracę z walidacją parametrów a zwłaszcza takich, które chcemy konwertować.
Dokumentację tych funkcji znajdziesz tutaj. Tak pokrótce napiszę Ci, że obie służą do tego samego: sprawdzają czy wartość zmiennej jest wymaganego typu. pg_input_is_valid zwraca true (czyli boolean 😉) jeśli wartość zmiennej jest danego typu a pg_input_error_info zwraca record (message text, detail text, hint text, sql_error_code text) czyli trochę więcej szczegółów 😉 Oczywiście to samo można zrobić w inny sposób i każdy z nas zna przynajmniej milion takich sposobów ale lepiej mieć wybór i to nie tylko w bazach danych 😉
Aby zaprezentować Ci jak można ich użyć napiszę prostą funkcję get_interval_hours, która będzie przyjmować tablicę stringów z interwałami a zwracać będzie ilość godzin po zsumowaniu tych interwałów. Czyli dla dwóch interwałów po 1 dzień powinna zwrócić 48 godzin. Natomiast jeśli jeden z elementów przesłanej tablicy nie jest typu INTERVAL to rzuci wyjątkiem.
CREATE OR REPLACE FUNCTION get_interval_hours( intervals TEXT[] )RETURNS int
AS $CODE$
DECLARE
interval_text TEXT;
hours INT;
e TEXT;
BEGIN
hours = 0;
FOREACH interval_text IN ARRAY intervals LOOP
IF pg_input_is_valid(interval_text, 'INTERVAL') THEN
SELECT EXTRACT(epoch FROM interval_text::INTERVAL)::INT/3600 + hours
INTO hours;
ELSE
SELECT message
INTO e
FROM pg_input_error_info(interval_text, 'date');
RAISE EXCEPTION '[%] is not valid: %', interval_text, e;
END IF;
END LOOP;
RETURN hours;
END
$CODE$
LANGUAGE plpgsql;
Ok to teraz sprawdźmy czy dobrze działa:
SELECT public.get_interval_hours(ARRAY['1 day','1 day', '1 week'])
Zwraca 216 czyli działa dobrze 🙂No to teraz sprawdźmy co się stanie jak wywołamy funkcję z błędną wartością aaaa:
SELECT public.get_interval_hours(ARRAY['1 day','1 day', '1 week','aaa'])
Funkcja zwróci nam:
ERROR: [aaa] is not valid: invalid input syntax for type date: "aaa" CONTEXT: PL/pgSQL function get_interval_hours(text[]) line 16 at RAISE SQL state: P0001
Mam nadzieję, że ten krótki post przyda Ci się w przyszłości.