github.com/scraniel/migrate@v0.0.0-20230320185700-339088f36cee/database/cockroachdb/TUTORIAL.md (about) 1 # CockroachDB tutorial for beginners (insecure cluster) 2 3 ## Create/configure database 4 5 First, let's start a local cluster - follow step 1. and 2. from [the docs](https://www.cockroachlabs.com/docs/stable/start-a-local-cluster.html#step-1-start-the-first-node). 6 7 Once you have it, create a database. Here I am going to create a database called `example`. 8 Our user here is `cockroach`. We are not going to use a password, since it's not supported for insecure cluster. 9 ``` 10 cockroach sql --insecure --host=localhost:26257 11 ``` 12 ``` 13 CREATE DATABASE example; 14 CREATE USER IF NOT EXISTS cockroach; 15 GRANT ALL ON DATABASE example TO cockroach; 16 ``` 17 18 When using Migrate CLI we need to pass to database URL. Let's export it to a variable for convienience: 19 ``` 20 export COCKROACHDB_URL='cockroachdb://cockroach:@localhost:26257/example?sslmode=disable' 21 ``` 22 `sslmode=disable` means that the connection with our database will not be encrypted. This is needed to connect to an insecure node. 23 24 **NOTE:** Do not use COCKROACH_URL as a variable name here, it's already in use for discrete parameters and you may run into connection problems. For more info check out [docs](https://www.cockroachlabs.com/docs/stable/connection-parameters.html#connect-using-discrete-parameters). 25 26 You can find further description of database URLs [here](README.md#database-urls). 27 28 ## Create migrations 29 Let's create a table called `users`: 30 ``` 31 migrate create -ext sql -dir db/migrations -seq create_users_table 32 ``` 33 If there were no errors, we should have two files available under `db/migrations` folder: 34 - 000001_create_users_table.down.sql 35 - 000001_create_users_table.up.sql 36 37 Note the `sql` extension that we provided. 38 39 In the `.up.sql` file let's create the table: 40 ``` 41 CREATE TABLE IF NOT EXISTS example.users 42 ( 43 user_id INT PRIMARY KEY, 44 username VARCHAR (50) UNIQUE NOT NULL, 45 password VARCHAR (50) NOT NULL, 46 email VARCHAR (300) UNIQUE NOT NULL 47 ); 48 ``` 49 And in the `.down.sql` let's delete it: 50 ``` 51 DROP TABLE IF EXISTS example.users; 52 ``` 53 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) 54 55 ## Run migrations 56 ``` 57 migrate -database ${COCKROACHDB_URL} -path db/migrations up 58 ``` 59 Let's check if the table was created properly by running `cockroach sql --insecure --host=localhost:26257 -e "show columns from example.users;"`. 60 The output you are supposed to see: 61 ``` 62 column_name | data_type | is_nullable | column_default | generation_expression | indices | is_hidden 63 +-------------+--------------+-------------+----------------+-----------------------+----------------------------------------------+-----------+ 64 user_id | INT8 | false | NULL | | {primary,users_username_key,users_email_key} | false 65 username | VARCHAR(50) | false | NULL | | {users_username_key} | false 66 password | VARCHAR(50) | false | NULL | | {} | false 67 email | VARCHAR(300) | false | NULL | | {users_email_key} | false 68 (4 rows) 69 ``` 70 Now let's check if running reverse migration also works: 71 ``` 72 migrate -database ${COCKROACHDB_URL} -path db/migrations down 73 ``` 74 Make sure to check if your database changed as expected in this case as well. 75 76 ## Database transactions 77 78 To show database transactions usage, let's create another set of migrations by running: 79 ``` 80 migrate create -ext sql -dir db/migrations -seq add_mood_to_users 81 ``` 82 Again, it should create for us two migrations files: 83 - 000002_add_mood_to_users.down.sql 84 - 000002_add_mood_to_users.up.sql 85 86 In Cockroach, when we want our queries to be done in a transaction, we need to wrap it with `BEGIN` and `COMMIT` commands, similar to PostgreSQL. 87 In our example, we are going to add a column to our database that can only accept enumerable values or NULL. 88 Migration up: 89 ``` 90 BEGIN; 91 92 ALTER TABLE example.users ADD COLUMN mood STRING; 93 ALTER TABLE example.users ADD CONSTRAINT check_mood CHECK (mood IN ('happy', 'sad', 'neutral')); 94 95 COMMIT; 96 ``` 97 Migration down: 98 ``` 99 ALTER TABLE example.users DROP COLUMN mood; 100 ``` 101 102 Now we can run our new migration and check the database: 103 ``` 104 migrate -database ${COCKROACHDB_URL} -path db/migrations up 105 cockroach sql --insecure --host=localhost:26257 -e "show columns from example.users;" 106 ``` 107 Expected output: 108 ``` 109 column_name | data_type | is_nullable | column_default | generation_expression | indices | is_hidden 110 +-------------+--------------+-------------+----------------+-----------------------+----------------------------------------------+-----------+ 111 user_id | INT8 | false | NULL | | {primary,users_username_key,users_email_key} | false 112 username | VARCHAR(50) | false | NULL | | {users_username_key} | false 113 password | VARCHAR(50) | false | NULL | | {} | false 114 email | VARCHAR(300) | false | NULL | | {users_email_key} | false 115 mood | STRING | true | NULL | | {} | false 116 (5 rows) 117 ``` 118 119 ## Optional: Run migrations within your Go app 120 Here is a very simple app running migrations for the above configuration: 121 ``` 122 import ( 123 "log" 124 125 "github.com/golang-migrate/migrate/v4" 126 _ "github.com/golang-migrate/migrate/v4/database/cockroachdb" 127 _ "github.com/golang-migrate/migrate/v4/source/file" 128 ) 129 130 func main() { 131 m, err := migrate.New( 132 "file://db/migrations", 133 "cockroachdb://cockroach:@localhost:26257/example?sslmode=disable") 134 if err != nil { 135 log.Fatal(err) 136 } 137 if err := m.Up(); err != nil { 138 log.Fatal(err) 139 } 140 } 141 ``` 142 You can find details [here](README.md#use-in-your-go-project)