PSQL Error: function does not exist - postgresql

I have made a function in postgres
CREATE OR REPLACE FUNCTION foobar(
x TEXT,
y TEXT,
z REAL
) RETURNS BOOLEAN AS $func$
.
.
.
$func$ LANGUAGE plpgsql;
When I do \df i get the following:
+----------+--------+------------------+------------------------+---------+
| Schema | Name | Result data type | Argument data types | Type |
+----------+--------+------------------+------------------------+---------+
| mySchema | foobar | boolean | x text, y text, z real | normal |
+----------+--------+------------------+------------------------+---------+
But when I try to use it I get [42883] ERROR: function foobar(text, text, real) does not exist. Hint: No function matches the given name and argument types. You might need to add explicit type casts. The call I'm doing is:
SELECT * FROM myTable WHERE foobar(column1::text, 'hello'::text, 7.2::real);
To me it seems like the function exists and the types match, I'm struggling to figure out what's wrong.

As a_horse_with_no_name mentioned in his comment, the solution is prefix the function with the schema.
Wrong: SELECT * FROM myTable WHERE foobar(column1::text, 'hello'::text, 7.2::real);
Correct: SELECT * FROM myTable WHERE mySchema.foobar(column1::text, 'hello'::text, 7.2::real);

Related

how to pass multiple variables to same parameter when calling postgresql function

i have total of 4 records in my table
id | url | name | description | last_update
----+------------------------------------+---------------------+-------------+-------------
1 | https://www.postgresqltutorial.com | PostgreSQL Tutorial | |
2 | http://www.oreilly.com | O'Reilly Media | |
3 | https://www.google.com | Google | | 2013-06-01
4 | http://www.postgresql.org | PostgreSQL | |
i have written a function to delete by passing name as a parameter, now i want to pass multiple names but i am facing error.
CREATE OR REPLACE FUNCTION testing(first_name varchar(255))
RETURNS INTEGER AS
$BODY$
DECLARE emp_id INTEGER;
BEGIN
SELECT id into emp_id from links e where name = first_name;
DELETE FROM links WHERE id = emp_id;
return emp_id;
END
$BODY$
LANGUAGE plpgsql;
select * from testing('Google, PostgreSQL');
Error:- no function matches the given name and argument types. you might need to add explicit type casts
Since you have a comma separated list, you can cast your parameter as an array with string_to_array function then apply the any operator. Further there is no reason for pgplsql, this can be written in a single sql statement, then wrapped it into a sql parameter/function. (see demo)
create or replace procedure testing(first_names varchar(255))
language sql
as $$
delete from links
where name = any(string_to_array(first_names, ','));
$$;
If you want to pass several values, you have to define the function to accept several values. There are two ways:
a variadic function:
CREATE FUNCTION testing(VARIADIC first_name text[]) ...
This is called like
SELECT testing('arg1', 'arg2', 'arg3');
a function that accepts an array as parameter:
CREATE FUNCTION testing(first_name text[]) ...
This is called like
SELECT testing(ARRAY['arg1', 'arg2', 'arg3']);

Postgresql error No function matches the given name and argument types. You might need to add explicit type casts

declare r double precision; b double precision; c double precision;
begin
r:=9.2;
b:=2.3;
c:=r/b;
select log(2.7, c);
...
But I get an error for this code:
ERROR: function log(numeric, double precision) does not exist
LINE 1: select log(2.7, c)
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
QUERY: select log(2.7, c)
CONTEXT: PL/pgSQL function inline_code_block line 11 at SQL statement
SQL state: 42883
As documented in the manual the log() function with two arguments requires numeric not double precision
do
$$
declare
r numeric;
b numeric;
c numeric;
result numeric;
begin
r:=9.2;
b:=2.3;
c:=r/b;
result := log(2.7, c);
raise notice 'Result %', result;
end;
$$
The log function in PostgreSQL with two arguments requires NUMERIC parameters:
\df log
List of functions
Schema | Name | Result data type | Argument data types | Type
------------+------+------------------+---------------------+--------
pg_catalog | log | double precision | double precision | normal
pg_catalog | log | numeric | numeric | normal
pg_catalog | log | numeric | numeric, numeric | normal
So you should cast your second argument or use a numeric variable instead:
SELECT LOG(2.7, c::NUMERIC);

search for multiple values in comma separated column (postgresql)

