Question

Let's say I want to find a list of functions that can work on jsonb, what is the most effective way to do this from the terminal without using google? Assuming only access to

  • man pages
  • psql
  • postgresql tables
Was it helpful?

Solution

There are a few ways, but let's try and address all three of them..

man pages

There are no man pages that will address these questions. There is a lot of PostgreSQL documentation but currently there is nothing like that nor perldoc for PostgreSQL. The docs covering this are only distributed as HTML -- which you can still view with a terminal browser (like elinks, lynx, w3m etc). Most distributions package this up separately, in Ubuntu you'd do this.

sudo apt-get install postgresql-doc
elinks /usr/share/doc/postgres*/html/index.html

psql

To use PSQL for this, you'll need to use \dfS. You can see a listing of all the psql commands with \?. After you do \dfS just search for the type. In the event \dfS is using a viewer that wraps on terminal width, you can tell it not to wrap by setting using `\setenv, most pagers accept arguments by their environmental variable so to use LESS without wrapping you can use

\setenv PAGER less
\setenv LESS -S

All of this is buried in the man page for psql. Most of the output of \? the in-shell psql help is better explained in that man page too, for instance this is what \? shows

\df[antw][S+] [PATRN]  list [only agg/normal/trigger/window] functions

And, this is what man psql shows,

Lists functions, together with their arguments, return types, and function types, which are classified as “agg” (aggregate), “normal”, “trigger”, or “window”. To display only functions of specific type(s), add the corresponding letters a, n, t, or w to the command. If pattern is specified, only functions whose names match the pattern are shown. By default, only user-created objects are shown; supply a pattern or the S modifier to include system objects. If the form \df+ is used, additional information about each function is shown, including security classification, volatility, owner, language, source code and description.

Tip To look up functions taking arguments or returning values of a specific type, use your pager's search capability to scroll through the \df output.

PostgreSQL catalog

First you need to have an idea of what to query. That's the complex party. In the above, we know that we're using \dfS, so we can get a starting point with psql like this:

psql -E -c"\dfS" -d myDB | less -S

This will start off with with the query,

********* QUERY **********
SELECT n.nspname as "Schema",
  p.proname as "Name",
  pg_catalog.pg_get_function_result(p.oid) as "Result data type",
  pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
 CASE
  WHEN p.proisagg THEN 'agg'
  WHEN p.proiswindow THEN 'window'
  WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
  ELSE 'normal'
 END as "Type"
FROM pg_catalog.pg_proc p
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE pg_catalog.pg_function_is_visible(p.oid)
ORDER BY 1, 2, 4;
**************************

Now, we now we p.proname as "Name", and pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types" and we can put that together to get a simplified version of \dfS which shows just what you want,

SELECT p.proname AS "Name",
  pg_get_function_arguments(p.oid) AS "Argument data types"
FROM pg_proc AS p
WHERE pg_get_function_arguments(p.oid) like '%jsonb%';

A little more research into pg_proc and we can see

proargtypes - oidvector - pg_type.oid - An array with the data types of the function arguments. This includes only input arguments (including INOUT and VARIADIC arguments), and thus represents the call signature of the function.

This would allow us to do a very specific query to pg_type over oid

SELECT proname AS "Name"
FROM pg_proc
  INNER JOIN pg_type ON ( pg_type.oid = ANY(proargtypes) )
WHERE typname = 'jsonb';

And, that gets us exactly what we want.

information_schema

While maybe not applicable here, generally speaking you can find some information in the information_schema. This generic interface doesn't support everything, it's slow, and psql doesn't use it internally. I did not see this information in information_schema.routines at all.

Some of this answer was shamelessly inspired from this question but aimed to be a more friendly resource.

OTHER TIPS

I want to find a list of functions that can work on jsonb

Your answer so far only finds:

  • Functions with one or more jsonb parameters in the function signature.

A good start, but only a subset of what you are asking for.

Your query can be simplified and improved using object identifier types:

SELECT oid::regprocedure AS func_with_params, prorettype::regtype AS return_type
FROM   pg_proc
WHERE  'jsonb'::regtype = ANY(proargtypes);

Understanding this query is the minimum requirement to start looking at the next:

WITH RECURSIVE cte AS (
   SELECT 'jsonb'::regtype AS my_type

   UNION      -- fold dupes
   SELECT a.attrelid::regclass::text::regtype
   FROM   cte t
   JOIN   pg_attribute a ON a.atttypid = t.my_type
   )
SELECT p.oid::regprocedure AS func, prorettype::regtype AS return_type
FROM   pg_proc p 
WHERE  EXISTS (
   SELECT 1
   FROM   cte 
   WHERE  my_type = ANY (proargtypes)
   OR     my_type = prorettype
   )
ORDER  BY 1;

This includes more functions that can work on jsonb:

  • Functions taking a composite / row type that contains a jsonb column.
  • The last point has to be resolved recursively, since types can be nested recursively.
  • Functions returning jsonb.
  • Functions returning any of the above mentioned types containing jsonb.

To test nested types:

CREATE TEMP TABLE j2(t text, j jsonb);
CREATE TEMP TABLE j22(j j2);
CREATE TEMP TABLE j222(j j22);

CREATE FUNCTION pg_temp.f_j() RETURNS jsonb AS 'SELECT NULL::jsonb' LANGUAGE sql;
CREATE FUNCTION pg_temp.f_j2(j2) RETURNS bool AS 'SELECT true' LANGUAGE sql;
CREATE FUNCTION pg_temp.f_j222(j222) RETURNS bool AS 'SELECT true' LANGUAGE sql;

And run the above query again.

More

And we haven't even talked about these, yet:

  • Polymorphic functions (can be called with various data types).

  • Functions working with jsonb in the body but neither take nor return jsonb. For example, PL/pgSQL function do not even store a dependency in the system table because the function body is stored a string and parsed and planned at the first call in the session ...

  • Implicit or assignment casts and function type resolution.

    The data type in question may very well be valid input to other functions after an implicit type cast.

  • Domains, typed tables, maybe other exotic features.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top