Skip to content

YDB support in SQLC #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: build build-endtoend test test-ci test-examples test-endtoend start psql mysqlsh proto
.PHONY: build build-endtoend test test-ci test-examples test-endtoend start psql mysqlsh proto sqlc-dev ydb test-examples-ydb gen-examples-ydb

build:
go build ./...
Expand All @@ -18,13 +18,21 @@ vet:
test-examples:
go test --tags=examples ./...

ydb-examples: sqlc-dev ydb gen-examples-ydb test-examples-ydb

test-examples-ydb:
YDB_SERVER_URI=localhost:2136 go test -v ./examples/authors/ydb/... -count=1

gen-examples-ydb:
cd examples/authors/ && SQLCDEBUG=1 ~/bin/sqlc-dev generate && cd ../..

build-endtoend:
cd ./internal/endtoend/testdata && go build ./...

test-ci: test-examples build-endtoend vet

sqlc-dev:
go build -o ~/bin/sqlc-dev ./cmd/sqlc/
go build -x -v -o ~/bin/sqlc-dev ./cmd/sqlc/

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

ydb:
docker compose up -d ydb

fmt:
go fmt ./...

Expand Down
13 changes: 13 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,16 @@ services:
POSTGRES_DB: postgres
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_USER: postgres

ydb:
image: ydbplatform/local-ydb:latest
ports:
- "2135:2135"
- "2136:2136"
- "8765:8765"
restart: always
environment:
- YDB_USE_IN_MEMORY_PDISKS=true
- GRPC_TLS_PORT=2135
- GRPC_PORT=2136
- MON_PORT=8765
11 changes: 11 additions & 0 deletions examples/authors/sqlc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ sql:
go:
package: authors
out: sqlite
- name: ydb
schema: ydb/schema.sql
queries: ydb/query.sql
engine: ydb
gen:
go:
package: authors
out: ydb
emit_json_tags: true


rules:
- name: postgresql-query-too-costly
message: "Too costly"
Expand Down
47 changes: 47 additions & 0 deletions examples/authors/ydb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Инструкция по генерации

В файлах `schema.sql` и `query.sql` записаны, соответственно, схема базы данных и запросы, из которых вы хотите сгенерировать код к базе данных.
В `db_test.go` находятся тесты для последних сгенерированных команд.
Ниже находятся команды для генерации и запуска тестов.

---

### 1. Создание бинарника sqlc

```bash
make sqlc-dev
```

### 2. Запуск YDB через Docker Compose

```bash
make ydb
```

### 3. Генерация кода для примеров для YDB

```bash
make gen-examples-ydb
```

### 4. Запуск тестов примеров для YDB

```bash
make test-examples-ydb
```

### 5. Полный цикл: сборка, генерация, тестирование (удобно одной командой)

```bash
make ydb-examples
```

Эта команда выполнит:

- Сборку `sqlc-dev`
- Запуск контейнера YDB
- Генерацию примеров
- Тестирование примеров

---

31 changes: 31 additions & 0 deletions examples/authors/ydb/db.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

169 changes: 169 additions & 0 deletions examples/authors/ydb/db_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package authors

import (
"context"
"testing"

"github.com/sqlc-dev/sqlc/internal/sqltest/local"
_ "github.com/ydb-platform/ydb-go-sdk/v3"
)

func ptr(s string) *string {
return &s
}

