Row Level Security functions - IMMUTABLE or STABLE
### Summary

Hey. I'm using Postgraphile with Postgres 11.17 and my problem is not strictly related to the Postgraphile engine, but to the RLS function provided in the documentation at https://www.graphile.org/postgraphile/security/ . There is a current_user_id function declaration that I am concerned about.

Having these functions declared as STABLE causes the planner to run very slowly. I have identified the source of the problem and have some query plans that I want to share and get your feedback.

I actually have 2 functions similar to current_user_id. They are access_team_ids() and access_territory_ids(). A user can only have one team_id and multiple territory ids. To allow access to a row, I have an array of team_ids varchars and an array of territory_ids varchars in each row. The user must be in a team or territory.

I set the local variables using pgSettings in the postgraphile() constructor function

```
  pgSettings: (req: CustomRequest) => ({
    'statement_timeout': '3500',
    'jwt.claims.user_id': req.user.id ?? undefined,
    'jwt.claims.territory_ids': `{${getUserTerritories(req.user)
      .join(',') ?? ''}}`
  }),
```

Row count is: 1792332 Row count after applying RLS is: 3067 Table size is: 2670 MB.

I have prepared generated following query from GraphiQL that describes my issue, GQL query is to select id and totalCount with ORDERing BY ID ASC.

```sql
explain(analyze, buffers)
WITH __local_0__ AS (
        SELECT to_json((json_build_object('@node'::TEXT, (json_build_object('__identifiers'::TEXT, json_build_array(__local_1__."id"), 'id'::TEXT, (__local_1__."id")))))) AS "@edges"
            ,to_json(json_build_array('id_asc', json_build_array(__local_1__."id"))) AS "__cursor"
        FROM (
            SELECT __local_1__.*
            FROM "public"."installed_base" AS __local_1__
            WHERE (TRUE)
                AND (TRUE)
            ORDER BY __local_1__."id" ASC limit 100 offset 0
            ) __local_1__
        )
    ,__local_2__ AS (
        SELECT json_agg(to_json(__local_0__)) AS data
        FROM __local_0__
        )

SELECT coalesce((
            SELECT __local_2__.data
            FROM __local_2__
            ), '[]'::json) AS "data"
    ,(
        SELECT json_build_object('totalCount'::TEXT, count(1))
        FROM "public"."installed_base" AS __local_1__
        WHERE 1 = 1
        ) AS "aggregates";
```

This produces following query plan:

```
 Result  (cost=29759.86..29759.87 rows=1 width=64) (actual time=5695.451..5695.455 rows=1 loops=1)
   Buffers: shared hit=1092424 dirtied=23
   CTE __local_0__
     ->  Subquery Scan on __local_1__  (cost=0.43..1306.70 rows=100 width=64) (actual time=223.995..5691.564 rows=100 loops=1)
           Buffers: shared hit=1091589 dirtied=23
           ->  Limit  (cost=0.43..1303.95 rows=100 width=2126) (actual time=223.979..5691.187 rows=100 loops=1)
                 Buffers: shared hit=1091589 dirtied=23
                 ->  Index Scan using installed_base_id_uindex on installed_base __local_1___1  (cost=0.43..349278.45 rows=26795 width=2126) (actual time=223.978..5691.181 rows=100 loops=1)
                       Filter: ((access_team_ids @> ARRAY[(NULLIF(current_setting('jwt.claims.user_id'::text, true), ''::text))::character varying]) OR (access_territory_ids && (NULLIF(current_setting('jwt.claims.territory_ids'::text, true), '{}'::text))::character varying[]))
                       Rows Removed by Filter: 1115221
                       Buffers: shared hit=1091589 dirtied=23
   CTE __local_2__
     ->  Aggregate  (cost=2.50..2.51 rows=1 width=32) (actual time=5691.806..5691.807 rows=1 loops=1)
           Buffers: shared hit=1091589 dirtied=23
           ->  CTE Scan on __local_0__  (cost=0.00..2.00 rows=100 width=24) (actual time=224.004..5691.655 rows=100 loops=1)
                 Buffers: shared hit=1091589 dirtied=23
   InitPlan 3 (returns $2)
     ->  CTE Scan on __local_2__  (cost=0.00..0.02 rows=1 width=32) (actual time=5691.814..5691.814 rows=1 loops=1)
           Buffers: shared hit=1091589 dirtied=23
   InitPlan 4 (returns $3)
     ->  Aggregate  (cost=28450.61..28450.63 rows=1 width=32) (actual time=3.624..3.625 rows=1 loops=1)
           Buffers: shared hit=835
           ->  Bitmap Heap Scan on installed_base __local_1___2  (cost=301.95..28383.63 rows=26795 width=0) (actual time=2.479..3.491 rows=3067 loops=1)
                 Recheck Cond: ((access_team_ids @> ARRAY[(NULLIF(current_setting('jwt.claims.user_id'::text, true), ''::text))::character varying]) OR (access_territory_ids && (NULLIF(current_setting('jwt.claims.territory_ids'::text, true), '{}'::text))::character varying[]))
                 Heap Blocks: exact=2837
                 Buffers: shared hit=835
                 ->  BitmapOr  (cost=301.95..301.95 rows=26885 width=0) (actual time=2.169..2.170 rows=0 loops=1)
                       Buffers: shared hit=78
                       ->  Bitmap Index Scan on installed_base_access_team_ids_idx  (cost=0.00..103.52 rows=8962 width=0) (actual time=0.841..0.842 rows=3048 loops=1)
                             Index Cond: (access_team_ids @> ARRAY[(NULLIF(current_setting('jwt.claims.user_id'::text, true), ''::text))::character varying])
                             Buffers: shared hit=31
                       ->  Bitmap Index Scan on installed_base_access_territory_ids_idx  (cost=0.00..185.03 rows=17923 width=0) (actual time=1.327..1.327 rows=2872 loops=1)
                             Index Cond: (access_territory_ids && (NULLIF(current_setting('jwt.claims.territory_ids'::text, true), '{}'::text))::character varying[])
                             Buffers: shared hit=47
 Planning Time: 0.551 ms
 Execution Time: 5695.772 ms
(36 rows)
```
Which is actually slow because it runs ~6 secs. I have identified that it is a problem with Index because the planner does not take the RLS function output into the consideration and does a poor job estimating the LIMIT (which is set to 100).

