steampipe-postgres-fdw icon indicating copy to clipboard operation
steampipe-postgres-fdw copied to clipboard

using output from a function as a qual?

Open judell opened this issue 3 years ago • 0 comments

For the Twitter plugin we give two examples of ways to convert a username to the required user_id.

1. id via subselect

select
  id,
  text
from
  twitter_user_tweet as t
where
  t.user_id in (select id from twitter_user where username = 'steampipeio')

2. id via join

select
  t.id,
  t.text
from
  twitter_user_tweet as t,
  twitter_user as u
where
  t.user_id = u.id
  and u.username = 'steampipeio'

I would rather do this:

3. id via function

select
  id,
  text
from
  twitter_user_tweet
where
  user_id = twitter_userid_for_username('steamipeio')

where twitter_userid_for_username() is defined as, e.g.:

create or replace function twitter_userid_for_username (_username text) returns text as $$
  declare user_id text;
  begin
    select
      id
    from
      twitter.twitter_user
    where
      username = _username
    into
      user_id;
    return user_id;
  end;
$$ language plpgsql;

This fails with:

Internal desc = 'List' call is missing required quals: column:'user_id' operator: =

It's possible to rewrite the function to be set-returning:

create or replace function twitter_userid_for_username (_username text) 
  returns table (
    user_id text
  ) as $$
  begin
    return query
      select
        id
      from
        twitter.twitter_user
      where
        username = _username;
    end;
$$ language plpgsql;

and then do this:

select
  id,
  text
from
  twitter_user_tweet
where
  user_id in ( select user_id from twitter_userid_for_username('steampipeio') )

but that loses the convenience, and economy of expression, that is the point of #3.

discussion

This is just one example of ways that functions could make queries easier to write and read. In the case of the Twitter API, the info you have (a username) will in many contexts need to be converted into the info the API needs (a user_id). Methods #1 and #2 impose a higher cognitive load than #3. As a user of a plugin, I'd appreciate not only being able to write functions that enable #3, but even more, having the most common/useful such functions provided by the plugin install.

For the purposes of this issue, though, the question for @kaidaguerre is only: what prevents the function from being used to provide a value for the qual? From a superficial Postgres perspective, these look the same.

 select pg_typeof ( ( select id from twitter_user where username = 'steampipeio' ) )

+-----------+
| pg_typeof |
+-----------+
| text      |
+-----------+

 select pg_typeof ( twitter_userid_for_username('steampipeio') )

+-----------+
| pg_typeof |
+-----------+
| text      |
+-----------+

Is there a restriction that could be easily/safely relaxed, or do dragons lurk there?

judell avatar Jan 21 '22 17:01 judell