Skip to content

Commit 96ae6e7

Browse files
authored
Merge pull request #1 from 1NepuNep1/yql-support
Initial YDB support in SQLC
2 parents e81b1b5 + 4284c27 commit 96ae6e7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+6781
-13
lines changed

Makefile

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: build build-endtoend test test-ci test-examples test-endtoend start psql mysqlsh proto
1+
.PHONY: build build-endtoend test test-ci test-examples test-endtoend start psql mysqlsh proto sqlc-dev ydb test-examples-ydb gen-examples-ydb
22

33
build:
44
go build ./...
@@ -18,13 +18,21 @@ vet:
1818
test-examples:
1919
go test --tags=examples ./...
2020

21+
ydb-examples: sqlc-dev ydb gen-examples-ydb test-examples-ydb
22+
23+
test-examples-ydb:
24+
YDB_SERVER_URI=localhost:2136 go test -v ./examples/authors/ydb/... -count=1
25+
26+
gen-examples-ydb:
27+
cd examples/authors/ && SQLCDEBUG=1 ~/bin/sqlc-dev generate && cd ../..
28+
2129
build-endtoend:
2230
cd ./internal/endtoend/testdata && go build ./...
2331

2432
test-ci: test-examples build-endtoend vet
2533

2634
sqlc-dev:
27-
go build -o ~/bin/sqlc-dev ./cmd/sqlc/
35+
go build -x -v -o ~/bin/sqlc-dev ./cmd/sqlc/
2836

2937
sqlc-pg-gen:
3038
go build -o ~/bin/sqlc-pg-gen ./internal/tools/sqlc-pg-gen
@@ -38,6 +46,9 @@ test-json-process-plugin:
3846
start:
3947
docker compose up -d
4048

49+
ydb:
50+
docker compose up -d ydb
51+
4152
fmt:
4253
go fmt ./...
4354

docker-compose.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,16 @@ services:
1919
POSTGRES_DB: postgres
2020
POSTGRES_PASSWORD: mysecretpassword
2121
POSTGRES_USER: postgres
22+
23+
ydb:
24+
image: ydbplatform/local-ydb:latest
25+
ports:
26+
- "2135:2135"
27+
- "2136:2136"
28+
- "8765:8765"
29+
restart: always
30+
environment:
31+
- YDB_USE_IN_MEMORY_PDISKS=true
32+
- GRPC_TLS_PORT=2135
33+
- GRPC_PORT=2136
34+
- MON_PORT=8765

examples/authors/sqlc.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ sql:
4343
go:
4444
package: authors
4545
out: sqlite
46+
- name: ydb
47+
schema: ydb/schema.sql
48+
queries: ydb/query.sql
49+
engine: ydb
50+
gen:
51+
go:
52+
package: authors
53+
out: ydb
54+
emit_json_tags: true
55+
56+
4657
rules:
4758
- name: postgresql-query-too-costly
4859
message: "Too costly"

examples/authors/ydb/README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Инструкция по генерации
2+
3+
В файлах `schema.sql` и `query.sql` записаны, соответственно, схема базы данных и запросы, из которых вы хотите сгенерировать код к базе данных.
4+
В `db_test.go` находятся тесты для последних сгенерированных команд.
5+
Ниже находятся команды для генерации и запуска тестов.
6+
7+
---
8+
9+
### 1. Создание бинарника sqlc
10+
11+
```bash
12+
make sqlc-dev
13+
```
14+
15+
### 2. Запуск YDB через Docker Compose
16+
17+
```bash
18+
make ydb
19+
```
20+
21+
### 3. Генерация кода для примеров для YDB
22+
23+
```bash
24+
make gen-examples-ydb
25+
```
26+
27+
### 4. Запуск тестов примеров для YDB
28+
29+
```bash
30+
make test-examples-ydb
31+
```
32+
33+
### 5. Полный цикл: сборка, генерация, тестирование (удобно одной командой)
34+
35+
```bash
36+
make ydb-examples
37+
```
38+
39+
Эта команда выполнит:
40+
41+
- Сборку `sqlc-dev`
42+
- Запуск контейнера YDB
43+
- Генерацию примеров
44+
- Тестирование примеров
45+
46+
---
47+

