Skip to content
This repository was archived by the owner on Jun 26, 2024. It is now read-only.

Commit 6335db9

Browse files
committed
initial commit
0 parents  commit 6335db9

File tree

4 files changed

+243
-0
lines changed

4 files changed

+243
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
certs
2+
private
3+
cockroach-data

Makefile

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
clean:
2+
rm -rf cockroach-data certs private
3+
4+
secure-node: clean
5+
mkdir -p certs private && \
6+
cockroach cert create-ca --certs-dir=certs --ca-key=private/ca.key && \
7+
cockroach cert create-node localhost --certs-dir=certs --ca-key=private/ca.key && \
8+
cockroach cert create-client root --certs-dir=certs --ca-key=private/ca.key && \
9+
cockroach cert create-client maxroach --certs-dir=certs --ca-key=private/ca.key && \
10+
cockroach start --certs-dir=certs
11+
12+
insecure-node: clean
13+
cockroach start --insecure
14+
15+
bank-database-insecure:
16+
cockroach sql --insecure -e 'CREATE USER IF NOT EXISTS maxroach; CREATE DATABASE IF NOT EXISTS bank; GRANT ALL ON DATABASE bank TO maxroach;'
17+
cockroach sql --insecure --database bank -e 'CREATE TABLE IF NOT EXISTS accounts (ID SERIAL PRIMARY KEY, balance INT);'
18+
19+
bank-database-secure:
20+
cockroach sql --certs-dir=certs -e 'CREATE USER IF NOT EXISTS maxroach; CREATE DATABASE IF NOT EXISTS bank; GRANT ALL ON DATABASE bank TO maxroach;'
21+
cockroach sql --certs-dir=certs --database bank -e 'CREATE TABLE IF NOT EXISTS accounts (ID SERIAL PRIMARY KEY, balance INT);'

README.md

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# upper/db + CockroachDB example
2+
3+
## Run the insecure node example
4+
5+
Create and run an insecure node:
6+
7+
```
8+
make insecure-node
9+
```
10+
11+
Open a second terminal and create the bank database:
12+
13+
```
14+
make bank-database-insecure
15+
```
16+
17+
Run the `main.go` example:
18+
19+
```
20+
go run main.go
21+
```
22+
23+
## Run the secure node example
24+
25+
Create and run a secure node:
26+
27+
```
28+
make secure-node
29+
```
30+
31+
Open a second terminal and create the bank database:
32+
33+
```
34+
make bank-database-secure
35+
```
36+
37+
Edit the `main.go` file and add options for secure connection:
38+
39+
```
40+
var settings = cockroachdb.ConnectionURL{
41+
Host: "localhost",
42+
Database: "bank",
43+
User: "maxroach",
44+
Options: map[string]string{
45+
// Insecure node.
46+
// "sslmode": "disable",
47+
// Secure node.
48+
"sslrootcert": "certs/ca.crt",
49+
"sslkey": "certs/client.maxroach.key",
50+
"sslcert": "certs/client.maxroach.crt",
51+
},
52+
}
53+
```
54+
55+
Run the `main.go` example:
56+
57+
```
58+
go run main.go
59+
```

