Create a function from a select that includes another function - postgresql

I need to create a function that outputs the integer from another function:
select schema.next_rowid('schema', 'table');
The next_rowid() function always outputs an integer. Using PostgreSQL 9.

Have you read the documentation for how to define functions?
CREATE FUNCTION my_pretty_function() RETURNS int AS $$
SELECT schema.next_rowid('schema', 'table');
$$ LANGUAGE 'sql';

Related

Call a sequence through a function in PostgreSql

I have a sequence in the database, and I wanted to call the sequence through a function.
I have tried below, need an assistance to create the function in a standard process, as this is not working.
select nextval('code_seq')
CREATE FUNCTION code_sequence(integer) RETURNS integer
LANGUAGE SQL
IMMUTABLE
return select nextval('code_seq');
CREATE FUNCTION local_accounts_sequence(integer) RETURNS integer
LANGUAGE SQL
IMMUTABLE
RETURN (select nextval('code_seq'));
select local_accounts_sequence(1)
check out this solution
I am able to achieve using below statements,
CREATE FUNCTION code_sequence(out seq int)
LANGUAGE plpgsql
as $$
begin
select nextval('code_seq') into seq;
end;$$
try this :
CREATE FUNCTION local_accounts_sequence() RETURNS integer
AS 'SELECT nextval(''code_seq'');'
LANGUAGE SQL;
call it like this :
select local_accounts_sequence();

What is the datatype required for the IN keyword