examples/authors/ydb/db.go

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/authors/ydb/db_test.go

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package authors
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/sqlc-dev/sqlc/internal/sqltest/local"
8+
_ "github.com/ydb-platform/ydb-go-sdk/v3"
9+
)
10+
11+
func ptr(s string) *string {
12+
return &s
13+
}
14+
15+
func TestAuthors(t *testing.T) {
16+
ctx := context.Background()
17+
18+
test := local.YDB(t, []string{"schema.sql"})
19+
defer test.DB.Close()
20+
21+
q := New(test.DB)
22+
23+
t.Run("InsertAuthors", func(t *testing.T) {
24+
authorsToInsert := []CreateOrUpdateAuthorParams{
25+
{P0: 1, P1: "Лев Толстой", P2: ptr("Русский писатель, автор \"Война и мир\"")},
26+
{P0: 2, P1: "Александр Пушкин", P2: ptr("Автор \"Евгения Онегина\"")},
27+
{P0: 3, P1: "Александр Пушкин", P2: ptr("Русский поэт, драматург и прозаик")},
28+
{P0: 4, P1: "Фёдор Достоевский", P2: ptr("Автор \"Преступление и наказание\"")},
29+
{P0: 5, P1: "Николай Гоголь", P2: ptr("Автор \"Мёртвые души\"")},
30+
{P0: 6, P1: "Антон Чехов", P2: nil},
31+
{P0: 7, P1: "Иван Тургенев", P2: ptr("Автор \"Отцы и дети\"")},
32+
{P0: 8, P1: "Михаил Лермонтов", P2: nil},
33+
{P0: 9, P1: "Даниил Хармс", P2: ptr("Абсурдист, писатель и поэт")},
34+
{P0: 10, P1: "Максим Горький", P2: ptr("Автор \"На дне\"")},
35+
{P0: 11, P1: "Владимир Маяковский", P2: nil},
36+
{P0: 12, P1: "Сергей Есенин", P2: ptr("Русский лирик")},
37+
{P0: 13, P1: "Борис Пастернак", P2: ptr("Автор \"Доктор Живаго\"")},
38+
}
39+
40+
for _, author := range authorsToInsert {
41+
if _, err := q.CreateOrUpdateAuthor(ctx, author); err != nil {
42+
t.Fatalf("failed to insert author %q: %v", author.P1, err)
43+
}
44+
}
45+
})
46+
47+
t.Run("CreateOrUpdateAuthorReturningBio", func(t *testing.T) {
48+
newBio := "Обновленная биография автора"
49+
arg := CreateOrUpdateAuthorReturningBioParams{
50+
P0: 3,
51+
P1: "Тестовый Автор",
52+
P2: &newBio,
53+
}
54+
55+
returnedBio, err := q.CreateOrUpdateAuthorReturningBio(ctx, arg)
56+
if err != nil {
57+
t.Fatalf("failed to create or update author: %v", err)
58+
}
59+
60+
if returnedBio == nil {
61+
t.Fatal("expected non-nil bio, got nil")
62+
}
63+
if *returnedBio != newBio {
64+
t.Fatalf("expected bio %q, got %q", newBio, *returnedBio)
65+
}
66+
67+
t.Logf("Author created or updated successfully with bio: %s", *returnedBio)
68+
})
69+
70+
t.Run("Update Author", func(t *testing.T) {
71+
arg := UpdateAuthorByIDParams{
72+
P0: "Максим Горький",
73+
P1: ptr("Обновленная биография"),
74+
P2: 10,
75+
}
76+
77+
singleAuthor, err := q.UpdateAuthorByID(ctx, arg)
78+
if err != nil {
79+
t.Fatal(err)
80+
}
81+
bio := "Null"
82+
if singleAuthor.Bio != nil {
83+
bio = *singleAuthor.Bio
84+
}
85+
t.Logf("- ID: %d | Name: %s | Bio: %s", singleAuthor.ID, singleAuthor.Name, bio)
86+
})
87+
88+
t.Run("ListAuthors", func(t *testing.T) {
89+
authors, err := q.ListAuthors(ctx)
90+
if err != nil {
91+
t.Fatal(err)
92+
}
93+
if len(authors) == 0 {
94+
t.Fatal("expected at least one author, got none")
95+
}
96+
t.Log("Authors:")
97+
for _, a := range authors {
98+
bio := "Null"
99+
if a.Bio != nil {
100+
bio = *a.Bio
101+
}
102+
t.Logf("- ID: %d | Name: %s | Bio: %s", a.ID, a.Name, bio)
103+
}
104+
})
105+
106+
t.Run("GetAuthor", func(t *testing.T) {
107+
singleAuthor, err := q.GetAuthor(ctx, 10)
108+
if err != nil {
109+
t.Fatal(err)
110+
}
111+
bio := "Null"
112+
if singleAuthor.Bio != nil {
113+
bio = *singleAuthor.Bio
114+
}
115+
t.Logf("- ID: %d | Name: %s | Bio: %s", singleAuthor.ID, singleAuthor.Name, bio)
116+
})
117+
118+
t.Run("GetAuthorByName", func(t *testing.T) {
119+
authors, err := q.GetAuthorsByName(ctx, "Александр Пушкин")
120+
if err != nil {
121+
t.Fatal(err)
122+
}
123+
if len(authors) == 0 {
124+
t.Fatal("expected at least one author with this name, got none")
125+
}
126+
t.Log("Authors with this name:")
127+
for _, a := range authors {
128+
bio := "Null"
129+
if a.Bio != nil {
130+
bio = *a.Bio
131+
}
132+
t.Logf("- ID: %d | Name: %s | Bio: %s", a.ID, a.Name, bio)
133+
}
134+
})
135+
136+
t.Run("ListAuthorsWithNullBio", func(t *testing.T) {
137+
authors, err := q.ListAuthorsWithNullBio(ctx)
138+
if err != nil {
139+
t.Fatal(err)
140+
}
141+
if len(authors) == 0 {
142+
t.Fatal("expected at least one author with NULL bio, got none")
143+
}
144+
t.Log("Authors with NULL bio:")
145+
for _, a := range authors {
146+
bio := "Null"
147+
if a.Bio != nil {
148+
bio = *a.Bio
149+
}
150+
t.Logf("- ID: %d | Name: %s | Bio: %s", a.ID, a.Name, bio)
151+
}
152+
})
153+
154+
t.Run("Delete All Authors", func(t *testing.T) {
155+
var i uint64
156+
for i = 1; i <= 13; i++ {
157+
if err := q.DeleteAuthor(ctx, i); err != nil {
158+
t.Fatalf("failed to delete authors: %v", err)
159+
}
160+
}
161+
authors, err := q.ListAuthors(ctx)
162+
if err != nil {
163+
t.Fatal(err)
164+
}
165+
if len(authors) != 0 {
166+
t.Fatalf("expected no authors, got %d", len(authors))
167+
}
168+
})
169+
}

