Skip to content

Commit 683926c

Browse files
authored
Added docs and rewrited examples for ydb (#17)
* Added docs and rewrited examples for ydb
1 parent be13a37 commit 683926c

35 files changed

+1870
-124
lines changed
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# Getting started with YDB
2+
3+
This tutorial assumes that the latest version of sqlc is
4+
[installed](../overview/install.md) and ready to use.
5+
6+
We'll generate Go code here, but other
7+
[language plugins](../reference/language-support.rst) are available. You'll
8+
naturally need the Go toolchain if you want to build and run a program with the
9+
code sqlc generates, but sqlc itself has no dependencies.
10+
11+
At the end, you'll push your SQL queries to [sqlc
12+
Cloud](https://dashboard.sqlc.dev/) for further insights and analysis.
13+
14+
## Setting up
15+
16+
Create a new directory called `sqlc-tutorial` and open it up.
17+
18+
Initialize a new Go module named `tutorial.sqlc.dev/app`:
19+
20+
```shell
21+
go mod init tutorial.sqlc.dev/app
22+
```
23+
24+
sqlc looks for either a `sqlc.(yaml|yml)` or `sqlc.json` file in the current
25+
directory. In our new directory, create a file named `sqlc.yaml` with the
26+
following contents:
27+
28+
```yaml
29+
version: "2"
30+
sql:
31+
- engine: "ydb"
32+
queries: "query.sql"
33+
schema: "schema.sql"
34+
gen:
35+
go:
36+
package: "tutorial"
37+
out: "tutorial"
38+
```
39+
40+
## Schema and queries
41+
42+
sqlc needs to know your database schema and queries in order to generate code.
43+
In the same directory, create a file named `schema.sql` with the following
44+
content:
45+
46+
```sql
47+
CREATE TABLE authors (
48+
id Serial,
49+
name Text NOT NULL,
50+
bio Text,
51+
PRIMARY KEY (id)
52+
);
53+
```
54+
55+
Next, create a `query.sql` file with the following five queries:
56+
57+
```sql
58+
-- name: GetAuthor :one
59+
SELECT * FROM authors
60+
WHERE id = $id LIMIT 1;
61+
62+
-- name: ListAuthors :many
63+
SELECT * FROM authors
64+
ORDER BY name;
65+
66+
-- name: CreateOrUpdateAuthor :one
67+
UPSERT INTO authors (name, bio)
68+
VALUES (
69+
$name, $bio
70+
)
71+
RETURNING *;
72+
73+
-- name: DeleteAuthor :exec
74+
DELETE FROM authors WHERE id = $id;
75+
76+
-- name: DropTable :exec
77+
DROP TABLE IF EXISTS authors;
78+
```
79+
80+
Note that YDB uses named parameters (`$id`, `$name`, `$bio`) rather than
81+
positional parameters.
82+
83+
## Generating code
84+
85+
You are now ready to generate code. You shouldn't see any output when you run
86+
the `generate` subcommand, unless something goes wrong:
87+
88+
```shell
89+
sqlc generate
90+
```
91+
92+
You should now have a `tutorial` subdirectory with three files containing Go
93+
source code. These files comprise a Go package named `tutorial`:
94+
95+
```
96+
├── go.mod
97+
├── query.sql
98+
├── schema.sql
99+
├── sqlc.yaml
100+
└── tutorial
101+
├── db.go
102+
├── models.go
103+
└── query.sql.go
104+
```
105+
106+
## Using generated code
107+
108+
You can use your newly-generated `tutorial` package from any Go program.
109+
Create a file named `tutorial.go` and add the following contents:
110+
111+
```go
112+
package main
113+
114+
import (
115+
"context"
116+
"log"
117+
118+
"github.com/ydb-platform/ydb-go-sdk/v3"
119+
"github.com/ydb-platform/ydb-go-sdk/v3/query"
120+
121+
"tutorial.sqlc.dev/app/tutorial"
122+
)
123+
124+
func ptr(s string) *string {
125+
return &s
126+
}
127+
128+
func run() error {
129+
ctx := context.Background()
130+
131+
// Create YDB connection
132+
// Replace with your actual YDB endpoint
133+
db, err := ydb.Open(ctx, "grpcs://localhost:2136/local")
134+
if err != nil {
135+
return err
136+
}
137+
defer db.Close(ctx)
138+
139+
queries := tutorial.New(db.Query())
140+
141+
// list all authors
142+
authors, err := queries.ListAuthors(ctx)
143+
if err != nil {
144+
return err
145+
}
146+
log.Println(authors)
147+
148+
// create an author
149+
insertedAuthor, err := queries.CreateOrUpdateAuthor(ctx, tutorial.CreateOrUpdateAuthorParams{
150+
Name: "Brian Kernighan",
151+
Bio: ptr("Co-author of The C Programming Language and The Go Programming Language"),
152+
}, query.WithIdempotent())
153+
if err != nil {
154+
return err
155+
}
156+
log.Println(insertedAuthor)
157+
158+
// get the author we just inserted
159+
fetchedAuthor, err := queries.GetAuthor(ctx, insertedAuthor.ID)
160+
if err != nil {
161+
return err
162+
}
163+
log.Println(fetchedAuthor)
164+
return nil
165+
}
166+
167+
func main() {
168+
if err := run(); err != nil {
169+
log.Fatal(err)
170+
}
171+
}
172+
```
173+
174+
Before this code will compile you'll need to fetch the relevant YDB driver:
175+
176+
```shell
177+
go get github.com/ydb-platform/ydb-go-sdk/v3
178+
go build ./...
179+
```
180+
181+
The program should compile without errors. To make that possible, sqlc generates
182+
readable, **idiomatic** Go code that you otherwise would've had to write
183+
yourself. Take a look in `tutorial/query.sql.go`.
184+
185+
Of course for this program to run successfully you'll need
186+
to compile after replacing the database connection parameters in the call to
187+
`ydb.Open()` with the correct parameters for your database. And your
188+
database must have the `authors` table as defined in `schema.sql`.
189+
190+
You should now have a working program using sqlc's generated Go source code,
191+
and hopefully can see how you'd use sqlc in your own real-world applications.
192+
193+
## Query verification (Not supported for YDB yet)
194+
195+
[sqlc Cloud](https://dashboard.sqlc.dev) provides additional verification, catching subtle bugs. To get started, create a
196+
[dashboard account](https://dashboard.sqlc.dev). Once you've signed in, create a
197+
project and generate an auth token. Add your project's ID to the `cloud` block
198+
to your sqlc.yaml.
199+
200+
```yaml
201+
version: "2"
202+
cloud:
203+
# Replace <PROJECT_ID> with your project ID from the sqlc Cloud dashboard
204+
project: "<PROJECT_ID>"
205+
sql:
206+
- engine: "ydb"
207+
queries: "query.sql"
208+
schema: "schema.sql"
209+
gen:
210+
go:
211+
package: "tutorial"
212+
out: "tutorial"
213+
```
214+
215+
Replace `<PROJECT_ID>` with your project ID from the sqlc Cloud dashboard. It
216+
will look something like `01HA8SZH31HKYE9RR3N3N3TSJM`.
217+
218+
And finally, set the `SQLC_AUTH_TOKEN` environment variable:
219+
220+
```shell
221+
export SQLC_AUTH_TOKEN="<your sqlc auth token>"
222+
```
223+
224+
```shell
225+
$ sqlc push --tag tutorial
226+
```
227+
228+
In the sidebar, go to the "Queries" section to see your published queries. Run
229+
`verify` to ensure that previously published queries continue to work against
230+
updated database schema.
231+
232+
```shell
233+
$ sqlc verify --against tutorial
234+
```

examples/authors/ydb/db_test.go

Lines changed: 30 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
package authors
23

34
import (
@@ -15,86 +16,38 @@ func ptr(s string) *string {
1516

1617
func TestAuthors(t *testing.T) {
1718
ctx := context.Background()
18-
1919
db := local.YDB(t, []string{"schema.sql"})
2020
defer db.Close(ctx)
2121

2222
q := New(db.Query())
2323

24-
t.Run("InsertAuthors", func(t *testing.T) {
25-
authorsToInsert := []CreateOrUpdateAuthorParams{
26-
{P0: 1, P1: "Leo Tolstoy", P2: ptr("Russian writer, author of \"War and Peace\"")},
27-
{P0: 2, P1: "Alexander Pushkin", P2: ptr("Author of \"Eugene Onegin\"")},
28-
{P0: 3, P1: "Alexander Pushkin", P2: ptr("Russian poet, playwright, and prose writer")},
29-
{P0: 4, P1: "Fyodor Dostoevsky", P2: ptr("Author of \"Crime and Punishment\"")},
30-
{P0: 5, P1: "Nikolai Gogol", P2: ptr("Author of \"Dead Souls\"")},
31-
{P0: 6, P1: "Anton Chekhov", P2: nil},
32-
{P0: 7, P1: "Ivan Turgenev", P2: ptr("Author of \"Fathers and Sons\"")},
33-
{P0: 8, P1: "Mikhail Lermontov", P2: nil},
34-
{P0: 9, P1: "Daniil Kharms", P2: ptr("Absurdist, writer and poet")},
35-
{P0: 10, P1: "Maxim Gorky", P2: ptr("Author of \"At the Bottom\"")},
36-
{P0: 11, P1: "Vladimir Mayakovsky", P2: nil},
37-
{P0: 12, P1: "Sergei Yesenin", P2: ptr("Russian lyric poet")},
38-
{P0: 13, P1: "Boris Pasternak", P2: ptr("Author of \"Doctor Zhivago\"")},
39-
}
40-
41-
for _, author := range authorsToInsert {
42-
if err := q.CreateOrUpdateAuthor(ctx, author, query.WithIdempotent()); err != nil {
43-
t.Fatalf("failed to insert author %q: %v", author.P1, err)
44-
}
45-
}
46-
})
47-
48-
t.Run("ListAuthors", func(t *testing.T) {
49-
authors, err := q.ListAuthors(ctx)
50-
if err != nil {
51-
t.Fatal(err)
52-
}
53-
if len(authors) == 0 {
54-
t.Fatal("expected at least one author, got none")
55-
}
56-
t.Log("Authors:")
57-
for _, a := range authors {
58-
bio := "Null"
59-
if a.Bio != nil {
60-
bio = *a.Bio
61-
}
62-
t.Logf("- ID: %d | Name: %s | Bio: %s", a.ID, a.Name, bio)
63-
}
64-
})
65-
66-
t.Run("GetAuthor", func(t *testing.T) {
67-
singleAuthor, err := q.GetAuthor(ctx, 10)
68-
if err != nil {
69-
t.Fatal(err)
70-
}
71-
bio := "Null"
72-
if singleAuthor.Bio != nil {
73-
bio = *singleAuthor.Bio
74-
}
75-
t.Logf("- ID: %d | Name: %s | Bio: %s", singleAuthor.ID, singleAuthor.Name, bio)
76-
})
77-
78-
t.Run("Delete All Authors", func(t *testing.T) {
79-
var i uint64
80-
for i = 1; i <= 13; i++ {
81-
if err := q.DeleteAuthor(ctx, i, query.WithIdempotent()); err != nil {
82-
t.Fatalf("failed to delete author: %v", err)
83-
}
84-
}
85-
authors, err := q.ListAuthors(ctx)
86-
if err != nil {
87-
t.Fatal(err)
88-
}
89-
if len(authors) != 0 {
90-
t.Fatalf("expected no authors, got %d", len(authors))
91-
}
92-
})
93-
94-
t.Run("Drop Table Authors", func(t *testing.T) {
95-
err := q.DropTable(ctx)
96-
if err != nil {
97-
t.Fatal(err)
98-
}
99-
})
24+
// list all authors
25+
authors, err := q.ListAuthors(ctx)
26+
if err != nil {
27+
t.Fatal(err)
28+
}
29+
t.Log(authors)
30+
31+
// create an author
32+
insertedAuthor, err := q.CreateOrUpdateAuthor(ctx, CreateOrUpdateAuthorParams{
33+
Name: "Brian Kernighan",
34+
Bio: ptr("Co-author of The C Programming Language and The Go Programming Language"),
35+
}, query.WithIdempotent())
36+
if err != nil {
37+
t.Fatal(err)
38+
}
39+
t.Log(insertedAuthor)
40+
41+
// get the author we just inserted
42+
fetchedAuthor, err := q.GetAuthor(ctx, insertedAuthor.ID)
43+
if err != nil {
44+
t.Fatal(err)
45+
}
46+
t.Log(fetchedAuthor)
47+
48+
// drop table
49+
err = q.DropTable(ctx)
50+
if err != nil {
51+
t.Fatal(err)
52+
}
10053
}

examples/authors/ydb/models.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/authors/ydb/query.sql

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
-- name: GetAuthor :one
22
SELECT * FROM authors
3-
WHERE id = $p0 LIMIT 1;
3+
WHERE id = $id LIMIT 1;
44

55
-- name: ListAuthors :many
6-
SELECT * FROM authors ORDER BY name;
6+
SELECT * FROM authors
7+
ORDER BY name;
78

8-
-- name: CreateOrUpdateAuthor :exec
9-
UPSERT INTO authors (id, name, bio) VALUES ($p0, $p1, $p2);
9+
-- name: CreateOrUpdateAuthor :one
10+
UPSERT INTO authors (name, bio)
11+
VALUES (
12+
$name, $bio
13+
)
14+
RETURNING *;
1015

1116
-- name: DeleteAuthor :exec
12-
DELETE FROM authors WHERE id = $p0;
17+
DELETE FROM authors WHERE id = $id;
1318

1419
-- name: DropTable :exec
15-
DROP TABLE IF EXISTS authors;
20+
DROP TABLE IF EXISTS authors;

0 commit comments

Comments
 (0)