func TestAuthors(t *testing.T) {
ctx := context.Background()

test := local.YDB(t, []string{"schema.sql"})
defer test.DB.Close()

q := New(test.DB)

t.Run("InsertAuthors", func(t *testing.T) {
authorsToInsert := []CreateOrUpdateAuthorParams{
{P0: 1, P1: "Лев Толстой", P2: ptr("Русский писатель, автор \"Война и мир\"")},
{P0: 2, P1: "Александр Пушкин", P2: ptr("Автор \"Евгения Онегина\"")},
{P0: 3, P1: "Александр Пушкин", P2: ptr("Русский поэт, драматург и прозаик")},
{P0: 4, P1: "Фёдор Достоевский", P2: ptr("Автор \"Преступление и наказание\"")},
{P0: 5, P1: "Николай Гоголь", P2: ptr("Автор \"Мёртвые души\"")},
{P0: 6, P1: "Антон Чехов", P2: nil},
{P0: 7, P1: "Иван Тургенев", P2: ptr("Автор \"Отцы и дети\"")},
{P0: 8, P1: "Михаил Лермонтов", P2: nil},
{P0: 9, P1: "Даниил Хармс", P2: ptr("Абсурдист, писатель и поэт")},
{P0: 10, P1: "Максим Горький", P2: ptr("Автор \"На дне\"")},
{P0: 11, P1: "Владимир Маяковский", P2: nil},
{P0: 12, P1: "Сергей Есенин", P2: ptr("Русский лирик")},
{P0: 13, P1: "Борис Пастернак", P2: ptr("Автор \"Доктор Живаго\"")},
}

for _, author := range authorsToInsert {
if _, err := q.CreateOrUpdateAuthor(ctx, author); err != nil {
t.Fatalf("failed to insert author %q: %v", author.P1, err)
}
}
})

t.Run("CreateOrUpdateAuthorReturningBio", func(t *testing.T) {
newBio := "Обновленная биография автора"
arg := CreateOrUpdateAuthorReturningBioParams{
P0: 3,
P1: "Тестовый Автор",
P2: &newBio,
}

returnedBio, err := q.CreateOrUpdateAuthorReturningBio(ctx, arg)
if err != nil {
t.Fatalf("failed to create or update author: %v", err)
}

if returnedBio == nil {
t.Fatal("expected non-nil bio, got nil")
}
if *returnedBio != newBio {
t.Fatalf("expected bio %q, got %q", newBio, *returnedBio)
}

t.Logf("Author created or updated successfully with bio: %s", *returnedBio)
})

t.Run("Update Author", func(t *testing.T) {
arg := UpdateAuthorByIDParams{
P0: "Максим Горький",
P1: ptr("Обновленная биография"),
P2: 10,
}

singleAuthor, err := q.UpdateAuthorByID(ctx, arg)
if err != nil {
t.Fatal(err)
}
bio := "Null"
if singleAuthor.Bio != nil {
bio = *singleAuthor.Bio
}
t.Logf("- ID: %d | Name: %s | Bio: %s", singleAuthor.ID, singleAuthor.Name, bio)
})

t.Run("ListAuthors", func(t *testing.T) {
authors, err := q.ListAuthors(ctx)
if err != nil {
t.Fatal(err)
}
if len(authors) == 0 {
t.Fatal("expected at least one author, got none")
}
t.Log("Authors:")
for _, a := range authors {
bio := "Null"
if a.Bio != nil {
bio = *a.Bio
}
t.Logf("- ID: %d | Name: %s | Bio: %s", a.ID, a.Name, bio)
}
})

t.Run("GetAuthor", func(t *testing.T) {
singleAuthor, err := q.GetAuthor(ctx, 10)
if err != nil {
t.Fatal(err)
}
bio := "Null"
if singleAuthor.Bio != nil {
bio = *singleAuthor.Bio
}
t.Logf("- ID: %d | Name: %s | Bio: %s", singleAuthor.ID, singleAuthor.Name, bio)
})

t.Run("GetAuthorByName", func(t *testing.T) {
authors, err := q.GetAuthorsByName(ctx, "Александр Пушкин")
if err != nil {
t.Fatal(err)
}
if len(authors) == 0 {
t.Fatal("expected at least one author with this name, got none")
}
t.Log("Authors with this name:")
for _, a := range authors {
bio := "Null"
if a.Bio != nil {
bio = *a.Bio
}
t.Logf("- ID: %d | Name: %s | Bio: %s", a.ID, a.Name, bio)
}
})

t.Run("ListAuthorsWithNullBio", func(t *testing.T) {
authors, err := q.ListAuthorsWithNullBio(ctx)
if err != nil {
t.Fatal(err)
}
if len(authors) == 0 {
t.Fatal("expected at least one author with NULL bio, got none")
}
t.Log("Authors with NULL bio:")
for _, a := range authors {
bio := "Null"
if a.Bio != nil {
bio = *a.Bio
}
t.Logf("- ID: %d | Name: %s | Bio: %s", a.ID, a.Name, bio)
}
})

t.Run("Delete All Authors", func(t *testing.T) {
var i uint64
for i = 1; i <= 13; i++ {
if err := q.DeleteAuthor(ctx, i); err != nil {
t.Fatalf("failed to delete authors: %v", err)
}
}
authors, err := q.ListAuthors(ctx)
if err != nil {
t.Fatal(err)
}
if len(authors) != 0 {
t.Fatalf("expected no authors, got %d", len(authors))
}
})
}
11 changes: 11 additions & 0 deletions examples/authors/ydb/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions examples/authors/ydb/query.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
-- name: ListAuthors :many
SELECT * FROM authors;

-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = $p0;

-- name: GetAuthorsByName :many
SELECT * FROM authors
WHERE name = $p0;

-- name: ListAuthorsWithNullBio :many
SELECT * FROM authors
WHERE bio IS NULL;

-- name: Count :one
SELECT COUNT(*) FROM authors;

-- name: COALESCE :many
SELECT id, name, COALESCE(bio, 'Null value!') FROM authors;

-- name: CreateOrUpdateAuthor :execresult
UPSERT INTO authors (id, name, bio) VALUES ($p0, $p1, $p2);

-- name: CreateOrUpdateAuthorReturningBio :one
UPSERT INTO authors (id, name, bio) VALUES ($p0, $p1, $p2) RETURNING bio;

-- name: DeleteAuthor :exec
DELETE FROM authors WHERE id = $p0;

-- name: UpdateAuthorByID :one
UPDATE authors SET name = $p0, bio = $p1 WHERE id = $p2 RETURNING *;
Loading
Loading