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
111 lines
2.7 KiB
Go
111 lines
2.7 KiB
Go
package analyzer_test
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/sqlc-dev/sqlc/internal/core"
|
|
"github.com/sqlc-dev/sqlc/internal/core/analyzer"
|
|
coreschema "github.com/sqlc-dev/sqlc/internal/core/schema"
|
|
"github.com/sqlc-dev/sqlc/internal/engine/googlesql"
|
|
"github.com/sqlc-dev/sqlc/internal/sql/ast"
|
|
)
|
|
|
|
const benchSchema = `
|
|
CREATE TABLE users (
|
|
id INT64 NOT NULL,
|
|
name STRING NOT NULL,
|
|
bio STRING,
|
|
) PRIMARY KEY (id);
|
|
|
|
CREATE TABLE posts (
|
|
id INT64 NOT NULL,
|
|
user_id INT64 NOT NULL,
|
|
title STRING(255),
|
|
created TIMESTAMP NOT NULL,
|
|
) PRIMARY KEY (id);
|
|
`
|
|
|
|
const benchQueries = `
|
|
SELECT * FROM users;
|
|
SELECT COUNT(*) AS total FROM users;
|
|
SELECT u.name, p.* FROM users u JOIN posts p ON p.user_id = u.id WHERE u.name = @name;
|
|
SELECT id, name, bio FROM users WHERE id = @id AND name = @name;
|
|
SELECT p.title, p.created FROM posts p WHERE p.user_id = @uid AND p.title = @t;
|
|
`
|
|
|
|
func parseAll(t testing.TB, src string) []ast.Node {
|
|
p := googlesql.NewParser()
|
|
stmts, err := p.Parse(strings.NewReader(src))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
out := make([]ast.Node, 0, len(stmts))
|
|
for i := range stmts {
|
|
out = append(out, stmts[i].Raw)
|
|
}
|
|
return out
|
|
}
|
|
|
|
// parseQueries mirrors the compiler pipeline. GoogleSQL is not preprocessed —
|
|
// "@name" is native syntax the converter turns into a ParamRef — so parsing is
|
|
// all it takes.
|
|
func parseQueries(t testing.TB, src string) []ast.Node {
|
|
return parseAll(t, src)
|
|
}
|
|
|
|
func newBenchCatalog(t testing.TB) (*core.Catalog, []ast.Node) {
|
|
cat, err := core.New(googlesql.Dialect())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, n := range parseAll(t, benchSchema) {
|
|
if err := coreschema.Apply(cat, n); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
return cat, parseQueries(t, benchQueries)
|
|
}
|
|
|
|
// BenchmarkCatalogNew measures per-compile catalog setup: open the SQLite
|
|
// catalog, install the schema, and run the dialect seed.
|
|
func BenchmarkCatalogNew(b *testing.B) {
|
|
for b.Loop() {
|
|
cat, err := core.New(googlesql.Dialect())
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
cat.Close()
|
|
}
|
|
}
|
|
|
|
// BenchmarkApplySchema measures loading user DDL into the catalog.
|
|
func BenchmarkApplySchema(b *testing.B) {
|
|
stmts := parseAll(b, benchSchema)
|
|
for b.Loop() {
|
|
cat, err := core.New(googlesql.Dialect())
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
for _, n := range stmts {
|
|
if err := coreschema.Apply(cat, n); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
cat.Close()
|
|
}
|
|
}
|
|
|
|
// BenchmarkPrepare measures steady-state query analysis against a warm catalog.
|
|
func BenchmarkPrepare(b *testing.B) {
|
|
cat, queries := newBenchCatalog(b)
|
|
defer cat.Close()
|
|
for b.Loop() {
|
|
for _, q := range queries {
|
|
if _, err := analyzer.Prepare(cat, q); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
}
|