snapshot of https://github.com/sqlc-dev/sqlc.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
kotlin / test (push) Has been skipped
python / test (push) Has been skipped
typescript / test (push) Has been skipped
go / build darwin/amd64 (push) Has been cancelled
go / build linux/amd64 (push) Has been cancelled
go / build windows/amd64 (push) Has been cancelled
go / build darwin/arm64 (push) Has been cancelled
go / build linux/arm64 (push) Has been cancelled
go / build windows/arm64 (push) Has been cancelled
go / test (push) Has been cancelled
go / vuln_check (push) Has been cancelled
Some checks failed
kotlin / test (push) Has been skipped
python / test (push) Has been skipped
typescript / test (push) Has been skipped
go / build darwin/amd64 (push) Has been cancelled
go / build linux/amd64 (push) Has been cancelled
go / build windows/amd64 (push) Has been cancelled
go / build darwin/arm64 (push) Has been cancelled
go / build linux/arm64 (push) Has been cancelled
go / build windows/arm64 (push) Has been cancelled
go / test (push) Has been cancelled
go / vuln_check (push) Has been cancelled
This commit is contained in:
32
examples/booktest/postgresql/db.go
Normal file
32
examples/booktest/postgresql/db.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package booktest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...any) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...any) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...any) pgx.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
174
examples/booktest/postgresql/db_test.go
Normal file
174
examples/booktest/postgresql/db_test.go
Normal file
@@ -0,0 +1,174 @@
|
||||
//go:build examples
|
||||
|
||||
package booktest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
|
||||
"github.com/sqlc-dev/sqlc/internal/sqltest/local"
|
||||
)
|
||||
|
||||
func TestBooks(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
uri := local.PostgreSQL(t, []string{"schema.sql"})
|
||||
db, err := pgx.Connect(ctx, uri)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close(ctx)
|
||||
|
||||
dq := New(db)
|
||||
|
||||
// create an author
|
||||
a, err := dq.CreateAuthor(ctx, "Unknown Master")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// create transaction
|
||||
tx, err := db.Begin(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tq := dq.WithTx(tx)
|
||||
|
||||
// save first book
|
||||
now := pgtype.Timestamptz{Time: time.Now(), Valid: true}
|
||||
_, err = tq.CreateBook(ctx, CreateBookParams{
|
||||
AuthorID: a.AuthorID,
|
||||
Isbn: "1",
|
||||
Title: "my book title",
|
||||
BookType: BookTypeFICTION,
|
||||
Year: 2016,
|
||||
Available: now,
|
||||
Tags: []string{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// save second book
|
||||
b1, err := tq.CreateBook(ctx, CreateBookParams{
|
||||
AuthorID: a.AuthorID,
|
||||
Isbn: "2",
|
||||
Title: "the second book",
|
||||
BookType: BookTypeFICTION,
|
||||
Year: 2016,
|
||||
Available: now,
|
||||
Tags: []string{"cool", "unique"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// update the title and tags
|
||||
err = tq.UpdateBook(ctx, UpdateBookParams{
|
||||
BookID: b1.BookID,
|
||||
Title: "changed second title",
|
||||
Tags: []string{"cool", "disastor"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// save third book
|
||||
_, err = tq.CreateBook(ctx, CreateBookParams{
|
||||
AuthorID: a.AuthorID,
|
||||
Isbn: "3",
|
||||
Title: "the third book",
|
||||
BookType: BookTypeFICTION,
|
||||
Year: 2001,
|
||||
Available: now,
|
||||
Tags: []string{"cool"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// save fourth book
|
||||
b3, err := tq.CreateBook(ctx, CreateBookParams{
|
||||
AuthorID: a.AuthorID,
|
||||
Isbn: "4",
|
||||
Title: "4th place finisher",
|
||||
BookType: BookTypeNONFICTION,
|
||||
Year: 2011,
|
||||
Available: now,
|
||||
Tags: []string{"other"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// tx commit
|
||||
err = tx.Commit(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// upsert, changing ISBN and title
|
||||
err = dq.UpdateBookISBN(ctx, UpdateBookISBNParams{
|
||||
BookID: b3.BookID,
|
||||
Isbn: "NEW ISBN",
|
||||
Title: "never ever gonna finish, a quatrain",
|
||||
Tags: []string{"someother"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// retrieve first book
|
||||
books0, err := dq.BooksByTitleYear(ctx, BooksByTitleYearParams{
|
||||
Title: "my book title",
|
||||
Year: 2016,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, book := range books0 {
|
||||
t.Logf("Book %d (%s): %s available: %s\n", book.BookID, book.BookType, book.Title, book.Available.Time.Format(time.RFC822Z))
|
||||
author, err := dq.GetAuthor(ctx, book.AuthorID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("Book %d author: %s\n", book.BookID, author.Name)
|
||||
}
|
||||
|
||||
// find a book with either "cool" or "other" tag
|
||||
t.Logf("---------\nTag search results:\n")
|
||||
res, err := dq.BooksByTags(ctx, []string{"cool", "other", "someother"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, ab := range res {
|
||||
t.Logf("Book %d: '%s', Author: '%s', ISBN: '%s' Tags: '%v'\n", ab.BookID, ab.Title, ab.Name.String, ab.Isbn, ab.Tags)
|
||||
}
|
||||
|
||||
// call function
|
||||
pgText, err := dq.SayHello(ctx, "world")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
str, err := pgText.Value()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if str != "hello world" {
|
||||
t.Fatal("expected function result to be \"hello world\". actual:", str)
|
||||
}
|
||||
|
||||
// get book 4 and delete
|
||||
b5, err := dq.GetBook(ctx, b3.BookID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := dq.DeleteBook(ctx, b5.BookID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
70
examples/booktest/postgresql/models.go
Normal file
70
examples/booktest/postgresql/models.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package booktest
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type BookType string
|
||||
|
||||
const (
|
||||
BookTypeFICTION BookType = "FICTION"
|
||||
BookTypeNONFICTION BookType = "NONFICTION"
|
||||
)
|
||||
|
||||
func (e *BookType) Scan(src any) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = BookType(s)
|
||||
case string:
|
||||
*e = BookType(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for BookType: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NullBookType struct {
|
||||
BookType BookType
|
||||
Valid bool // Valid is true if BookType is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullBookType) Scan(value any) error {
|
||||
if value == nil {
|
||||
ns.BookType, ns.Valid = "", false
|
||||
return nil
|
||||
}
|
||||
ns.Valid = true
|
||||
return ns.BookType.Scan(value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (ns NullBookType) Value() (driver.Value, error) {
|
||||
if !ns.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return string(ns.BookType), nil
|
||||
}
|
||||
|
||||
type Author struct {
|
||||
AuthorID int32
|
||||
Name string
|
||||
}
|
||||
|
||||
type Book struct {
|
||||
BookID int32
|
||||
AuthorID int32
|
||||
Isbn string
|
||||
BookType BookType
|
||||
Title string
|
||||
Year int32
|
||||
Available pgtype.Timestamptz
|
||||
Tags []string
|
||||
}
|
||||
63
examples/booktest/postgresql/query.sql
Normal file
63
examples/booktest/postgresql/query.sql
Normal file
@@ -0,0 +1,63 @@
|
||||
-- name: GetAuthor :one
|
||||
SELECT * FROM authors
|
||||
WHERE author_id = $1;
|
||||
|
||||
-- name: GetBook :one
|
||||
SELECT * FROM books
|
||||
WHERE book_id = $1;
|
||||
|
||||
-- name: DeleteBook :exec
|
||||
DELETE FROM books
|
||||
WHERE book_id = $1;
|
||||
|
||||
-- name: BooksByTitleYear :many
|
||||
SELECT * FROM books
|
||||
WHERE title = $1 AND year = $2;
|
||||
|
||||
-- name: BooksByTags :many
|
||||
SELECT
|
||||
book_id,
|
||||
title,
|
||||
name,
|
||||
isbn,
|
||||
tags
|
||||
FROM books
|
||||
LEFT JOIN authors ON books.author_id = authors.author_id
|
||||
WHERE tags && $1::varchar[];
|
||||
|
||||
-- name: CreateAuthor :one
|
||||
INSERT INTO authors (name) VALUES ($1)
|
||||
RETURNING *;
|
||||
|
||||
-- name: CreateBook :one
|
||||
INSERT INTO books (
|
||||
author_id,
|
||||
isbn,
|
||||
book_type,
|
||||
title,
|
||||
year,
|
||||
available,
|
||||
tags
|
||||
) VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateBook :exec
|
||||
UPDATE books
|
||||
SET title = $1, tags = $2
|
||||
WHERE book_id = $3;
|
||||
|
||||
-- name: UpdateBookISBN :exec
|
||||
UPDATE books
|
||||
SET title = $1, tags = $2, isbn = $4
|
||||
WHERE book_id = $3;
|
||||
|
||||
-- name: SayHello :one
|
||||
select * from say_hello($1);
|
||||
258
examples/booktest/postgresql/query.sql.go
Normal file
258
examples/booktest/postgresql/query.sql.go
Normal file
@@ -0,0 +1,258 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: query.sql
|
||||
|
||||
package booktest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const booksByTags = `-- name: BooksByTags :many
|
||||
SELECT
|
||||
book_id,
|
||||
title,
|
||||
name,
|
||||
isbn,
|
||||
tags
|
||||
FROM books
|
||||
LEFT JOIN authors ON books.author_id = authors.author_id
|
||||
WHERE tags && $1::varchar[]
|
||||
`
|
||||
|
||||
type BooksByTagsRow struct {
|
||||
BookID int32
|
||||
Title string
|
||||
Name pgtype.Text
|
||||
Isbn string
|
||||
Tags []string
|
||||
}
|
||||
|
||||
func (q *Queries) BooksByTags(ctx context.Context, dollar_1 []string) ([]BooksByTagsRow, error) {
|
||||
rows, err := q.db.Query(ctx, booksByTags, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []BooksByTagsRow
|
||||
for rows.Next() {
|
||||
var i BooksByTagsRow
|
||||
if err := rows.Scan(
|
||||
&i.BookID,
|
||||
&i.Title,
|
||||
&i.Name,
|
||||
&i.Isbn,
|
||||
&i.Tags,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const booksByTitleYear = `-- name: BooksByTitleYear :many
|
||||
SELECT book_id, author_id, isbn, book_type, title, year, available, tags FROM books
|
||||
WHERE title = $1 AND year = $2
|
||||
`
|
||||
|
||||
type BooksByTitleYearParams struct {
|
||||
Title string
|
||||
Year int32
|
||||
}
|
||||
|
||||
func (q *Queries) BooksByTitleYear(ctx context.Context, arg BooksByTitleYearParams) ([]Book, error) {
|
||||
rows, err := q.db.Query(ctx, booksByTitleYear, arg.Title, arg.Year)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Book
|
||||
for rows.Next() {
|
||||
var i Book
|
||||
if err := rows.Scan(
|
||||
&i.BookID,
|
||||
&i.AuthorID,
|
||||
&i.Isbn,
|
||||
&i.BookType,
|
||||
&i.Title,
|
||||
&i.Year,
|
||||
&i.Available,
|
||||
&i.Tags,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const createAuthor = `-- name: CreateAuthor :one
|
||||
INSERT INTO authors (name) VALUES ($1)
|
||||
RETURNING author_id, name
|
||||
`
|
||||
|
||||
func (q *Queries) CreateAuthor(ctx context.Context, name string) (Author, error) {
|
||||
row := q.db.QueryRow(ctx, createAuthor, name)
|
||||
var i Author
|
||||
err := row.Scan(&i.AuthorID, &i.Name)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createBook = `-- name: CreateBook :one
|
||||
INSERT INTO books (
|
||||
author_id,
|
||||
isbn,
|
||||
book_type,
|
||||
title,
|
||||
year,
|
||||
available,
|
||||
tags
|
||||
) VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7
|
||||
)
|
||||
RETURNING book_id, author_id, isbn, book_type, title, year, available, tags
|
||||
`
|
||||
|
||||
type CreateBookParams struct {
|
||||
AuthorID int32
|
||||
Isbn string
|
||||
BookType BookType
|
||||
Title string
|
||||
Year int32
|
||||
Available pgtype.Timestamptz
|
||||
Tags []string
|
||||
}
|
||||
|
||||
func (q *Queries) CreateBook(ctx context.Context, arg CreateBookParams) (Book, error) {
|
||||
row := q.db.QueryRow(ctx, createBook,
|
||||
arg.AuthorID,
|
||||
arg.Isbn,
|
||||
arg.BookType,
|
||||
arg.Title,
|
||||
arg.Year,
|
||||
arg.Available,
|
||||
arg.Tags,
|
||||
)
|
||||
var i Book
|
||||
err := row.Scan(
|
||||
&i.BookID,
|
||||
&i.AuthorID,
|
||||
&i.Isbn,
|
||||
&i.BookType,
|
||||
&i.Title,
|
||||
&i.Year,
|
||||
&i.Available,
|
||||
&i.Tags,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteBook = `-- name: DeleteBook :exec
|
||||
DELETE FROM books
|
||||
WHERE book_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteBook(ctx context.Context, bookID int32) error {
|
||||
_, err := q.db.Exec(ctx, deleteBook, bookID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAuthor = `-- name: GetAuthor :one
|
||||
SELECT author_id, name FROM authors
|
||||
WHERE author_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetAuthor(ctx context.Context, authorID int32) (Author, error) {
|
||||
row := q.db.QueryRow(ctx, getAuthor, authorID)
|
||||
var i Author
|
||||
err := row.Scan(&i.AuthorID, &i.Name)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getBook = `-- name: GetBook :one
|
||||
SELECT book_id, author_id, isbn, book_type, title, year, available, tags FROM books
|
||||
WHERE book_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetBook(ctx context.Context, bookID int32) (Book, error) {
|
||||
row := q.db.QueryRow(ctx, getBook, bookID)
|
||||
var i Book
|
||||
err := row.Scan(
|
||||
&i.BookID,
|
||||
&i.AuthorID,
|
||||
&i.Isbn,
|
||||
&i.BookType,
|
||||
&i.Title,
|
||||
&i.Year,
|
||||
&i.Available,
|
||||
&i.Tags,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const sayHello = `-- name: SayHello :one
|
||||
select say_hello from say_hello($1)
|
||||
`
|
||||
|
||||
func (q *Queries) SayHello(ctx context.Context, s string) (pgtype.Text, error) {
|
||||
row := q.db.QueryRow(ctx, sayHello, s)
|
||||
var say_hello pgtype.Text
|
||||
err := row.Scan(&say_hello)
|
||||
return say_hello, err
|
||||
}
|
||||
|
||||
const updateBook = `-- name: UpdateBook :exec
|
||||
UPDATE books
|
||||
SET title = $1, tags = $2
|
||||
WHERE book_id = $3
|
||||
`
|
||||
|
||||
type UpdateBookParams struct {
|
||||
Title string
|
||||
Tags []string
|
||||
BookID int32
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateBook(ctx context.Context, arg UpdateBookParams) error {
|
||||
_, err := q.db.Exec(ctx, updateBook, arg.Title, arg.Tags, arg.BookID)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateBookISBN = `-- name: UpdateBookISBN :exec
|
||||
UPDATE books
|
||||
SET title = $1, tags = $2, isbn = $4
|
||||
WHERE book_id = $3
|
||||
`
|
||||
|
||||
type UpdateBookISBNParams struct {
|
||||
Title string
|
||||
Tags []string
|
||||
BookID int32
|
||||
Isbn string
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateBookISBN(ctx context.Context, arg UpdateBookISBNParams) error {
|
||||
_, err := q.db.Exec(ctx, updateBookISBN,
|
||||
arg.Title,
|
||||
arg.Tags,
|
||||
arg.BookID,
|
||||
arg.Isbn,
|
||||
)
|
||||
return err
|
||||
}
|
||||
32
examples/booktest/postgresql/schema.sql
Normal file
32
examples/booktest/postgresql/schema.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
CREATE TABLE authors (
|
||||
author_id SERIAL PRIMARY KEY,
|
||||
name text NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
CREATE INDEX authors_name_idx ON authors(name);
|
||||
|
||||
CREATE TYPE book_type AS ENUM (
|
||||
'FICTION',
|
||||
'NONFICTION'
|
||||
);
|
||||
|
||||
CREATE TABLE books (
|
||||
book_id SERIAL PRIMARY KEY,
|
||||
author_id integer NOT NULL REFERENCES authors(author_id),
|
||||
isbn text NOT NULL DEFAULT '' UNIQUE,
|
||||
book_type book_type NOT NULL DEFAULT 'FICTION',
|
||||
title text NOT NULL DEFAULT '',
|
||||
year integer NOT NULL DEFAULT 2000,
|
||||
available timestamp with time zone NOT NULL DEFAULT 'NOW()',
|
||||
tags varchar[] NOT NULL DEFAULT '{}'
|
||||
);
|
||||
|
||||
CREATE INDEX books_title_idx ON books(title, year);
|
||||
|
||||
CREATE FUNCTION say_hello(s text) RETURNS text AS $$
|
||||
BEGIN
|
||||
RETURN CONCAT('hello ', s);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE INDEX books_title_lower_idx ON books(title);
|
||||
Reference in New Issue
Block a user