Passing nulls into PL/pgSQL functions

Started by Adam Witneyalmost 23 years ago9 messagesgeneral
Jump to latest
#1Adam Witney
awitney@sghms.ac.uk

Hi,

Is it possible to pass a null value into a PL/pgSQL function. For example

CREATE TABLE mytable(id int, name text);

CREATE OR REPLACE FUNCTION myfunc(int, text) returns int AS '
DECLARE
_id ALIAS FOR $1;
_name ALIAS FOR $2;

BEGIN
EXECUTE ''INSERT INTO mytable (id, name) VALUES(''||_id||'',
''''''||_name||'''''')'';

RETURN _id;
END

' LANGUAGE 'plpgsql';

Now, this works ok

select myfunc(1, 'foo');

However, this fails

select myfunc(1, null);

Is there a way of doing it such that I can pass a null sometimes?

Thanks for any help

Adam

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Adam Witney (#1)
Re: Passing nulls into PL/pgSQL functions

Adam Witney <awitney@sghms.ac.uk> writes:

Is it possible to pass a null value into a PL/pgSQL function.

Certainly.

Your problem is with the EXECUTE, or even more specifically with the
string concatenation expression you're using to build the EXECUTE
expression. Do you really need an EXECUTE here at all? If so,
something involving COALESCE would work. I'd try

EXECUTE ''INSERT ....'' || coalesce(quote_literal(_name), ''NULL'') || '')'';

regards, tom lane

