sqlc-dev / sqlc

Generate type-safe code from SQL
https://sqlc.dev
MIT License
13.54k stars 809 forks source link

faulty SQL nested query segfault sqlc generate #3621

Open nexovec opened 1 month ago

nexovec commented 1 month ago

Version

1.27.0

What happened?

sqlc generate sometimes silently fails and sometimes segfaults. I managed to isolate the issue to this nested query

-- name: GetAnsweredTasksWithQuestionText :many
SELECT * FROM (
    SELECT room_tasks.*, cards.question FROM room_tasks
    JOIN cards ON room_tasks.card_id = cards.id
    WHERE room_id = $1 AND answer_submitted_at IS NOT NULL AND room_tasks.deleted_at IS NULL AND cards IS NULL ORDER BY order_in_attempt DESC -- TODO: LIMIT 1000
) ORDER BY order_in_attempt ASC;

if you add the LIMIT 1000, it seems to segfault always

There is a mistake in the cards IS NULL part of the nested query, nevertheless, it should not segfault.

Relevant log output

sqlc generate --file internal/models/sqlc.yaml
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x10c0ae7]

goroutine 19 [running]:
github.com/sqlc-dev/sqlc/internal/compiler.(*Compiler).sourceTables(0xc0003aaf08, 0xc0008e8420, {0x1da4160?, 0xc0004d6d10?})
        /root/go/pkg/mod/github.com/sqlc-dev/sqlc@v1.27.0/internal/compiler/output_columns.go:601 +0xaa7
github.com/sqlc-dev/sqlc/internal/compiler.(*Compiler).outputColumns(0xc0003aaf08, 0xc0008e8420, {0x1da4160, 0xc0004d6d10})
        /root/go/pkg/mod/github.com/sqlc-dev/sqlc@v1.27.0/internal/compiler/output_columns.go:55 +0x45
github.com/sqlc-dev/sqlc/internal/compiler.(*Compiler)._analyzeQuery(0xc0003aaf08, 0xc00076e380, {0xc0006cd5bd, 0x182}, 0x0)
        /root/go/pkg/mod/github.com/sqlc-dev/sqlc@v1.27.0/internal/compiler/analyze.go:180 +0xccd
github.com/sqlc-dev/sqlc/internal/compiler.(*Compiler).inferQuery(...)
        /root/go/pkg/mod/github.com/sqlc-dev/sqlc@v1.27.0/internal/compiler/analyze.go:114
github.com/sqlc-dev/sqlc/internal/compiler.(*Compiler).parseQuery(0xc0003aaf08, {0x1da4320, 0xc00076e380}, {0xc0006cca80, 0x29ca}, {{0x0, 0x0, {0x0, 0x0}, 0x0, ...}})
        /root/go/pkg/mod/github.com/sqlc-dev/sqlc@v1.27.0/internal/compiler/parse.go:75 +0x386
github.com/sqlc-dev/sqlc/internal/compiler.(*Compiler).parseQueries(0xc0003aaf08, {{0x0, 0x0, {0x0, 0x0}, 0x0, 0x0, 0x0, 0x0}})
        /root/go/pkg/mod/github.com/sqlc-dev/sqlc@v1.27.0/internal/compiler/compile.go:81 +0x467
github.com/sqlc-dev/sqlc/internal/compiler.(*Compiler).ParseQueries(...)
        /root/go/pkg/mod/github.com/sqlc-dev/sqlc@v1.27.0/internal/compiler/engine.go:72
github.com/sqlc-dev/sqlc/internal/cmd.parse({_, _}, {_, _}, {_, _}, {{0xc000422498, 0x8}, {0xc0004224b0, 0xa}, ...}, ...)
        /root/go/pkg/mod/github.com/sqlc-dev/sqlc@v1.27.0/internal/cmd/generate.go:322 +0x2eb
github.com/sqlc-dev/sqlc/internal/cmd.processQuerySets.func1()                                                                                                                             /root/go/pkg/mod/github.com/sqlc-dev/sqlc@v1.27.0/internal/cmd/process.go:107 +0x81a
golang.org/x/sync/errgroup.(*Group).Go.func1()
        /root/go/pkg/mod/golang.org/x/sync@v0.8.0/errgroup/errgroup.go:78 +0x56
created by golang.org/x/sync/errgroup.(*Group).Go in goroutine 1
        /root/go/pkg/mod/golang.org/x/sync@v0.8.0/errgroup/errgroup.go:75 +0x96

Database schema

-- Card
CREATE TABLE IF NOT EXISTS cards (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
    deleted_at TIMESTAMP DEFAULT NULL,
    question VARCHAR NOT NULL
);

-- RoomTasks
CREATE TABLE IF NOT EXISTS room_tasks (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
    deleted_at TIMESTAMP DEFAULT NULL,
    answer_submitted_at TIMESTAMP DEFAULT NULL,

    order_in_attempt INT NOT NULL,
    room_id INT NOT NULL,
    card_id INT NOT NULL,

    answer TEXT DEFAULT '' NOT NULL,
    FOREIGN KEY (card_id) REFERENCES cards (id)
);

SQL queries

-- name: GetAnsweredTasksWithQuestionText :many SELECT FROM ( SELECT room_tasks., cards.question FROM room_tasks JOIN cards ON room_tasks.card_id = cards.id WHERE room_id = $1 AND answer_submitted_at IS NOT NULL AND room_tasks.deleted_at IS NULL AND cards IS NULL ORDER BY order_in_attempt DESC ) ORDER BY order_in_attempt ASC;

Configuration

No response

Playground URL

No response

What operating system are you using?

Linux

What database engines are you using?

PostgreSQL

What type of code are you generating?

Go

nexovec commented 1 month ago

Since noone has responded yet, I assume it's okay to edit the issue due to the fact I managed to find what the issue is.