main.go

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
7+
"github.com/upper/db/v4"
8+
"github.com/upper/db/v4/adapter/cockroachdb"
9+
)
10+
11+
// The settings variable stores connection details.
12+
var settings = cockroachdb.ConnectionURL{
13+
Host: "localhost",
14+
Database: "bank",
15+
User: "maxroach",
16+
Options: map[string]string{
17+
// Insecure node.
18+
"sslmode": "disable",
19+
// Secure node.
20+
// "sslrootcert": "certs/ca.crt",
21+
// "sslkey": "certs/client.maxroach.key",
22+
// "sslcert": "certs/client.maxroach.crt",
23+
},
24+
}
25+
26+
// Accounts is a handy way to represent a collection.
27+
func Accounts(sess db.Session) db.Store {
28+
return sess.Collection("accounts")
29+
}
30+
31+
// Account is used to represent a single record in the "accounts" table.
32+
type Account struct {
33+
ID uint64 `db:"id,omitempty"`
34+
Balance int64 `db:"balance"`
35+
}
36+
37+
// Collection is required in order to create a relation between the Account
38+
// struct and the "accounts" table.
39+
func (a *Account) Store(sess db.Session) db.Store {
40+
return Accounts(sess)
41+
}
42+
43+
// crdbForceRetry can be used to simulate a transaction error and
44+
// demonstrate upper/db's ability to retry the transaction automatically.
45+
//
46+
// By default, upper/db will retry the transaction five times, if you want
47+
// to modify this number use: sess.SetMaxTransactionRetries(n).
48+
//
49+
// This is only used for demonstration purposes.
50+
func crdbForceRetry(sess db.Session) error {
51+
var err error
52+
53+
_, err = sess.SQL().Exec(`SELECT NOW()`)
54+
if err != nil {
55+
return err
56+
}
57+
58+
_, err = sess.SQL().Exec(`SELECT crdb_internal.force_retry('1ms'::INTERVAL)`)
59+
if err != nil {
60+
return err
61+
}
62+
63+
return nil
64+
}
65+
66+
func main() {
67+
// Connect to the local CockroachDB node.
68+
sess, err := cockroachdb.Open(settings)
69+
if err != nil {
70+
log.Fatal("cockroachdb.Open: ", err)
71+
}
72+
defer sess.Close()
73+
74+
// Adjust this number to fit your specific needs (set to 5, by default)
75+
// sess.SetMaxTransactionRetries(10)
76+
77+
// Delete all the previous items in the "accounts" table.
78+
err = Accounts(sess).Truncate()
79+
if err != nil {
80+
log.Fatal("Truncate: ", err)
81+
}
82+
83+
// Create a new account with a balance of 1000.
84+
account1 := Account{Balance: 1000}
85+
err = Accounts(sess).InsertReturning(&account1)
86+
if err != nil {
87+
log.Fatal("sess.Save: ", err)
88+
}
89+
90+
// Create a new account with a balance of 250.
91+
account2 := Account{Balance: 250}
92+
err = Accounts(sess).InsertReturning(&account2)
93+
if err != nil {
94+
log.Fatal("sess.Save: ", err)
95+
}
96+
97+
// Printing records
98+
printRecords(sess)
99+
100+
// Change the balance of the first account.
101+
account1.Balance = 500
102+
err = sess.Save(&account1)
103+
if err != nil {
104+
log.Fatal("sess.Save: ", err)
105+
}
106+
107+
// Change the balance of the second account.
108+
account2.Balance = 999
109+
err = sess.Save(&account2)
110+
if err != nil {
111+
log.Fatal("sess.Save: ", err)
112+
}
113+
114+
// Printing records
115+
printRecords(sess)
116+
117+
// Delete the first record.
118+
err = sess.Delete(&account1)
119+
if err != nil {
120+
log.Fatal("Delete: ", err)
121+
}
122+
123+
// Add a couple of new records within a transaction.
124+
err = sess.Tx(func(tx db.Session) error {
125+
var err error
126+
127+
// Increases the possibility of transaction failure
128+
_ = crdbForceRetry(tx)
129+
130+
err = tx.Save(&Account{Balance: 887})
131+
if err != nil {
132+
return err
133+
}
134+
135+
err = tx.Save(&Account{Balance: 342})
136+
if err != nil {
137+
return err
138+
}
139+
140+
return nil
141+
})
142+
if err != nil {
143+
log.Fatal("Could not commit transaction: ", err)
144+
}
145+
146+
// Printing records
147+
printRecords(sess)
148+
}
149+
150+
func printRecords(sess db.Session) {
151+
accounts := []Account{}
152+
err := Accounts(sess).Find().All(&accounts)
153+
if err != nil {
154+
log.Fatal("Find: ", err)
155+
}
156+
log.Printf("Balances:")
157+
for i := range accounts {
158+
fmt.Printf("\taccounts[%d]: %d\n", accounts[i].ID, accounts[i].Balance)
159+
}
160+
}

0 commit comments

Comments
 (0)