I need to fetch all records where these (5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5) values exists in categories_id column.
The value that I need to search in categories_id can be multiple because it coming from the form.
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name | alias | description | categories_id |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 5565c08d-9f18-4b76-9cae-4a8261af48f5 | Honeycolony | honeycolony | null | ["5565bffd-7f64-494c-8950-4bef61af48f5"] |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| c8f16660-32cf-11e6-b73c-1924f891ba4d | LOFT | loft | null | ["5565bffd-25bc-4b09-8a83-4bef61af48f5","5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"] |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 5565c17f-80d8-4390-aadf-4a8061af48f5 | Fawn Shoppe | fawn-shoppe | null | ["5565bffd-25bc-4b09-8a83-4bef61af48f5","5565bffd-0744-4740-81f5-4bef61af48f5","5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"] |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
I have this function which work as in_array function php.
CREATE OR REPLACE FUNCTION public.arraycontain(
x json,
y json)
RETURNS boolean
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
DECLARE a text;b text;
BEGIN
FOR a IN SELECT json_array_elements_text($1)
LOOP
FOR b IN SELECT json_array_elements_text($2)
LOOP
IF a = b THEN
RETURN TRUE;
END IF;
END LOOP;
END LOOP;
RETURN FALSE ;
END;
$BODY$;
ALTER FUNCTION public.arraycontain(json, json)
OWNER TO postgres;
But when I do this:
select * from "stores"
where arrayContain(stores.categories_id::JSON,'["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"]')
it shows
ERROR: invalid input syntax for type json
DETAIL: The input string
ended unexpectedly.
CONTEXT: JSON data, line 1: SQL state: 22P02
here is the sqlfiddle (I couldn't update the arraycontain function in fiddle.)
My expected output from the fiddle is it should return last 3 rows that is Furbish Studio,Fawn Shoppe AND LOFT if search using this values ["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"])
I am open for any recommendation.
I also tried this query below but it returns empty.
select id
from stores
where string_to_array(categories_id,',') && array['5565bffd-cd78-4e6f-ae13-4bef61af48f5','5565bffd-b1c8-4556-ae5d-4bef61af48f5'];
EDIT:
This code is actually a filter to filter data. So if I only filter using categories it didn't work but if there is a query before it it works
select * from "stores"
where name like '%ab%' and arrayContain(stores.categories_id::JSON,'["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"]')
also the thing that amaze me is that the '%ab%' must contain more than two character if there's below <2 it will throw error. what could be wrong.
Click: demo:db<>fiddle
You can use the ?| operator, which takes a jsonb array (your column in that case) and checks a text array if any elements are included:
SELECT
*
FROM
mytable
WHERE categories_id ?| '{5565bffd-b1c8-4556-ae5d-4bef61af48f5,5565bffd-cd78-4e6f-ae13-4bef61af48f5}'
If your categories_id is not of type json (which is what the error message says) but a simple text array, you can compare two text arrays directly using the && operator:
Click: demo:db<>fiddle
SELECT
*
FROM
mytable
WHERE categories_id && '{5565bffd-b1c8-4556-ae5d-4bef61af48f5,5565bffd-cd78-4e6f-ae13-4bef61af48f5}'
Your code seems to work fine so perhaps sqlfiddle is the problem.
Try changing the separator in the schema building part to / (instead of ;) and make sure you have the correct version for Postgresql. json_array_elements_text is not supported in 9.3 (you can use json_array_elements instead in this case).
Also skip the " in the select statement.
Look here http://sqlfiddle.com/#!17/918b75/1
There might be an error in your data. Perhaps categories_id is an empty string somewhere.
Try this to see the offending data if any.
do $$
declare
r record;
b boolean;
begin
for r in (select * from stores) loop
b:= arrayContain(r.categories_id::JSON,'["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"]') ;
end loop;
exception
when others
then raise notice '%,%',r,r.categories_id;
return;
end;
$$
Best regards.
Bjarni

How do I call this Postgres function with custom enum input?

