Your first query: TimescaleDB and PostgreSQL
TimescaleDB and PostgreSQL run the same files for this example: the SQL and the Go are identical.
Configuration
sgl.yamlidentical
TimescaleDB
PostgreSQL
1
version: 11
version: 12
2
3
databases:3
databases:4
- name: tasks4
- name: tasks5
dialect: postgres5
dialect: postgres6
migrations: db/migrations6
migrations: db/migrations7
queries: db/queries7
queries: db/queries8
go:8
go:9
package: store9
package: store10
out: internal/store10
out: internal/store11
driver: database/sql11
driver: database/sql12
doc_comments: true12
doc_comments: true13
migrate:13
migrate:14
dsn: ${env:DATABASE_URL}14
dsn: ${env:DATABASE_URL}Migrations
db/migrations/0001_init.up.sqlidentical
TimescaleDB
PostgreSQL
1
CREATE TABLE tasks (1
CREATE TABLE tasks (2
id BIGSERIAL PRIMARY KEY,2
id BIGSERIAL PRIMARY KEY,3
title TEXT NOT NULL,3
title TEXT NOT NULL,4
completed BOOLEAN NOT NULL DEFAULT false,4
completed BOOLEAN NOT NULL DEFAULT false,5
created_at TIMESTAMPTZ NOT NULL DEFAULT now()5
created_at TIMESTAMPTZ NOT NULL DEFAULT now()6
);6
);7
7
8
COMMENT ON TABLE tasks IS 'Jobs to do around the harbour.';8
COMMENT ON TABLE tasks IS 'Jobs to do around the harbour.';9
COMMENT ON COLUMN tasks.completed IS 'Whether the job is done.';9
COMMENT ON COLUMN tasks.completed IS 'Whether the job is done.';db/migrations/0001_init.down.sqlidentical
TimescaleDB
PostgreSQL
1
DROP TABLE tasks;1
DROP TABLE tasks;Queries
CreateTaskidentical
TimescaleDB · db/queries/tasks.sql
PostgreSQL · db/queries/tasks.sql
1
-- CreateTask adds a task and returns it with the id and creation time the database1
-- CreateTask adds a task and returns it with the id and creation time the database2
-- gave it.2
-- gave it.3
-- sgl.query(CreateTask, one)3
-- sgl.query(CreateTask, one)4
INSERT INTO tasks (title) VALUES ($1) RETURNING id, title, completed, created_at;4
INSERT INTO tasks (title) VALUES ($1) RETURNING id, title, completed, created_at;ListTasksidentical
TimescaleDB · db/queries/tasks.sql
PostgreSQL · db/queries/tasks.sql
1
-- ListTasks returns every task, oldest first.1
-- ListTasks returns every task, oldest first.2
-- sgl.query(ListTasks, many)2
-- sgl.query(ListTasks, many)3
SELECT id, title, completed, created_at FROM tasks ORDER BY id;3
SELECT id, title, completed, created_at FROM tasks ORDER BY id;CompleteTaskidentical
TimescaleDB · db/queries/tasks.sql
PostgreSQL · db/queries/tasks.sql
1
-- CompleteTask marks a task done and returns how many tasks it changed.1
-- CompleteTask marks a task done and returns how many tasks it changed.2
-- sgl.query(CompleteTask, execrows)2
-- sgl.query(CompleteTask, execrows)3
UPDATE tasks SET completed = true WHERE id = $1;3
UPDATE tasks SET completed = true WHERE id = $1;What sgl generates
CreateTaskidentical
TimescaleDB
PostgreSQL
1
func (queries *Queries) CreateTask(ctx context.Context, title string) (CreateTaskRow, error)1
func (queries *Queries) CreateTask(ctx context.Context, title string) (CreateTaskRow, error)2
2
3
type CreateTaskRow struct {3
type CreateTaskRow struct {4
ID int64 `json:"id"`4
ID int64 `json:"id"`5
Title string `json:"title"`5
Title string `json:"title"`6
Completed bool `json:"completed"`6
Completed bool `json:"completed"`7
CreatedAt time.Time `json:"created_at"`7
CreatedAt time.Time `json:"created_at"`8
}8
}ListTasksidentical
TimescaleDB
PostgreSQL
1
func (queries *Queries) ListTasks(ctx context.Context) ([]ListTasksRow, error)1
func (queries *Queries) ListTasks(ctx context.Context) ([]ListTasksRow, error)2
2
3
type ListTasksRow struct {3
type ListTasksRow struct {4
ID int64 `json:"id"`4
ID int64 `json:"id"`5
Title string `json:"title"`5
Title string `json:"title"`6
Completed bool `json:"completed"`6
Completed bool `json:"completed"`7
CreatedAt time.Time `json:"created_at"`7
CreatedAt time.Time `json:"created_at"`8
}8
}CompleteTaskidentical
TimescaleDB
PostgreSQL
1
func (queries *Queries) CompleteTask(ctx context.Context, id int64) (int64, error)1
func (queries *Queries) CompleteTask(ctx context.Context, id int64) (int64, error)The program
example.goidentical
TimescaleDB
PostgreSQL
1
package main1
package main2
2
3
import (3
import (4
"context"4
"context"5
"database/sql"5
"database/sql"6
"fmt"6
"fmt"7
"io"7
"io"8
8
9
"seagull.sh/seagull/examples/postgres/001_first_query/internal/store"9
"seagull.sh/seagull/examples/postgres/001_first_query/internal/store"10
)10
)11
11
12
// run adds two tasks, completes the first and lists them all, through the methods sgl12
// run adds two tasks, completes the first and lists them all, through the methods sgl13
// generated from db/queries/tasks.sql. The id column is BIGSERIAL, so ID is int64, and13
// generated from db/queries/tasks.sql. The id column is BIGSERIAL, so ID is int64, and14
// created_at is TIMESTAMPTZ, so CreatedAt is a time.Time; the example leaves it out of14
// created_at is TIMESTAMPTZ, so CreatedAt is a time.Time; the example leaves it out of15
// the output, as it changes on every run.15
// the output, as it changes on every run.16
//16
//17
// sgl.yaml sets go.doc_comments, so the comment above each query in tasks.sql becomes its17
// sgl.yaml sets go.doc_comments, so the comment above each query in tasks.sql becomes its18
// method's doc comment, and the migration's COMMENT ON TABLE and COMMENT ON COLUMN become18
// method's doc comment, and the migration's COMMENT ON TABLE and COMMENT ON COLUMN become19
// the doc comments of the Tasks model and its Completed field: open internal/store to see19
// the doc comments of the Tasks model and its Completed field: open internal/store to see20
// them, or hover over queries.CreateTask in an editor.20
// them, or hover over queries.CreateTask in an editor.21
//21
//22
// Takes database (*sql.DB) which is a migrated database, opened with pgx's database/sql22
// Takes database (*sql.DB) which is a migrated database, opened with pgx's database/sql23
// driver.23
// driver.24
// Takes output (io.Writer) which receives the task list.24
// Takes output (io.Writer) which receives the task list.25
//25
//26
// Returns error when a query fails.26
// Returns error when a query fails.27
func run(ctx context.Context, database *sql.DB, output io.Writer) error {27
func run(ctx context.Context, database *sql.DB, output io.Writer) error {28
queries := store.New(database)28
queries := store.New(database)29
29
30
feed, err := queries.CreateTask(ctx, "Feed the seagulls")30
feed, err := queries.CreateTask(ctx, "Feed the seagulls")31
if err != nil {31
if err != nil {32
return fmt.Errorf("creating a task: %w", err)32
return fmt.Errorf("creating a task: %w", err)33
}33
}34
if _, err := queries.CreateTask(ctx, "Count the chips"); err != nil {34
if _, err := queries.CreateTask(ctx, "Count the chips"); err != nil {35
return fmt.Errorf("creating a task: %w", err)35
return fmt.Errorf("creating a task: %w", err)36
}36
}37
37
38
completed, err := queries.CompleteTask(ctx, feed.ID)38
completed, err := queries.CompleteTask(ctx, feed.ID)39
if err != nil {39
if err != nil {40
return fmt.Errorf("completing task %d: %w", feed.ID, err)40
return fmt.Errorf("completing task %d: %w", feed.ID, err)41
}41
}42
fmt.Fprintf(output, "completed %d task\n", completed)42
fmt.Fprintf(output, "completed %d task\n", completed)43
43
44
tasks, err := queries.ListTasks(ctx)44
tasks, err := queries.ListTasks(ctx)45
if err != nil {45
if err != nil {46
return fmt.Errorf("listing tasks: %w", err)46
return fmt.Errorf("listing tasks: %w", err)47
}47
}48
for _, task := range tasks {48
for _, task := range tasks {49
fmt.Fprintf(output, "%d\t%-18s completed=%t\n", task.ID, task.Title, task.Completed)49
fmt.Fprintf(output, "%d\t%-18s completed=%t\n", task.ID, task.Title, task.Completed)50
}50
}51
return nil51
return nil52
}52
}