#3Drew Wilson
amw@speakeasy.net
In reply to: Adam Witney (#1)
"ERROR: Argument of WHERE must not be a set function"?

I want to use a function to generate a list of OIDs to be used in a
subselect.

However, I can't figure out what to return from my function that will
properly work in a WHERE clause.

I tried:
CREATE FUNCTION myTest() RETURNS SETOF oid AS 'SELECT id FROM foo;'
LANGUAGE SQL;

But when I try:
SELECT * FROM foo WHERE id in in (myTest());

I get this error message:
"ERROR: Argument of WHERE must not be a set function"

How can I use a function to generate my subselect? (I want to cal my
function just once, and avoid calling it once per row.)

Thanks,

Drew

#4Drew Wilson
amw@speakeasy.net
In reply to: Drew Wilson (#3)
Re: "ERROR: Argument of WHERE must not be a set function"?

I have to insert/update/delete into these tables. If I use views, I'd
have to write rules to handle the write-through operations.

I'd like to avoid that extra code.

Drew

On Friday, May 16, 2003, at 04:54 PM, Dennis Gearon wrote:

Show quoted text

a view instead of the function?

Drew Wilson wrote:

I want to use a function to generate a list of OIDs to be used in a
subselect.
However, I can't figure out what to return from my function that will
properly work in a WHERE clause.
I tried:
CREATE FUNCTION myTest() RETURNS SETOF oid AS 'SELECT id FROM foo;'
LANGUAGE SQL;
But when I try:
SELECT * FROM foo WHERE id in in (myTest());
I get this error message:
"ERROR: Argument of WHERE must not be a set function"
How can I use a function to generate my subselect? (I want to cal my
function just once, and avoid calling it once per row.)
Thanks,
Drew
---------------------------(end of
broadcast)---------------------------
TIP 6: Have you searched our list archives?
http://archives.postgresql.org

---------------------------(end of
broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to
majordomo@postgresql.org

#5Stephan Szabo
sszabo@megazone23.bigpanda.com
In reply to: Drew Wilson (#3)
Re: "ERROR: Argument of WHERE must not be a set function"?

On Wed, 16 Apr 2003, Drew Wilson wrote:

I want to use a function to generate a list of OIDs to be used in a
subselect.

However, I can't figure out what to return from my function that will
properly work in a WHERE clause.

I tried:
CREATE FUNCTION myTest() RETURNS SETOF oid AS 'SELECT id FROM foo;'
LANGUAGE SQL;

But when I try:
SELECT * FROM foo WHERE id in in (myTest());

I think the syntax would be:
select * from foo where id in (select * from myTest())

I get this error message:
"ERROR: Argument of WHERE must not be a set function"

How can I use a function to generate my subselect? (I want to cal my
function just once, and avoid calling it once per row.)

I think 7.4 might let you get away with calling the function only once for
the above, but current versions don't AFAIK. I assume the actual
conditions are more complicated than the above (which could probably be
reformulated into a join manually).

#6Drew Wilson
amw@speakeasy.net
In reply to: Drew Wilson (#4)
Re: "ERROR: Argument of WHERE must not be a set function"?

Oh, also, regarding using a view... I need the SQL statement to pass a
variable to the function, which I'm not sure I can do with a view.

So my example would be more like:
CREATE FUNCTION myTest(text) RETURNS SETOF oid AS 'SELECT id FROM foo
WHERE name = $1;' LANGUAGE SQL;
and
SELECT * FROM foo WHERE id in in (myTest("bar"));

Thanks,

Drew

On Wednesday, April 16, 2003, at 04:58 PM, Drew Wilson wrote:

Show quoted text

I have to insert/update/delete into these tables. If I use views, I'd
have to write rules to handle the write-through operations.

I'd like to avoid that extra code.

Drew

On Friday, May 16, 2003, at 04:54 PM, Dennis Gearon wrote:

a view instead of the function?

Drew Wilson wrote:

I want to use a function to generate a list of OIDs to be used in a
subselect.
However, I can't figure out what to return from my function that
will properly work in a WHERE clause.
I tried:
CREATE FUNCTION myTest() RETURNS SETOF oid AS 'SELECT id FROM foo;'
LANGUAGE SQL;
But when I try:
SELECT * FROM foo WHERE id in in (myTest());
I get this error message:
"ERROR: Argument of WHERE must not be a set function"
How can I use a function to generate my subselect? (I want to cal my
function just once, and avoid calling it once per row.)
Thanks,
Drew
---------------------------(end of
broadcast)---------------------------
TIP 6: Have you searched our list archives?
http://archives.postgresql.org

---------------------------(end of
broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to
majordomo@postgresql.org

---------------------------(end of
broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to
majordomo@postgresql.org

#7Drew Wilson
amw@speakeasy.net
In reply to: Stephan Szabo (#5)
Re: "ERROR: Argument of WHERE must not be a set function"?

Thank you very much. Yes, "select * from foo where id in (select * from
myTest())" is the syntax I was looking for.

On Wednesday, April 16, 2003, at 05:12 PM, Stephan Szabo wrote:

On Wed, 16 Apr 2003, Drew Wilson wrote:

I want to use a function to generate a list of OIDs to be used in a
subselect.

However, I can't figure out what to return from my function that will
properly work in a WHERE clause.

I tried:
CREATE FUNCTION myTest() RETURNS SETOF oid AS 'SELECT id FROM foo;'
LANGUAGE SQL;

But when I try:
SELECT * FROM foo WHERE id in in (myTest());

I think the syntax would be:
select * from foo where id in (select * from myTest())

I get this error message:
"ERROR: Argument of WHERE must not be a set function"

How can I use a function to generate my subselect? (I want to cal my
function just once, and avoid calling it once per row.)

I think 7.4 might let you get away with calling the function only once
for
the above, but current versions don't AFAIK. I assume the actual
conditions are more complicated than the above (which could probably be
reformulated into a join manually).

Yes, the SQL function is a join spanning 5 tables, as well as an OR
clause to test for a null relationship at the top.

Thanks again,

Drew

#8Stephan Szabo
sszabo@megazone23.bigpanda.com
In reply to: Drew Wilson (#7)
Re: "ERROR: Argument of WHERE must not be a set function"?

On Wed, 16 Apr 2003, Drew Wilson wrote:

Thank you very much. Yes, "select * from foo where id in (select * from
myTest())" is the syntax I was looking for.

On Wednesday, April 16, 2003, at 05:12 PM, Stephan Szabo wrote:

On Wed, 16 Apr 2003, Drew Wilson wrote:

I want to use a function to generate a list of OIDs to be used in a
subselect.

However, I can't figure out what to return from my function that will
properly work in a WHERE clause.

I tried:
CREATE FUNCTION myTest() RETURNS SETOF oid AS 'SELECT id FROM foo;'
LANGUAGE SQL;

But when I try:
SELECT * FROM foo WHERE id in in (myTest());

I think the syntax would be:
select * from foo where id in (select * from myTest())

I get this error message:
"ERROR: Argument of WHERE must not be a set function"

How can I use a function to generate my subselect? (I want to cal my
function just once, and avoid calling it once per row.)

I think 7.4 might let you get away with calling the function only once
for
the above, but current versions don't AFAIK. I assume the actual
conditions are more complicated than the above (which could probably be
reformulated into a join manually).

Yes, the SQL function is a join spanning 5 tables, as well as an OR
clause to test for a null relationship at the top.

I wasn't worried about the function (per-se) but the usage.
Select * from foo where id in (select id from myTest())

seems to me anyway pretty equivalent (excepting any possible null related
wierdness) to something like:
select * from foo, (select * from myTest()) bar where foo.id=bar.id

Which should only call the function once.

#9Dennis Gearon
gearond@cvc.net
In reply to: Drew Wilson (#3)
Re: "ERROR: Argument of WHERE must not be a set function"?

a view instead of the function?

Drew Wilson wrote:

Show quoted text

I want to use a function to generate a list of OIDs to be used in a
subselect.

However, I can't figure out what to return from my function that will
properly work in a WHERE clause.

I tried:
CREATE FUNCTION myTest() RETURNS SETOF oid AS 'SELECT id FROM foo;'
LANGUAGE SQL;

But when I try:
SELECT * FROM foo WHERE id in in (myTest());

I get this error message:
"ERROR: Argument of WHERE must not be a set function"

How can I use a function to generate my subselect? (I want to cal my
function just once, and avoid calling it once per row.)

Thanks,

Drew

---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://archives.postgresql.org