Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 12f7e22

Browse files
author
Marcin K
committed
Put tutorial specific info into a separate file
1 parent 86e4e49 commit 12f7e22

File tree

3 files changed

+107
-35
lines changed

3 files changed

+107
-35
lines changed

GETTING_STARTED.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Getting started
2+
Before you start, you should understand the concept of forward/up and reverse/down database migrations.
3+
4+
Configure a database for your application. Make sure that your database driver is supported [here](README.md#databases)
5+
6+
## Create migrations
7+
Create some migrations using migrate CLI. Here is an example:
8+
```
9+
migrate create -ext sql -dir db/migrations -seq create_users_table
10+
```
11+
Once you create your files, you should fill them.
12+
13+
**IMPORTANT:** In a project developed by more than one person there is a small probability of migrations incosistency - e.g. two developers can create conflicting migrations, and the developer that created his migration later gets it merged to the repository first.
14+
Keep an eye on such cases (and be even more careful when cherry picking).
15+
16+
Consider making your migrations idempotent - we can run the same sql code twice in a row with the same result. This makes our migrations more robust. On the other hand, it causes slightly less control over database schema - e.g. let's say you forgot to drop the table in down migration. You run down migration - the table is still there. When you run up migration again - `CREATE TABLE` would return an error, helping you find an issue in down migration, while `CREATE TABLE IF NOT EXISTS` would not. Use those conditions wisely.
17+
18+
In case you would like to run several commands/queries in one migration, you should wrap them in a transaction (if your database supports it).
19+
This way if one of commands fails, our database will remain unchanged.
20+
21+
## Run migrations
22+
Run your migrations through the CLI or your app and check if they applied expected changes.
23+
Just to give you an idea:
24+
```
25+
migrate -database YOUR_DATBASE_URL -path PATH_TO_YOUR_MIGRATIONS up
26+
```
27+
28+
Just add the code to your app and you're ready to go!
29+
30+
Before commiting your migrations you should run your migrations up, down, and then up again to see if migrations are working properly both ways.
31+
(e.g. if you created a table in a migration but reverse migration did not delete it, you will encounter an error when running the forward migration again)
32+
It's also worth checking your migrations in a separate, containerized environment. You can find some tools in the end of this document.
33+
34+
**IMPORTANT:** If you would like to run multiple instances of your app on different machines be sure to use a database that supports locking when running migrations. Otherwise you may encounter issues.
35+
36+
## Further reading:
37+
- [PostgreSQL tutorial](database/postgres/TUTORIAL.md)
38+
- [Best practices](MIGRATIONS.md)
39+
- [FAQ](FAQ.md)
40+
- Tools for testing your migrations in a container:
41+
- https://github.com/dhui/dktest
42+
- https://github.com/ory/dockertest

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,13 @@ func main() {
142142

143143
## Getting started
144144

145-
Go to [tutorial](TUTORIAL.md)
145+
Go to [getting started](GETTING_STARTED.md)
146+
147+
## Tutorials
148+
149+
- [PostgreSQL](database/postgres/TUTORIAL.md)
150+
151+
(more tutorials to come)
146152

147153
## Migration files
148154

TUTORIAL.md renamed to database/postgres/TUTORIAL.md

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# Getting started
2-
Before you start, you should understand the concept of forward/up and reverse/down database migrations.
1+
# PostgreSQL tutorial for beginners
2+
3+
## Create/configure database
34

4-
Configure a database for your application. Make sure that your database driver is supported [here](README.md#databases)
55
For the purpose of this tutorial let's create PostgreSQL database called `example`.
66
Our user here is `postgres`, password `password`, and host is `localhost`.
77
```
@@ -14,6 +14,7 @@ export POSTGRESQL_URL=postgres://postgres:password@localhost:5432/example?sslmod
1414
`sslmode=disable` means that the connection with our database will not be encrypted. Enabling it is left as an exercise.
1515

1616
You can find further description of database URLs [here](README.md#database-urls).
17+
1718
## Create migrations
1819
Let's create table called `users`:
1920
```
@@ -22,10 +23,8 @@ migrate create -ext sql -dir db/migrations -seq create_users_table
2223
If there were no errors, we should have two files available under `db/migrations` folder:
2324
- 000001_create_users_table.down.sql
2425
- 000001_create_users_table.up.sql
25-
Note the `sql` extension that we provided.
2626

27-
**IMPORTANT:** In a project developed by more than one person there is a small probability of migrations incosistency - e.g. two developers can create conflicting migrations, and the developer that created his migration later gets it merged to the repository first.
28-
Keep an eye on such cases (and be even more careful when cherry picking).
27+
Note the `sql` extension that we provided.
2928

3029
In the `.up.sql` file let's create the table:
3130
```
@@ -40,10 +39,46 @@ And in the `.down.sql` let's delete it:
4039
```
4140
DROP TABLE IF EXISTS users;
4241
```
43-
By adding `IF EXISTS/IF NOT EXISTS` we are making migrations idempotent - we can run the same sql code twice in a row with the same result. This makes our migrations more robust. On the other hand, it causes slightly less control over database schema - e.g. let's say you forgot to drop the table in down migration. You run down migration - the table is still there. When you run up migration again - `CREATE TABLE` would return an error, helping you find an issue in down migration, while `CREATE TABLE IF NOT EXISTS` would not. Use those conditions wisely.
42+
By adding `IF EXISTS/IF NOT EXISTS` we are making migrations idempotent - you can read more about idempotency in [getting started](GETTING_STARTED.md#create-migrations)
4443

45-
In case you would like to run several commands/queries in one migration, you should wrap them in a transaction (if your database supports it).
46-
In our postgres example it would be (migration up):
44+
## Run migrations
45+
```
46+
migrate -database ${POSTGRESQL_URL} -path db/migrations up
47+
```
48+
Let's check if the table was created properly by running `psql example -c "\d users"`.
49+
The output you are supposed to see:
50+
```
51+
Table "public.users"
52+
Column | Type | Modifiers
53+
----------+------------------------+---------------------------------------------------------
54+
user_id | integer | not null default nextval('users_user_id_seq'::regclass)
55+
username | character varying(50) | not null
56+
password | character varying(50) | not null
57+
email | character varying(300) | not null
58+
Indexes:
59+
"users_pkey" PRIMARY KEY, btree (user_id)
60+
"users_email_key" UNIQUE CONSTRAINT, btree (email)
61+
"users_username_key" UNIQUE CONSTRAINT, btree (username)
62+
```
63+
Great! Now let's check if running reverse migration also works:
64+
```
65+
migrate -database ${POSTGRESQL_URL} -path db/migrations down
66+
```
67+
Make sure to check if your database changed as expected in this case as well.
68+
69+
## Database transactions
70+
71+
To show database transactions usage, let's create another set of migrations by running:
72+
```
73+
migrate create -ext sql -dir db/migrations -seq add_mood_to_users
74+
```
75+
Again, it should create for us two migrations files:
76+
- 000002_add_mood_to_users.down.sql
77+
- 000002_add_mood_to_users.up.sql
78+
79+
In Postgres, when we want our queries to be done in a transaction, we need to wrap it with `BEGIN` and `COMMIT` commands.
80+
In our example, we are going to add a column to our database that can only accept enumerable values or NULL.
81+
Migration up:
4782
```
4883
BEGIN;
4984
@@ -56,14 +91,22 @@ ALTER TABLE users ADD COLUMN mood enum_mood;
5691
5792
COMMIT;
5893
```
59-
This way if one of commands fails, our database will remain unchanged.
94+
Migration down:
95+
```
96+
BEGIN;
6097
61-
## Run migrations
98+
ALTER TABLE users DROP COLUMN mood;
99+
DROP TYPE enum_mood;
100+
101+
COMMIT;
102+
```
103+
104+
Now we can run our new migration and check the database:
62105
```
63106
migrate -database ${POSTGRESQL_URL} -path db/migrations up
107+
psql example -c "\d users"
64108
```
65-
Let's check if the table was created properly by running `psql example -c "\d users"`.
66-
The output you are supposed to see:
109+
Expected output:
67110
```
68111
Table "public.users"
69112
Column | Type | Modifiers
@@ -72,20 +115,12 @@ The output you are supposed to see:
72115
username | character varying(50) | not null
73116
password | character varying(50) | not null
74117
email | character varying(300) | not null
118+
mood | enum_mood |
75119
Indexes:
76120
"users_pkey" PRIMARY KEY, btree (user_id)
77121
"users_email_key" UNIQUE CONSTRAINT, btree (email)
78122
"users_username_key" UNIQUE CONSTRAINT, btree (username)
79123
```
80-
Great! Now let's check if running reverse migration also works:
81-
```
82-
migrate -database ${POSTGRESQL_URL} -path db/migrations down
83-
```
84-
Make sure to check if your database changed as expected in this case as well.
85-
86-
**IMPORTANT:** Before commiting your migrations you should run your migrations up, down, and then up again to see if migrations are working properly both ways.
87-
(e.g. if you created a table in a migration but reverse migration did not delete it, you will encounter an error when running the forward migration again)
88-
It's also worth checking your migrations in a separate, containerized environment. You can find some tools in the end of this tutorial.
89124

90125
## Optional: Run migrations within your Go app
91126
Here is a very simple app running migrations for the above configuration:
@@ -110,15 +145,4 @@ func main() {
110145
}
111146
}
112147
```
113-
You can find details [here](README.md#use-in-your-go-project)
114-
115-
Just add the code to your app and you're ready to go!
116-
117-
**IMPORTANT:** If you would like to run multiple instances of your app on different machines be sure to use a database that supports locking when running migrations. Otherwise you may encounter issues.
118-
119-
## Further reading:
120-
- [Best practices](MIGRATIONS.md)
121-
- [FAQ](FAQ.md)
122-
- Tools for testing your migrations in a container:
123-
- https://github.com/dhui/dktest
124-
- https://github.com/ory/dockertest
148+
You can find details [here](README.md#use-in-your-go-project)

0 commit comments

Comments
 (0)