Skip to content

Commit 6083399

Browse files
committed
Round out the example.
1 parent 3d13ec8 commit 6083399

File tree

1 file changed

+100
-49
lines changed

1 file changed

+100
-49
lines changed

@app/db/migrations/current.sql

Lines changed: 100 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,117 @@
1-
-- Enter migration here
2-
31
/*
4-
example of a table that could be created after setup complete
5-
6-
- uncomment the statements below
7-
- save the file and graphile-migrate will update the schema into database automagically
8-
- any "drop" statements should be at the top (in reverse order)
9-
reverse order as we could have references
10-
from the second created table to the first created table
11-
12-
here is an pseudo example:
13-
DROP C;
14-
DROP B;
15-
DROP A;
16-
CREATE A;
17-
CREATE B;
18-
CREATE C;
19-
20-
if references exists from B -> A
21-
we have to DROP B before DROP A we have references that point to A from B
22-
23-
In the example below post and feed need to be
24-
deleted in reverse order due to feed -> post
2+
3+
This project is using Graphile Migrate to manage migrations; please be aware
4+
the Graphile Migrate works in a different way to most other migration
5+
frameworks:
6+
7+
- it's "up-only" (there are no down migrations)
8+
- the current migration (this file) is executed every time it is saved
9+
- it requires *significant discipline* as changes made in this file will
10+
persist locally even after they are deleted from the file
11+
12+
Because during development the current migration is expected to run multiple
13+
times, the migration has to deal with both the situation where it _has_ been
14+
executed before, and where it _hasn't_ been executed before.
15+
16+
You can (and should) read more on Graphile Migrate in its repository:
17+
18+
https://github.com/graphile/migrate
19+
20+
You can absolutely switch out Graphile Migrate for a more traditional
21+
migration framework if you prefer.
22+
2523
*/
2624

27-
-- UNCOMMENT FROM HERE --
25+
--------------------------------------------------------------------------------
26+
27+
/*
28+
29+
What follows is an example of a table that could be created after setup is
30+
complete. To use it uncomment the statements below and save the file -
31+
graphile-migrate will update the schema into database automagically and
32+
PostGraphile should automatically detect these changes and reflect them
33+
through GraphQL which you should see immediately in GraphiQL.
2834
29-
-- drop table if exists app_public.feed;
30-
-- drop table if exists app_public.post;
35+
Note any "DROP" statements should be at the top in reverse order of creation.
36+
The reason for reverse order is because we could have references from the
37+
second created resource to the first created resource. So your migration
38+
might look something like this pseudo-example:
3139
32-
-- drop type if exists app_public.post_topic;
40+
DROP C;
41+
DROP B;
42+
DROP A;
43+
CREATE A;
44+
CREATE B REFERENCING A;
45+
CREATE C REFERENCING A;
3346
34-
-- create type app_public.post_topic as enum (
35-
-- 'discussion',
36-
-- 'inspiration',
37-
-- 'help',
38-
-- 'showcase'
47+
We have to DROP B before DROP A because we have references that point to A
48+
from B.
49+
50+
You can uncomment the following lines one block a time and safe the file to view
51+
the changes.
52+
53+
**IMPORTANT**: when you uncomment the `CREATE TABLE` statements this will not
54+
result in the table being added to the GraphQL API, this is because we are
55+
using `ignoreRBAC: false` so we do not expose tables until you `GRANT` the
56+
relevant operations on them. The tables will appear when you uncomment the
57+
`GRANT` lines.
58+
59+
*/
60+
61+
-- drop table if exists app_public.user_feed_posts;
62+
-- drop table if exists app_public.posts;
63+
-- drop table if exists app_public.topics;
64+
65+
-- create table app_public.topics (
66+
-- title text not null primary key
3967
-- );
68+
-- alter table app_public.topics enable row level security;
4069

41-
-- create table app_public.post (
70+
-- create table app_public.posts (
4271
-- id serial primary key,
43-
-- author_id integer not null references app_public.users(id),
72+
-- author_id int default app_public.current_user_id() references app_public.users(id) on delete set null,
4473
-- headline text not null check (char_length(headline) < 280),
4574
-- body text,
46-
-- topic app_public.post_topic,
47-
-- created_at timestamp default now()
75+
-- topic text not null references app_public.topics on delete restrict,
76+
-- created_at timestamptz not null default now(),
77+
-- updated_at timestamptz not null default now()
4878
-- );
79+
-- alter table app_public.posts enable row level security;
4980

50-
-- comment on table app_public.post is 'a forum post written by a user.';
51-
-- comment on column app_public.post.id is 'the primary key for the post.';
52-
-- comment on column app_public.post.headline is 'the title written by the user.';
53-
-- comment on column app_public.post.author_id is 'the id of the author user.';
54-
-- comment on column app_public.post.topic is 'the topic this has been posted in.';
55-
-- comment on column app_public.post.body is 'the main body text of our post.';
56-
-- comment on column app_public.post.created_at is 'the time this post was created.';
81+
-- create trigger _100_timestamps before insert or update on app_public.posts for each row execute procedure app_private.tg__timestamps();
5782

58-
-- create table app_public.feed (
83+
-- grant
84+
-- select,
85+
-- insert (headline, body, topic),
86+
-- update (headline, body, topic),
87+
-- delete
88+
-- on app_public.posts to :DATABASE_VISITOR;
89+
90+
-- create policy select_all on app_public.posts for select using (true);
91+
-- create policy manage_own on app_public.posts for all using (author_id = app_public.current_user_id());
92+
-- create policy manage_as_admin on app_public.posts for all using (exists (select 1 from app_public.users where is_admin is true and id = app_public.current_user_id()));
93+
94+
-- comment on table app_public.posts is 'A forum post written by a `User`.';
95+
-- comment on column app_public.posts.id is 'The primary key for the `Post`.';
96+
-- comment on column app_public.posts.headline is 'The title written by the `User`.';
97+
-- comment on column app_public.posts.author_id is 'The id of the author `User`.';
98+
-- comment on column app_public.posts.topic is 'The `Topic` this has been posted in.';
99+
-- comment on column app_public.posts.body is 'The main body text of our `Post`.';
100+
-- comment on column app_public.posts.created_at is 'The time this `Post` was created.';
101+
-- comment on column app_public.posts.updated_at is 'The time this `Post` was last modified (or created).';
102+
103+
-- create table app_public.user_feed_posts (
59104
-- id serial primary key,
60-
-- posts integer not null references app_public.post(id),
61-
-- created_at timestamp default now()
105+
-- user_id int not null references app_public.users on delete cascade,
106+
-- post_id int not null references app_public.posts on delete cascade,
107+
-- created_at timestamptz not null default now()
62108
-- );
109+
-- alter table app_public.user_feed_posts enable row level security;
110+
111+
-- grant select on app_public.user_feed_posts to :DATABASE_VISITOR;
112+
113+
-- create policy select_own on app_public.user_feed_posts for select using (user_id = app_public.current_user_id());
63114

64-
-- comment on table app_public.feed is 'the feed of the posts';
65-
-- comment on column app_public.feed.id is 'the primary key for the feed.';
66-
-- comment on column app_public.feed.created_at is 'the time this feed was created.';
115+
-- comment on table app_public.user_feed_posts is 'A feed of `Post`s relevant to a particular `User`.';
116+
-- comment on column app_public.user_feed_posts.id is 'An identifier for this entry in the feed.';
117+
-- comment on column app_public.user_feed_posts.created_at is 'The time this feed item was added.';

0 commit comments

Comments
 (0)