I expected this to be simple, but I've tried multiple combinations and I can't get PostgreSQL to accept them. It claims there are no matching functions, yet the types listed (as seen in the example below) clearly matches my defined function.
List of data types
Schema | Name | Internal name | Size | Elements | Access privileges | Description
--------+--------+---------------+------+----------+-------------------+-------------
public | levels | levels | 4 | debug +| |
| | | | info +| |
| | | | warn +| |
| | | | critical | |
CREATE FUNCTION public."logEvent"(IN in_type text,IN in_priority public.levels,IN in_message text)
RETURNS void
LANGUAGE 'sql'
NOT LEAKPROOF
AS $function$
INSERT INTO public.log (type,priority,message) VALUES (in_type, in_priority, in_message);
$function$;
The failing query:
SELECT 1 FROM public.logEvent('test'::text,'debug'::public.levels,'test from sql prompt'::text);
ERROR: function public.logevent(text, levels, text) does not exist
LINE 1: SELECT 1 FROM public.logEvent('test'::text,'debug'::public.l...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
An alternate function definition: I get the same error when trying to execute this create function call:
CREATE FUNCTION public."logEvent"(IN in_type text, IN in_priority text, IN in_message text)
RETURNS boolean
LANGUAGE 'sql'
NOT LEAKPROOF
AS $function$
SELECT public.logEvent( in_type, CAST(lower(in_priority) AS public.levels), in_message);
$function$;
Are you aware that double-quoted identifiers are case-sensitive?
Are PostgreSQL column names case-sensitive?
CREATE FUNCTION public."logEvent"
But:
SELECT 1 FROM public.logEvent
This should work:
SELECT 1 FROM public."logEvent"('test', 'debug', 'test from sql prompt');
Explicit type casts are only necessary if there can be ambiguity with overloaded function.
Either keep double-quoting "logEvent" for the rest of its existence, or (smarter) use unquoted (effectively lower-case), legal identifiers.

"function does not exist," but I really think it does

Am I crazy or just plain dumb?
dev=# \df abuse_resolve
List of functions
-[ RECORD 1 ]-------+------------------------------------------------------------------------------------------------------------------------------------
Schema | public
Name | abuse_resolve
Result data type | record
Argument data types | INOUT __abuse_id bigint, OUT __msg character varying
Type | normal
dev=# select abuse_resolve('30'::bigint);
ERROR: function abuse_resolve(bigint) does not exist
LINE 1: select abuse_resolve('30'::bigint);
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Here's the CREATE FUNCTION, I've omitted the meat of the code, but that should be irrelevant:
CREATE OR REPLACE FUNCTION abuse_resolve(INOUT __abuse_id bigint, OUT __msg character varying) RETURNS record AS $_$
DECLARE
__abuse_status VARCHAR;
BEGIN
...snip...
UPDATE abuse SET abuse_status = __abuse_status,
edate = now(),
closed_on = now()
WHERE abuse_id = __abuse_id;
__msg = 'SUCCESS';
END;
$_$ LANGUAGE plpgsql SECURITY DEFINER;
And just for giggles:
GRANT ALL ON FUNCTION abuse_resolve(INOUT __abuse_id, OUT __msg character varying) TO PUBLIC;
GRANT ALL ON FUNCTION abuse_resolve(INOUT __abuse_id, OUT __msg character varying) TO myuser;
That function seems like it exists. What could I be missing?
This is resolved, the answer is: I'm dumb. I had improperly defined the arguments originally, but my code was using the correct ones. There was an extra bigint that had no business being there.
Well, something is odd. I did:
steve#steve#[local] =# create function abuse_resolve(inout __abuse_id bigint,
out __msg text) returns record language plpgsql as
$$ begin __msg = 'ok'; end; $$;
CREATE FUNCTION
steve#steve#[local] =# \df abuse_resolve
List of functions
-[ RECORD 1 ]-------+----------------------------------------
Schema | so9679418
Name | abuse_resolve
Result data type | record
Argument data types | INOUT __abuse_id bigint, OUT __msg text
Type | normal
steve#steve#[local] =# select abuse_resolve('30'::bigint);
-[ RECORD 1 ]-+--------
abuse_resolve | (30,ok)
Have you had any other issues with this database? Can you copy it with dump/restore and try this on the new copy? Does explicitly qualifying the function name with the "public" schema help? Which version of PostgreSQL are you using?
update: sql function
It also worked fine for me using:
create function abuse_resolve(inout __abuse_id bigint, out __msg text)
language sql as $$ select $1, 'ok'::text $$;
If you can and if is that problem. I recommend to use
"set search_path = mainSchemaName, secondOnes"
to set correct schema where function is created or in a place where you call it directly specify the schema name
select schemaName.abuse_resolve('30'::bigint);
Try this syntax:
SELECT * FROM abuse_resolve('30'::bigint);
I had everything but no usage on the schema. Granting usage on schema fixed it.