title: PL/pgSQL: structure of query does not match function result type
body: <p>I have a table </p>
  
  <pre><code>create table abac_object (
      inbound abac_attribute,
      outbound abac_attribute,
      created_at timestamptz not null default now(),
  
      primary key (inbound, outbound)
  );
  </code></pre>
  
  <p><code>abac_attribute</code> is my custom type that is defined like</p>
  
  <pre><code>create type abac_attribute as (
      value text,
      key text,
      namespace_id uuid
  );
  </code></pre>
  
  <p>I try to create a number of functions that work over the table</p>
  
  <pre><code>create function abac_object_list_1(_attr abac_attribute)
  returns setof abac_object as $$
      select *
      from abac_object
      where outbound = _attr
  $$ language sql stable;
  
  create function abac_object_list_2(_attr1 abac_attribute, _attr2 abac_attribute)
  returns setof abac_object as $$
      select t1.*
      from abac_object as t1
      inner join abac_object as t2 on t1.inbound = t2.inbound
      where
          t1.outbound = _attr1
          and t2.outbound = _attr2
  $$ language sql stable;
  
  create function abac_object_list_3(_attr1 abac_attribute, _attr2 abac_attribute, _attr3 abac_attribute)
  returns setof abac_object as $$
      select t1.*
      from abac_object as t1
      inner join abac_object as t2 on t1.inbound = t2.inbound
      inner join abac_object as t3 on t1.inbound = t3.inbound
      where
          t1.outbound = _attr1
          and t2.outbound = _attr2
          and t3.outbound = _attr3
  $$ language sql stable;
  
  create function abac_object_list(_attrs abac_attribute[], _offset integer, _limit integer)
  returns setof abac_attribute as $$
  begin
      case array_length(_attrs, 1)
          when 1 then return query
              select t.inbound
              from abac_object_list_1(_attrs[1]) as t
              order by t.created_at
              offset _offset
              limit _limit;
          when 2 then return query
              select t.inbound
              from abac_object_list_2(_attrs[1], _attrs[2]) as t
              order by t.created_at
              offset _offset
              limit _limit;
          when 3 then return query
              select t.inbound
              from abac_object_list_3(_attrs[1], _attrs[2], _attrs[3]) as t
              order by t.created_at
              offset _offset
              limit _limit;
          else raise exception 'bad argument' using detail = 'array length should be less or equal to 3';
      end case;
  end
  $$ language plpgsql stable;
  </code></pre>
  
  <p><code>abac_object_list_1</code> works fine</p>
  
  <pre><code>select *
  from abac_object_list_1(('apple', 'type', '00000000-0000-1000-a000-000000000010') ::abac_attribute);
  </code></pre>
  
  <p>However with <code>abac_object_list</code> I get the following error</p>
  
  <pre><code>select *
  from abac_object_list(array [('apple', 'type', '00000000-0000-1000-a000-000000000010')] :: abac_attribute[], 0, 100);
  </code></pre>
  
  <blockquote>
    <p>[42804] ERROR: structure of query does not match function result type Detail: Returned type abac_attribute does not match expected type text in column 1. Where: PL/pgSQL function abac_object_list(abac_attribute[],integer,integer) line 4 at RETURN QUERY</p>
  </blockquote>
  
  <p>I can't understand where <code>text</code> type comes from.</p>
  
  <p>These functions worked before but then I added <code>created_at</code> column to be able to add explicit <code>ORDER BY</code> clause. And now I can't rewrite functions correctly.</p>
  
  <p>Also maybe there is a better (or more idiomatic) way to define these function.</p>
  
  <p>Could you please help me to figure it out?
  Thank you.</p>
  
  <p>P. S.</p>
  
  <p>Well, it seems to work if I write </p>
  
  <pre><code>return query select (t.inbound).*
  </code></pre>
  
  <p>But I am not sure if it is a right approach.
  Also I wonder what is better to use <code>return table</code> or <code>return setof</code>.</p>