I'm trying to create a function in PostgreSQL that uses the keyword IN. For example:
SELECT * FROM test WHERE test.value IN (1,2,23,5,123 ...etc)
I would like to make the part after the IN a function argument. However I don't know what the data type is for this. I've looked at the data type in the docs, but couldn't figure it out.
Complete example:
create function testing(test_value ???) returns SETOF test
stable
language sql
as
$$
SELECT * FROM test WHERE test.value IN test_value
$$;
alter function testing(???) owner to postgres;
You can pass an array and use the ANY operator (the condition IN (...) is being converted to = ANY(array[...])` by the optimizer anyway).
create function testing(test_values int[]) returns SETOF test
stable
language sql
as
$$
SELECT * FROM test WHERE test.value = any(test_values)
$$;
Then use it like this:
select *
from testing(array[1,2,3,4]);

what are some valid way of overloading functions in plpgsql?

If two stored functions have the same name,name and types of arguments, but different return type, will they be considered as two distinct functions?
It is an error to try to create a function with the same name and arguments
create function f() returns int as $$
select 1;
$$ language sql;
CREATE FUNCTION
create function f() returns text as $$
select '1';
$$ language sql;
ERROR: function "f" already exists with same argument types

Using ENUM types in functions

I have a function defined as follows:
CREATE OR REPLACE FUNCTION public.somefcn(
_somevar enum_my_type
)
RETURNS integer AS
$body$
DECLARE
ret_id INTEGER
BEGIN
INSERT INTO mytable(somevar) VALUES (_somevar) RETURNING id INTO ret_id;
RETURN ret_id;
END;
$body$
LANGUAGE 'plpgsql'
When I call this like this
SELECT somefcn('validenumitem');
I get this error:
ERROR: column "somevar" is of type enum_my_type but expression is of type text
How should I update my function or call to make it work?
Found it. I had another, incorrect function as
CREATE OR REPLACE FUNCTION public.somefcn(
_somevar text
)
...
Apparently, PostgreSQL took that one, because it fits better.

Optional argument in PL/pgSQL function

I am trying to write a PL/pgSQL function with optional arguments. It performs a query based on a filtered set of records (if specified), otherwise performs a query on the entire data set in a table.
For example (PSEUDO CODE):
CREATE OR REPLACE FUNCTION foofunc(param1 integer, param2 date, param2 date, optional_list_of_ids=[]) RETURNS SETOF RECORD AS $$
IF len(optional_list_of_ids) > 0 THEN
RETURN QUERY (SELECT * from foobar where f1=param1 AND f2=param2 AND id in optional_list_of_ids);
ELSE
RETURN QUERY (SELECT * from foobar where f1=param1 AND f2=param2);
ENDIF
$$ LANGUAGE SQL;
What would be the correct way to implement this function?
As an aside, I would like to know how I could call such a function in another outer function. This is how I would do it - is it correct, or is there a better way?
CREATE FUNCTION foofuncwrapper(param1 integer, param2 date, param2 date) RETURNS SETOF RECORD AS $$
BEGIN
CREATE TABLE ids AS SELECT id from foobar where id < 100;
RETURN QUERY (SELECT * FROM foofunc(param1, param2, ids));
END
$$ LANGUAGE SQL
Since PostgreSQL 8.4 (which you seem to be running), there are default values for function parameters. If you put your parameter last and provide a default, you can simply omit it from the call:
CREATE OR REPLACE FUNCTION foofunc(_param1 integer
, _param2 date
, _ids int[] DEFAULT '{}')
RETURNS SETOF foobar -- declare return type!
LANGUAGE plpgsql AS
$func$
BEGIN -- required for plpgsql
IF _ids <> '{}'::int[] THEN -- exclude empty array and NULL
RETURN QUERY
SELECT *
FROM foobar
WHERE f1 = _param1
AND f2 = _param2
AND id = ANY(_ids); -- "IN" is not proper syntax for arrays
ELSE
RETURN QUERY
SELECT *
FROM foobar
WHERE f1 = _param1
AND f2 = _param2;
END IF;
END -- required for plpgsql
$func$;
Major points:
The keyword DEFAULT is used to declare parameter defaults. Short alternative: =.
I removed the redundant param1 from the messy example.
Since you return SELECT * FROM foobar, declare the return type as RETURNS SETOF foobar instead of RETURNS SETOF record. The latter form with anonymous records is very unwieldy, you'd have to provide a column definition list with every call.
I use an array of integer (int[]) as function parameter. Adapted the IF expression and the WHERE clause accordingly.
IF statements are not available in plain SQL. Has to be LANGUAGE plpgsql for that.
Call with or without _ids:
SELECT * FROM foofunc(1, '2012-1-1'::date);
Effectively the same:
SELECT * FROM foofunc(1, '2012-1-1'::date, '{}'::int[]);
You have to make sure the call is unambiguous. If you have another function of the same name and two parameters, Postgres might not know which to pick. Explicit casting (like I demonstrate) narrows it down. Else, untyped string literals work, too, but being explicit never hurts.
Call from within another function:
CREATE FUNCTION foofuncwrapper(_param1 integer, _param2 date)
RETURNS SETOF foobar
LANGUAGE plgpsql AS
$func$
DECLARE
_ids int[] := '{1,2,3}';
BEGIN
-- whatever
RETURN QUERY
SELECT * FROM foofunc(_param1, _param2, _ids);
END
$func$;
Elaborating on Frank's answer on this thread:
The VARIADIC agument doesn't have to be the only argument, only the last one.
You can use VARIADIC for functions that may take zero variadic arguments, it's just a little fiddlier in that it requires a different calling style for zero args. You can provide a wrapper function to hide the ugliness. Given an initial varardic function definition like:
CREATE OR REPLACE FUNCTION foofunc(param1 integer, param2 date, param2 date, optional_list_of_ids VARIADIC integer[]) RETURNS SETOF RECORD AS $$
....
$$ language sql;
For zero args use a wrapper like:
CREATE OR REPLACE FUNCTION foofunc(integer, date, date) RETURNS SETOF RECORD AS $body$
SELECT foofunc($1,$2,$3,VARIADIC ARRAY[]::integer[]);
$body$ LANGUAGE 'sql';
or just call the main func with an empty array like VARIADIC '{}'::integer[] directly. The wrapper is ugly, but it's contained ugliness, so I'd recommend using a wrapper.
Direct calls can be made in variadic form:
SELECT foofunc(1,'2011-01-01','2011-01-01', 1, 2, 3, 4);
... or array call form with array ctor:
SELECT foofunc(1,'2011-01-01','2011-01-01', VARIADIC ARRAY[1,2,3,4]);
... or array text literal form:
SELECT foofunc(1,'2011-01-01','2011-01-01', VARIADIC '{1,2,3,4}'::int[]);
The latter two forms work with empty arrays.
You mean SQL Functions with Variable Numbers of Arguments? If so, use VARIADIC.