SupabaseにGraphQLのエクステンションができたと聞いて🔥

## はじめに
[アドベントカレンダー](https://qiita.com/advent-calendar/2021/myjlab)24日目です。クリスマスイブ！私はアドベントカレンダーの投稿が遅れているにも関わらず、朝の8時から呪術◯戦の映画を見てきました。
昨日の[@nyaxの記事](https://qiita.com/nyax/items/98dbb955f517b447d294)は、「自然言語処理の国際会議・論文探しのいろは
」という内容でした。私は就職活動を言い訳に、研究を全くしていないので耳が痛いですが、とても参考になりました！

## これは
12月3日にSupabaseのブログに「[pg_graphql: A GraphQL extension for PostgreSQL](https://supabase.com/blog/2021/12/03/pg-graphql)」という記事が投稿されました。
その記事によると、pg_graphqlはスキーマ生成、クエリパース、リゾルバのすべてをデータベースサーバに収めて、外部サービスを必要としないそうです。
しかも、pg_graphqlは既存のPostgreSQLスキーマを検査し、リゾルバにGraphQLスキーマを反映させてくれるらしいです。Hasuraみたいなイメージだと思います。
本記事では、プレアルファ版としてリリースされたpg_graphqlを試してみようと思います！

## やってみる
Supabaseのエクステンションにはまだ追加されていなかったので、[公式のQuickstart](https://supabase.github.io/pg_graphql/quickstart/)をポチポチして、dbサーバーをdockerで立ててやっていきます。せっかくなので、テーブルを作成する部分のコードを少しだけ書き換えてみます。
productテーブルは1つのtagを持っていて、tagテーブルは複数のproductを持っているというような1対Nの関係です。前回の記事ではN対Nの関係にしましたが、今回は簡単のため1対Nにしました。

```dockerfiles/db/setup.sql
---- この辺りは変更なし
create role anon;
create extension if not exists "uuid-ossp";
create extension if not exists pg_graphql cascade;


grant usage on schema public to postgres, anon;
alter default privileges in schema public grant all on tables to postgres, anon;
alter default privileges in schema public grant all on functions to postgres, anon;
alter default privileges in schema public grant all on sequences to postgres, anon;

grant usage on schema graphql to postgres, anon;
grant all on function graphql.resolve to postgres, anon;

alter default privileges in schema graphql grant all on tables to postgres, anon;
alter default privileges in schema graphql grant all on functions to postgres, anon;
alter default privileges in schema graphql grant all on sequences to postgres, anon;


-- GraphQL Entrypoint
create function graphql("operationName" text default null, query text default null, variables jsonb default null)
    returns jsonb
    language sql
as $$
    select graphql.resolve(query, variables);
$$;

---- ここまで変更なし

create table tag(
    id serial primary key,
    name varchar(255) not null,
    created_at timestamp not null,
    updated_at timestamp not null
);

create table product(
    id serial primary key,
    name varchar(255) not null,
    created_at timestamp not null,
    updated_at timestamp not null,
    tag_id integer not null references tag(id)
);

-- insert data
insert into tag(name, created_at, updated_at)
values
    ('果物', now(), now()),
    ('魚', now(), now()),
    ('肉', now(), now());

insert into product(name, tag_id, created_at, updated_at)
values
    ('りんご', 1, now(), now()),
    ('みかん', 1, now(), now()),
    ('さば', 2, now(), now()),
    ('うに', 2, now(), now()),
    ('馬刺し', 3, now(), now());

```

上記のようにして```docker compose up```を実行し、```http://localhost:4000/```を開くと、GraphiQLのGUIを開くことができ、スキーマ、クエリを自動生成してくれていることがわかります。

![query.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533290/1d1e547d-a99a-34b2-76ca-1707ec6ae7cc.png)


以下のようなクエリを投げると、

```
{
  allTags {
    totalCount
    edges {
      node {
        id
        name
        products {
          edges {
            node {
              id
              name
	    }
	  }
	}
      }
    }
  }
}
```

こんな感じで返ってきます。

```json
{
  "data": {
    "allTags": {
      "edges": [
        {
          "node": {
            "id": 1,
            "name": "果物",
            "products": {
              "edges": [
                {
                  "node": {
                    "id": 1,
                    "name": "りんご"
                  }
                },
                {
                  "node": {
                    "id": 2,
                    "name": "みかん"
                  }
                }
              ]
            }
          }
        },
        {
          "node": {
            "id": 2,
            "name": "魚",
            "products": {
              "edges": [
                {
                  "node": {
                    "id": 3,
                    "name": "さば"
                  }
                },
                {
                  "node": {
                    "id": 4,
                    "name": "うに"
                  }
                }
              ]
            }
          }
        },
        {
          "node": {
            "id": 3,
            "name": "肉",
            "products": {
              "edges": [
                {
                  "node": {
                    "id": 5,
                    "name": "馬刺し"
                  }
                }
              ]
            }
          }
        },
      ],
      "totalCount": 4
    }
  },
  "errors": []
}
```

ちなみに、productを一つ取得したい場合、自動生成されているドキュメントには、```nodeId```を指定するように書かれていたり、ネストしているtagを取得するときにも```nodeId```を指定するように書かれていて、実際にエディターに以下のクエリを入力すると怒られますが、レスポンスは想定したものが返ってきます。🤔

```json
{
  product(id: 1) {
    id
    name
		tag {
			id
			name
		}
	}
}
```

↓怒られ<br>
![ang.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533290/5f2f9349-e17e-8ba8-ac78-53fa40f4a930.png)


↓レスポンス

```json
{
  "data": {
    "product": {
      "id": 1,
      "tag": {
        "id": 1,
        "name": "果物"
      },
      "name": "りんご"
    }
  },
  "errors": []
}
```

## 所感
- Hasuraと比べたメリットは現時点ではあまり感じられない？
- MutationやSubscriptionなど、ドキュメントに書かれていないことについても調べていきたい
- まだプレアルファ版なので、今後に期待！
- リリースのたびにテンションが上がるOSSなので、自分も貢献したい！

以上、雑記事かつ遅れてすみませんでした〜🙏