examples/authors/ydb/models.go

Lines changed: 11 additions & 0 deletions
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: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
-- name: ListAuthors :many
2+
SELECT * FROM authors;
3+
4+
-- name: GetAuthor :one
5+
SELECT * FROM authors
6+
WHERE id = $p0;
7+
8+
-- name: GetAuthorsByName :many
9+
SELECT * FROM authors
10+
WHERE name = $p0;
11+
12+
-- name: ListAuthorsWithNullBio :many
13+
SELECT * FROM authors
14+
WHERE bio IS NULL;
15+
16+
-- name: Count :one
17+
SELECT COUNT(*) FROM authors;
18+
19+
-- name: COALESCE :many
20+
SELECT id, name, COALESCE(bio, 'Null value!') FROM authors;
21+
22+
-- name: CreateOrUpdateAuthor :execresult
23+
UPSERT INTO authors (id, name, bio) VALUES ($p0, $p1, $p2);
24+
25+
-- name: CreateOrUpdateAuthorReturningBio :one
26+
UPSERT INTO authors (id, name, bio) VALUES ($p0, $p1, $p2) RETURNING bio;
27+
28+
-- name: DeleteAuthor :exec
29+
DELETE FROM authors WHERE id = $p0;
30+
31+
-- name: UpdateAuthorByID :one
32+
UPDATE authors SET name = $p0, bio = $p1 WHERE id = $p2 RETURNING *;

0 commit comments

Comments
 (0)