0

I have a plpgsql function in Postgres. It's working fine when keyword is not null and returning the matching results but when keyword is null I want to ignore it and return arbitrary rows.

CREATE OR REPLACE FUNCTION get_all_companies(_keyword varchar(255))
RETURNS TABLE(
id INTEGER,
name VARCHAR,
isactive boolean
) AS $$

BEGIN
RETURN Query 
SELECT c.id, c.name, c.isactive FROM companydetail AS c
WHERE c.name ~* _keyword LIMIT 50 ;
END;$$
LANGUAGE plpgsql;
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
Sachin
  • 2,912
  • 16
  • 25

2 Answers2

2

Verify if it's NULL or it's empty:

RETURN QUERY
SELECT c.id, c.name, c.isactive 
FROM companydetail AS c 
WHERE _keyword IS NULL
   OR _keyword = ''::varchar(255) 
   OR c.name ~* _keyword 
LIMIT 50 ;
4ndt3s
  • 3,238
  • 2
  • 20
  • 30
1

@jahuuar provided a simple and elegant solution with a single SELECT to solve this with a single query (also skipping empty strings if you need that). You don't need plpgsql or even a function for this.

While working with plpgsql, you can optimize performance:

CREATE OR REPLACE FUNCTION get_all_companies(_keyword varchar(255))
  RETURNS TABLE(id INTEGER, name VARCHAR, isactive boolean) AS
$func$
BEGIN
   IF _keyword <> '' THEN  -- exclude null and empty string
      RETURN QUERY 
      SELECT c.id, c.name, c.isactive
      FROM   companydetail AS c
      WHERE  c.name ~* _keyword
      LIMIT  50;
   ELSE
      RETURN QUERY 
      SELECT c.id, c.name, c.isactive
      FROM   companydetail AS c
      LIMIT  50;
   END IF;
END
$func$  LANGUAGE plpgsql;

Postgres can use separate, optimized plans for the two distinct queries this way. A trigram GIN index scan for the first query (you need the matching index, of course - see links below), a sequential scan for the second. And PL/pgSQL saves query plans when executed repeatedly in the same session.

Related:

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228