However, if I make access_team_ids() and access_territory_ids() IMMUTABLE it makes the planner actually use values instead of calling functions.

```
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|QUERY PLAN                                                                                                                                                                                     |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|Result  (cost=4489.51..4489.52 rows=1 width=64) (actual time=1.760..1.762 rows=1 loops=1)                                                                                                      |
|  Buffers: shared hit=432                                                                                                                                                                      |
|  InitPlan 1 (returns $0)                                                                                                                                                                      |
|    ->  Aggregate  (cost=2257.05..2257.06 rows=1 width=32) (actual time=1.568..1.570 rows=1 loops=1)                                                                                           |
|          Buffers: shared hit=420                                                                                                                                                              |
|          ->  Limit  (cost=2253.54..2253.79 rows=100 width=2126) (actual time=1.262..1.272 rows=100 loops=1)                                                                                   |
|                Buffers: shared hit=420                                                                                                                                                        |
|                ->  Sort  (cost=2253.54..2255.02 rows=591 width=2126) (actual time=1.261..1.266 rows=100 loops=1)                                                                              |
|                      Sort Key: __local_1__.id                                                                                                                                                 |
|                      Sort Method: top-N heapsort  Memory: 39kB                                                                                                                                |
|                      Buffers: shared hit=420                                                                                                                                                  |
|                      ->  Bitmap Heap Scan on installed_base __local_1__  (cost=48.73..2230.96 rows=591 width=2126) (actual time=0.104..0.569 rows=585 loops=1)                                |
|                            Recheck Cond: ((access_team_ids @> '{100000015837579}'::character varying[]) OR (access_territory_ids && '{100000000510888,100000000574796}'::character varying[]))|
|                            Heap Blocks: exact=412                                                                                                                                             |
|                            Buffers: shared hit=420                                                                                                                                            |
|                            ->  BitmapOr  (cost=48.73..48.73 rows=591 width=0) (actual time=0.074..0.075 rows=0 loops=1)                                                                       |
|                                  Buffers: shared hit=8                                                                                                                                        |
|                                  ->  Bitmap Index Scan on installed_base_access_team_ids_idx  (cost=0.00..16.03 rows=537 width=0) (actual time=0.067..0.067 rows=585 loops=1)                 |
|                                        Index Cond: (access_team_ids @> '{100000015837579}'::character varying[])                                                                              |
|                                        Buffers: shared hit=3                                                                                                                                  |
|                                  ->  Bitmap Index Scan on installed_base_access_territory_ids_idx  (cost=0.00..32.40 rows=54 width=0) (actual time=0.006..0.007 rows=0 loops=1)               |
|                                        Index Cond: (access_territory_ids && '{100000000510888,100000000574796}'::character varying[])                                                         |
|                                        Buffers: shared hit=5                                                                                                                                  |
|  InitPlan 2 (returns $1)                                                                                                                                                                      |
|    ->  Aggregate  (cost=2232.43..2232.45 rows=1 width=32) (actual time=0.189..0.189 rows=1 loops=1)                                                                                           |
|          Buffers: shared hit=12                                                                                                                                                               |
|          ->  Bitmap Heap Scan on installed_base __local_1___1  (cost=48.73..2230.96 rows=591 width=0) (actual time=0.088..0.146 rows=585 loops=1)                                             |
|                Recheck Cond: ((access_team_ids @> '{100000015837579}'::character varying[]) OR (access_territory_ids && '{100000000510888,100000000574796}'::character varying[]))            |
|                Heap Blocks: exact=412                                                                                                                                                         |
|                Buffers: shared hit=12                                                                                                                                                         |
|                ->  BitmapOr  (cost=48.73..48.73 rows=591 width=0) (actual time=0.064..0.064 rows=0 loops=1)                                                                                   |
|                      Buffers: shared hit=8                                                                                                                                                    |
|                      ->  Bitmap Index Scan on installed_base_access_team_ids_idx  (cost=0.00..16.03 rows=537 width=0) (actual time=0.057..0.057 rows=585 loops=1)                             |
|                            Index Cond: (access_team_ids @> '{100000015837579}'::character varying[])                                                                                          |
|                            Buffers: shared hit=3                                                                                                                                              |
|                      ->  Bitmap Index Scan on installed_base_access_territory_ids_idx  (cost=0.00..32.40 rows=54 width=0) (actual time=0.006..0.006 rows=0 loops=1)                           |
|                            Index Cond: (access_territory_ids && '{100000000510888,100000000574796}'::character varying[])                                                                     |
|                            Buffers: shared hit=5                                                                                                                                              |
|Planning:                                                                                                                                                                                      |
|  Buffers: shared hit=4                                                                                                                                                                        |
|Planning Time: 0.343 ms                                                                                                                                                                        |
|Execution Time: 1.807 ms                                                                                                                                                                       |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
```

In conclusion, shouldn't it be that RLS functions are declared as IMMUTABLE? Or are there some serious implications here that I did not foresee?

