patternsqlMinor
Postgres function return table with extra column
Viewed 0 times
postgrescolumnreturnwithfunctiontableextra
Problem
Newbie to Postgres here..
I have a Postgres / plpgsql function that will return a table. I want to return everything from a query plus a logical value that I create and return along with it.
However, after searching around I can't seem to figure out how I can return this data along with a logical value that I generate on the fly within the query?
I have a Postgres / plpgsql function that will return a table. I want to return everything from a query plus a logical value that I create and return along with it.
However, after searching around I can't seem to figure out how I can return this data along with a logical value that I generate on the fly within the query?
CREATE OR REPLACE FUNCTION public.sp_user_get_credentials_by_email(email_address character varying)
RETURNS TABLE(credential_id integer, user_id integer, password_hash character varying, password_salt character varying, created_at timestamp without time zone, last_updated_at timestamp without time zone, logical_value_return SMALLINT)
LANGUAGE plpgsql
AS $function$
DECLARE
sproc_logical_value_return SMALLINT;
BEGIN
-- also want to return logical_value_return along with the query below
-- ex: sproc_logical_value_return = (2)::INT2; how do I add this as a column logical_value_return along with the query below?
RETURN QUERY
SELECT
myapp_users_credentials.credential_id,
myapp_users_credentials.user_id,
myapp_users_credentials.password_hash,
myapp_users_credentials.password_salt,
myapp_users_credentials.created_at,
myapp_users_credentials.last_updated_at
FROM
myapp_users_credentials
JOIN myapp_contacts_assoc ON
myapp_contacts_assoc.user_id = myapp_users_credentials.user_id AND
myapp_users_credentials.expired_at IS NULL
JOIN myapp_contacts ON
myapp_contacts.contact_id = myapp_contacts_assoc.contact_id AND
myapp_users_credentials.expired_at IS NULL
WHERE
myapp_contacts.value = $1 AND
myapp_contacts.type = 1 AND
myapp_contacts.is_primary = 1
LIMIT 1;
IF NOT FOUND THEN
RAISE EXCEPTION 'Credentials not found';
END IF;
END
$function$Solution
Just add the variable to the
I simplified with table aliases.
Since your function returns a single row by definition, the value is also returned only once.
I would use
The subtle difference: You can still return the logical constant, even when no row is found. Other columns would be NULL in this case. Details:
SELECT list:CREATE OR REPLACE FUNCTION public.sp_user_get_credentials_by_email(email_address varchar)
RETURNS TABLE (credential_id integer
, user_id integer
, password_hash varchar
, password_salt varchar
, created_at timestamp
, last_updated_at timestamp
, logical_value_return smallint)
LANGUAGE plpgsql ROWS 1 AS
$func$
DECLARE
sproc_logical_value_return SMALLINT := 2; -- you can assign at declaration time
BEGIN
RETURN QUERY
SELECT uc.credential_id,
uc.user_id,
uc.password_hash,
uc.password_salt,
uc.created_at,
uc.last_updated_at
sproc_logical_value_return -- just put it in the SELECT list
FROM myapp_users_credentials uc
JOIN myapp_contacts_assoc ca ON ca.user_id = uc.user_id AND uc.expired_at IS NULL
JOIN myapp_contacts c ON c.contact_id = ca.contact_id AND uc.expired_at IS NULL
WHERE c.value = $1
AND c.type = 1
AND c.is_primary = 1
LIMIT 1;
IF NOT FOUND THEN
RAISE EXCEPTION 'Credentials not found';
END IF;
END
$func$;I simplified with table aliases.
Since your function returns a single row by definition, the value is also returned only once.
I would use
RETURNS RECORD combined with OUT parameters instead of RETURNS TABLE since you return exactly 1 row anyway.CREATE OR REPLACE FUNCTION public.sp_user_get_credentials_by_email(
IN email_address varchar
, OUT credential_id integer
, OUT user_id integer
, OUT password_hash varchar
, OUT password_salt varchar
, OUT created_at timestamp
, OUT last_updated_at timestamp
, OUT logical_value_return smallint)
LANGUAGE plpgsql AS
$func$
BEGIN
logical_value_return := 2; -- assign separately or with SELECT list
SELECT uc.credential_id, uc.user_id, uc.password_hash, uc.password_salt, uc.created_at, uc.last_updated_at
INTO credential_id, user_id, password_hash, password_salt, created_at, last_updated_at
FROM myapp_users_credentials uc
JOIN myapp_contacts_assoc ca ON ca.user_id = uc.user_id AND uc.expired_at IS NULL
JOIN myapp_contacts c ON c.contact_id = ca.contact_id AND uc.expired_at IS NULL
WHERE c.value = $1
AND c.type = 1
AND c.is_primary = 1
LIMIT 1;
IF NOT FOUND THEN
RAISE EXCEPTION 'Credentials not found';
END IF;
END
$func$;RETURNS RECORD is redundant noise which can be omitted in this case.The subtle difference: You can still return the logical constant, even when no row is found. Other columns would be NULL in this case. Details:
- Return multiple fields as a record in PostgreSQL with PL/pgSQL
- Declaring the tuple structure of a record in PL/pgSQL
Code Snippets
CREATE OR REPLACE FUNCTION public.sp_user_get_credentials_by_email(email_address varchar)
RETURNS TABLE (credential_id integer
, user_id integer
, password_hash varchar
, password_salt varchar
, created_at timestamp
, last_updated_at timestamp
, logical_value_return smallint)
LANGUAGE plpgsql ROWS 1 AS
$func$
DECLARE
sproc_logical_value_return SMALLINT := 2; -- you can assign at declaration time
BEGIN
RETURN QUERY
SELECT uc.credential_id,
uc.user_id,
uc.password_hash,
uc.password_salt,
uc.created_at,
uc.last_updated_at
sproc_logical_value_return -- just put it in the SELECT list
FROM myapp_users_credentials uc
JOIN myapp_contacts_assoc ca ON ca.user_id = uc.user_id AND uc.expired_at IS NULL
JOIN myapp_contacts c ON c.contact_id = ca.contact_id AND uc.expired_at IS NULL
WHERE c.value = $1
AND c.type = 1
AND c.is_primary = 1
LIMIT 1;
IF NOT FOUND THEN
RAISE EXCEPTION 'Credentials not found';
END IF;
END
$func$;CREATE OR REPLACE FUNCTION public.sp_user_get_credentials_by_email(
IN email_address varchar
, OUT credential_id integer
, OUT user_id integer
, OUT password_hash varchar
, OUT password_salt varchar
, OUT created_at timestamp
, OUT last_updated_at timestamp
, OUT logical_value_return smallint)
LANGUAGE plpgsql AS
$func$
BEGIN
logical_value_return := 2; -- assign separately or with SELECT list
SELECT uc.credential_id, uc.user_id, uc.password_hash, uc.password_salt, uc.created_at, uc.last_updated_at
INTO credential_id, user_id, password_hash, password_salt, created_at, last_updated_at
FROM myapp_users_credentials uc
JOIN myapp_contacts_assoc ca ON ca.user_id = uc.user_id AND uc.expired_at IS NULL
JOIN myapp_contacts c ON c.contact_id = ca.contact_id AND uc.expired_at IS NULL
WHERE c.value = $1
AND c.type = 1
AND c.is_primary = 1
LIMIT 1;
IF NOT FOUND THEN
RAISE EXCEPTION 'Credentials not found';
END IF;
END
$func$;Context
StackExchange Database Administrators Q#155955, answer score: 3
Revisions (0)
No revisions yet.